I/O Mapping When FB uses AT %I* or %Q*

jzhvymetal
2015-03-22
2015-04-09
  • jzhvymetal - 2015-03-22

    In CoDesys V3 how can you uses the I/O Mapping tab when FB uses AT %I or %Q? The FB is defined as follows:

    FUNCTION_BLOCK netacc
    VAR_INPUT
       aState      AT %I*: UINT;
       RxControl   AT %Q*: DWORD;
       RxData      AT %Q*: DWORD;
    END_VAR
    VAR_OUTPUT
       TxControl   AT %I*: DWORD;
       TxData      AT %I*: DWORD;
    END_VAR
    

    I can get it to compile if create a GVL with VAR_CONFIG as follows:

    VAR_CONFIG
       GVL.MY_AXIS.netacc.aState AT %MW0 : UINT;
       GVL.MY_AXIS.netacc.RxControl AT %QD0 :UDINT;
       GVL.MY_AXIS.netacc.RxData AT %QD1 :UDINT;
       GVL.MY_AXIS.PLCopenRx2 AT %QD2 :UDINT;
       GVL.MY_AXIS.PLCopenRx1 AT %QD3 :UDINT;   
       
       GVL.MY_AXIS.netacc.TxControl AT %ID0 :UDINT;
       GVL.MY_AXIS.netacc.TxData AT %ID1 :UDINT;
        GVL.MY_AXIS.PLCopenTx2 AT %ID2 :UDINT;
       GVL.MY_AXIS.PLCopenTx1 AT %ID3 :UDINT;
    END_VAR
    

    I would like to us the CoDeSys I/O Mapping so if the fixed I/O address shift because of hardware changes the VAR_CONFIG does not require updates. When I try to use the I/O Mapping tab I get the following compile errors shown in the picture below

    IMG: I_O_MAPPING.png

     
  • Anonymous - 2015-04-09

    Originally created by: scott_cunningham

    You cannot use AT declarations for input or output variables of POUs - per the CoDeSys help files.

    Closest workaround for you is to change your ins and outs to pointers:

    FUNCTION_BLOCK netacc
    VAR_INPUT
       paState    : POINTER TO UINT;
       pRxControl : POINTER TO DWORD;
       pRxData    : POINTER TO DWORD;
    END_VAR
    VAR_OUTPUT
       pTxControl : POINTER TO DWORD;
       pTxData    : POINTER TO DWORD;
    END_VAR
    

    And then create the Fb_init() method this way:

    METHOD Fb_init : BOOL
    VAR_INPUT
       bInitRetains : BOOL; // Initialization of the retain variables (required by Fb_init)
       bInCopyCode : BOOL; // Instance moved into copy code (required by Fb_init)
       aStatePtr    : POINTER TO UINT; // hardware address to use
       RxControlPtr : POINTER TO DWORD; // hardware address to use
       RxDataPtr    : POINTER TO DWORD; // hardware address to use
       TxControlPtr : POINTER TO DWORD; // hardware address to use
       TxDataPtr    : POINTER TO DWORD; // hardware address to use
    END_VAR
    paState:= aStatePtr;
    pRxControl:= RxControlPtr;
    ...
    pTxData:= TxDataPtr;
    

    Then when you declare your FB instance, you need to include your assignments (or you get a compile error):

    PROGRAM PLC_PRG
    VAR
      Inst1 : netacc(aStatePtr:= ADR(%MW0), RxControlPtr:= ADR(%QD0), ..., TxDataPtr:= ADR(%ID1));
    END_VAR
    

    Now Inst1 Ins and Outs point to the hardware address you desire. In your code, you need to dereference your pointers (like this example for a counter):

    pCounter:= pCounter^ + 1;
    

    Another workaround that I prefer, but it does add some variables to memory space:

    Define some generic arrays (e.g. DigIn[0]..DigIn[15]) and map them at the CoDeSys I/O mapping. Then in my code I add one POU (program) called HardwareMapping where I map my local variables that have meaning. The advantage is I have one program where all of the code to real world connections are made.

    PROGRAM HardwareMapping
    // real world to code
    Drive1.HomeSwitch:= Application.GVL_VARS.Bank1.DigInput[3];
    Drive1.EndLimit:= Application.GVL_VARS.Bank1.DigInput[5];
    // code to real world
    Application.GVL_VARS.Bank5.DigOutput[2]:= Drive1.Faulted;
    ...
    

    Works with Drive1 as a FB instance or a structure.

    NOTE: This solution can add one scan latency (FBs don't see the value until the next scan) - some applications maybe can't tolerate this.

     

    Related

    Talk.ru: 2
    Talk.ru: 3
    Talk.ru: 5


Log in to post a comment.