Comparing Values in the 2000 Series: What Actually Happens
When you're working with Allen-Bradley's 2000 series controllers, the comparator instructions are one of those things that sound simple but trip people up when the process actually runs. I've seen engineers spend half a day hunting a bug because they didn't understand how the CMP instruction handles signed versus unsigned data, or why their comparison was returning unexpected results during a scan. The comparator instruction in these controllers lets you compare two values and set a status bit based on the result. The basic CMP instruction checks whether one value is greater than, less than, or equal to another. There are also more specialized variants depending on your controller model. You typically set up the instruction with a destination bit, a source A reference, a source B reference, and the operation code that determines what kind of comparison you're running.
2000 Series Comparator Instructions Reference
Here's the actual instruction format you'll see in the programming software. The standard CMP instruction uses three main elements. The first is the operation itself - this determines whether you're checking GT, LT, or EQ. The second is the first value you're comparing, which can be a constant or a register reference. The third is the second value, same deal. The result comes back as a status bit that you then use in your logic rung. It's not complicated, but the devil is in the details of how your data types line up. I learned this the hard way on a packaging line where we were comparing weight measurements against a target tolerance band. The comparator was returning false negatives intermittently. The problem turned out to be that the weight sensor was feeding floating-point data into a register, and I had the comparator set up to compare against an integer constant. The controller was implicitly truncating the float before the comparison, which meant any value under 1.0 above or below the target was getting flagged incorrectly. I switched the entire comparison to work with scaled integer values across the full operating range and the problem disappeared. That cost us about three days of debugging before someone pointed out the data type mismatch. The key thing most people miss is that the CMP instruction doesn't just check equality. You have separate operation codes for each relationship. If you need to check a range, you're not writing one instruction - you're chaining at least two comparators together. One checks if the value is greater than or equal to the lower bound, and another checks if it's less than or equal to the upper bound. Both results feed into an AND logic structure on your rung. This is standard practice, but it adds up quickly when you're building complex interlock sequences.
There's also the question of scan timing. The comparator instruction executes during the normal instruction scan cycle, which means it's evaluated every single scan just like any other rung logic. If you're comparing high-frequency updating registers and your comparison logic is feeding into a latch that toggles on every true evaluation, you can get what looks like chatter or metastable behavior in your output. I've dealt with this in applications where a comparator was driving a contactor coil and the process variable was oscillating right at the threshold. The solution was a simple timer-based debounce - you add a one-second delay between when the comparison becomes true and when the output actually actuates. That eliminated the cycling entirely. Another thing worth noting is how the 2000 series handles negative numbers in comparisons. If you're working with signed integers, the CMP instruction does understand two's complement representation. But if your data source is feeding raw binary or unsigned values that happen to have the high bit set, the controller will interpret them as negative numbers. This has caught me out when reading from certain analog input modules where the raw counts map to a 0 to 32000 range. A comparison against a small positive number would appear to show the value as always greater, when in reality the controller was treating 32000 as a large negative number. The workaround is to verify your data format at the source and make sure you're using the right instruction type for the data representation. For computing more complex comparisons, there's the CPT instruction which lets you evaluate expressions. You can chain multiple comparisons in a single computed instruction rather than spreading them across five or six rungs. This is cleaner from a maintenance standpoint and reduces scan time slightly, though the improvement is marginal unless you're running tight control loops. I tend to use CPT for the range-checking logic and keep the simple CMP instructions for the straightforward pass/fail comparisons that feed into alarms.
Get the Full Details

If you need comparator functionality beyond what the standard CMP instruction provides, some of the later 2000 series controllers support floating-point comparison instructions that handle precision better than doing everything through scaled integers. The tradeoff is scan time. A floating-point comparison takes noticeably longer than an integer comparison on these older processors. In a tight loop running at millisecond scan intervals, this adds up. I've seen full scan times double when someone replaced integer comparisons with floating-point ones across an entire control routine. You can find the detailed instruction manuals through Rockwell Automation's official documentation portal. Search for the specific controller model you're working with since the instruction set varies slightly between the 1747, 1771, and later SLC 500 platforms. The manual will show you the exact addressing format, the complete list of supported operation codes, and the data type compatibility matrix. That matrix alone is worth reviewing before you start writing comparison logic. The practical takeaway is that comparator instructions work well when you understand their limitations. They're fast, reliable, and straightforward for basic value comparisons. They break down when you try to push them into territory where data types don't match, or when you need sub-scan response times that these controllers simply can't deliver. In those cases you're better off moving the logic to a dedicated motion or process controller and using the 2000 series for what it was designed to do.