First time posting, been looking through the forum for a while though.
I know that you can have arrays of varying size (at compile) if you declare them with constants so i want to create a series of objects(FBs) that have a property which is an array all extending from the one Interface but depending on the object will depend on the size of the array.
FUNCTION_BLOCKclsPLCOneIMPLEMENTSitfPLCModuleVARCONSTANTÂ Â NUM_DIG_OUTPUTS:INT:=15;END_VAR//ThisisapropertyattachedtotheobjectnotactuallyinthevariabledeclarationsectionPROPERTYaDigOut:array[0..NUM_DIG_OUTPUTS]ofstruct_OutputDig
FUNCTION_BLOCKclsPLCTwoEXTENDSclsPLCOneVARCONSTANTÂ Â NUM_DIG_OUTPUTS:INT:=8;END_VAR//ThisisapropertyattachedtotheobjectnotactuallyinthevariabledeclarationsectionPROPERTYaDigOut:array[0..NUM_DIG_OUTPUTS]ofstruct_OutputDig
However when i compile this I get two different errors
1. Interface of overridden method '__SetADIGOUT' of interface 'ITFPLCMODULE' doesnt match declaration.
2. Duplicate definition of variable 'NUM_DIG_OUTPUTS' in function block 'clsPLCTwo' and in base 'clsPLCOne'
So my question is, is there a way to have varying sizes for arrays when stored as arrays if they are inheriting or extending from the same interface.
Any advice would be greatly appreciated
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks so much for your speedy reply. I was worried that it may not have been possible.
My intention was that in my current project I will be having one master PLC/Screen and then a number of slave IO units that will communicate over can. In the CANOpen_Manager for a single output i have at least four variables or bit that are linked together (xValue, xIsOpen, xIsShort, xIsOvercurrent) so I wanted to group all of the related variables/states into one place. And then some of the physical valves I am driving require two outputs to be active on two different PLC's to be active at the same time. So having them stored in a plc object means that when an output is turned on if a short occures it can easily be determined that its on a certain PLC and also all the health parameters of the plc.
Its probably overkill but the intention of then having all the PLCs relate back to the same interface is that i can just store all plc's used in the project in an array and can loop through all of the PLC's as desired to check system health of each.
For reference i have attached a rough UML of what i am trying to do.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2018-10-05
Originally created by: Viacheslav Mezentsev
You can use pointer to struct as a type for property. This is not safe but will work.
function_blockTFBvarconstant
  MAX_SIZE: int :=100;end_varvar
  _items: array [ 0 .. MAX_SIZE ] ofTStruct;end_varpropertyItems : pointertoTStruct
[get] Items :=adr(_items);// ...
typeTStruct :
struct
  Value: real;end_structend_type// ...
programPLC_PRGvar
  bInit: bool :=true;
  r1, r2: real;
  tmp: pointertoTStruct;
  fb: TFB;end_varifbInitthen
 Â
  tmp :=fb.Items;
  tmp[0].Value :=1.5;Â
  tmp[1].Value :=10.5;
  bInit :=false; Â
 Â
end_ifr1 :=tmp[0].Value;r2 :=tmp[1].Value;
I would create an fb which manages the state, overcurrent, ... Of every output valbe. (Fb_valb)
I would create an fb with an array of pointer to fb_valb, with method add. This fb has to be instantiate before any fb_valb, there exist an attribute to do that.
In the fb_init of the fb_valb, add himself to the array of pointers.
You will have an array of fb_valbs to monitorize its.
To know wich valb is, use in fb_valb the attribute 'parameterstringof'. And you will have on an string the name of the fb.
Sent from my Moto G (5S) Plus using Tapatalk
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
michaelADE hat geschrieben:
My intention was that in my current project I will be having one master PLC/Screen and then a number of slave IO units that will communicate over can. In the CANOpen_Manager for a single output i have at least four variables or bit that are linked together (xValue, xIsOpen, xIsShort, xIsOvercurrent) so I wanted to group all of the related variables/states into one place. And then some of the physical valves I am driving require two outputs to be active on two different PLC's to be active at the same time. So having them stored in a plc object means that when an output is turned on if a short occures it can easily be determined that its on a certain PLC and also all the health parameters of the plc.
Are you talking about remote IOs when saying " two different PLC's" ? or IO units are themselves PLCs ?
About your issue, understanding you have one PLC and remote IOs (that may be PLCs but used only for IOs), I would process as following :
1) Declare your full class with maximum size arrays
2) Declare one (retentive) parameter to know which are in use (or just the last one)(embeded in your class, but not initialized)
3) Declare each class instance
4) Address your IOs using your class instance members directly
5) Force your parameter to the right value (I would recommend by code, this avoid retentive flag)
6) Don't forget your instance calls (if you did an array of your class, this can be easily looped)
I decided to just go with having a pointer to a global array of the various IO parameters in the object.
Not amazing practice re OO but I also realised that i could map property calls of an object to to the CANopen I/O mapping parameters.
And by having pointers for the various outputs/inputs that means that if the specific PLC doesnt have a specific output/input type i can have them all point to the same 'empty' array.
Note:
FUNCTION_BLOCKclsBasicPLCIMPLEMENTSitfPLCModuleVARCONSTANTÂ Â MAX_ANALOG_OUTPUT:DINT:=1024;END_VARVARÂ Â xSuspendOutputs:BOOL:=FALSE;Â Â pDigOut:POINTERTOARRAY[0..MAX_DIG_OUT_INDEX]OFstruct_OutputDig;Â Â pAnalogIn:POINTERTOARRAY[0..MAX_ANA_IN_INDEX]OFstruct_InputAnalog;Â Â pAnalogOut:POINTERTOARRAY[0..MAX_ANA_OUT_INDEX]OFstruct_OutputAnalog;Â Â pDigIn:POINTERTOARRAY[0..MAX_DIG_IN_INDEX]OFstruct_InputDig;Â Â pSupplyVoltage:POINTERTOARRAY[0..MAX_SUPPLY_VOLT_INDEX]OFstruct_SupplyVoltage;Â Â enumPartNumber:enum_PLCPartNumbers;Â Â sPLCName:STRING;Â Â iMaxAnaInIndex:INT;Â Â iMaxAnaOutIndex:INT;Â Â iMaxDigInIndex:INT;Â Â iMaxDigOutIndex:INT;Â Â iMaxSupplyVoltIndex:INT;Â Â END_VAR
GlobalVariableList
  aSprayHeadPLC_DigOut: ARRAY [0..CR2050_DIG_OUT_INDEX] OFstruct_OutputDig:=aCR2050OutputIDs;
  aSprayHeadPLC_SupplyVolt: ARRAY [0..2] OFstruct_SupplyVoltage:=aCR20XXSupplyVoltIDs;
 Â
  //UsedasplaceholdersforwhenaPLCcontrollerdoesn't have an input or input of a certain type
  aPLC_NoAnalogOut: ARRAY [0..0] OFstruct_OutputAnalog;
  aPLC_NoDigOut: ARRAY [0..0] OFstruct_OutputDig;
  aPLC_NoDigIn: ARRAY [0..0] OFstruct_InputDig;
  aPLC_NoAnalogIn: ARRAY [0..0] OFstruct_InputAnalog;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hey Everyone,
