LIM and MEQ: Testing a Value Against a Window, and Against a Mask
A LIM with a Low Limit of 4000 and a High Limit of 20000 passes the rung while a 4-20 mA input is in range. Type the same two numbers into the opposite fields and the instruction passes the rung for exactly the values that are out of range — not a fault, not an undefined state, but a documented second mode that most people never find.
Both instructions on this page are input conditions. Neither writes a value anywhere.
LIM asks whether a number falls in a span, MEQ asks whether the bits you selected match a pattern, and each hands the rung a true or a false and nothing else. Two things are worth carrying away before the detail: a LIM whose Low Limit is greater than its High Limit tests for values outside the span, and a MEQ mask passes a bit with a 1 and blocks it with a 0. The rest of this is consequences of those two sentences.

The Test operand accepts REAL. The MEQ operands do not — its list stops at the unsigned 64-bit integers, and that difference decides which instruction can look at a scaled engineering value.

Both sit where a contact would sit. What follows them on the rung is your business; what they contribute is one bit of rung condition.
One naming note before anything else, because it will confuse anyone reading a printout from a newer project: in Logix Designer version 36 the mnemonic LIM became LIMIT, in the same release that turned MOV into MOVE and GRT into GT. The instruction did not change. MEQ kept its name.
The window, and the same window inside out
The operation table on page 403 has two rows, and almost everybody has only ever read the first.
If the Low Limit is less than or equal to the High Limit, the output is true when the test value is equal to or between the limits, which is the behaviour anyone would expect and the reason the instruction exists. If the Low Limit is greater than the High Limit, the output is true when the test value is equal to or outside the limits. That second row is a complete out-of-range alarm in one instruction: Low Limit 20000, High Limit 4000, Test the raw count, and the rung is true whenever the transmitter is over range or under range or broken, with no NOT and no second rung to keep in step with the first. The manual’s own worked example uses negative numbers to make the same point — with a low limit of 0 and a high limit of -100, the output is set when the value is at or above 0 or at or below -100, and cleared for everything between.

