State Machines¶
Use a state machine when the logic has phases, modes, or ordered steps. It is usually easier to review than a web of markers.
The diagram below shows the same small motor sequence as the SCL example. The state number in the
diagram matches the value of _inState in the code.
PlantUML source: simple-motor-state-machine.puml
VAR
_inState : Int;
END_VAR
BEGIN
CASE _inState OF
0: // Idle
xboMotorRunCommand := FALSE;
IF xboStartRequest AND xboMotorReady THEN
_inState := 10;
END_IF;
10: // Starting
xboMotorRunCommand := TRUE;
IF xboMotorRunning THEN
_inState := 20;
ELSIF xboStartTimeout THEN
_inState := 90;
END_IF;
20: // Running
xboMotorRunCommand := TRUE;
IF xboStopRequest OR NOT xboMotorReady THEN
_inState := 0;
END_IF;
90: // Fault
xboMotorRunCommand := FALSE;
IF xboResetFault THEN
_inState := 0;
END_IF;
ELSE
_inState := 0;
END_CASE;
END_FUNCTION_BLOCK
Good state machines have:
- One variable that represents the active state.
- Clear transition conditions.
- Safe output assignments in each relevant state.
- A fallback for unknown states.
- State names documented in comments, constants, or an enum-like UDT where useful.
Reading The Example¶
The initial state is Idle (0). In this state the motor command is off. When a start request is
present and the motor is ready, the state changes to Starting (10).
Starting keeps the motor command on while the motor is expected to begin running. If running
feedback arrives, the state changes to Running (20). If the start timeout becomes true first,
the state changes to Fault (90).
Running keeps the motor command on until the operator requests stop or the motor is no longer
ready. Both conditions lead back to Idle.
Fault switches the command off and waits for an explicit reset before returning to Idle.
The ELSE branch in the SCL CASE is the fallback path. If _inState ever contains an unexpected
number, the block returns to Idle instead of staying in an undefined mode.