State machines in ST (Siemens SCL)

bara_hence

Member
Join Date
Aug 2007
Location
Ockelbo
Posts
225
Quote from another thread:

I wrote:
How do you do paralell tasking using State machines??

One way is to program a system of state machine and start another state machine with the other and use a interface between these state machines.. But I for one are really curios how you Peter does this??



Peter Nachtwey wrote:
Start a new thread
State Machines in SCL or ST
I don't like posting the same thing over and over and over and over again. No one will find this information if it doesn't have a title that people will search for and recognize.

I am getting grumpier and grumpier. Perhaps a fixed section of "The Best of Peter Posts" is needed.

Peter showed us all some great example code how to do a basic state machine with entry, always and exit actions we even talked about timeout actions..

The code:

Code:
CASE NewState OF
   0:                          // STATE 0
       IF OldState <> NewState
                               // DO OTHER ON ENTRY CODE HERE  
          OldState = NewState   
       END_IF
                               // DO CODE THAT GET EXECUTED EVERY SCAN HERE.  POSSIBLY CHANGE NewState TO THE NEXT STATE     
                              
       IF OldState <> NewState THEN
                               // DO CLEAN UP CODE FOR CURRENT STATE ON EXITING STATE 
 
       END_IF
   1:                          // STATE 1
       IF OldState <> NewState
                               // DO OTHER ON ENTRY CODE HERE  
          OldState = NewState   
       END_IF
                               // DO CODE THAT GET EXECUTED EVERY SCAN HERE.  POSSIBLY CHANGE NewState TO THE NEXT STATE     
                              
       IF OldState <> NewState THEN
                               // DO CLEAN UP CODE FOR CURRENT STATE ON EXITING STATE 
 
       END_IF
   2:                          // STATE 2
       IF OldState <> NewState
                               // DO OTHER ON ENTRY CODE HERE  
          OldState = NewState   
       END_IF
                               // DO CODE THAT GET EXECUTED EVERY SCAN HERE.  POSSIBLY CHANGE NewState TO THE NEXT STATE     
                              
       IF OldState <> NewState THEN
                               // DO CLEAN UP CODE FOR CURRENT STATE ON EXITING STATE 
 
       END_IF
   3:                          // STATE 3
       IF OldState <> NewState
                               // DO OTHER ON ENTRY CODE HERE  
          OldState = NewState   
       END_IF
                               // DO CODE THAT GET EXECUTED EVERY SCAN HERE.  POSSIBLY CHANGE NewState TO THE NEXT STATE     
                              
       IF OldState <> NewState THEN
                               // DO CLEAN UP CODE FOR CURRENT STATE ON EXITING STATE 
 
       END_IF
    // ADD STATES AS NECESSARY
END_CASE

Quote about timeout actions:

If the state must be executed in a certain amount of time a timer should be started in the ON_ENTRY section of the code. The timer should be checked in the part of the scan that is executed every scan the state is executed. There may a potential fourth IF ON_TIMEOUT THEN section. On a timeout an error code, error message number is written to variable that is read by an HMI and displays an error message. Now when there is a hangup because some limit switch didn't get hit and error message can be displayed that tells the operator why the machine stopped.

Therefore each state could have a
ON_ENTRY
DO_EVERY_SCAN
ON_TIMEOUT
ON_EXIT
 
How about these timeouts if we should do a framework that is usable on many platforms such as Mitsubishi (GX IEC Developer), Siemens (Step7) and all other that follows the IEC standard to some extent we should use the TON timers. TON timers have these inputs:
IN (Starts the timer)
PT (Preset time)
and outputs
Q (Timer done)
ET (Elapsed time)

To get the timer to reset we must have the timer to execute for one scan after the input goes to false so therefore we should keep the timers out of the State machine and execute them always the statemachine only starts the timers and checks their signals..

So if we extend the framework that Peter has laid out for us it could look something like this:

