Skip to content

Latest commit

 

History

History
184 lines (131 loc) · 5.15 KB

TrafficLight.md

File metadata and controls

184 lines (131 loc) · 5.15 KB

Traffic light

This simple Trafficlight example is solved with a state pattern of the @simatic-ax/statemachine library. This traffic light shows the the phases of a german traffic light (red --> red-yellow --> green --> yellow --> red and so on). Each phase will be active for one second.

stateDiagram-v2
    [*] --> red
    red --> redyellow : T#1s
    redyellow --> green : T#1s
    green --> yellow : T#1s
    yellow --> red : T#1s
    state : "red-yellow" AS redyellow
Loading

How a state will be created

Each state is realized as a own class which is extended from State1Transition

Example:

CLASS StateRed EXTENDS AbstractTrafficLightState
    VAR
        count : LINT;
        activations : LINT;
    END_VAR
    VAR PUBLIC 
        rd : REF_TO BOOL;
    END_VAR
    METHOD PUBLIC OVERRIDE OnEntry
        activations := activations + 1;
        rd^ := TRUE;
    END_METHOD
    METHOD PUBLIC OVERRIDE Action
        count := count + 1;
    END_METHOD
    METHOD PUBLIC OVERRIDE OnExit
        rd^ := FALSE;
    END_METHOD
        METHOD PUBLIC OVERRIDE GetColor : Colors
            GetColor := Colors#Red;
        END_METHOD
END_CLASS

In this example, the methods OnEntry, OnExit and OnAction of the class StateRed will be overridden with our own code. For example, When the state will be activated, the OnEntry method will be execute once. That means, the this example, the variable activation will be incremented by 1 and the variable rd which is a reference to a boolean variable will be set to true.

For the traffic light application, there are four states necessary:

  • StateGreen
  • StateRed
  • StateRedYellow
  • StateYellow

For each state are unit tests available. You'll find them in the test-folder:

tests

These tests can be executed direct in the IDE:

execute tests

Transition of the states

This happens in the TrafficlightWrapper. This wrapper has internally the instances of all states. Additionally, the each state needs a Transition of type ITransition - in this example jsut of the Type Transition which has implemented the interface ITransition.

The Transition is responsible, to switch from the one state to the next state. That means, the transition need to know, the NextState of type IState and the condition of type IGuard, when the transition is fulfilled. In this case, the Check() method of a Guard returns true.

In our example we use a TimeoutGuard wich returns true after a configured time is elapsed.

In Our example, you'll find the instances of the states, transitions and the TimeoutGuard.

VAR
    _stateRed : StateRed;
    _stateRedTrans : Transition;
    _TimeoutGuard : TimeoutGuard;
    _stateRedYellow : StateRedYellow;
    _stateRedYellowTrans : Transition;
    _stateGreen : StateGreen;
    _stateGreenTrans : Transition;
    _stateYellow : StateYellow;
    _stateYellowTrans : Transition;
    init : BOOL;
END_VAR

State controller

In order for the state machine to work in the end, we also need a StateController. This only needs the initial state.

VAR
    _sc : StateController;
END_VAR

Configure the statemachine

Since it is currently not possible, to use initializers for references and also not possible to use initial values in the TIAX use case, we need to define a init routine in our wrapper which is called once.

IF NOT init THEN
    // Congfigure StateController
    _sc.InitialState := _stateRed;
    _TimeoutGuard.Timeout := T#1000ms;
    // Configure Red
    _stateRed.Transition1 := _stateRedTrans;
    _stateRed.StateID := 1;
    _stateRedTrans.NextState := _stateRedYellow;
    _stateRedTrans.Guard := _TimeoutGuard;
    _stateRed.rd := REF(rd);
    // ...
    init := TRUE;
END_IF;

In ths init routine, we parametrize our state machine.

  1. Set the initial state to _stateRed

    Example:

    _sc.InitialState := _stateRed;
    
  2. Set the Timeout parameter for the TimeoutGuard to 1000ms;

    Example:

    _TimeoutGuard.Timeout := T#1000ms;
    
  3. Configure the Transitions for each state

    Example:

    _stateRedTrans.NextState := _stateRedYellow;
    _stateRedTrans.Guard := _TimeoutGuard;
    
  4. Configure all states:

    Example for state red:

    _stateRed.Transition1 := _stateRedTrans;
    _stateRed.StateID := 1;
    

Run the state controller

That the state machine runs, the cyclic method Execute() must be called in the Wrapper.

_sc.Execute();

Create Global Library for the TrafficLightWrapper

Now our traffic light is complete and can be imported in a TIA Portal global library --> How to crate a global library

Use TrafficLightWrapper in TIA Portal

  1. Open a TIA Portal project, which contains any 1500 PLC

  2. Open the TIAPortalGlobalLibrary

    open lib

  3. Select the function block

    select

  4. Instantiate the TrafficLightWrapper in e.g. the Main OB

    Instantiate

  5. Download the program to a PLC/PLCSIM Advanced and monitor the Main OB

    mon