Reputation: 573
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
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.
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];
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
If you would deccribe what you are trying to achieve, I would give you a better suggestion.
Upvotes: 2
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