First time posting, been looking through the forum for a while though.
I know that you can have arrays of varying size (at compile) if you declare them with constants so i want to create a series of objects(FBs) that have a property which is an array all extending from the one Interface but depending on the object will depend on the size of the array.
So my logic was
However when i compile this I get two different errors
1. Interface of overridden method '__SetADIGOUT' of interface 'ITFPLCMODULE' doesnt match declaration.
2. Duplicate definition of variable 'NUM_DIG_OUTPUTS' in function block 'clsPLCTwo' and in base 'clsPLCOne'
So my question is, is there a way to have varying sizes for arrays when stored as arrays if they are inheriting or extending from the same interface.
Any advice would be greatly appreciated
Codesys help tells you may overwrite methods but I don't see it about variable definition.
moreover
BTW, this is PLC programming, so it's basic about inheritance.
To get back in your troubles, what is the aim of such interfaces ?
Hey dFx,
Thanks so much for your speedy reply. I was worried that it may not have been possible.
My intention was that in my current project I will be having one master PLC/Screen and then a number of slave IO units that will communicate over can. In the CANOpen_Manager for a single output i have at least four variables or bit that are linked together (xValue, xIsOpen, xIsShort, xIsOvercurrent) so I wanted to group all of the related variables/states into one place. And then some of the physical valves I am driving require two outputs to be active on two different PLC's to be active at the same time. So having them stored in a plc object means that when an output is turned on if a short occures it can easily be determined that its on a certain PLC and also all the health parameters of the plc.
Its probably overkill but the intention of then having all the PLCs relate back to the same interface is that i can just store all plc's used in the project in an array and can loop through all of the PLC's as desired to check system health of each.
For reference i have attached a rough UML of what i am trying to do.
Originally created by: Viacheslav Mezentsev
You can use pointer to struct as a type for property. This is not safe but will work.
Related
Talk.ru: 1
I would create an fb which manages the state, overcurrent, ... Of every output valbe. (Fb_valb)
I would create an fb with an array of pointer to fb_valb, with method add. This fb has to be instantiate before any fb_valb, there exist an attribute to do that.
In the fb_init of the fb_valb, add himself to the array of pointers.
You will have an array of fb_valbs to monitorize its.
To know wich valb is, use in fb_valb the attribute 'parameterstringof'. And you will have on an string the name of the fb.
Sent from my Moto G (5S) Plus using Tapatalk
Are you talking about remote IOs when saying " two different PLC's" ? or IO units are themselves PLCs ?
About your issue, understanding you have one PLC and remote IOs (that may be PLCs but used only for IOs), I would process as following :
1) Declare your full class with maximum size arrays
2) Declare one (retentive) parameter to know which are in use (or just the last one)(embeded in your class, but not initialized)
3) Declare each class instance
4) Address your IOs using your class instance members directly
5) Force your parameter to the right value (I would recommend by code, this avoid retentive flag)
6) Don't forget your instance calls (if you did an array of your class, this can be easily looped)
This feels way more reliable to me than using unmanaged pointers, just because of the complexity of the code, and issues related to online changes.
Moreover, you cannot resize arrays at runtime (as far as I know). see https://stackoverflow.com/questions/39723966/creat-an-array-in-codesys-with-changeable-size
Hey Everyone,
Thanks for your advice,
I decided to just go with having a pointer to a global array of the various IO parameters in the object.
Not amazing practice re OO but I also realised that i could map property calls of an object to to the CANopen I/O mapping parameters.
And by having pointers for the various outputs/inputs that means that if the specific PLC doesnt have a specific output/input type i can have them all point to the same 'empty' array.
Note: