Most unstable PLC systems do not fail because the programmer ran out of ladder instructions.
They fail because the machine’s behaviour was never structured clearly.
A project may contain hundreds of networks, timers, latches and interlocks, yet nobody can confidently explain what state the machine is currently in, why it entered that state or what must happen next.
Under ideal conditions, the program may appear to work. Once commissioning begins, however, small timing variations expose the weakness of the design.
Remote inputs arrive late. An operator presses START during initialization. A valve reaches its position after a timeout expires. Communication returns while old permissives are still present. An online edit changes scan timing slightly.
The result is familiar:
- Intermittent startup failures
- Sequences that skip or repeat steps
- Unexpected restart behaviour
- Outputs remaining active during recovery
- Machines that work only after several reset attempts
- Faults that cannot be reproduced offline
The solution is rarely more scattered ladder logic.
The solution is a deterministic, state-based architecture.
What Deterministic PLC Logic Means
Deterministic logic produces a defined result from every relevant operating condition.
The machine should have a clear answer to questions such as:
- What happens immediately after power restoration?
- Which devices must initialize before startup?
- What happens when START is pressed too early?
- Which condition has priority when START and STOP occur together?
- What happens if a permissive disappears during a transition?
- Does a fault cancel the current sequence?
- Can the machine resume automatically after communication recovery?
- Which outputs are allowed during manual recovery?
- What state follows a successful reset?
The answers should not depend on:
- Rung order that nobody documented
- A retained latch left true
- Which network packet arrives first
- Multiple blocks writing to the same output
- An HMI value updating at the right moment
- A technician remembering to clear a temporary bit
Predictable systems define these behaviours explicitly.
Why Scattered Latches Become Dangerous
Latch bits are not inherently wrong. They become dangerous when they are used as an informal substitute for machine state.
A typical project may contain tags such as:
Cycle_Started
Motor_Enable
Valve_Sequence_Active
Step_Complete
Auto_Request
Restart_Allowed
Recovery_Mode
Fault_Reset_DoneEach bit may be set in one part of the program and reset somewhere else.
Individually, the logic looks simple. Together, the bits create dozens of possible combinations.
For example:
Cycle_Started = TRUE
Recovery_Mode = TRUE
Fault_Reset_Done = FALSE
Motor_Enable = TRUE
Auto_Request = FALSEIs that a valid operating condition?
Often, nobody knows.
A state machine replaces many loosely related Boolean memories with one authoritative machine state.
Machine_State = RECOVERY_REQUIREDThat single value explains the machine’s current operating phase far more clearly.
What Is a PLC State Machine?
A state machine divides machine operation into a limited number of defined states.
Each state describes:
- What the machine is currently doing
- Which outputs are permitted
- Which conditions are monitored
- Which transitions are allowed
- What fault response applies
- What state may come next
A basic industrial sequence might use:
POWER_UP
INITIALIZING
READY
STARTING
RUNNING
STOPPING
FAULTED
RECOVERY_REQUIREDThe machine occupies one main state at a time.
This prevents impossible combinations such as being simultaneously in normal production, startup and fault recovery.
States Must Represent Real Machine Behaviour
State names should describe meaningful physical or operational conditions.
Weak state names include:
Step_1
Step_2
Step_3
Bit_14
Sequence_AThese labels provide little diagnostic value.
Stronger names include:
WAITING_FOR_AIR_PRESSURE
OPENING_INLET_VALVE
STARTING_TRANSFER_PUMP
FILLING_TANK
CONTROLLED_SHUTDOWN
WAITING_FOR_OPERATOR_RESETWhen the HMI displays the current state, maintenance personnel can understand what the PLC expects the machine to be doing.
A state should represent a real phase of operation—not merely a convenient location in the code.
A Simple State-Machine Structure
A deterministic sequence typically contains four parts:
- Current state
- State actions
- Transition conditions
- Fault and priority handling
A simplified Structured Text example might look like this:
CASE Machine_State OF
POWER_UP:
Motor_Command := FALSE;
Valve_Command := FALSE;
IF Startup_Data_Valid THEN
Machine_State := INITIALIZING;
END_IF;
INITIALIZING:
Motor_Command := FALSE;
Valve_Command := FALSE;
IF Initialization_Complete THEN
Machine_State := READY;
ELSIF Initialization_Fault THEN
Machine_State := FAULTED;
END_IF;
READY:
Motor_Command := FALSE;
IF Stop_Request THEN
Machine_State := READY;
ELSIF Start_Request AND Start_Permissive THEN
Machine_State := STARTING;
END_IF;
STARTING:
Valve_Command := TRUE;
IF Fault_Active THEN
Machine_State := FAULTED;
ELSIF Valve_Open_Confirmed THEN
Machine_State := RUNNING;
ELSIF Start_Timeout THEN
Machine_State := FAULTED;
END_IF;
RUNNING:
Valve_Command := TRUE;
Motor_Command := TRUE;
IF Fault_Active THEN
Machine_State := FAULTED;
ELSIF Stop_Request THEN
Machine_State := STOPPING;
END_IF;
STOPPING:
Motor_Command := FALSE;
Valve_Command := FALSE;
IF Equipment_Stopped THEN
Machine_State := READY;
END_IF;
FAULTED:
Motor_Command := FALSE;
Valve_Command := FALSE;
IF Fault_Cleared AND Reset_Request THEN
Machine_State := RECOVERY_REQUIRED;
END_IF;
RECOVERY_REQUIRED:
Motor_Command := FALSE;
IF Recovery_Validated THEN
Machine_State := READY;
END_IF;
END_CASE;This is not the only correct structure, but the behaviour is visible.
Each state owns its actions and defines its permitted transitions.
Use One Authoritative State Variable
A strong sequence normally has one authoritative state variable for that machine function.
For example:
Machine_StateAvoid having separate competing variables such as:
Current_Step
Active_Mode
Recovery_Step
Startup_Phase
Shutdown_Phaseunless they represent genuinely separate state machines with clearly defined ownership.
Multiple state variables can be appropriate for large systems, but their relationship must be explicit. Otherwise, the program recreates the same ambiguity that state-based design was supposed to remove.
For example, a packaging line may contain:
- One line-level state machine
- One state machine for each machine module
- Separate device-control blocks for motors and valves
The hierarchy should be documented so lower-level equipment cannot independently enter a state that conflicts with the line-level command.
Define Transition Conditions Explicitly
A transition is the condition that moves the machine from one state to another.
For example:
READY → STARTINGmay require:
Fresh_Start_Request
AND Start_Permissives_Validated
AND Safety_Healthy
AND No_Active_FaultA transition should not occur merely because several unrelated bits happened to become true during one scan.
Good transition logic defines:
- Required conditions
- Priority
- Stability time
- Timeout
- Data validity
- Resulting state
A transition should also have a clear reason that can be recorded for diagnostics.
Avoid Hidden Transitions
A hidden transition occurs when the state changes as a side effect of unrelated logic.
For example:
IF Valve_Open THEN
Step_Number := Step_Number + 1;
END_IF;This appears convenient, but it may execute repeatedly while the valve remains open. The sequence can advance through several steps unexpectedly.
A stronger design checks both the current state and the required edge or validation:
IF Machine_State = OPENING_VALVE
AND Valve_Open_Confirmed
AND Valve_Feedback_Valid THEN
Machine_State := STARTING_PUMP;
END_IF;The program now states exactly which transition is allowed.
Allow One Main Transition Per Scan
A common state-machine problem occurs when multiple transitions execute during the same PLC cycle.
Suppose:
State 10 → State 20becomes true early in the scan.
Later in the same scan, the program immediately evaluates State 20 and transitions to State 30.
The machine skips the observable behaviour of State 20.
This can happen when sequence logic is written as several independent IF statements:
IF State = 10 AND Condition_A THEN
State := 20;
END_IF;
IF State = 20 AND Condition_B THEN
State := 30;
END_IF;If Condition_A and Condition_B are both true, both transitions may occur in one scan.
A CASE structure or next-state architecture can prevent accidental multi-step advancement.
For example:
Next_State := Machine_State;
CASE Machine_State OF
STATE_10:
IF Condition_A THEN
Next_State := STATE_20;
END_IF;
STATE_20:
IF Condition_B THEN
Next_State := STATE_30;
END_IF;
END_CASE;
Machine_State := Next_State;The sequence evaluates the current state once and applies one resulting state at the end of the scan.
State Entry and Exit Actions
Some actions should occur only once when a state begins.
Examples include:
- Resetting a timer
- Recording a timestamp
- Clearing an acknowledgement
- Capturing process values
- Incrementing a production counter
- Logging the transition reason
If these actions run on every scan, they may repeatedly reset timers or overwrite diagnostics.
An entry pulse can be created by comparing current and previous states:
State_Changed :=
Machine_State <> Previous_State;
State_Entry :=
State_Changed;
Previous_State := Machine_State;Or:
IF Machine_State <> Previous_State THEN
State_Entry := TRUE;
Previous_State := Machine_State;
ELSE
State_Entry := FALSE;
END_IF;Then:
IF Machine_State = STARTING
AND State_Entry THEN
Start_Timer_Reset := TRUE;
Start_Time := Current_Time;
END_IF;The same principle applies to exit actions.
Startup Must Be Its Own Controlled Sequence
Power restoration should not place the machine directly into its previous production state.
A deterministic startup may move through:
POWER_UP
↓
WAITING_FOR_PLC_IO
↓
WAITING_FOR_COMMUNICATION
↓
VALIDATING_PROCESS_DATA
↓
CHECKING_FIELD_POSITIONS
↓
READY_FOR_RESET
↓
READYEach state answers a different question.
Waiting for PLC I/O
Are the required local and remote modules available?
Waiting for communication
Are drives, remote controllers and intelligent devices connected?
Validating process data
Are current values fresh, plausible and inside their valid ranges?
Checking field positions
Do valve, cylinder and contactor feedback signals match the expected safe condition?
Ready for reset
Has the system recovered enough to accept deliberate operator acknowledgement?
The PLC should not treat “CPU in RUN” as “machine ready.”
Shutdown Must Also Be Structured
Weak programs often focus on startup and treat shutdown as simply removing all outputs.
That can be unsuitable for real processes.
A controlled shutdown may require:
- Stop material feeding.
- Allow the downstream conveyor to clear.
- Reduce speed.
- Stop the motor.
- Close valves.
- Confirm zero motion.
- Release auxiliary systems.
A state-based shutdown could use:
STOP_REQUESTED
STOPPING_FEED
CLEARING_PROCESS
STOPPING_DRIVES
CLOSING_VALVES
VERIFYING_STOPPED
READYThe exact sequence depends on the machine.
Emergency or safety-related stopping functions remain the responsibility of the appropriate safety-rated control architecture. A standard PLC shutdown sequence must not replace required safety functions.
Fault States Should Be Deliberate
A generic FAULTED state can be useful, but complex equipment may require several fault categories.
Examples include:
PROCESS_FAULT
DEVICE_FAULT
COMMUNICATION_FAULT
SAFETY_STOPPED
RECOVERY_REQUIRED
MANUAL_INTERVENTION_REQUIREDThe state should determine:
- Which outputs are removed immediately
- Which outputs may complete a controlled stop
- Whether automatic restart is blocked
- Whether manual recovery is allowed
- What reset conditions are required
- What diagnostic information is retained
A fault should not simply reset every state bit and hope the machine returns to normal.
Recovery Is Not the Same as Reset
Resetting an alarm does not prove that the machine is ready to operate.
After a fault, the physical machine may have changed:
- A cylinder drifted
- A valve returned to its fail position
- Product remains inside the machine
- Pressure decayed
- A drive lost its position reference
- Communication returned with stale data
- An operator moved equipment manually
A recovery state should verify the real machine condition.
A controlled recovery may require:
Communication healthy
AND process data valid
AND actuators in known positions
AND no active fault
AND operator reset acceptedOnly then should the state return to READY.
In many machines, a fresh START command should still be required after recovery.
Outputs Should Be Derived From State
Physical outputs should not be scattered throughout the sequence.
A strong architecture calculates requests from the active state and then assigns each physical output once.
For example:
Motor_Run_Request :=
Machine_State = RUNNING;
Valve_Open_Request :=
Machine_State = STARTING
OR Machine_State = RUNNING;The final device command is then owned by the device-control block:
Motor_Command :=
Motor_Run_Request
AND Motor_Run_Permissive
AND NOT Motor_Fault
AND NOT Stop_Required;Finally:
Physical_Motor_Output := Motor_Command;This separates:
- Sequence intent
- Device permission
- Final output command
- Physical feedback
The sequence requests operation. The device block decides whether that request can be executed safely and reports the result.
State Machines Do Not Eliminate Interlocks
A state machine organizes behaviour. It does not replace permissives, interlocks or device diagnostics.
Each state may still require:
- Safety healthy
- Communication valid
- Pressure available
- Valve position confirmed
- Drive ready
- Motor feedback
- Process value inside limits
The advantage is that the program clearly defines when each condition matters.
For example:
Drive_Readymay be required before enteringSTARTING.Drive_Healthymay be required throughoutRUNNING.Zero_Speed_Confirmedmay be required before leavingSTOPPING.Communication_Validatedmay be required before leavingPOWER_UP.
This is more precise than placing every condition into one enormous System_OK bit.
Transition Timeouts Are Essential
Every transition that depends on field movement should have a defined timeout.
For example:
OPENING_VALVEexpects:
Valve_Open_ConfirmedIf feedback does not arrive within the permitted time, the sequence should enter a defined fault state.
IF Valve_Open_Confirmed THEN
Machine_State := STARTING_PUMP;
ELSIF Valve_Open_Timeout THEN
Fault_Code := VALVE_FAILED_TO_OPEN;
Machine_State := FAULTED;
END_IF;Without a timeout, the machine may wait forever.
The HMI may show only that the sequence is “running,” while it is actually stuck.
Validate Feedback Quality
A transition should not rely only on the Boolean feedback value.
For remote or analog-derived conditions, also verify:
- Communication health
- Data validity
- Signal age
- Module diagnostics
- Plausibility
For example:
Valve_Open_Valid :=
Remote_IO_Healthy
AND Valve_Feedback_Data_Valid
AND Valve_Open_Input;A stale true value should not advance the sequence.
Transition Priority Must Be Clear
Several events may occur during the same scan:
- Fault becomes active
- Stop is requested
- Normal transition becomes true
- Timeout expires
The program must define which event wins.
A typical priority might be:
- Safety or critical stop
- Active fault
- Operator stop
- Timeout
- Normal transition
For example:
IF Critical_Stop THEN
Next_State := SAFE_STOPPED;
ELSIF Fault_Active THEN
Next_State := FAULTED;
ELSIF Stop_Request THEN
Next_State := STOPPING;
ELSIF Transition_Condition THEN
Next_State := NEXT_PROCESS_STATE;
END_IF;The required order depends on the process, but it must be deliberate.
Use Enumerated State Names Where Available
Many PLC platforms support enumerations or named constants.
Instead of:
Machine_State := 40;use:
Machine_State := RUNNING;Named states reduce mistakes and improve online diagnostics.
Where enumerations are not available, use documented constants:
STATE_POWER_UP := 0
STATE_READY := 10
STATE_STARTING := 20
STATE_RUNNING := 30
STATE_STOPPING := 40
STATE_FAULTED := 900Leaving gaps between numerical states makes later additions easier.
Record Transition Reasons
Knowing the current state is useful.
Knowing why the state changed is even better.
Record:
Previous_State
Current_State
Transition_Reason
Transition_Time
Fault_Code
Operator_Request
Relevant_Process_ValuesA transition log might show:
14:22:10.105 — READY → STARTING
Reason: Operator start accepted
14:22:10.820 — STARTING → FAULTED
Reason: Valve V12 failed to confirm open
14:22:14.330 — FAULTED → RECOVERY_REQUIRED
Reason: Fault cleared and reset acceptedThis removes much of the guesswork from intermittent commissioning faults.
Online Edits and State Integrity
Online edits are sometimes necessary during commissioning, but state-based programs still require caution.
An edit may:
- Change transition conditions
- Add a new state
- Alter timer behaviour
- Modify data types
- Reset non-retentive variables
- Leave the current state incompatible with the new code
Before applying a sequence edit, engineers should know:
- What state the machine currently occupies
- Which outputs that state commands
- Whether the new logic recognizes the existing state value
- What happens if the PLC restarts
- Whether recovery should be forced through a controlled state
Unknown or unsupported state values should move the machine into a safe diagnostic state:
ELSE
Fault_Code := INVALID_MACHINE_STATE;
Machine_State := FAULTED;The program should never continue operating from an undefined state number.
Hierarchical State Machines
Large systems should not place every detail into one enormous sequence.
A better structure may use several coordinated levels.
Line-level state
LINE_STOPPED
LINE_STARTING
LINE_RUNNING
LINE_STOPPING
LINE_FAULTEDMachine-module state
MODULE_IDLE
MODULE_PREPARING
MODULE_PROCESSING
MODULE_COMPLETE
MODULE_FAULTEDDevice state
MOTOR_STOPPED
MOTOR_STARTING
MOTOR_RUNNING
MOTOR_STOPPING
MOTOR_FAULTEDThe line requests behaviour from machine modules. Machine modules request behaviour from devices.
Each layer reports readiness, completion and fault status upward.
This prevents one massive state machine from becoming as difficult to understand as scattered latch logic.
State Machines in Ladder Logic
State machines do not require Structured Text.
They can be implemented in ladder using:
- State comparison contacts
- Transition networks
- State move instructions
- One-hot state bits
- Step-sequence instructions
- Function blocks
For example:
Current State = READY
AND Start Request
AND Start Permissive
---------------------------
MOVE STARTING to Next StateStructured Text may be convenient for large CASE structures, but ladder can remain clear when:
- Each state has a dedicated section
- Transitions are grouped
- State ownership is centralized
- Output assignments remain separate
- Comments describe physical behaviour
The programming language matters less than the architecture.
One-Hot State Bits Versus State Numbers
Some programs use one bit for each state:
State_Ready
State_Starting
State_Running
State_Stopping
State_FaultedThis can work, but the design must guarantee that only one state bit is active.
Otherwise, conflicting states may exist simultaneously.
A numeric or enumerated state variable naturally enforces one main state at a time.
One-hot states can still be useful for HMI display or diagnostics, but they are often best derived from the authoritative state value:
State_Ready := Machine_State = READY;
State_Running := Machine_State = RUNNING;Do not allow every state bit to be set and reset independently throughout the program.
Common State-Machine Mistakes
No default fault handling
An invalid state leaves outputs in their previous condition.
State changes from multiple blocks
Different routines compete to control the sequence.
Outputs written inside many states and elsewhere
Final ownership becomes unclear.
Transition conditions use stale data
A remote true bit advances the sequence after communication fails.
Several transitions execute in one scan
The machine skips states.
Timers are reset every scan
Timeouts never complete.
Retained state resumes after power loss
The physical machine no longer matches the stored sequence.
Reset jumps directly to RUNNING
The machine restarts without revalidation.
Maintenance mode bypasses the state machine
Operators create undocumented operating combinations.
A state machine is only deterministic when its rules are consistently enforced.
Testing a State-Based Sequence
Commissioning should test more than the normal cycle.
Test:
- Power restoration in every important state
- Communication loss during every transition
- Feedback arriving late
- Feedback arriving exactly as timeout expires
- Stop request during startup
- Fault during controlled shutdown
- Reset while fault remains active
- Manual movement during recovery
- Unexpected field-position combinations
- HMI reconnect with a request active
- Invalid state value
- Output feedback missing
- Rapid repeated start and stop commands
- Transition conditions changing in the same scan
For each test, verify:
- Current state
- Next state
- Transition reason
- Output requests
- Device commands
- Fault code
- Recovery requirement
The sequence should always move toward a defined condition.
Safety Functions Remain Separate
State machines improve ordinary control behaviour, but they do not replace safety-rated functions.
Emergency stopping, guard monitoring, safe motion and prevention of unexpected startup may require:
- Safety relays
- Fail-safe PLCs
- Safety-rated feedback
- Safe drive functions
- Independent energy isolation
The standard PLC state machine can coordinate with the safety system, but it must not imitate safety integrity through ordinary software alone.
The machine risk assessment determines the required architecture.
Final Thoughts
Most unstable PLC systems do not need more logic.
They need clearer behaviour.
Scattered latch bits, hidden transitions and duplicate output writes may work under ideal conditions, but they become unpredictable during real commissioning events.
A deterministic state machine defines:
- Where the machine is
- What it is allowed to do
- What condition moves it forward
- What stops it
- What happens during a fault
- How it recovers
- Who owns each output
The strongest industrial programs are not necessarily the most complicated.
They are the ones where engineers can look at the current state and immediately understand what the machine is doing, why it is doing it and what must happen next.
Predictability saves commissioning time.
More importantly, it prevents undefined machine behaviour from becoming a production or safety problem.
