Every programmer spends a considerable amount of time debugging their software. In the world of PLC programming it’s common to login to the PLC and monitor and write your variables. However, with the introduction of properties for your function blocks monitoring is not as plain as it used to be. In this post I’ll explain how to use monitoring attributes for your properties in TwinCAT.
The problem
Consider the following code: A common function block with an input variable ‘Execute’ and the output variables ‘Busy’ and ‘Done’.
FUNCTION_BLOCK NonPropertyFB VAR_INPUT Execute:BOOL; END_VAR VAR_OUTPUT Busy:BOOL; Done:BOOL; END_VAR
;
I added this function block to our main program and wrote a few lines of code as an example.
As the example programs shows when login to this program we can monitor and edit variable values in both the declaration editor and the program editor. So far, so good.
To refactor this to a more object oriented approach, you could replace the variables by properties. This is not the topic to discuss the benefits of this approach, but trust me 🙂 , there are plenty. So we create the backing fields ‘_Execute’, ‘Busy’ and ‘Done’ and add the properties.
FUNCTION_BLOCK PropertyFB VAR _Execute:BOOL; _Busy:BOOL; _Done:BOOL; END_VAR
PROPERTY Execute : BOOL
Execute:=_Execute;
_Execute:=Execute;
PROPERTY Busy : BOOL
Busy:=_Busy;
PROPERTY Done : BOOL
Done:=_Done;
Notice that for the Busy and Done property we have only have a getter because we only want read these properties. When we download and login to this program we get the following view:
We can edit the backing field variables in the declaration editor. However, it’s not possible to see the actual values of the properties! With a minimalistic program like this it’s not a big problem, but you can imagine the struggle if your programs get much bigger. Or if your properties are not simply properties with a one backing field any more.. well it gets quickly annoying.
The solution
Luckily, we have some options here. Codesys (and thus TwinCAT) has the option to use ‘Pragma attributes’ which affects the compilation and pre-compilation of your code. For this case Codesys gives us two monitoring attributes to decorate our properties:
- {attribute ‘monitoring’ := ‘variable’}Â If we add this monitoring attribute to a property the compiler adds an additional variable to the program. Each time your program set or gets the the property, is also assigns the value to the added variable. The online view then shows the added variable.
- {attribute ‘monitoring’ := ‘call’} If we add this monitoring attribute, the monitoring service will execute the getter or setter of your property directly.
Both monitoring attributes have their pros and cons. Setting the monitoring mode to ‘variable’ is always safe, your property is not called unintentionally. However, you cannot write or force your properties, and there is change that you are fooled by the state of outdated properties!
Now if you set you variable mode to ‘call’, you can also write your properties. Your online view is always up to date, because the monitoring service call your property getter periodically. This comes however with a down side, if your property contains more logic than only a backing field, you might see some unexpected behaviour.
An example
I added an additional property called ‘ThisPropertyIsNeverCalled’ to our function block which increases a counter every time it’s called and then returns that value. Placed the ‘monitoring call’ attribute to the properties: ‘Execute’, ‘Done’ and ‘ThisPropertyIsNeverCalled’ and placed the ‘monitoring variable’ attribute to our ‘Busy’ property.
FUNCTION_BLOCK PropertyFBWithPragmas VAR _Execute:BOOL; _Busy:BOOL; _Done:BOOL; _Counter:INT; END_VAR
{attribute 'monitoring':='call'} PROPERTY Execute : bool
Execute:=_Execute;
_Execute:=Execute;
{attribute 'monitoring':='variable'} PROPERTY Busy : BOOL
Busy:=_Busy;
{attribute 'monitoring':='call'} PROPERTY Done : bool
Done:=_Done;
{attribute 'monitoring':='call'} PROPERTY ThisPropertyIsNeverCalled : int
_Counter:=_Counter+1; ThisPropertyIsNeverCalled:= _Counter;
I added this function block to a main program and logged in, which gave some interesting results!
All our properties are visible now in the online view! I manually modified the property ‘Execute’. And I also manually set the values of the _Done and _Busy backing fields to true (they have no setter). But notice that the online view is showing us the wrong info for the ‘Busy’ property! This property is in fact TRUE, but because we have set its monitoring attribute to ‘variable’, and we never call the property, the online view shows its last known value.
This image also shows the drawback of the ‘Monitoring call’ attribute. Take a look at our property ‘ThisPropertyIsNeverCalled’, it is never called in our program, but it already has a value of 383 and it keeps increasing while i’m logged in. This shows perfectly that the online monitoring service does call your properties if you use the ‘monitoring call’ attribute. For more complex properties this might cause some unwanted behaviour.
Conclusion
We have seen that the online view the Codesys environment doesn’t show your property values by default. However, we have two monitoring attributes which we can use.
- {attribute ‘monitoring’:=’variable’} The compiler adds a variable for your property and when your program gets or sets the property the additional variable is also set. This attribute doesn’t affect your program flow in any way. But you cannot write to your properties and out dated data might fool you! This attribute is use full for properties which contains logic that changes by every call.
- {attribute ‘monitoring’:=’call’} The only monitoring service will call your property to get or set its data. This attribute is most suited for simple data properties who don’t have any logic which changes with every call.
For more information on this subject have a look the Codesys online help or the infosys from Beckhoff. If you have any questions or remarks feel free to contact me.