Massimo
Massimo

Reputation: 573

CodeSys get constant value by name

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

Upvotes: 0

Views: 635

Answers (2)

Sergey Romanov
Sergey Romanov

Reputation: 3080

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.

Upvotes: 2

Filippo Boido
Filippo Boido

Reputation: 1206

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

Upvotes: 2

Related Questions