0

It is possibile in CodeSys get the value of a constant dinamically?

For example:

VAR CONSTANT
    MYCONST_1 : INT := 1;
    MYCONST_2 : INT := 2;
    MYCONST_3 : INT := 3;
    MYCONST_4 : INT := 4;
END_VAR

toCheck := 3; // INT
result := 0; // INT

FOR i := 1 TO 4 DO
    IF toCheck = i THEN
        result := GET_CONSTANT_VALUE_BYNAME(CONCAT('MYCONST_', INT_TO_STR(i)))
    END_IF
END_FOR
Massimo
  • 553
  • 7
  • 24

2 Answers2

2

What is you goal with this code? At the end of your loop, the result var will always be 4 if toCheck is equal to 3.

So why not writing 4 directly?

IF toCheck = 3 THEN
    result := MYCONST_4; 
END_IF

If you want a constant value depending on the index value of the loop why not using an array of const integers?

VAR CONSTANT
    iConstValues : ARRAY[1..4] OF INT := [20,21,22,23];
END_VAR

FOR i := 1 to (eMAX_AXES_NUM-1) DO

    //Let's check an array of references to axes
    if NOT aAxes[i].isOperational()
    THEN
        //If one axis in the group is not operational return a result value
        result := iConstValues[i] ;
        RETURN
    END_IF
    
END_FOR

Normally though you would have something like this:

TYPE E_Actuator :
(
    eNO_ACTUATOR := 0,
    eAXIS, //has value 1
    eVALVE //has value 2
);
END_TYPE

TYPE E_Status :
(
    eNO_RESULT := 0,
    eOPERATIONAL,
    eERROR
);
END_TYPE

TYPE E_AxisType :
(
    eX_AXIS := 1,
    eY_AXIS,
    eZ_AXIS,
    eA_AXIS,
    eB_AXIS,
    eMAX_AXES_NUM
);
END_TYPE

FUNCTION_BLOCK CheckActuators 
VAR_INPUT
    eActuator : E_Actuator;
END_VAR
VAR_OUTPUT
    eStatus : E_Status;
    eFaultyAxis : E_AxisType;
END_VAR

CASE eActuator OF

    //Check for type Axis
    eAXIS:
        //Check status here and return a value
        (*
        FOR i := 1 to (eMAX_AXES_NUM - 1) DO
            //CheckActuators has an array with references to all axes in the project for example..
            if NOT aAxes[i].isOperational()
            THEN
                //If one axis in the group is not operational return error status
                eStatus := eERROR;
                eFaultyAxis := i;

                RETURN
            END_IF
        END_FOR
        *)
        
    //Check for type Valve
    eVALVE:
            
END_CASE
Filippo Boido
  • 1,136
  • 7
  • 11
  • In my code I have a list of alarm numbered, like ALARM_1, ALARM_2, ecc.. What I want to achieve is not to write 10 lines of codes for each alarm. Sorry for late response – Massimo Jul 19 '20 at 10:10
  • Use enumerations in combination with switch case statements as in the example above. – Filippo Boido Jul 19 '20 at 10:33
  • I think is the only choice, I was searching a solution to not change the current structure, thanks for the help – Massimo Jul 19 '20 at 12:44
2

First of all your example is very strange. Confition IF will work in every cycle and it is not clear how condition depends on cycle. I think you mean.

IF toCheck = i THEN

Anyway, in codesys you cannot do something like in PHP Variable variables

$a = "hello";
$$a = "world";
echo $helo // output world

Or like this

$b = 2;
$a1 = 1;
$a2 = 2;
echo ${"a" . $b}; // Output 2

Those all will not work in ST. You have use different aproach. If you would tell in your question the final task you want to solve, I would suggect you the best, but now I'll give you only general idea. All examples for Codesys 2.3. In 3.5 there is slightly different syntax.

  1. Arrays

VAR 
    aSteps: ARRAY[1..4] OF INT := 1, 2, 3, 4;
END_VAR

toCheck := 3; // INT
result := 0; // INT

FOR i := 1 TO 4 DO
    IF toCheck = i THEN
        result := aSteps[i];
    END_IF
END_FOR

But even simplier, as you already know index with toCheck and you do not need to convert it to variable name, you can simply.

VAR 
    aSteps: ARRAY[1..4] OF INT := 1, 2, 3, 4;
END_VAR

toCheck := 3; // INT
result := aSteps[toCheck];
  1. Enumerations

First you define a type.

TYPE enSteps : (
    stepIdle, stepStart, stepEnd := 5
);
END_TYPE

Now stepIdle := 0, stepStart := 1 and stepEnd := 5

VAR
    result: enSteps;
END_VAR

toCheck := 1;
result := toCheck;

IF result = stepStart THEN
   // DO something
END_IF

or you can use CASE

CASE result OF
stepIdle: // do something
stepStart: // do something
stepEnd:
    result := stepIdle;
END_CASE

Remarks

If you would deccribe what you are trying to achieve, I would give you a better suggestion.

Guiorgy
  • 1,405
  • 9
  • 26
Sergey Romanov
  • 2,949
  • 4
  • 23
  • 38
  • Yeah there was an error in the code, corrected. Yeah you got the point, I want like in PHP get the value of the constant dinamically, like the constant() function just to not repeat for each constant the same code. Sorry for late response – Massimo Jul 19 '20 at 10:14
  • @Paper-batDid my post helped you? – Sergey Romanov Jul 20 '20 at 11:31
  • yes, I have upvoted your response, but thats not solve the main question, thanks anyway – Massimo Jul 27 '20 at 09:05