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_Done

Each 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 = FALSE

Is 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_REQUIRED

That 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_REQUIRED

The 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_A

These 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_RESET

When 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:

  1. Current state
  2. State actions
  3. Transition conditions
  4. 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_State

Avoid having separate competing variables such as:

Current_Step
Active_Mode
Recovery_Step
Startup_Phase
Shutdown_Phase

unless 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 → STARTING

may require:

Fresh_Start_Request
AND Start_Permissives_Validated
AND Safety_Healthy
AND No_Active_Fault

A 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 20

becomes 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
↓
READY

Each 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:

  1. Stop material feeding.
  2. Allow the downstream conveyor to clear.
  3. Reduce speed.
  4. Stop the motor.
  5. Close valves.
  6. Confirm zero motion.
  7. Release auxiliary systems.

A state-based shutdown could use:

STOP_REQUESTED
STOPPING_FEED
CLEARING_PROCESS
STOPPING_DRIVES
CLOSING_VALVES
VERIFYING_STOPPED
READY

The 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_REQUIRED

The 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 accepted

Only 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_Ready may be required before entering STARTING.
  • Drive_Healthy may be required throughout RUNNING.
  • Zero_Speed_Confirmed may be required before leaving STOPPING.
  • Communication_Validated may be required before leaving POWER_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_VALVE

expects:

Valve_Open_Confirmed

If 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:

  1. Safety or critical stop
  2. Active fault
  3. Operator stop
  4. Timeout
  5. 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 := 900

Leaving 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_Values

A 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 accepted

This 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_FAULTED

Machine-module state

MODULE_IDLE
MODULE_PREPARING
MODULE_PROCESSING
MODULE_COMPLETE
MODULE_FAULTED

Device state

MOTOR_STOPPED
MOTOR_STARTING
MOTOR_RUNNING
MOTOR_STOPPING
MOTOR_FAULTED

The 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 State

Structured 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_Faulted

This 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.

Leave a Reply

Your email address will not be published. Required fields are marked *