For a valid selected count N, the PLC runs N-1 adjacent-pair comparisons, length 1 against length 2 through length N-1 against length N, and ignores every register beyond N. Six selected lengths mean five comparisons and 20 mean 19. Clamp the count register to 1 through 20 in the PLC and reject 0 and anything above 20; the panel hiding unused fields never gates the logic.
The operator picks how many feed lengths the recipe uses, and the ordering check has to follow that number. It does not follow the 20 registers the machine could hold. The rule: for a valid selected count N, the PLC runs N minus 1 adjacent-pair comparisons, length 1 against length 2 through length N minus 1 against length N, and it never reads a register beyond N. Six selected lengths mean five comparisons, 20 mean 19, and a single length means none. The gate is the count register in the PLC. Hiding fields on the panel is a display change the logic never sees. This article covers reading the count, clamping it to 1 through 20, bounding the loop, and testing counts 1, 6 and 20 before you release the change.
How does the PLC know how many lengths the operator selected?
The count is an ordinary PLC register that the operator's numeric entry writes. Read that register in the PLC and confirm it tracks the selection before you trust it as a loop limit. Six lengths selected means six registers hold fresh values.
The logic only cares about two things in its own memory: the register the count entry writes, and the storage that holds the lengths. Collect these before writing any rungs:
- The count register the panel's numeric entry writes, with its address and data type
- The length storage, one indexed array or individually named registers, with its data type and any scaling
- The command bit that says the operator has finished entering and accepts the recipe
Put the panel in setup, enter 6, and watch the count register; enter 20 and watch again. The register has to track the selection every time. Then enter a few lengths and confirm they land in the registers you expect, in the order the screen shows them. If the count stalls or the lengths arrive shuffled, fix the panel-to-PLC mapping first. A loop built on a stale count checks the wrong pairs, and no loop tuning repairs a mapping fault. Note now whether the lengths sit in one array or in named registers, because that decides how the loop reaches them.
How many pair comparisons does a selected count need?
A count of N lengths needs N minus 1 adjacent comparisons: 6 selected lengths mean 5 pairs from 1-2 through 5-6, 20 lengths mean 19 pairs, and a single selected length means no pair at all.
Transitivity does the heavy lifting. If length 1 is less than length 2 and length 2 is less than length 3, then length 1 is less than length 3 with no rung of its own. Once every adjacent pair holds, the whole chain holds. That is why N lengths need N minus 1 comparisons instead of the N times N over 2 pairs a full cross-check would demand: 20 lengths would need 190 pairs cross-checked and only 19 adjacent pairs.
| Selected count N | Comparisons N-1 | Pairs checked | Decision |
|---|---|---|---|
| 1 | 0 | none | Valid; no pair exists, check passes |
| 6 | 5 | 1-2 through 5-6 | Registers 7-20 stay out of the check |
| 20 | 19 | 1-2 through 19-20 | Full check of every adjacent pair |
| 0 or above 20 | none run | none | Invalid setup; reject before any indexing |
The recipe rule on this machine is strict ordering: each length must be less than the next. Equal adjacent values fail, so the failing condition is Length[i] greater than or equal to Length[i + 1]. If a machine ever allows equal lengths, change that comparison to a strict greater-than and nothing else in the loop moves.
Does hiding the unused fields on the panel stop the comparisons?
No; hiding is a display-side change. The register behind a hidden field keeps its last value, every comparison reads registers, and the gate has to be the PLC count register.
Panel documentation describes functions for hiding buttons and fields on screen, and those functions act on the display side of the panel. A fixed check that runs all 19 pairs reads the leftovers anyway. With 6 lengths selected and a stale 5,000 mm sitting in the register for length 12, the fixed check dies somewhere in the stale range and rejects a perfectly ordered six-length recipe. It points the operator at fields the screen never showed.
So the gate belongs to the count register, and every comparison pass carries it. If you already drive what the panel displays from PLC values, the split is the same one as when you gate HMI button visibility on a PLC timer done bit: visibility is display state, the ordering check is logic, and each side needs its own condition.
How do you stop an invalid count from running the loop?
Clamp or reject the count in the PLC before any indexing: accept 1 through 20, treat 0 and anything above 20 as an invalid setup that blocks recipe acceptance, and keep the raw entry away from every loop bound and index.
The panel can put an entry limit on the numeric field, and that is worth having at the keypad. The clamp still belongs in the PLC, because a recipe download, a second panel or a debugging write can put any value into the register without going near the keypad. The clamp is the same pattern that clamps HMI numeric entry limits in PLC ladder logic, and if the operator steps the count with plus and minus buttons, enforce the increment and decrement value limits in PLC logic on those buttons too. Decide the zero case once and write it down: unless this machine genuinely runs an empty recipe, 0 is an invalid setup.
The loop construct itself is documented behavior. FOR and NEXT form a matched pair with an index and inclusive initial and final bounds, and the pass count at a step of 1 is final minus initial plus 1. Instruction references also put hard ceilings on the construct: one allows up to three nested loops and counts loops inside called subroutines toward that limit, and another documents a maximum of 32,767 iterations while warning that scan-timeout risk keeps practical loop lengths far lower, typically under 1,000. A 19-pass loop sits well inside every one of those numbers.
Recommendation: when the operator can enter up to 20 lengths, clamp the PLC count register to 1 through 20, reject 0 and any value above 20 before any indexing, and bound one flat loop at count minus 1; write 19 gated comparison rungs instead only if your platform has no indexed addressing.
What does a worked example look like with six lengths selected?
With six lengths selected, the PLC owes five comparisons. In the example below pair 2-3 fails because 180 < 180 is false, so the logic stores failing pair 2 and raises the order fault while registers 7 through 20 stay out of the check.
The operator selects 6 lengths; the panel writes 6 into the count register, and the length registers hold:
| Register | Length |
|---|---|
| Length 1 | 120 mm |
| Length 2 | 180 mm |
| Length 3 | 180 mm |
| Length 4 | 240 mm |
| Length 5 | 300 mm |
| Length 6 | 360 mm |
Registers 7 through 20 still hold the previous run's values, 400 to 900 mm. The count of 6 gives 6 - 1 = 5 comparisons, and the loop starts at pair 1-2:
- Pair 1-2: 120 < 180, true, pass
- Pair 2-3: 180 < 180, false, fail
The loop stops at pair 2-3, stores failing pair index 2 with both values, 180 mm and 180 mm, and raises the order fault. Pairs 3-4 through 5-6 never run this pass, and the stale 900 mm in length 20 never enters the logic.
The operator raises entry 3 from 180 to 210 mm and accepts again. The same 5 comparisons now read 120 < 180, 180 < 210, 210 < 240, 240 < 300, 300 < 360, all true, so the fault clears and the setup is accepted. Both passes ran 5 comparisons, because the count set the loop length, never the number of fields the panel happened to show.
How do you write the check when the lengths sit in single registers?
Reach Length[i] and Length[i + 1] with the platform's indexed addressing inside a FOR/NEXT loop, and where indexed addressing of named registers is unsupported, write the 19 comparisons out and gate every rung with the count.
The loop form, in language-neutral pseudocode. The names here are this article's; map them to your platform's documented loop and compare instructions, and Length[] is the application's own length array:
count : INT := 0 // operator-selected length count, valid 1 to 20
i : INT := 1 // loop index
fail : BOOL := FALSE // ordering result, TRUE = setup rejected
fail_pair : INT := 0 // first failing pair index, 0 = none
fail := FALSE
fail_pair := 0
IF count < 1 OR count > 20 THEN
fail := TRUE // invalid setup: block acceptance
ELSIF count >= 2 THEN
FOR i := 1 TO count - 1 DO // inclusive bounds: count - 1 passes
IF Length[i] >= Length[i + 1] THEN
fail := TRUE
fail_pair := i // first failing pair is kept
EXIT
END_IF
END_FOR
END_IF
// count = 1 leaves fail FALSE: one length has no pair to order
The bounds are inclusive, so the documented pass count applies. At count 6 the loop runs 1 to 5, and 5 - 1 + 1 = 5 passes. At count 20 it runs 1 to 19 and makes 19 passes. At count 1 the branch skips the loop entirely, which keeps the empty-range behavior of any particular platform out of the argument.
If the lengths are named registers with no indexed access, do not build register names from the index at run time; the supported path is 19 explicit compare rungs, each gated by the count. Pair k compares length k with length k + 1 and runs while the count is at least k + 1. Pair 1-2 runs while the count is at least 2, pair 5-6 while it is at least 6, pair 19-20 only while it is 20. A missing gate on any one rung is what lets an unselected register into the result, so check the gates as a set.
Run the check when the operator accepts the recipe, not free-running. Reset fail and fail_pair at the start of the acceptance, run the loop, and latch the result. The fault that trips stays on screen with its pair index until the entries are corrected and accepted again.
How do you test the boundary counts before you trust the check?
Test the smallest count, a middle count and the maximum, each once with a valid ascending set and once with a deliberate fault, then put junk in the unselected registers and confirm the result still passes.
- Set count to 1 with a single length entered. Confirm no pair runs, the check passes, and no access touches length 2.
- Set count to 6 and enter 120, 180, 210, 240, 300, 360 mm. Confirm 5 pairs run and the check passes with fail_pair at 0.
- Change entry 4 from 240 to 200 mm. Confirm the check fails at pair 3-4, since 210 is greater than or equal to 200, and fail_pair holds 3 with the values 210 and 200 mm.
- Leave count at 6 and write 5,000 mm into the registers for lengths 7 and 20. Confirm the result stays passing: unselected entries have no vote.
- Set count to 20 and enter 20 ascending lengths. Confirm 19 pairs run. Break the last pair so length 20 is smaller than length 19, and confirm fail_pair holds 19.
- Enter 0 as the count, then 21. Confirm the rejection path fires both times and no index reads outside lengths 1 through 20.
- After a 20-length recipe, watch the count register while the operator re-enters 6. Confirm the loop bound follows; a stale count of 20 would check 19 pairs against six fresh values and reject on leftovers.
Keep the count, the fail bit and fail_pair on the maintenance screen. Release the change when three things hold: the count register tracks every entry the operator makes, a deliberate fault reports its pair with both values, and junk beyond the selected count cannot change the result.
Questions
Does the panel's own numeric entry limit protect the loop?
An entry limit on the panel rejects out-of-range keystrokes at the input, which is worth having, but the PLC clamp is what protects the loop. The count register is memory, and logic, a second panel, a recipe download or a debugging write can all change it without touching the keypad. Validate the value where it is used: accept 1 through 20, reject 0 and anything above 20 before any indexing, and keep that validation in the PLC even when the panel already enforces a range.
How many FOR/NEXT loops can one PLC program nest?
One documented instruction set allows up to three nested loops, and loops running inside called subroutines count toward that limit. This check needs no nesting: a single loop from 1 to count minus 1 covers every adjacent pair, and a flat loop is easier to trace when a fault pair shows up. If you stack several checks in one program, keep each loop's start, end and index in its own registers so a fault in one loop cannot walk on another's index.
The panel shows the right lengths but the compare still fails: what now?
Check the value the comparison actually reads before blaming the loop. Open the two registers named in the fail pair in the PLC and compare them with the panel display: if the numbers disagree, the tag data type, the word order or the engineering-unit scaling differs between the panel write and the compare instruction. A displayed 210 mm that sits in the register as 21000 tenths or as a binary-coded-decimal word will fail a plain integer compare. Fix the type or scaling once at the tag, and the loop needs no change.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.