Объединить переменную

Мне нужно объединить строку, целое число и строку в переменную - в данном случае вход.

Входы называются следующим образом:

DI_Section1_Valve AT %I*: BOOL;
DI_Section2_Valve AT %I*: BOOL;
DI_Section3_Valve AT %I*: BOOL;

Теперь я хочу пройтись по ним (это всего лишь короткий пример):

For i:= 1 TO 3 DO
    Var[i] := NOT CONCAT(CONCAT('DI_Section', INT_TO_STRING(i)), '_Valve')
END_FOR

Но, объединив строки, я получу строку, например. 'DI_Section1_Valve', а не логическая переменная, например. DI_Section1_Клапан.

Как мне получить переменную, а не просто строку? Любая помощь приветствуется, заранее спасибо. /Tft99


person Thoft    schedule 28.10.2020    source источник


Ответы (2)


Этот метод называется переменными переменными. К сожалению, это недоступно в ST. Есть несколько способов обойти это. Насколько я понимаю, Twincat 3 основан на Codesys 3.5. Это означает, что UNION доступен. Также есть хитрость, что ссылки на BOOL работают не так, как ожидалось, и одна ссылка занимает один байт. Таким образом, вы не можете расположить их по порядку, поэтому вам нужно знать BYTE адрес входного модуля.

TYPE DI_Bits : STRUCT
        DI_Section1_Valve  : BIT; (* Bit 1 *)
        DI_Section2_Valve  : BIT; (* Bit 2 *)
        DI_Section3_Valve  : BIT; (* Bit 3 *)
        DI_Section4_Valve  : BIT; (* Bit 4 *)
        DI_Section5_Valve  : BIT; (* Bit 5 *)
        DI_Section6_Valve  : BIT; (* Bit 6 *)
        DI_Section7_Valve  : BIT; (* Bit 7 *)
        DI_Section8_Valve  : BIT; (* Bit 8 *)
    END_STRUCT
END_TYPE

TYPE DI_Sections : UNION
        ByName : DI_Bits; 
        ByID : ARRAY[1..8] OF BOOL; (* Comment *)
        ByMask: BYTE;
    END_UNION
END_TYPE

PROGRAM PLC_PRG
    VAR
        DIS AT %IB0.0: DI_Sections; (* Our union *)
        xOut : BOOL;
    END_VAR


    xOut := DIS.ByID[1];
    xOut := DIS.ByName.DI_Section1_Valve;
    
    DIS.ByID[5] := TRUE; 
    // Now DIS.ByName.DI_Section5_Valve also EQ TRUE

END_PROGRAM
person Sergey Romanov    schedule 29.10.2020

Вы не можете получить доступ к переменным с помощью строк. Вместо этого вы можете вручную создать массив указателей на значения, которые вы хотите проиндексировать, например:

    DI_Section1_Valve AT %I*: BOOL;
    DI_Section2_Valve AT %I*: BOOL;
    DI_Section3_Valve AT %I*: BOOL;

    DI_Section_Valves: ARRAY [1..3] OF POINTER TO BOOL
        := [ADR(DI_Section1_Valve), ADR(DI_Section2_Valve), ADR(DI_Section3_Valve)];
    FOR i:= 1 TO 3 DO
        out[i] := DI_Section_Valves[i]^;
    END_FOR

РЕДАКТИРОВАТЬ: В качестве альтернативы вы можете создать функцию, которая делает это:

METHOD Get_DI_Selection_Valve : BOOL
VAR_INPUT
    i: INT;
END_VAR

    CASE i OF
    1: Get_DI_Selection_Valve := DI_Section1_Valve;
    2: Get_DI_Selection_Valve := DI_Section2_Valve;
    3: Get_DI_Selection_Valve := DI_Section3_Valve;
    END_CASE
FOR i:= 1 TO 3 DO
    out[i] := Get_DI_Selection_Valve(i);
END_FOR

Хотя идея та же

person Guiorgy    schedule 28.10.2020