Zum Inhalt

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.

Simple Motor State Machine

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.