IO Role mapping in Data Lists - structures
Hello,
I am fairly new to PhoenixContacts PLCs and so I am still getting used to them. I worked a lot with B&R PLCs before. There I used structures a lot so I have planned to use similar concept in PLCnext Eng.
But it looks that it's not possible to link variables of the structure to the "IO datums" in Data Lists. Since IO datums only accept basic data types (for example Digital input only accepts BOOL, but can't "see" BOOL that is stored inside a structure for example struct myDigIns.DigIn1.
Am i missing something or is this really not possible? I am using ST programming language.


I would really appreciate you help.
Best regards.
I am fairly new to PhoenixContacts PLCs and so I am still getting used to them. I worked a lot with B&R PLCs before. There I used structures a lot so I have planned to use similar concept in PLCnext Eng.
But it looks that it's not possible to link variables of the structure to the "IO datums" in Data Lists. Since IO datums only accept basic data types (for example Digital input only accepts BOOL, but can't "see" BOOL that is stored inside a structure for example struct myDigIns.DigIn1.
Am i missing something or is this really not possible? I am using ST programming language.


I would really appreciate you help.
Best regards.
Comments
Please try creating a variable, e.g. in a Program, with the Type of one of your STRUCT data types. If that struct variable has the Usage "IN port", and if the program containing that variable is instantiated in a Task, then you should be able to connect an OUT port of type BOOL (like a digital input channel) to a BOOL field in the struct variable in the program instance.
You can make those Port variable connections in the "GDS Port List" tab of the "PLCnext" branch of the project tree.
thank you for your answer. Sorry I didn't write clear enough in the first post. Of course I created global variable Din of structure type DinStruct.
But this global variable isn't seen in the IO datums mapping.
Then I tried your suggestion by using "IN port" and "OUT port" and this does work, but then this structure is limited only to the program in which it's defined. It's not a global variable. I would like to have global IO structure with all DI DO AI AO variables inside and then link/map this variables (which are inside structure) to corresponding physical modules.
In this way program can be read easier since you can have production line seperated in "sections" by structure, for example: We have 3 conveyors. Conveyor1, Conveyor2, Conveyor3. In this case I would create 1 structure Conveyor with
1DO BOOL - Start
1DO BOOL - Stop
1DI BOOL - Running
1DI BOOL - InFault
Then I would simply create array [0..2] of structure Conveyor. Then I would link/map each array element and structure sub-element to corresponding physical element. For example:
Physical DO1 <- array[0].Start
Physical DO2 <- array[0].Stop
Physical DI1 <- array[0].Running
Physical DI2 <- array[0].InFault
Physical DO3 <- array[1].Start
Physical DO4 <- array[1].Stop
Physical DI3 <- array[1].Running
Physical DI4 <- array[1].InFault
and so on for remaining 1 conveyor.
If this is not possible then I have to create as many variables as there is inputs/outputs? For example above:
Conveyor1Start
Conveyor2Start
Conveyor3Start
Conveyor1Stop
Conveyor2Stop
Conveyor3Stop
And so on...
Or am I missing something?
Maybe I am to used of this concept and there is something simpler I could do but I just don't know it yet...
If you don't want to connect every bit of a DI or DO module, you can also use the the I/O item with the tilde ~ (e.g. Bitstring16 can connect to a WORD variable) . Then, only one variable has to be created for each I/O module, and the bits in that WORD variable can be mapped or used individually in your code. This is not the same as the Role Mapping feature you are asking about, but perhaps it will be useful.
The possibility of use structure variables is a great way for code clearance and reducing amount of global variables.
During my work over projects I find out that the best way for me is to use WORD, DWORD or LWORD variables attached to bitstring input\output parameter of a module, as Martin noted before. And use additional parsing function, it need to be used because order of inputs\outputs of bitstring variable does not directly assigned to bits in WORD variable. Actually it have inverted byte order.
Here is the part of parsing function block code for input module with 64 inputs:
Where _00_00...15_17 is function outputs, as if you attach your variables to data list page of the module, and DI_64_IN.X* is a partial access to a bits of a variable you actually attach to bitstring input of the module.
_00_00 := DI_64_IN.%X56;
_01_01 := DI_64_IN.%X57;
_02_02 := DI_64_IN.%X58;
_03_03 := DI_64_IN.%X59;
_04_04 := DI_64_IN.%X60;
_05_05 := DI_64_IN.%X61;
_06_06 := DI_64_IN.%X62;
_07_07 := DI_64_IN.%X63;
_08_10 := DI_64_IN.%X48;
_09_11 := DI_64_IN.%X49;
_10_12 := DI_64_IN.%X50;
_11_13 := DI_64_IN.%X51;
_12_14 := DI_64_IN.%X52;
_13_15 := DI_64_IN.%X53;
_14_16 := DI_64_IN.%X54;
_15_17 := DI_64_IN.%X55;
...
In this case you can connect members of your structured variables to the outputs of the function block
AXL_F_DI64_DECODE1(
DI_64_IN := PN_DD1_DI64, //Global variable attached to bitstring input of the module
_00_00 => TRN_IO.K1_1.xIN_ST_KM1, //Parsed boolean outputs
_01_01 => TRN_IO.N1.xIN_ST_KM,
_02_02 => TRN_IO.N1.xIN_ST_SAFETY_SWITCH,
_03_03 => TRN_IO.N1.xIN_ST_SB_WM,
_04_04 => TRN_IO.N1.xIN_SN_BELT_BOT_L,
_05_05 => TRN_IO.N1.xIN_SN_BELT_TOP_L,
_06_06 => TRN_IO.N1.xIN_SN_JAM,
_07_07 => TRN_IO.N1.xIN_SN_ROT,
_08_10 => TRN_IO.K1_1.xIN_ST_KM2,
_09_11 => TRN_IO.N2.xIN_ST_KM,
_10_12 => TRN_IO.N2.xIN_ST_SAFETY_SWITCH,
_11_13 => TRN_IO.N2.xIN_ST_SB_WM,
_12_14 => TRN_IO.N2.xIN_SN_BELT_BOT_L,
_13_15 => TRN_IO.N2.xIN_SN_BELT_TOP_L,
_14_16 => TRN_IO.N2.xIN_SN_JAM,
_15_17 => TRN_IO.N2.xIN_SN_ROT,
.....
I don't use SWAP because, have additional functionality for inverting and time shifting of input signals inside function block.