Indirect Addressing

  • PauloRicardoSS - 2020-10-13

    Hi guys,
    I want to do a simple indirect address using Codesys V3.5.
    On Simenes I can simple check any input using %IW[Index]. Which is not allowed on Codesys.

    The Idea is have a FB to pickup all information from a IO_Link device, so one of the inputs will be the first address (Ex: Index:= 240), and on my code I should be able to use Status:= %IW[index+2], but so far, I didn't see any resource for that.

    Anyone with an idea?

    Thanks a lot


    Last edit: PauloRicardoSS 2020-10-13

    JAPIB - 2020-10-13

    You can declare an ARRAY, for example:
    MyArray AT %IW0: ARRAY [0..100] OF INT;

    And declare an index
    MyIndex :INT;

    And then you can reach the variable you want read or write


    • PauloRicardoSS - 2020-10-13

      In my case this not make any sense, since I want to create a FB which I can call several times for several different IOLink Devices, in that case my first address must be a parameter.
      I have declarated on my software 2000 inputs, if I create inside of the FB one array with 2000 elements and call this FB several times it will cause a a memory problem. I know that I have maximum 32 bytes input and I also know that we not going to use 32 bytes, it will be less than that.

      So, in my case the best option is:
      On my FB
      Var Input
      End Var
      END Var

      MyStatus := %IW[DeviceAddress+2];
      MyAnalogValue :=%W[DeviceAddress+8];

      In that case I don't even need an array and save memory.

      That's the resource I am looking for. And I couldn't find a way to do it.

      Or if I have to create an Array it should be able to be small and receive the address from the input parameter.

      MyArray AT %IW[DeviceAddress]: ARRAY [0..20] OF INT;

      Or even better copy from the %W[DeviceAddress] to one variable which is an UDT (as the move on Siemens or COP on AB).
      Best Regards,


      Last edit: PauloRicardoSS 2020-10-13
      • aliazzz

        aliazzz - 2020-10-13


        I'd like to give you the advice to avoid using direct adressing(!)
        In CODESYS it is not neccesary to use it allthough it is permitted.
        On the other hand, just because it is permitted, doesn't mean that is a good way to do things.

        On an Digital In IO card Channel 1 you simply declare eg: Pump1_Feedback.
        While in fact the actual addres for this IO var is %IB0.0
        just use the named variable Pump1_Feedback in your code, at least it says what the IO means so the maintenace man can understand what this IO is connected to in the machine, even without extra comment.

        On the FB design;
        using actual adresses (even with offsets) in an FB is also not a good design idea. Yes your trick may work but your code is poorly readable and poorly extensible.
        A better way is to pass a UDT eg. a named struct in which you map your IO. struct with 20 Integers which are named after their usage or meaning.
        Now you have the freedom to you can do as you wish if you pass this named IO struct into your FB. As a bonus you can even your stuct without changing the code in the FB ;-)

        If you have many IO, you could use Excel to automate the declaration proces
        Also saving memory is something that is mostly not neccesary.

        Good luck and with kind regards

        • PauloRicardoSS - 2020-10-13

          In the case of simple digital inputs and outputs doesn't make sense to create an indirect addressing.
          But in my case and others more complex cases, you cannot addressing bit by bit, because is a byte oriented on the hardware declaration and you have bits and words and some words need to use a ROL to have the correct value, because it repeats several times make sense create an FB the do the work and organize the data to be copied to an udt, that's a resource used even in some automotive standards with robots FB (some times you need a byte information but it start on the middle of one byte and ends on the middle of the next one), and surprising good for maintenance, because what they will see is only organized data, and that is the idea behind the FB, it will be called several times with a instance with a easy name and will provide organized data, or otherwise you have to do ROLs, and create logics, etc.
          So, you can realize the indirect addressing is just a tool to use in the program, to help to create organized data, and organized data is a good programming practice.
          Of course, if only have on type of data, or if the device provide data on a organized way, just a copy to a variable with the correct udt will be the best choice.

          Best Regard,

  • dFx

    dFx - 2020-10-14

    I see two ways doing this.

    First one, declare your fb instances, then directly map fb inputs bit by bit. Exemple, Lets say you have an alarm status input that is fbPump01.bAlm. Just declare the fb as Pump01, and add an input as bAlm. Then map fbPump01.bAlm to the right input bit.

    Second one, if you need dynamic addressing, just define an array on your I/Os. Then use a pointer to get the starting address I/O ADR(arBDigInputs). Last, inside the fb, using a slice input parameter, move your pointer to the desired address. This involve some pointer address manipulation, and you may carefully read the warnings about pointers :;product=codesys;version=
    To avoid compilation warnings you may need a copy of your inputs into memory.


    Last edit: dFx 2020-10-14
    • aliazzz

      aliazzz - 2020-10-14

      Yup, afaik actually he's using V3..

      So instead of using pointers, use references as they are compiler safe, while pointers are not.
      In usage it does not quite differ in idea apart from some minor syntax differences.;product=codesys;version=

      According to the documentation a reference has the following advantages over a pointer:

      Easier to use:
      A reference can access the contents of the referenced object directly and without dereferencing.
      Finer and simpler syntax when passing values:
      Call of a function block which passes a reference without an address operator instead of a pointer
      Example: fbDoIt(riInput:=iValue);
      Instead of: fbDoIt_1(piInput:=ADR(iValue));
      Type safety:
      When assigning two references, the compiler checks whether their base types match. This is not checked in the case of pointers.

      Also consider using structures instead of Byte/Word blobs...


      Last edit: aliazzz 2020-10-14

Log in to post a comment.