Using FB_INIT with a Struct of Objects

jspyker
2021-11-09
2021-11-09
  • jspyker - 2021-11-09

    I am looking to see if there is any way to use FB_INIT on function blocks nested inside a struct. I want to init the struct when I use it in the main code.

    I've looked around and the closest I can find is initializing an array of objects using FB_INIT. (https://forge.codesys.com/forge/talk/Engineering/thread/dbf5a245f1/).

    I can think of several work arounds to get around this without using FB_INIT, but was just wondering if anyone knew a way to do this as it would be useful to keep my code tidier.

    See code snippet for what I am trying to achieve in essence (this doesn't work at all!)


    FUNCTION_BLOCK FB_OBJECT
    VAR
        data : INT;
    END_VAR
    
    METHOD FB_INIT: BOOL
    VAR_INPUT
        bInitRetains: BOOL;
        bInCopyCode: BOOL;
        data : INT;
    END_VAR
    
    TYPE MY_STRUCT :
    STRUCT
        // NOTE - I dont want to init the variables here as I reuse the struct multiple times with different init values each time.
        MyObject1 : FB_OBJECT(0); 
        MyObject2 : FB_OBJECT(0);
        MyObject3 : FB_OBJECT(0);
    END_STRUCT
    END_TYPE
    
    
    PROGRAM PRG_MAIN
    VAR 
        // NOTE - This does not work, but want to do something similar.
        // Have tried a few variations on this but can't find anything that works. maybe its not possible.
        Foo : MY_STRUCT := (
           MyObject1 := FB_OBJECT(data:=1),
           MyObject2 := FB_OBJECT(data:=2),
           MyObject3 := FB_OBJECT(data:=3));
    END_VAR
    
     

    Last edit: jspyker 2021-11-09
  • hermsen

    hermsen - 2021-11-09

    I'd like to take your question one step back, zooming out so to speak.
    What is it you want to achieve via the this construction?
    Could you explain what you are to trying to achieve? Maybe there are other ways to help you out.
    Hoping you would take the time to explain what the application should solve.

    PS STRUCTS need to be decalered as a DUT in IEC(!)
    See: https://help.codesys.com/api-content/2/codesys/3.5.14.0/en/_cds_obj_dut/

    I hope this may help you a step further but I suspect the dynamic initialization in the program is not possible?
    I have no experience with that, so you have to try. Could you provide feedback on it?

    TYPE ST_MyStruct :
    STRUCT
        Obj1 := FB_Object(data:=1); // Data cannot be initialised dynamicly now?
        Obj2 := FB_Object(data:=2);// Data cannot be initialised dynamicly now?
        Obj3 := FB_Object(data:=3);// Data cannot be initialised dynamicly now?
    END_STRUCT
    END_TYPE
    
    
    PROGRAM PRG_TEATWAND_POSTSPRAY
    VAR 
        // NOTE - This does not work, but want to do something similar.
        // Have tried a few variations on this but can't find anything that works. maybe its not possible.
        Foo : ST_MyStruct := (// dynamic data init stuff goes here?? );
    END_VAR
    
     

    Last edit: hermsen 2021-11-09
  • jspyker - 2021-11-09

    I'll try summarized what I am trying to do in a more simple format. I am essentially trying to to create a mapping structure to map variables to ports on an IO block.

    I have a class FB_PORT which accesses a particular port on an IO block and grabs the data from it. This class has various methods such as GetDigitalInput(), GetConnectionStatus(), GetShortCircuitDetected(). I use this class within my code to access my IO.

    When the port class is initialized I pass in a pointer to both the IO_Block class and the desired port.

    Port_1 : FB_PORT(ADR(IO_BLOCK_1), PORT.X01)
    

    Ideally I want to have a struct of these ports so I can have them nicely named for accessing within the code. It would look something like this:

    TYPE PORT_MAPPING :
    STRUCT
        Port_1 : FB_PORT(0,0);
        Port_2 : FB_PORT(0,0);
        Port_3 : FB_PORT(0,0);
        Port_4 : FB_PORT(0,0);
    END_STRUCT
    END_TYPE
    
    // Access the IO data in the code like follows:
    PortMapping.Port_1.GetDigitalInput();
    

    Our system has one PLC running multiple copies of the same system, but with different port mapping. So I want to make multiple copies of the port mapping struct each mapped differently. So when I init the variables for my class I ideally want to do something like this:

    PortMapping : PORT_MAPPING := (
           Port_1 := FB_PORT(pIOBlock:=ADR(IO_Block_1), port:=PORT.X01),
           Port_2 := FB_PORT(pIOBlock:=ADR(IO_Block_1), port:=PORT.X02),
           Port_3 := FB_PORT(pIOBlock:=ADR(IO_Block_2), port:=PORT.X01),
           Port_4 := FB_PORT(pIOBlock:=ADR(IO_Block_2), port:=PORT.X02);
    

    I've put in a workaround for now, manually updating each of the FB_Port objects after the struct is initialized. This isn't as tidy as was looking to see if there was a way to do it directly. (or a similar approach that could work).

    Cheers

     

    Last edit: jspyker 2021-11-09

Log in to post a comment.