tomatoeshift
tomatoeshift

Reputation: 485

Is it possible to indirectly index an array in structured text (IEC 61131-3 standard)

I have an array of a structure: myStructure[0..100]

I would like to index that structure by name.

It works by giving each index a name:

P101_AI := 9
P102_AI := 10
P103_AI := 11
P104_AI := 12

So indexing a member in the structure: myStructure[P103_AI].value (i.e. indexing myStructure[11].value)

However, is it possible to index this indirectly?

i.e. if delcaring TempString : STRING[30];

altering TempString at runtime to index the array.

Here is some pseudocade to describe what I would like to do:

FOR i:=101 TO 104 DO
   TempString := CONCAT('P',i);
   TempString := CONCAT(TempString,'_AI');
   MyStructure[ indirect(TempString)].value := 'some value';
END_FOR;

Upvotes: 0

Views: 2240

Answers (3)

tomatoeshift
tomatoeshift

Reputation: 485

This is how i solved it.

TYPE infoType: STRUCT
    name: STRING[20];
    END_STRUCT
END_TYPE
TYPE sensorType: STRUCT
    value: INT;
    info:  infoType;
    END_STRUCT
END_TYPE
TYPE IO_Type: STRUCT
    AI: ARRAY[1..100] OF sensorType;
    END_STRUCT
END_TYPE
TYPE E_AnalogInput :
(
    P101_AI := 9,
    P102_AI,
    P103_AI,
    P104_AI
);
END_TYPE
PROGRAM PLC_PRG:
    VAR
        IOs: IO_Type;
    END_VAR

    IOs.AI[P101_AI].info.name := 'P101_AI';

    FOR i:=101 TO 104 DO
        TempString := CONCAT('P',i);
        TempString := CONCAT(TempString,'_AI');
        FOR i:=0 TO SIZE_OF(ADR(IOs.AI)) / SIZE_OF(ADR(IOs.AI[0]))  DO
            IF TempString = IOs.AI[i].info.name THEN
                IOs.AI[i].value := 123; // Some value
                EXIT;
            END_IF;
        END_FOR;
    END_FOR;

END_PROGRAM

Upvotes: 0

Arndt
Arndt

Reputation: 98

What about creating an enum?

{attribute 'qualified_only'}
TYPE E_AnalogInput :
(
    P101_AI := 9,
    P102_AI,
    P103_AI,
    P104_AI
);
END_TYPE

Then you can declare:

analogInputs : ARRAY[E_AnalogInput.P101_AI..E_AnalogInput.P104_AI] OF INT;

Running a for loop:

FOR inputCount:=E_AnalogInput.P101_AI TO E_AnalogInput.P104_AI BY 1 DO
    //Do something
END_FOR

Hope this helps

Upvotes: 1

Sergey Romanov
Sergey Romanov

Reputation: 3080

I would use pointers and mapping. First, change your structure to the pointer.

TYPE MyType: STRUCT
        input: POINTER TO INT;
        value: INT;
        // other properties
    END_STRUCT
END_TYPE

Then, create a global array.

VAR_GLOBAL
    MyStructure: ARRAY[1..100] OR MyType;
END_VAR

Now in a program create one time running code.

PROGRAM PLC_PRG:
    VAR
        xInit:= FALSE;
    END_VAR

    IF NOT xInit THEN
        xInit := TRUE;
        mMap();
    END_IF
END_PROGRAM

Now in a method or action mMap do this for every array element.

MyStructure[1].input:= ADR(AI_Name);
MyStructure[2].input:= ADR(P102_AI);
MyStructure[3].input:= ADR(%ID0.1);

I used 3 different ways to bind pointer. The order is not important I think. Then in a program, you can do this.

FOR i := 1 TO 100 DO
   MyStructure[i].value := 'MyStructure[i].input^;
END_FOR;

Upvotes: 0

Related Questions