Step
- Namespace
- ZCore
- Implements
The Step function block is the main tool in the Zeugwerk Framework to implement sequences.
This function bocks uses a simple statemachine to make navigation within a step easy. This allows to check if a step was just entered ( OnEntry ) or if it was just exited ( OnExit ) by using the ( SetNext ) method. This reduces the number of steps that have to be used to implement a sequence by up to a factor of 2 and make the code much more pleasant to read.
The most common way to change from one step to another step is the SetNext method. However, there are some derivatives from this function that also have its use cases (Increment, RepeatStep ). Note, that this is not the implementation of a finite statemachine. Hence, there are no conditions for step changes. Any step may be changed to or from every other step. For a more advanced implementation of a sequence that uses transitions, see StateMachine.
A step usually gets initialized with an enumeration that describes every step of a sequence. Using an ENUM instead of merely numbers allows for easy string conversion, using the to_string attribute of Codesys and make debugging much easier. Since the range of potential steps is a prerequisite for any sequence, this range is directly parametrized when construction an instance of this functionblock
Here is an example on how to use the Step fb without an enumeration, simply initialize with a start and maximum step number in between this step should function
PROGRAM MAIN
VAR
Step : ZCore.Step(begin:=0, end:=100);
Count : UDINT;
END_VAR
----------------------
CASE Step.CurrentIndex() OF
0:
IF Step.OnEntry() THEN
Count := Count + 1;
END_IF
Step.SetNext(index:=10);
10:
;
END_CASE
This example shows how to use the Step fb with an enumeration and to_string attribute. First lets introduce an enumeration ExampleStep
{attribute 'qualified_only'}
{attribute 'to_string'}
TYPE ExampleStep :
(
Begin,
Wait,
End
);
END_TYPE
Now instantiate the Step and initialize it with this newly created enumeration.
PROGRAM MAIN
VAR
Step : Step(begin:=ExampleStep.Begin, end:=ExampleStep.End);
Timer : ZAux.Timer;
END_VAR
---------------------------
CASE Step.CurrentIndex() OF
ExampleStep.Begin:
; // Initialize some things
Step.SetNext(ExampleStep.Wait);
ExampleStep.Wait:
IF Step.OnEntry() THEN
Timer.WaitAsync(10.0);
END_IF
IF Timer.Done THEN
Step.SetNext(ExampleStep.End);
END_IF
ExampleStep.End:
; // Idling
END_CASE
Last but not least we can use this to_string feature with the Logger, see in the following example how: First lets introduce an enumeration ExampleStep
{attribute 'qualified_only'}
{attribute 'to_string'}
TYPE ExampleStep :
(
Begin,
Wait,
End
);
END_TYPE
PROGRAM MAIN
VAR
DateTime : ZAux.DateTimeUM;
Logger : ZAux.LoggerFile7FFUM(datetime:=DateTime, filePath:='C:\temp\logfile.log', target:='');
Step : Step(begin:=ExampleStep.Begin, end:=ExampleStep.End);
Timer : ZAux.Timer;
StringBuilder : ZAux.StringBuilder;
END_VAR
-------------------------
DateTime.Cyclic();
Logger.Cyclic();
CASE Step.CurrentIndex() OF
ExampleStep.Begin:
IF Step.OnEntry() THEN
Timer.WaitAsync(5.0);
END_IF
IF Logger.Operational
THEN
Step.SetNext(ExampleStep.Wait);
Logger.Trace(StringBuilder.Append('Changed Step from ').Append(TO_STRING(ExampleStep.Begin)).Append(' to ').Append(TO_STRING(ExampleStep.Wait)).ToString());
END_IF
ExampleStep.Wait:
IF Step.OnEntry() THEN
Logger.Debug(StringBuilder.Append('Logger needed ').AppendLreal(Timer.ElapsedSeconds, 3).Append(' seconds for initialization').ToString());
END_IF
IF Timer.Done THEN
Step.SetNext(ExampleStep.End);
Logger.Trace(StringBuilder.Append('Changed Step from ').Append(TO_STRING(ExampleStep.Wait)).Append(' to ').Append(TO_STRING(ExampleStep.End)).ToString());
END_IF
IF Step.OnExit() THEN
Logger.Debug('Exiting Wait Step!');
END_IF
ExampleStep.End: // Idling
;
END_CASE
Note
Although it is recommended to use enums, it is ok to use numbers directly for very simple sequences.
FUNCTION_BLOCK Step IMPLEMENTS ZCore.IStep (
MaxConsecutiveChanges : INT)
Inputs
MaxConsecutiveChanges
INTMaximum number of consecutive, actual step changes before IsNotRepeatable returns
TRUE
. The value defaults to 0, which means that there are unlimited step changes allowed.- Setting default value to a smaller value can be done globally by adjusting ParameterList.StepMaxConsecutiveChanges or locally, which is useful for hunting done programming errors where consecutive step changes lead to an infinite loop.
- For unittesting it is sometimes useful to set
MaxConsecutiveChanges := 1
to test indiviual steps.
Outputs
Index
INTindex of the step to access directly in readonly without any method, manipulation is only possible by using methods
Constructor
FB_init
When constructing this functionblock the minimum and maximum step index has to be passed to it by its constructor. Later, the methods Begin and End may be used to retrieve this values.
Constructing a step will set the CurrentIndex() to Begin and
initialize the statemachine that is used within a step to entry, such that
Index() = Begin()
and OnEntry() = True
.
METHOD FB_init (
bInitRetains : BOOL,
bInCopyCode : BOOL,
begin : INT,
end : INT) : BOOL
Inputs
bInitRetains
BOOLif TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCode
BOOLif TRUE, the instance afterwards gets moved into the copy code (online change)
begin
INTfirst step of the sequence usually given as enumeration value
end
INTlast step of the sequence usually given as enumeration value
Returns
- BOOL
Methods
Begin
This method returns the index of the first step in this Sequence. It is the same value as given when this object is being constructed via FB_init
METHOD PUBLIC Begin () : INT
Returns
- INT
CurrentIndex
Returns the current step in which the object is actually in
METHOD CurrentIndex () : INT
Returns
- INT
End
This method returns the index of the last step in this Sequence. It is the same value as given when this object is being constructed via FB_init
METHOD PUBLIC End () : INT
Returns
- INT
Increment
This method increments the step index by 1. It is the same as calling
_step.SetNext(_step.Index() + 1);
METHOD Increment ()
IsNotRepeatable
This method returns TRUE if a step is not repeatable. This means that the code within the current step has been executed at least once,
such that the OnEntry method could have been entered (if the step implements a call to this method)
This method is usually used in the REPEAT (...) UNTIL
section of a sequence.
The input variable MaxConsecutiveChanges
can change this behavior by bypassing this check.
REPEAT
(...)
UNTIL _step.IsNotRepeatable() END_REPEAT
METHOD PUBLIC IsNotRepeatable () : BOOL
Returns
- BOOL
OnEntry
this method return TRUE if a step is accessed for the first time calling this method will advance the internal statemachine. Hence, if this method is called once, the next time the method is called it is guaranteed to return FALSE.
METHOD PUBLIC OnEntry () : BOOL
Returns
- BOOL
OnExit
this method returns TRUE whenever a step change occured. Thus, any call to SetNext makes this method return TRUE if called AFTER it. This applies also for the derivatives of SetNext() such as RepeatStep() and Increment().
METHOD OnExit () : BOOL
Returns
- BOOL
Previous
This method returns the previous step index. At initialization of this function block previous is equal to 0.
METHOD PUBLIC Previous () : INT
Returns
- INT
RepeatStep
Calling this method sets the next step to be taken to the same that we are already in. Use this method if it is required to get into the OnEntry section of a step. Internally, this method calls
_step.SetNext(_step.Index());
METHOD RepeatStep ()
Restart
This method changes the step index to Begin and OnExit of the actual step will trigger and OnEntry of the Begin step will also trigger.
This method can be used during execution of the sequence to jump right at the beginning and be sure to trigger OnExit and OnEntry correctly.
METHOD PUBLIC Restart ()
SetNext
Set the next provided step. Also, it changes the state of this step object
to the changed status such that IsNotRepeatable will return FALSE the
next time that it is called. Hence, if used properly (see Step the next step will be called
in the same cycle.
If index
is out of bounds (Begin and End) the internal state
switches to error.
METHOD PUBLIC SetNext (
index : INT)