Machine Design #52: State Machines — Do Not Put the Whole Machine in One StepNo Variable
Machine Design #52: State Machines — Do Not Keep a Machine's Whole Behaviour in One StepNo Variable
In many PLC programs the sequence is driven by a single variable:
StepNo = 0, 10, 20, 30...
While the machine runs normally this looks tidy. A few years later:
- step 120 was added to handle a new model;
- step 125 is a hotfix for a slow sensor;
- step 127 only runs after a recovery;
- one coil is written both at step 90 and in the fault routine;
- on power loss StepNo is retained, but the mechanism has drifted;
- nobody dares delete step 240 because "it might be used".
The problem is not the integer. The problem is that the behaviour contract has disappeared into the code.
A good state machine separates mode, state, transition, action and invariant. That separation is what lets a designer answer: where is the machine, why was it allowed to move there, who owns the outputs, and how does it recover when the logical state no longer matches the physical one.
1. StepNo is not wrong — StepNo without a contract is
An integer is a perfectly valid implementation if:
- every value has a name and a meaning;
- transitions are controlled;
- an invalid value has defined behaviour;
- output ownership is clear;
- the state is observable and logged;
- requirements and tests can be traced to it.
Conversely, an elegant state-machine framework can still be wrong if the guards are vague, transitions are hidden across several tasks, or outputs get overwritten.
The goal is not to replace every CASE StepNo with a complex library. The goal is behaviour that can be understood, verified and maintained.
2. Separate mode, state and step
Three ideas that often get mixed together.
Mode
The mode determines how the machine or unit is controlled and which set of behaviours is permitted: production or automatic, manual, maintenance, setup, or a mode defined by the application.
A mode is not just a label on the HMI. It affects:
- who may command what;
- which transitions are permitted;
- speed and energy behaviour;
- which sequence is active;
- diagnostics;
- recovery;
- safety-related functions, where the architecture involves them.
State
A state describes a behavioural condition stable enough to decide how to react to an event. For example Idle, Starting, Execute, Holding, Held, Stopping, Stopped, Aborting, Aborted, Completing, Complete — if the application model chooses to use those.
Step
A step is usually one detailed move inside a procedure: clamp, lift, transfer, place. Many steps can live inside the Execute state. A step is not necessarily a high-level machine state.
If every mechanical step, every mode and every fault is pushed into one enum, the model turns into a maze.
ISA-TR88.00.02-2022 and OMAC PackML give reference patterns for machine and unit states and modes. They are useful for standardising vocabulary, but they do not oblige every machine to adopt the whole model or the same list of states.
3. A state has to answer six questions
Each state should carry a definition:
- Purpose: what does this state exist to do?
- Entry condition: how does the system know it has entered?
- Invariant: what must always be true while in it?
- Permitted events and commands: which inputs mean anything here?
- Outputs and actions: which outputs or activities does the state own?
- Exit and transition: what condition allows leaving?
A hypothetical example:
Held: the process has stopped under control at a defined checkpoint; product identity and ownership are retained; no motion command from the production sequence may be issued; resume is accepted only when the hold cause is cleared, the required conditions are valid, and the operator or system authorisation is appropriate.
That definition is worth more than State = 40 // held.
4. The invariant matters more than the state name
Naming a state Idle does not prove the machine is idle.
Invariants can include:
- no automatic motion command is active;
- no transaction is left without an owner;
- gripper and product state are determined;
- the recipe is loaded but not executing;
- a shared zone is not reserved by two units at once;
- actuator command and feedback do not disagree for longer than the permitted duration.
Invariants help you:
- detect state corruption;
- write meaningful alarms and diagnostics;
- define recovery;
- build negative tests;
- review concurrency;
- decide whether a state may be retained.
Alongside invariants, define the forbidden states:
- clamp open while an axis moves through a zone that requires holding;
- product present but ownership = none;
- Automatic mode and a Maintenance command both active;
- Complete while the quality result is missing;
- Execute while the interface version is incompatible.
The happy path only proves the machine can run. A forbidden-state review is what proves it cannot fall into a combination nobody intended.
5. A transition is a contract
A transition is not just:
IF SensorA THEN StepNo := 20;
It needs:
Source and target
From which state to which state? Is there a global transition?
Trigger
Which event, command or time condition starts it?
Guard
Which conditions must be true at the moment of transition?
Action
What is performed on the way through? Update ownership, capture data, clear a timer, issue a command?
Priority
If several transitions are true at once, which one wins, and why?
Invalid-event behaviour
If an event arrives in a state where it does not belong: ignore, reject, log, alarm or escalate?
For example:
From Ready to Executing on StartRequest, guarded by a valid recipe, an accepted interface, no active blocking fault and a reserved resource; the action creates the transaction context and captures the baseline; a repeated request with the same ID returns the current state instead of creating a second execution.
This transition contract connects directly to the interface control discussed in article #51.
6. Hidden priority is a hard fault to see
In a PLC scan, the order of code can become an unpublished priority:
IF Start THEN State := Execute;
IF Stop THEN State := Stopping;
IF Fault THEN State := Aborting;
If Start, Stop and Fault are all true, the final value depends on the order. A reader may assume Fault has the highest priority — while another routine rewrites the state afterwards.
So:
- define the priority in the model;
- commit transitions in exactly one place;
- log the events that were superseded;
- test simultaneous events;
- avoid several tasks or routines writing the state.
Priority follows the machine context; there is no universal table. A safety reaction should not depend on operational-state priority when it belongs to a safety-related control path.
7. Entry, do and exit actions must be distinct
An action may:
- run once on entry;
- run cyclically inside the state;
- run once on exit;
- belong to one specific transition.
Without that separation, an "initialise" command can end up being sent every scan, or an output can be cleared too early.
Entry action
- reset timers;
- capture the transaction;
- initialise local variables;
- issue a command edge if the contract requires one.
Do activity
- maintain outputs;
- monitor guards and invariants;
- update progress;
- check the timeout.
Exit action
- release resources;
- archive the result;
- clear commands owned by the state.
Output ownership should be explicit:
| Output | Owning state or component | Default | Override path |
|---|
| Transfer command | Transfer sequence | OFF | Abort handler |
| Clamp command | Fixture controller | Defined by the local state | Safe reaction route |
| HMI state | State manager | Current state | None |
Several routines writing the same coil is the clearest sign that ownership has broken down.
8. Hierarchy keeps the state count from exploding
If every combination becomes a flat state:
- AutoExecuting;
- AutoHolding;
- ManualIdle;
- ManualFaulted;
- MaintenanceFaulted;
- SetupWaiting…
the number grows quickly.
A hierarchical state machine lets a child state inherit behaviour:
Operational- Idle
- Starting
- Execute
- Holding
Stopped- StoppedNormal
- Aborted
Faulted- Recoverable
- RequiresIntervention
But hierarchy needs its own semantics:
- is the event handled in the child or in the parent?
- what is the entry and exit order?
- does the parent invariant always apply?
- is a history state used?
- which child state does resume return to?
Do not use hierarchy only to make the diagram look better. It has to make ownership and transitions clearer.
9. Concurrency: two parallel sequences need coordination
A machine may at the same time:
- process a product;
- prepare the next material;
- communicate with the upstream station;
- log data;
- monitor a utility.
Orthogonal or concurrent regions are useful, but they create races:
- two regions request the same actuator;
- region A completes first while region B faults;
- a stop command arrives while one region is mid-transition;
- one region restarts while the other retains its state;
- the aggregation of results is undefined.
The design has to settle:
- resource ownership;
- synchronisation points;
- join and merge semantics;
- fault propagation;
- how the overall state is calculated;
- a cancellation token or transaction context;
- timeouts per region and overall.
Where concurrency is not needed, a sequential design is easier to verify. Do not create a parallel branch just because the PLC can run one.
10. A mode change is a conditional transition
Avoid this:
Mode := HMI_ModeSelection;
A mode request is not the same thing as the active mode.
A mode-change lifecycle:
- request;
- authorisation;
- compatibility with the current state;
- a controlled stop or transition if needed;
- cleanup of resources and commands;
- entry conditions for the new mode;
- an acknowledgement that it is active.
The questions to answer:
- what happens on Auto → Manual while an axis is moving?
- does Maintenance mode require a key, a role or a procedure?
- what if a remote and a local request arrive together?
- is the mode retained across a power cycle, or does it default?
- is the interface peer informed?
- what happens to a product that is part-way through?
Mode management can involve safety functions. Where it does, the applicable safety architecture and validation decide — not an enum in the standard PLC program.
11. Fault, stop, hold, abort and complete are not the same
Stop
Bring the activity to a stopped state through the normal process.
Hold
Pause with the ability to resume from a designed checkpoint.
Abort
An abnormal exit; the ability to resume may be lost and recovery is required.
Fault
A condition that prevents a function or violates an expectation, with a diagnostic and a reaction.
Complete
The procedure reached its intended outcome and the result and context are ready to close.
If all of them lead back to StepNo = 0, the machine loses:
- product ownership;
- the checkpoint;
- the cause;
- the actions already performed;
- the ability to resume;
- the evidence.
Reset should not mean "erase all state". Which conditions a reset acknowledges or clears, what its prerequisites are, and which target state it leads to all have to be defined.
12. Startup and restart: reconcile logical state with physical state
After a power loss:
- state variables may be retained;
- a pneumatic actuator may have changed position;
- a servo may have lost its absolute context;
- a workpiece may still sit in the gripper;
- the peer PLC may have restarted at a different moment;
- a transaction may be incomplete.
Three dangerous patterns:
- always return to Idle;
- always resume the retained step;
- auto-home every mechanism.
None of them is universally right.
Startup should:
- determine the boot reason;
- check configuration and versions;
- gather physical feedback;
- determine product, resource and interface state;
- compare that against the retained logical context;
- classify the result as consistent, recoverable ambiguity, or unknown;
- choose the designed initialisation or recovery path;
- require appropriate authorisation before motion or resume.
Unexpected-start risk follows the risk assessment and the applicable machinery-safety requirements. This article does not supply generic auto-resume logic.
13. State observability is a requirement
If the state exists only in an internal variable that is never logged, troubleshooting becomes guesswork.
Expose, at an appropriate level:
- the active mode, state and substate;
- the last transition;
- its timestamp or cycle;
- the trigger, and which guard was not met;
- the active transaction or product;
- elapsed time and the remaining timeout margin;
- the fault or hold reason;
- the prerequisites for recovery;
- the state-model and interface version.
Do not show the operator hundreds of raw bits. The HMI needs answers to the task at hand:
- what is the machine doing?
- which condition is it waiting for?
- who owns the next action?
- what is preventing the transition?
- which recovery is permitted?
The event record should distinguish a command, a transition request, a transition accepted or rejected, and a state entered.
14. IEC 61131-3:2025 helps the implementation, not the architecture
IEC 61131-3:2025 Edition 4 defines the syntax and semantics of Structured Text, Ladder Diagram, Function Block Diagram and the Sequential Function Chart elements.
SFC can express steps, transitions and actions more clearly than integer code. ST and function blocks can implement a hierarchical state manager well. But the choice of language does not by itself resolve:
- missing requirements;
- transition ambiguity;
- output ownership;
- races and concurrency;
- unsafe recovery;
- incomplete testing.
A program that is "IEC 61131-3 compliant" says something about the language. It does not prove the machine behaves correctly or reaches any safety integrity.
15. How to use IEC 61512 / ISA-88 and PackML
IEC 61512-1:2026 addresses batch and related procedure-oriented manufacturing, with a separation between recipe procedural elements and equipment procedural elements. Some of those procedural and equipment separation principles, and the state references, are useful — as long as the scope is respected.
ISA-TR88.00.02-2022 provides implementation examples for automated machine states and modes. OMAC PackML promotes consistent behaviour and data.
They help by giving:
- a shared vocabulary;
- fewer custom state models;
- consistent HMI and data;
- easier integration.
But a standard model still has to be tailored to:
- the machine's function;
- its lifecycle and modes;
- the safety and control architecture;
- product flow;
- interfaces;
- recovery.
Do not add a state only to look compliant if it has no semantics and no test.
16. A worked example: pick, transfer, place
Behaviour hierarchy
- Stopped
- Idle
- Executing
- Acquire
- Transfer
- Place
- Verify
- Holding
- Held
- Completing
- Complete
- Aborting
- Aborted
Invariants
- A product has exactly one owner.
- Motion through the transfer zone happens only while the zone reservation is valid.
- The gripper releases only in Place, and only when position and receiver conditions are met.
- Complete is reached only after presence and quality results are confirmed.
An example transition
Transfer → Place
- Trigger: the target position is reached.
- Guard: the receiver accepted the transaction, the identity matches, the place zone is reserved.
- Action: transfer the ownership checkpoint; initialise the place timeout.
- Invalid case: if the receiver revokes before the checkpoint, transition to Holding or Aborting per the defined policy.
A fault case
Product feedback is lost during Transfer.
Do not jump back to Idle. The state manager should:
- keep the transaction context;
- stop and react as designed;
- record the last confirmed checkpoint;
- determine the physical ambiguity;
- move to Aborting or Recovery-required;
- allow only the appropriate recovery procedure.
A restart case
The retained state says Transfer, but the axis feedback is at a different position and product presence is unknown. Reconciliation concludes the situation is ambiguous; the machine does not auto-resume, and moves to controlled recovery.
17. Verification matrix
| Requirement | Model element | Implementation | Test |
|---|
| No release before the place condition | Invariant plus guard | Place transition | Negative boundary test |
| A stop request is handled from Execute | Global transition | State manager | Stop in every substate |
| A duplicate start creates no second cycle | Invalid-event rule | Command handler | Repeated command |
| No auto-resume on an ambiguous restart | Reconciliation | Startup manager | Power-cycle state matrix |
Testing should cover:
- every state and transition;
- guard boundaries, both true and false;
- simultaneous events and priority;
- invalid commands;
- timeouts;
- sensor disagreement;
- mode changes;
- hold, stop and abort;
- restart at each critical phase;
- interface loss and reconnection;
- retained and non-retained data;
- output ownership;
- forbidden-state monitoring.
One hundred per cent transition coverage is still not enough if guard combinations and physical boundaries were never tested.
18. Review checklist
- Are mode, state and step separated?
- Does each state have a purpose, entry, invariant, permitted events, outputs and exit?
- Are the forbidden states defined?
- Does each transition have source, target, trigger, guard, action and priority?
- Does an invalid event have defined behaviour?
- Are entry, do and exit actions distinct?
- Does every output have exactly one owner?
- Does the hierarchy define event, entry, exit and history semantics?
- Do concurrent regions have resource ownership and synchronisation?
- Does a mode request go through a lifecycle instead of writing the active mode directly?
- Are stop, hold, abort, fault and complete distinguished?
- Do reset and recovery have a target state and prerequisites?
- Does restart perform a physical reconciliation?
- Are state, transition and guard observable enough?
- Is a language or framework being used as a substitute for architecture or safety assessment?
- Can requirement, model, code and test be traced to each other?
Conclusion
A state machine is not just a way to organise code. It is a description of how the machine behaves: which states exist, which invariants must hold, which events are accepted, and what the system does when the logic no longer matches the physical world.
When mode, state, transition and output ownership each have a contract, the sequence becomes easier to review, to test and to recover. When everything lives in StepNo, the machine may run today — but the cost of understanding and changing it rises at every maintenance visit that follows.
Public references
- IEC 61131-3:2025 — Programmable-controller languages: https://webstore.iec.ch/en/publication/68533
- ISA-TR88.00.02-2022 — Machine and Unit States: https://www.isa.org/products/isa-tr88-00-02-2022-machine-and-unit-states-an-imp
- OMAC PackML: https://www.omac.org/packml
- IEC 61512-1:2026 — Batch-control models and terminology: https://webstore.iec.ch/en/publication/75287
- ISO/IEC/IEEE 15288:2023 — System life cycle processes: https://www.iso.org/standard/81702.html
View all MINATA technical articles