Code:
State1Timer(IN:= , PT:=T#30s) //Whe do not need a variable for the IN because we can set it directly but if we do not want hardcoded timeouts we do need a variable for the PT..

CASE NewState OF
   0:                          // STATE 0
       IF OldState <> NewState
       State1Timer.IN:=TRUE
                               // DO OTHER ON ENTRY CODE HERE  
          OldState = NewState   
       END_IF
                               // DO CODE THAT GET EXECUTED EVERY SCAN HERE.  POSSIBLY CHANGE NewState TO THE NEXT STATE

       IF State1Timer.Q=TRUE THEN
                                //DO TIME OUT CODE
       END_IF     
                              
       IF OldState <> NewState THEN
       State1.Timer.IN:=FALSE
                               // DO CLEAN UP CODE FOR CURRENT STATE ON EXITING STATE 
 
       END_IF

    // ADD STATES AS NECESSARY
END_CASE

Just showed one state what do you others think is this ok?? Any other idea??
 
Last edited:
Multi Tasking

The is simple, instead of running one CASE OF statement you use two or more.

Code:
CASE NewTask1State OF
    0:   // Task1Step0
    1:   // Task1Step1
    2:   // Task1Step2
END_CASE

CASE NewTask2State OF
    0:  // Task2Step0
    1:  // Task2Step1
    2:  // Task2Step2
    3:  // Task2Step3
END_CASE

CASE NewTask3State OF
    0: // Task3Step0
    1: // Task3Step1
    2: // Task3Step2
    3: // Task3Step3
END_CASE
Obviously none of the tasks can run in a hard loop or the other tasks will not run. The states should be relatively short so that all the tasks can running every few milliseconds but this style of programming should be MUCH faster than general PLC programming because the only code that is executed is the CASE statements and the current state for each task instead of scanning all the ladder.

When using this style of programming FOR and WHILE loops should be avoided unless they are guaranteed to be short. FOR and WHILE loops can be done one loop at a time using the state machine.

It is also possible to have subtasks. Normally these run in parallel inside a step. For instance:

Code:
CASE NewTask1State OF
    0:  // Task1Step0
    1:  // Task1 Step1 
         CASE SubTaskAState OF
         END_CASE;
         CASE SubTaskAState OF
         END_CASE;
         // USE ONE OF THE FOLLOWING IF STATEMENTS
         IF SubTaskADone OR SubTaskBDone THEN    // USE THIS IF THEN IF STEP 1 IS EXITED WHEN EITHER SUB TASKS COMPLETES
             NewTask1State:=NewTask1State+1;
         END_IF
          
         IF SubTaskADone AND SubTaskBDone THEN
             NewTask1State:=NewTask1State+1;         // USE THIS IF THEN IF STEP 1 IS EXITED WHEN BOTH SUB TASKS MUST COMPLETE                              
         END_IF
     
         IF NewTask1State <> OldTask1State THEN
              // DO ON_EXIT CODE
         END_IF
    2:  // Task1Step2 
END_CASE;

I have shown the code as one big program. In practice the tasks, steps and subtasks should be FBs. It would have been nicer if SCL/ST supported classes an methods. Once the general framework for the task, step, and subtasks are written the code falls into place quickly if you have a definition of what the machine is supposed to do.

I have done applications with as many as 128 tasks running in parallel this way without a real time operating system. Each task had about 10 steps. It wasn't a fast system compared to a motion controller but there was a lot to it but mostly it was the same thing copied over and over again with small variations.

This method of running multiple tasks does not provide the highest performance, an RTOS would be MUCH faster, but it is easy to put together big systems quickly and it is easy to debug if there are error codes that have the task and step number encoded. Usually a state doesn't have more than one error. Since this is a non-preemptive system features like mutual exclusion are not required.

One can also make a queue that logs the ON_ENTRY and ON_EXIT times.

When programming in STL use the JL instruction in place of the CASE OF statement. The JL instruction makes S7 state machines very efficient. Normally the sparkies don't need to or want to get into the STL code but the individual states should be FBs or FC that can be written in LAD if necessary.

I am a big believer in state machines.
 
Last edited:
Is graph Siemen's version of SFC?

If so then I agree. SFC is designed for state machine applications but you are talking about yet another tool and not the knowledge of how to organize a state machine without the aid of a real time operating system.

My first experience with something like this was on a HP1000 back in the early 80s. There were 4 tasks in the state machine with about 6 to 15 states. The program was written in assembly language. The techniques are sill the same as used almost 30 years ago.
 
Why not use Graph instead of SCL ?

Simon, S7 Graph is for sequencers... S7 HiGraph is for implementing state machines.

(Have you seen how lardy the code for sequencers and state machines is when generated by these packages vs a DIY version in STL?)

Kevin
 
KRK makes a good point

L D[AR2,P#0.0], what does the generated STL code look like?

KRK, SCL isn't that efficient either. Many compilers implement the CASE OF as a bunch of IF THEN statements anyway and don't have any optimization for the times when the cases are sequential so a jump table can be used as in the case of the JL instruction.

I know our compiler doesn't do that and I have found few that do. I would like it if our compiler writer would check to see if the CASE OF can be implemented as a jump table. This would require special code.
 
Have you seen how lardy the code for sequencers and state machines is when generated by these packages vs a DIY version in STL?

Kevin

Only for S7-Graph.

The DIY versions I have done (STL&LADDER) are indeed slimmer than that produced by Graph/SCL. However, if I wanted to implement a sequence with step timeouts, multiple active steps, manual overrides etc, then I wouldn't use SCL to create my own controller, I would use S7-Graph. (Caveat: Assuming this is not an academic exercise in SCL)
 
If you have a function wich jumps between different states instead of a straight sequence the Graph does get a bit cluttered.. Then I think one should use a state machine implementation instead.

And if you are doing an easy function such as a motor controller or something like that i think doing it in Graph is just overkill and by doing it in SCL it is portable to many more platforms and often easy..
 

Similar Topics

Sorry about this vague question but... How do I know, where can I find what standards a machine needs to be built to for a specific state, for...
Replies
10
Views
4,811
Hi, I am looking for basic ladder logic to create a PLC state machine or sequence. For starters I'd just like to alternate between different...
Replies
20
Views
7,643
Hello All. I've been reading increasingly about State Machines when browsing through these threads trying to expand my limited knowledge...
Replies
14
Views
7,205
K
In X years of programming I have not had one customer say that sequential function charts (or similar) PLC programming was acceptable. Everyone...
Replies
25
Views
34,147
We have a new machine that uses an armor block to transfer input signals for conveyor position that continuously alarms out on no position change...
Replies
0
Views
83
Back
Top Bottom