0

The compiler gives an error for the following program. I can't solve it.

This is the Codesys system writing it in ST language. I want to operate a solenoid valve using bit operation.

CanRx := can_getDatabox (CAN_2, 10, ADR(CanRx_data), ADR(CanRxNumBytes));
Rx_test_1 := CanRx_data[1];
Rx_test_2 := CanRx_data[2];
Rx_test_3 := CanRx_data[3];
Rx_test_4 := CanRx_data[4];

IF(Rx_test_1 & 4 = 4)THEN
  out (OUT_1_POH_CL, 1500);
  ELSE IF(Rx_test_1 & 8 = 8)THEN
  out (OUT_1_POH_CL, 0);
END_IF

Compiler error:

 Error: 4011:Callback_MAIN_Task(XX): Type mismatch in parameter 1 of 'AND':Cannot convert 'INT' to 'ANY_BIT'  
 Error: 4024:Callback_MAIN_Task(XX): Expecting END_IF_before"
Dai
  • 141,631
  • 28
  • 261
  • 374

2 Answers2

1

The documentation for ST's operators says that the comparison and equality operators <, >, <=, >=, =, and <> have a higher precedence than boolean logic operators and bitwise logic operators.

Also, in ST bitwise logic operators are AND and OR instead of & and |. Similarly, the boolean logic operators are AND_THEN and OR_ELSE instead of && and ||. (beware though, that the boolean logic operator were added to CODESYS compiler V3.5 SP4, if you are using an older one, they won't be available. For example, SoMachine uses an older one)

Additionally, the syntax for IF is as follows:

IF condition THEN
    statement1;
ELSEIF condition THEN
    statement2;
ELSE
    statement3;
END_IF;

But your code has ELSE IF instead of ELSEIF and your END_IF is lacking a semicolon. (Though I have never had any compiler complain if I skipped that, and they themselves often omit them in their examples in the documentation)

So, you just need to parenthesize the bitwise operation before the comparison. (It's the same situation in C-family languages too, which leads to unreadable expressions with too many parentheses), replace them with valid ST operators, and fix the ELSE IF part.

Try incorporating those changes, like so:

(Note I also added whitespace for readability. ST does not impose any semantics on whitespace (unlike Python, Haskell, etc) so you should use whitespace to maximize readability and maintainability). (My personal style is to have spaces within parentheses, not outside them - other people strongly disagree, YMMV)

IF ( ( Rx_test_1 AND 4 ) = 4 ) THEN

    out ( OUT_1_POH_CL, 1500 );

ELSEIF ( ( Rx_test_1 AND 8 ) = 8 ) THEN

    out ( OUT_1_POH_CL, 0 );

END_IF;
Guiorgy
  • 1,405
  • 9
  • 26
Dai
  • 141,631
  • 28
  • 261
  • 374
  • Thank you for your advice. Certainly your code is easy to read.However, the problem could not be solved. There may be a problem with the data type, but I'm not really sure about "Error: 4024: Callback_MAIN_Task (XX): Expecting END_IF_before". – Taro NAKAMURA Nov 20 '20 at 08:45
  • @TaroNAKAMURA Is the compiler error message the same with my changes? (note the paren around `Rx_test_1 & 4`) – Dai Nov 20 '20 at 08:46
  • @TaroNAKAMURA I also corrected the `ELSE IF` / `ELSEIF` and added another semicolon. Please try my code now and report back the **exact** compiler error. – Dai Nov 20 '20 at 08:49
  • Tihs is additional error. Error 4253:Callback_MAIN_Task(XX): 'IF' or 'ELSIF' require 'Bool' expresson as condition – Taro NAKAMURA Nov 20 '20 at 08:51
  • Error: 4024:Callback_MAIN_Task(XX): Expecting ')' before '&' Error: 4024:Callback_MAIN_Task(XX): Expecting ')' before '4' Error: 4253:Callback_MAIN_Task(XX): 'IF' or 'ELSIF' require 'Bool' expresson as condition Error: 4024:Callback_MAIN_Task(XX): Expecting THEN before ')' – Taro NAKAMURA Nov 20 '20 at 08:57
  • All errors are point this code line. IF ( ( Rx_test_1 & 4 ) = 4 ) THEN – Taro NAKAMURA Nov 20 '20 at 09:02
  • There's no `&` or `|` in ST, instead you have to use `AND` and `OR` (those are bit operators. The equivalent of `&&` and `||` in other languages is `AND_THEN` and `OR_ELSE` in ST). Also, I have yet to run into a compiler that enforces a semicolon (`;`) at the end of `END_IF`, so you can ignore that – Guiorgy Nov 20 '20 at 14:11
  • @Guiorgy I was helped by your explanation. The additional information about bit operations helped me further my studies. Thank you. – Taro NAKAMURA Nov 20 '20 at 14:26
1

I was able to solve it myself. I used AND instead of &, used ELSIF insted of ELSEIF. Here is the correct code.

Rx_test_1 : BYTE;

IF ((Rx_test_1 AND 1) =1) THEN
   statement1;
ELSIF (( Rx_test_1 AND 2) =1) THEN
   statement2;
ELSIF (( Rx_test_1 AND 4) =1) THEN
   statement3;
ELSE
   statement4;
END_IF