Module I/O Mapping, Symbolic access?

janber
2022-02-02
2022-02-02
  • janber - 2022-02-02

    Hi All,
    I have an application with many EtherCAT slaves, where I need to access the data - if possible - easily without much typing errors and rewryting all if I change the slave type.

    So, a way with "Create new variable" or "Map to existing variable" is not the way I really like.

    Is here any chance how to get access to I/O mapping via the EtherCAT slave name?

    Basically, I'd like to copy all 16 words from this mapping to my array or structure - these data:

    [-img src=2022-02-02 14_41_35-testproj.project_ - CODESYS.png width=50%: missing =-]

    So, I wonder - it here any method how to get starting address of the PO1? Then I can use MemCpy or similar to use the data easily...

    Thanks!

    Jan.

     

    Last edit: janber 2022-02-02
  • fajean - 2022-02-02

    If I understand, you would like to use a single mapping.

    You can do something like this.

    PROGRAM MAIN_b59c24a9eb
    VAR
      data: POINTER TO WORD;
    END_VAR
    
    data := ADR(%QW0);
    data[0] := 1;
    data[1] := 2;
    

    However, this hard codes the address in your program, so the component that deals with the addresses is not reusable.

    What I do is something like this :

    • Define a structure that describes the memory block.
    • In a (reusable) component, declare a variable with "AT %I" or "AT %Q" using this structure.
    • Use a VAR_CONFIG in my project where I map the reusable components to the project-specific addresses.

    This is how I achieve I/O-mapped, reusable components that do not require manually mapping every variable (as long as they belong to the same structure).

     

    Related

    Talk.ru: 1

  • janber - 2022-02-02

    Yep, I'm using this way as well. And what I'd like is to go one step futher - instead of declaring a start of the structure with AT %.. keyword, I'd like to ask the component - tell me where your data starts and then use them. Dynamically, according to the component name... any fault in addressing will be eliminated. Then either set my structure to the address (via pointers) or copy it to my variables.

    So far I did not found a way how to achieve it.

    Thanks!

     
  • fajean - 2022-02-02

    I think I see what you mean, an before I settled on this method, I tried to achieve something along those lines. The roadblocks to a better solution that I see :

    • The AT %Q/I* works with addresses so that is a bit low-level, but that solution is very concise. One mapping, one line. It takes a very easy solution to beat that from a complexity perspective.
    • Mapped structures can be big, and nested. For instance, we have Profinet I/O with hundreds of bytes, which are an aggregate of several different nested structures that can be mapped with a single line. The "AT" solution shines when you are mapping a lot more than the 8 inputs of a simple digital inputs module.
    • Hardware addresses can be locked so that "AT" mappings are not on shifting ground.
    • If you forget "AT" mappings, you get compilation errors. Any solution that requires adding code to the project to perform the mapping is prone to forgetting of your gazillion structures, and that can be hard to debug.
    • To beat "AT" mappings, you would need a solution that has zero coding in the project (i.e. the mere declaration of some function block causes it to find the right I/O card and map itself). This will still require some form of implicit mapping, and structured text is not reflexive as far as I know (cannot map based on instance variable name, for instance). Based on my current knowledge, I am not able to see how a function block could find out, by itself, which of the (potentially many identical) I/O cards in the project it should link with. If there is a way to do that, it would probably require some form of initialization (something passed to FB_Init, an annotation, whatever), and if I am going to be doing a mapping in my project, I would rather go with "AT" mappings.
    • "AT" mappings works outside of CODESYS (at least with TwinCAT, I can't tell for other environments). I design libraries intended to be used in both environments. "AT" mappings in TwinCAT need to be performed variable-by-variable (we have not found a way to get a pointer to I/O memory or to map structures like CODESYS allows, maybe we missed it), but at least we can work from the same code base, just faster with CODESYS.
    • A solution relying on the enumeration of I/O cards would probably not be portable, so you would actually need one separate mechanism for each "flavor", and that mechanism would have to be able to link up with portable components. I am able to live with a lot of tradeoffs on I/O mapping to preserve control logic components portability.

    At this time, I feel like the "AT" solution, while it feels a bit primitive, still is my best bet. I would be very glad to be proven wrong!

     

    Last edit: fajean 2022-02-02

Log in to post a comment.