Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Addressing memory area

2022-08-30
2022-08-31
  • aivarasutkus - 2022-08-30

    Hi.
    Im looking for a way to address variables in memory are. I know you can address it like %Mw0. Is it possible to make this with index like %mw(index) or should i use another way to read and write values. Any ideas would be great.

     
  • fajean - 2022-08-30

    Do you mean something like this?

    PROGRAM MAIN_b223d63214
    VAR
      int_array AT %MW0: ARRAY[0..1000] OF INT;
      value_0, value_1: INT;
    END_VAR
    
    int_array[0] := 12;
    int_array[1] := 13;
    value_0 := int_array[0];
    value_1 := int_array[1];
    

    This will also work using a structure as a type rather than an "ARRAY OF", where said structure may itself recursively contain structures and arrays.

    Maybe you could explain a bit why you want to use %M addresses to help us understand what you are trying to achieve?

     

    Related

    Talk.ru: 1

    • aivarasutkus - 2022-08-31

      Not exactly.
      So i have my custom structure in global variables list. It goes like:
      Analog_300_A13EGA10CF001
      Analog_301_A13EGA20CF001 ect.
      Since Scada system is goes over modbus, variables has to have address.
      So my tag goes like Ana_list.Analog_300_A13EGA10CF001. I cant really use array, because it will impossible to code process.
      And since i have more objects including valves, motors, that makes quite a lot of tags. So i was wondering if i could just copy of my item to HMI to configuration window and then read/write values over it.
      First attempt

      PROGRAM PLC_PRG
      VAR
      NR : INT; // number tage
      A,B,C,D : Ana; // test objects
      Indr: Ana;
      Copy: Ana;
      ptInt, ptInt2: POINTER TO Ana;
      e : BOOL;
      Before,after1 : real;
      END_VAR
      // program
      CASE NR OF // selecting object from tag list
      1: ptInt := ADR(A);
      2: ptInt := ADR(B);
      3: ptInt := ADR(C);
      4: ptInt := ADR(D);
      ELSE
      ptInt :=ADR(Indr); // If none selected give spare copy
      END_CASE
      Copy:= ptInt^; // Write values from tag in GVL item to copy -part working
      Before := Copy.Sim_value; // testing tag
      ptInt^.Sim_value :=Copy.Sim_value; // Writing values from copy to tag inG VL- not working, too fast rewrites values
      After1 :=Copy.Sim_value;// testing tag

       
  • fajean - 2022-08-31

    I am a bit confused. The code you provide does not seem to reference your global variables list, there are no "AT" addresses. I do not understand what your intent is with the code at the bottom, or what you mean exactly by "working, too fast rewrites values".

     
    • aivarasutkus - 2022-08-31

      Like i said, its just a test.
      My structure looks like in picture. You can address it by using %MW or there is another way to address it. My test code was done with symbolic address. If i make break points and go line by line and i write value to Copy tag
      Copy:= ptInt^;// <- here while program is halted
      then this operation writes value from copy tag to tag in test area
      ptInt^.Sim_value :=Copy.Sim_value; //

      This idea comes from simatic where you can reach so called Data blocks with Area Registers (IL). Then you could read and transfer values in you data block

       
  • fajean - 2022-08-31

    Here is what I think you are trying to achieve :

    • Allow access to variables without the use of arrays for parts of your code that cannot deal with arrays
    • Allow access to variables as an array for other parts of your code that are simpler (and easier to modify) done this way.
    • Allow mapping to "AT" addresses for communications purposes

    Here is one way this may be done.

    First, I will assume you have a structure for each of your analog values that looks like this :

    TYPE Analog_300_A13EGA10CF001 :
    STRUCT
      MV: REAL;
      Sim_value: REAL;
      // ...
    END_STRUCT
    END_TYPE
    

    Then, define a structure that has all the entries you need. Please note this is much like defining an array by explicitly instantiating each entry.

    TYPE Analog_300_entries :
    STRUCT
      entry_0: Analog_300_A13EGA10CF001;
      entry_1: Analog_300_A13EGA10CF001;
      entry_2: Analog_300_A13EGA10CF001;
      entry_3: Analog_300_A13EGA10CF001;
    END_STRUCT
    END_TYPE
    

    Now, define a union, which will give two "views" of the same memory area, so that we can see it both as an array and as a structure of individual entries.

    TYPE Analog_300_union :
    UNION
      entries: Analog_300_entries;
      arrayed: ARRAY[0..3] OF Analog_300_A13EGA10CF001;
    END_UNION
    END_TYPE
    

    You instantiate that union in a global variables list :

    VAR_GLOBAL
      Analog_300 AT %MW0: Analog_300_union;
    END_VAR
    

    In your program, you now have both the "individual variable view", the "arrayed view", and the "AT" addressing. Here is example code to show that both "views" really work on the same data.

    // MAIN PROGRAM HEADER
    PROGRAM MAIN_b223d63214
    VAR
      s1, s2: LINT;
      p1, p2: POINTER TO Analog_300_A13EGA10CF001;
      r1: REAL;
    END_VAR
    
    // MAIN PROGRAM CODE BLOCK
    // We can access the same memory area in two ways
    globals.Analog_300.arrayed[1].Sim_value := 2;
    r1 := globals.Analog_300.entries.entry_1.Sim_value;
    // Let us show that the memory layout truly matches
    s1 := SIZEOF(globals.Analog_300.entries);
    s2 := SIZEOF(globals.Analog_300.arrayed);
    p1 := ADR(globals.Analog_300.entries.entry_3);
    p2 := ADR(globals.Analog_300.arrayed[3]);
    

    Is that close to what you want to do?

     

    Related

    Talk.ru: 1
    Talk.ru: 3


    Last edit: fajean 2022-08-31
    • aivarasutkus - 2022-08-31

      Bingo. Thanks!

       
    • aivarasutkus - 2022-08-31

      Bingo. Thanks!

       
    • aivarasutkus - 2022-08-31

      Bingo. Thanks!

       
    • aivarasutkus - 2022-08-31

      Bingo. Thanks

       
  • aivarasutkus - 2022-08-31

    Sorry, crashed browser.

     
    • fajean - 2022-08-31

      Personally, I would forego the union and individual entry structures and only use the array. It is more concise, and allows adjusting array size with a "configurable constant" (no other code change). This still allows "AT" addresses for communication. I only use structured code, maybe this blinds me to cases where arrays are not as easy to code for.

      However, if you prefer, or for some reason are forced, to have variables accessible in a way that does not use arrays, the above should work.

       

Log in to post a comment.