I would like to have the behaviour of a public constant in C#. So:
In CODESYS V3, is it possible to externally access VAR_STAT CONSTANTS of an FB without instantiation in CODESYS V3? and If not, what would be the most proper way to do so?
The emphasis here is "on the FB", and with externally, I mean other places in the program. There are a couple of work-arounds given below, but maybe more cleaner solutions are at hand.
An application of this would be having a list of text resources that I would like to have available at other places in the code. e.g. a list of pneumatic cylinder states:
FUNCTION_BLOCK PUBLIC CylinderStates
VAR_STAT CONSTANT
Idle : STRING := 'Idle';
MoveToWork : STRING := 'Move to Work';
MoveToBase : STRING := 'Move to Base';
AtWork : STRING := 'At Base';
AtBase : STRING := 'At Base';
Error : STRING := 'Error';
END_VAR
So that in PRG_MAIN, I could do something like this (this does not work):
str := CylinderStates.MoveToWork;
This generates the error:
- Function block 'CylinderStates' must be instantiated to be accessed.
Other examples are constants like PI, that I would like to contain under a Math FB (similar to how it is done in C#)
I have a couple of workarounds for this
Work-around 1: Instantiating in GVL or VARs
It is possible to define an instance in a global variable list and then call it from there (this works):
str := GVL.CylinderStatesInst.MoveToWork;
Another option is to create an instance in the VAR list of the current FB/PRG/...
Work-around 2: TO_STRING attribute
Defining an enum and adding the attribute 'to_string':
{attribute 'to_string'}
TYPE CylinderState :
(
Idle,
MoveToWork,
MoveToBase ,
AtWork,
AtBase,
Error
);
END_TYPE
Allows me to do the following:
str := TO_STRING(CylinderState.AtBase);
The greatest downside of this is that I cannot use spaces or special characters.
Work-around 3: flatten into GVL
This is something I do not want to do, but also provides a solution:
VAR_GLOBAL
CylinderStates_Idle : STRING := 'Idle';
CylinderStates_MoveToWork : STRING := 'Move to Work';
CylinderStates_MoveToBase : STRING := 'Move to Base';
CylinderStates_AtWork : STRING := 'At Base';
CylinderStates_AtBase : STRING := 'At Base';
CylinderStates_Error : STRING := 'Error';
END_VAR
Work-around 4: Dedicated GVL:
Simply creating a dedicated GVL also does the trick, and seems like the best option, but the question is if it is possible to define the constants on the FB.
{attribute 'qualified_only'}
VAR_GLOBAL
Idle : STRING := 'Idle';
MoveToWork : STRING := 'Move to Work';
MoveToBase : STRING := 'Move to Base';
AtWork : STRING := 'At Base';
AtBase : STRING := 'At Base';
Error : STRING := 'Error';
END_VAR