I'll first describe the goal:
1. Have an outside device write into a variable of codesys.
2. Detect the variable in (1) has been changed.
3. After detection, make the modbus master write to another device via trigger.
what I've tried to do:
make a stuct with:
LastValue : BOOL; //linked to the another device in (3)
CurrentValue : BOOL; //linked to the outside device in (1)
Trigger : BOOL; //linked to the modbus master trigger
now i got a task where I do the following:
Trigger := FALSE;
IF (CurrentValue <> LastValue) THEN
LastValue := CurrentValue;
Trigger := TRUE;
END_IF
When i ran this code, the trigger didn't work as planned, meaning the modbus master didn't update me about the change.
i mainly suspect about the syncing of the tasks, one task runs the code above controlling the trigger and another task runs the modbus master module who checks the trigger rising edge and performs the writing action.
Questions:
1. how would you sync between the two tasks? how to control the trigger properly?
2. What type of scheduler protocol is being used, might help me understand the problem.
Thanks in advance for any help
Roy.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
after linking code program and the modbus module to the same task
and also found a bug i had with the program, the trigger worked well!
no need for different tasks.
adding the code i ran with:
TYPE Modbus_Data :
STRUCT
Old:ARRAY[0..15] OF BOOL := [16(FALSE)];
New:ARRAY[0..15] OF BOOL := [16(FALSE)];
Trigger:BOOL := FALSE;
END_STRUCT
END_TYPE
arrModbusData: ARRAY[0..1] OF Modbus_Data;
PROGRAM Modbus_programm
VAR
wordIndex : UINT;
bitIndex : UINT;
isTriggerNeeded : BOOL;
modbusDataArrayLength : int := SIZEOF(arrModbusData)/SIZEOF(Modbus_Data);
END_VAR
VAR CONSTANT
NUMBER_OF_BITS_IN_WORD : INT := 16;
END_VAR
isTriggerNeeded := FALSE;
FOR wordIndex:=0 TO modbusDataArrayLength -1 DO
arrModbusData[wordIndex].Trigger := FALSE;
FOR bitIndex:=0 TO NUMBER_OF_BITS_IN_WORD - 1 DO
IF(arrModbusData[wordIndex].New[bitIndex] <> arrModbusData[wordIndex].Old[bitIndex]) THEN
arrModbusData[wordIndex].Old[bitIndex] := arrModbusData[wordIndex].New[bitIndex];
isTriggerNeeded := TRUE;
END_IF;
END_FOR;
IF(isTriggerNeeded = TRUE) THEN
arrModbusData[wordIndex].Trigger := TRUE;
END_IF;
END_FOR;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi all,
I'll first describe the goal:
1. Have an outside device write into a variable of codesys.
2. Detect the variable in (1) has been changed.
3. After detection, make the modbus master write to another device via trigger.
what I've tried to do:
make a stuct with:
LastValue : BOOL; //linked to the another device in (3)
CurrentValue : BOOL; //linked to the outside device in (1)
Trigger : BOOL; //linked to the modbus master trigger
now i got a task where I do the following:
Trigger := FALSE;
IF (CurrentValue <> LastValue) THEN
LastValue := CurrentValue;
Trigger := TRUE;
END_IF
When i ran this code, the trigger didn't work as planned, meaning the modbus master didn't update me about the change.
i mainly suspect about the syncing of the tasks, one task runs the code above controlling the trigger and another task runs the modbus master module who checks the trigger rising edge and performs the writing action.
Questions:
1. how would you sync between the two tasks? how to control the trigger properly?
2. What type of scheduler protocol is being used, might help me understand the problem.
Thanks in advance for any help
Roy.
Reset the trigger in the other task.
after linking code program and the modbus module to the same task
and also found a bug i had with the program, the trigger worked well!
no need for different tasks.
adding the code i ran with:
TYPE Modbus_Data :
STRUCT
Old:ARRAY[0..15] OF BOOL := [16(FALSE)];
New:ARRAY[0..15] OF BOOL := [16(FALSE)];
Trigger:BOOL := FALSE;
END_STRUCT
END_TYPE
arrModbusData: ARRAY[0..1] OF Modbus_Data;
PROGRAM Modbus_programm
VAR
wordIndex : UINT;
bitIndex : UINT;
isTriggerNeeded : BOOL;
modbusDataArrayLength : int := SIZEOF(arrModbusData)/SIZEOF(Modbus_Data);
END_VAR
VAR CONSTANT
NUMBER_OF_BITS_IN_WORD : INT := 16;
END_VAR
isTriggerNeeded := FALSE;
FOR wordIndex:=0 TO modbusDataArrayLength -1 DO
arrModbusData[wordIndex].Trigger := FALSE;
FOR bitIndex:=0 TO NUMBER_OF_BITS_IN_WORD - 1 DO
IF(arrModbusData[wordIndex].New[bitIndex] <> arrModbusData[wordIndex].Old[bitIndex]) THEN
arrModbusData[wordIndex].Old[bitIndex] := arrModbusData[wordIndex].New[bitIndex];
isTriggerNeeded := TRUE;
END_IF;
END_FOR;
IF(isTriggerNeeded = TRUE) THEN
arrModbusData[wordIndex].Trigger := TRUE;
END_IF;
END_FOR;