Same two numbers, swapped operands, opposite test. The shaded span is where the rung passes.
That is a nice trick and a nasty typing error.
Swap those two operands by accident — copying a rung and editing one field, or a find-and-replace that catches both numbers — and you do not get a compile error, an instruction fault or an obviously stuck output. You get a range check that is true precisely when the process is wrong, which on a level interlock means the pump runs when the tank is empty and stops when it is at setpoint. It will look like a wiring fault for a while, and the scaling side of that argument is usually eliminated first: the raw-count arithmetic for a 4-20 mA loop is worked through in reading a 4-20 mA transmitter into a 1756-IF8.
Why it inverts: the number line is a circle
The reference does not leave this as a quirk. It explains it, and the explanation is the useful part.
Signed integers wrap. The manual spells it out with sixteen-bit numbers: the largest positive INT is 32,767, which is 16#7FFF; add one and you get 16#8000, which as a signed integer is -32,768; keep going and you arrive at 16#FFFF, which is -1. So the range of an integer is not a line with two ends but a circle, and LIMIT walks that circle. It starts at the Low Limit and increments clockwise until it reaches the High Limit, and any test value in that clockwise arc makes the output true. When Low is below High the arc is the ordinary span between them. When Low is above High the arc runs off the top of the range, through the wrap, and back up to the High Limit from the bottom — which is the same set of values as “outside the span”, described in a way that also tells you what happens to a test value sitting exactly on the wrap.
One instruction, one behaviour, two appearances.
The value that is neither inside nor outside
There is a third outcome and it is stated twice on the LIMIT page, which is usually a sign that somebody got caught by it.
If any operand is Not A Number, the output is cleared to false. That is the whole rule, and its consequence depends entirely on which way you wired the test. A NAN arriving on a LIMIT used as an in-range permissive clears the permissive, which fails safe and looks like a process problem. The same NAN arriving on a swapped-operand LIMIT used as an out-of-range alarm also clears the output — so the alarm that exists to catch bad data goes quiet at the exact moment the data goes bad. If a REAL in your system can become NAN, and any REAL that is ever divided by a measured value can, then the out-of-range form of this instruction needs an explicit companion test rather than trust.
False is the output for a good value outside the window and for no usable value at all.
MEQ: testing the bits you care about while the rest of the word moves
A status word from a drive or a smart device is rarely a value. It is a bag of bits, and most of them are none of your business.
MEQ passes the Source and the Compare value through the same Mask and compares the results, so a mask of 16#0013
16#0003 against that mask — and a source of 16#5A03 satisfies it even though four of its upper bits are set, because the mask blocked all four. That is the property that makes MEQ worth reaching for: the sequence counter in the high byte changes every scan, and the test does not care. Writing the same check as three XIC and XIO contacts works and is arguably clearer for three bits; it stops being clearer at six, and it stops being maintainable when the device’s manual describes the condition as a hex pattern and your rung describes it as a row of contacts. Where the bits come from on a real drive is covered in commanding a PowerFlex 525 from a ControlLogix.
Bits 9, 11, 12 and 14 of the source are set and the compare value has none of them. The mask blocks all four, and the test is still true.
Three contacts are clearer than a mask. Six of them are not.
Two details on the mask itself, both of which come straight off the page.
The programming software defaults the mask field to decimal, and a mask in any other radix needs its prefix — 16#, 8# or 2#. And a SINT or INT tag is converted to a DINT value by zero-fill before the comparison, which is the behaviour you want for a bit pattern and is worth pairing with the immediate-value rule from the common attributes chapter: enter 16#FFFF as an immediate and the controller stores 16#0000FFFF, which is 65535, not -1. Mask and compare values that were written for a sixteen-bit device and then pasted into a rung working on a DINT are where this goes wrong, silently, because the top sixteen bits of the compare are zero and the top sixteen bits of the masked source are zero too, so the test passes and keeps passing.
The data types differ, and in function block they change again
LIMIT accepts REAL and LREAL on its three operands. MEQ does not accept REAL at all.
That is not an arbitrary restriction — a mask has no meaning applied to a floating-point value — but it does decide the shape of your logic, because a temperature in degrees has to be tested with LIMIT or with the discrete compares, while a status word has to be tested with MEQ or with contacts. Then the function block versions add a wrinkle that catches people moving logic between languages: the FBD_LIMIT structure declares LowLimit, Test and HighLimit as REAL, while the FBD_MASK_EQUAL structure declares Source, Mask and Compare as DINT. So the ladder LIMIT compares your DINT as a DINT, and the function block LIMIT takes that same DINT through a REAL input member. For a scaled analogue value that changes nothing. For a raw count above sixteen million it can, because a REAL carries twenty-four significant bits and a DINT carries thirty-one. There is a second split in the same place worth knowing before you draw the sheet: both instructions offer an FBD block on every controller in the family, and an FBD function — the small one with bare pins and no backing tag — only on the CompactLogix 5380, ControlLogix 5580, Compact GuardLogix 5380, GuardLogix 5580 and ControlLogix 5590. Open a sheet built on a 5580 in a 5570 project and the functions are the parts that do not come across.
REAL on one instruction, integers only on the other, and nothing to be done about it.
Neither one exists in structured text
The compare chapter’s availability list is short and absolute: Structured Text, not available.
That applies to every instruction in the chapter, LIMIT and MEQ included, and it is not the hardship it first appears — ST has comparison operators, so an in-range test is IF low <= x AND x <= high THEN, and a mask-equal test is IF (source AND mask) = (compare AND mask) THEN, which is precisely what MEQ does and is arguably more readable than the instruction. What you cannot write that way is the inverted window. low <= x AND x <= high with low above high is simply always false; reproducing LIMIT’s wrap-around arc in ST means writing the two-sided test yourself and thinking about the wrap, which is the point at which the ladder instruction starts looking like the better tool for that one rung. If most of your logic has moved to ST, the six constructs a ladder programmer needs covers the translation of the rest.
What to check next
Open every LIM in the project and read the two limits in order, out loud, low first. Any rung where the first number is larger than the second is either a deliberate out-of-range test — in which case the rung comment should say so, because the next person will read it as a mistake and fix it — or it is a mistake, in which case the process has been running against an inverted interlock and you want to know for how long. Then look at what the test operand is: if it is a raw count, decide whether a clamp belongs there instead of a test, since an analogue output that drives a valve needs scaling, clamping and a fail position rather than a bit that says the number was wrong. And if the value is a scaled engineering unit coming from an input card, confirm the scaling before you trust the window, because a LIMIT is only as honest as the number handed to it — which is the argument in scaling a 4-20 mA temperature transmitter on a CompactLogix 5380.