Runtime - Krystian-L-Lis/Stage GitHub Wiki

#Guide #Runtime

Overview

Do not repeat yourself, but PLC programming often requires us to do this:

VAR  
    fbMotorControl  : MotorControl;  
END_VAR  
fbMotorControl();  

This is fine when there are only a few function blocks. But what if there are many, each with unique names and types?

VAR  
    fbMotorControl1  : MotorControl;  
    fbMotorControl2  : MotorControl;  
    fbMotorControl3  : MotorControl;  
    fbMotorControl4  : MotorControl;  
    fbMotorControl5  : MotorControl;  
  
    fbTemperature1   : TemperatureSensor;  
    fbTemperature2   : TemperatureSensor;  
    fbTemperature3   : TemperatureSensor;  
    fbTemperature4   : TemperatureSensor;  
  
    fbPressure1      : PressureSensor;  
    fbPressure2      : PressureSensor;  
  
    fbConveyor1      : ConveyorControl;  
    fbConveyor2      : ConveyorControl;  
    fbConveyor3      : ConveyorControl;  
  
    fbLighting1      : LightingControl;  
    fbLighting2      : LightingControl;  
    fbLighting3      : LightingControl;  
    fbLighting4      : LightingControl;  
END_VAR  
  
fbMotorControl1();  
fbMotorControl2();  
fbMotorControl3();  
fbMotorControl4();  
fbMotorControl5();  
  
fbTemperature1();  
fbTemperature2();  
fbTemperature3();  
fbTemperature4();  
  
fbPressure1();  
fbPressure2();  
  
fbConveyor1();  
fbConveyor2();  
fbConveyor3();  
  
fbLighting1();  
fbLighting2();  
fbLighting3();  
fbLighting4();  

This is overwhelming. Of course, it is possible to iterate over them, but we would still need four separate update loops. Each loop requires its own management to ensure it doesn't go out of bounds. Wouldn't it be nice to somehow add them automagically to some kind of execution loop and eliminate the need for all the calls in the code?

The Runtime provides exactly this capability. Additionally, as with everything in Stage, it does not require inheritance.

On top of that, Runtime provides an initialization method that is executed during the first loop of the program, after every FB_Init method has been executed. This allows the creation of couplings between individual function blocks using the EC system. Although it uses more memory than the call-after-init attribute, there is a good reason to prefer it. The IDE will notify you if you make a typo, unlike the attribute. Similar to the cyclic execution functionality, it also does not require inheritance.


Core Elements

Use the Execute function block in tandem with I_Execute to notify the Runtime to add a given function block to the cyclic execution loop.

Example:

FUNCTION_BLOCK ExecutableFb IMPLEMENTS I_Execute  
VAR  
    _exe : Execute(THIS^);  
END_VAR  
METHOD Execute  
    // Logic  
END_METHOD  

Init and I_Init

Use the Init function block in tandem with I_Init to notify the Runtime to execute this function block during the first iteration of the program, before the execution cycle.

Example:

FUNCTION_BLOCK InitiableFb IMPLEMENTS I_Init  
VAR  
    _init : Init(THIS^);  
END_VAR  
METHOD Init  
    // Logic  
END_METHOD  

Now that we have both executable and initiable function blocks, we can execute them!

Example:

PROGRAM Main  
VAR  
    initFb1 : InitiableFb;  
    initFb2 : InitiableFb;  
    initFb3 : InitiableFbOtherType;  
    initFb4 : ARRAY[1..5] OF InitiableFb;  
    
    exeFb1 : ExecutableFb;  
    exeFb2 : ExecutableFb;  
    exeFb3 : ExecutableFbOtherType;  
    exeFb4 : ARRAY[1..5] OF ExecutableFb;  
END_VAR  
  
Runtime();  

That's all! There is no need to modify any parameters. Everything works without additional user input. And because the composition is used, the FB may implement multiple interfaces, so we can have a FB that is both initiable and executable.

Note: Both initialization and execution occur in the order of declaration.

Warning: The system does not check if a given function block is registered multiple times. You can use Phase and the nPhase argument to determine when methods are called.


< Previous | Home | Next >

⚠️ **GitHub.com Fallback** ⚠️