learn · South Africa
Sequencer logic patterns: step control without spaghetti
Sequencer logic patterns for SA control engineers — state-machine vs step-counter, mutual exclusion, E-stop reset, and a 5-step bottling-line example.
Sequencer logic patterns is the part of PLC work where the difference between a programmer who has written ten machines and one who has written one shows up loudly in the code. A new tech approaches a five-step packaging line by writing twenty rungs of ladder, each with its own ad-hoc latch, each cross-referencing the others, with timer accumulators and proximity-sensor inputs threaded through every rung. The machine works on the bench. It works for the first month on the line. It breaks in week six during a recipe changeover when an operator E-stops mid-cycle and the machine restarts in the wrong step because nobody handled the reset case. This tutorial walks through the two patterns that working machine builders actually use — state-machine and step-counter — and the rules that make each one survive recipe changeovers, E-stops, and a six-month commissioning.
Try the simulator →Why this matters on real plants
A bad sequencer is not a bug you find in code review. It is a behaviour you find on the line at 02:00 when an operator presses E-stop because a label web jammed, clears the jam, releases E-stop, and the machine starts capping a bottle that was never filled. We have walked into a brownfield FMCG plant where exactly this scenario was tripping six recordable quality incidents a week. The root cause was a sequencer that latched each step independently and never cleared the active step bit on E-stop, so the restart picked up wherever the cycle was when the E-stop hit. The fix was a fifteen-line refactor of the step-transition logic. The cost of finding the fix was four months of operators getting blamed for "not following procedure" before someone read the ladder properly.
The cost of getting sequencer logic wrong scales with how many cycles the machine runs per shift. A line running 20 bottles a minute does about 9000 cycles in an eight-hour shift. A 0.05% intermittent failure rate is one bad bottle every twelve minutes, which is forty bad bottles a shift. On a small batching plant making once-a-day product the same code might fail once a year. The same code, two failure rates, two operational costs. The machines that need disciplined sequencer patterns are the high-cycle ones: bottling lines, packaging lines, palletisers, filler-cappers, conveyor sortation. Anything that runs a sub-30-second cycle and clocks tens of thousands of cycles a week.
The third reason this matters more in SA than in textbook examples: load-shedding. A power dip during a sequence is not a scheduled event the machine builder can plan for. The sequencer must come back from a cold start in a known state, regardless of which step was active when the lights went out. The pattern that gets this right is the one with explicit step-bit clearing on first-scan and a master "where do we restart" decision tree. The pattern that gets this wrong is the one that relies on retentive memory to "remember" the active step — because retentive memory survives power-off but it does not survive a power dip that holds the CPU in fault, and the machine comes back online with a stale step bit and an actuator firing on a part that is not there.
The mental model
A sequencer is a finite state machine with a small set of states (steps), explicit transitions between states (step-completion conditions), and an output mapping from each state to the actuators that should fire in that state. Two patterns dominate working code.
The first is the state-machine pattern. One BOOL bit per step. At any time exactly one step bit is true, and the others are all false. Transitions are explicit rungs that clear the current step bit and set the next one in a single rung, gated on the step-completion condition. Outputs are driven by reading the step bits — if step bit Step03 is true, the output Wrap_Solenoid is true. This pattern is readable, debuggable, and the mutual-exclusion invariant is checkable: a single rung that ORs all step bits and counts the resulting 1s should always read exactly 1.
The second is the step-counter pattern. One INT or DINT register holding the current step number. Transitions are explicit rungs that increment the counter on the step-completion condition, gated on the current value of the counter. Outputs are driven by comparators — if the counter equals 3, the wrap solenoid is true. This pattern is more compact for long sequences (a 32-step palletiser fits in one INT plus 32 comparator rungs instead of 32 step bits plus 32 transition rungs).
The general rule, learned the hard way: state-machine for sequences of 8 or fewer steps, step-counter for longer sequences. The state-machine pattern's debuggability advantage shrinks as the number of step bits grows; the step-counter pattern's compactness advantage grows with the same number. The crossover is around 8-12 steps depending on how branchy the sequence is.
A third hybrid pattern exists — the SFC (Sequential Function Chart) pattern that IEC 61131-3 formalises as a fifth IEC language. Most modern IDEs (TIA Portal, Studio 5000, CODESYS) support SFC natively, and SFC is the right tool when the sequence has parallel branches and rejoin points (a packaging line with two filler heads running in parallel feeding into a single capper). For straight-line sequencers SFC is overkill; for parallel-branch logic it is the cleanest pattern. The decision tree is sequential-only-ladder for ≤8 steps, step-counter ladder for 9-32 sequential steps, SFC for any sequence with parallel branches.
Worked example
Open the simulator and load the sequencer ladder preset. We are going to build a 5-step bottling-line sequencer using the state-machine pattern, then compare it to the step-counter version of the same logic.
The 5 steps are:
- Step01 Fill — bottle on station, fill solenoid open until weight setpoint reached
- Step02 Cap — cap-applicator down, torque to spec, retract
- Step03 Label — label-applicator engaged, label adhered, retracted
- Step04 Wrap — shrink-wrap film fed, heat-tunnel pass timer
- Step05 Reject-or-pass — vision check, divert to reject lane or pass to crate
The state-machine pattern in pseudo-ladder. Five step bits, one transition rung per step, explicit clear-all on E-stop:
| StartCycle Step01..Step05 all false Step01 |
|---| |---------[NOT (Step01 OR Step02 OR Step03 OR -+--(L)----|
| Step04 OR Step05)] | |
| |
| Step01 Fill_Done Step01 |
|---| |--------| |-----------------------------------+--(U)----|
| | |
| | Step02 |
| +-(L)-----|
| |
| Step02 Cap_Done Step02 |
|---| |--------| |-----------------------------------+--(U)----|
| | |
| | Step03 |
| +-(L)-----|
| |
| ...same pattern for Step03->Step04 and Step04->Step05... |
| |
| Step05 Vision_Done Step05 |
|---| |--------| |-----------------------------------+--(U)----|
| |
| EStop_NotPressed |
|---|/|---+-----[Clear all step bits] |
| FirstScan |
|---| |---+ |
| |
| Step01 Fill_Solenoid |
|---| |----------------------------------------( )--------------|
| |
| Step02 Cap_Down |
|---| |----------------------------------------( )--------------|
| |
| ...same output mapping for Step03..Step05... |
Read it as five sections. The first is the start-of-cycle rung — it sets Step01 only when StartCycle is pressed AND no step is currently active. This is the gate that prevents a mid-cycle restart from re-entering at Step01 while Step03 is still active. The second through fifth are the step-transition rungs, each one clearing the previous step bit and setting the next one in a single scan when the step-completion input fires. The sixth is the E-stop / first-scan reset rung — on either condition, all step bits are cleared, returning the sequencer to its idle state where the start-cycle rung becomes the only way to re-enter. The seventh and onward are the output rungs — pure read-only mappings from step bits to actuator outputs. Each output is driven by exactly one step bit; no step bit drives more than one output.
Run the simulator. Press StartCycle. Step01 latches, the fill solenoid opens, the simulator's bottle-fill animation runs. The Fill_Done input fires when the weight reaches setpoint — Step01 unlatches, Step02 latches in the same scan, the cap-applicator descends. Step02 to Step03 to Step04 to Step05 in sequence, each transition gated on its own completion input, each output cleanly driven by the current step bit. At the end of Step05, Vision_Done fires, Step05 unlatches, no further step latches, and the sequencer returns to idle. Press StartCycle again and Step01 re-enters. Press E-stop mid-Step03 — the reset rung fires, all step bits clear, all outputs drop. Release E-stop and press StartCycle — Step01 re-enters cleanly because all step bits are false. The mutual-exclusion invariant holds at every scan.
The step-counter version of the same logic compresses to one INT and five comparator rungs:
| StartCycle StepCnt = 0 StepCnt |
|---| |---------[EQ 0]-------------------------------[MOV 1]---|
| |
| StepCnt = 1 Fill_Done StepCnt |
|---[EQ 1]--------| |--------------------------------[MOV 2]---|
| |
| ...same pattern for StepCnt 2->3, 3->4, 4->5... |
| |
| StepCnt = 5 Vision_Done StepCnt |
|---[EQ 5]--------| |--------------------------------[MOV 0]---|
| |
| EStop_NotPressed |
|---|/|---+-------------------------------------------[MOV 0]---|
| FirstScan |
|---| |---+ |
| |
| StepCnt = 1 Fill_Solenoid |
|---[EQ 1]-------------------------------------( )--------------|
| |
| ...same EQ-driven outputs for StepCnt 2..5... |
Same behaviour, more compact code. The mutual-exclusion invariant is automatic — an INT can only hold one value at a time. The trade-off: harder to read at a glance because the active step is a number, not a bit name. On a 5-step sequence the state-machine pattern wins on readability. Push the same example to 32 steps (a palletiser sequence with stack-row, stack-column, layer transitions) and the step-counter wins on compactness. The simulator's sequencer preset has a toggle that switches between the two patterns so you can compare side-by-side on the same five steps.
Common mistakes
-
Allowing two step-bits high simultaneously. The state-machine pattern's invariant is that exactly one step bit is true at any time. The most common way to break it is to write the transition rung as two separate rungs — one that sets the next step, one that clears the current step — instead of as a single rung. If the set-rung fires on scan N and the clear-rung fires on scan N+1, there is a one-scan window where two step bits are both true. During that window the output rungs fire two actuators at once. The fix is a single transition rung that uses an immediate-set-and-clear pattern, with the unlatch and the latch on the same rung gated by the step-completion edge. Verify the invariant by adding a diagnostic rung that sums all step bits and triggers a fault when the sum is anything other than 1.
-
Forgetting to clear all step bits on E-stop. The most expensive mistake in sequencer code. If E-stop only drops the actuator outputs without clearing the step bits, the restart picks up at the same step the machine was in when E-stop fired. On a bottling line that means starting a fill cycle on a half-capped bottle, or capping a bottle that was never filled. The fix is the explicit clear-all rung gated on
EStop_NotPressedgoing false ORFirstScangoing true, which guarantees a known state on every E-stop and every cold start. -
Latching a step bit without an exit condition. A common pattern in junior code is
Step03latched on entry and unlatched only by the next-step transition. IfCap_Done(the exit condition) is wired to a proximity sensor that has failed, the step never exits. The sequence is locked. There is no timeout, no operator-visible fault, just a machine standing still with one solenoid energised. The fix is to add a step-timeout TON to every step, with a preset of 2x the expected step time, and to fault the sequence if the TON expires without a transition. The fault drops actuators, raises an HMI alarm, and waits for operator intervention. No locked sequences. -
Driving outputs from step-bits without a one-shot. If
Cap_Downis driven directly byStep02, the actuator is energised continuously while Step02 is active. For a solenoid-driven cap-applicator that pulses down then retracts, that is wrong — the actuator should fire on Step02 entry, not be held for the whole step duration. The fix is to drive the output from a one-shot triggered by the rising edge of the step bit, which gives a single-scan pulse on entry. The retraction then comes from a timer or a return-position proximity sensor inside the same step. -
Putting actuator logic inside the step-transition rung. A rookie pattern is to fire actuators directly from the transition rung — clear
Step02, setStep03, AND turn onWrap_Solenoidall on the same rung. This couples the transition logic to the output logic and makes refactoring the sequence painful. The clean separation: transition rungs handle step-bit changes only; output rungs map step bits to actuators in a separate, read-only block. Touch one without touching the other. -
No first-scan handler. A CPU coming out of STOP into RUN with retentive memory holding stale step bits will start the sequence partway through. The first-scan bit (
S:FS,M1.0,_FirstScan) must clear all step bits in the very first scan, before any transition rung fires. Without this the machine restarts in the wrong step after every power-cycle.
How to practise this in the simulator
The simulator's sequencer preset ships with the 5-step bottling-line example pre-built. Open it, run the cycle, watch the step bits transition. Then break each rule and watch what fails. Remove the E-stop reset rung and press E-stop mid-cycle — the machine restarts in the wrong step. Add the rung back. Remove the step-bit clear in the transition rung — watch two step bits go high during a one-scan window and two actuators fire. Set the step-completion input to a sensor that never fires — watch the sequence lock at that step until you add a step-timeout TON. Switch the toggle from state-machine to step-counter and watch the same five steps run with the same behaviour but a different code shape. Twenty minutes of breaking and fixing teaches more about sequencer logic patterns than two hours of reading SFC theory.
Vendor reference
The cross-vendor reference for sequence-of-operation modelling is the Wikipedia Sequential function chart article, which covers the IEC 61131-3 SFC language — the formal cousin of the state-machine pattern shown above. SFC is one of the five IEC 61131-3 languages and every modern PLC IDE supports it (Siemens TIA Portal as GRAPH, Rockwell Studio 5000 as SFC, CODESYS as SFC, Mitsubishi GX Works as SFC). The mental model in the article maps cleanly onto the state-machine pattern in this tutorial — each SFC step is a step bit, each transition is a transition rung, the ladder pattern is the manual implementation of what SFC does graphically. Read the SFC article once. The vocabulary becomes the language you use when discussing sequence design with a senior machine builder.
What we don't claim
This site is not SAQA-registered, not MerSETA-accredited, and not an NQF-registered qualification provider. Our completion certificates are course-level only — they describe what you covered, not an NQF Level X qualification. The CCST cert from ISA is the portable industry credential we recommend; we are not an ISA cert delivery partner either, but our cert packs are CCST-aligned. Sequencer design is covered in the discrete-control portion of the CCST Level 2 syllabus and the patterns shown here are the ones working machine builders converge on after a few hundred commissioned cycles.