创建定时循环结构化文本
Create Timed For Loop Structured Text
我正在尝试创建一个具有时间延迟的 FOR TO 循环。但它似乎无法正常工作我无法弄清楚错误在哪里,但似乎循环 运行s 完全没有考虑时间延迟。
FOR vCount := 0 TO 800 DO
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
所以我预计这个循环会占用 801 秒。因此,每一秒都有一个新值被添加到数组中。但是当我 运行 代码在短时间后(例如 1 秒)我已经在数组中有 801 个值,所以计时器不工作。
我已经用 TON 尝试过代码,现在我在这个论坛上找到了 FB Blink,但它仍然不起作用。
谁能帮帮我
BINK
和 TON
不像“等待”或“延迟”那样工作,程序将卡在上面直到到达时间)。当时间到时,将触发输出位(Q、OUT、OUTPUT 或其他取决于您使用的库),但您应该在每个程序周期处理它,连续地等待输出。
更好的处理PLC程序的方法是它永远不应该停止,它应该总是运行,然后在流程中做出决定。
因此,由于这个延迟,FOR
不是最好的方法...状态机是您可以使用的一个好概念。
由于您没有指定程序的启动方式,它包含一个 bStart
位来控制何时开始循环。
VAR
bStart : BOOL;
vVsample : ARRAY [0 .. 800] OF REAL;
vVin : WORD;
fbTon : TON;
bStartTimer : BOOL := FALSE;
vCount : INT := 0;
vState : INT := 0;
END_VAR
//The timer is processed continuously
fbTon(IN := bStartTimer, PT := T#1S);
//State Machine
CASE vState OF
0 : //Start the Timer
IF bStart THEN
bStartTimer := TRUE;
//Go to State 10 (Wait Timer)
vState := 10;
END_IF
10 : //Wait for the timer
IF fbTon.Q AND vCount <= 800 THEN
//Set value and increment counter
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount + 1;
//Reset the timer in the next cycle
bStartTimer := FALSE;
//Return to state 0
vState := 0;
END_IF
//Checks if reached the end of the array
IF vCount > 800 THEN
//reset flags
bStartTimer := FALSE;
bStart := FALSE;
vCount := 0;
//Return to state 0
vState := 0;
END_IF
END_CASE
您似乎对 CODESYS 运行 代码的使用方式存在误解。与 C/C++ 等代码从上到下执行一次的语言不同,在 codesys 中,代码每秒执行多次,只要控制器有电(在我工作的 PLC 上,它被执行每 20 毫秒,换句话说,每秒 50 次)。
因此,您无法拥有 stall/delay 执行的函数。计时器在 CODESYS 中的实际作用是,它们会记住您第一次调用它们的时间,然后在每次调用时它们只会检查经过了多少时间(它们不会停止!)。一旦设定的时间过去,他们会在他们的输出上升起一个标志,这样你就可以执行一些任务。
所以让我们分解一下当您 运行 您的代码时会发生什么:
// first run:
FOR vCount := 0 TO 800 DO
// on first itewration (vCount = 0) this will remember the current time,
// however it won't stop here and it will continue to the next line.
// on next iterations (vCount >= 1) the timer will check the elapsed time,
// which will be 0, so it will do nothing and continue to the next line.
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
// the timer just started so bSignal is FALSE
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
// second run:
FOR vCount := 0 TO 800 DO
// the timer will compare current time to the recorded first time.
// the elapsed time is below the target, so skip to the next line.
// this will be repeated 800 times for no good reason...
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
// the timer hasn't reached target time so bSignal is FALSE
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
// the above will reapeat for another 48 cycles
// 50th run:
FOR vCount := 0 TO 800 DO
// the timer will compare current time to the recorded first time.
// the elapsed time has reached the target 1 second (TIMELOW := T#1s),
// so it will raise the OUT flag to TRUE.
// the comparison will happen on every 800 iterations, and every time
// it will be set to TRUE.
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
// since bSignal is TRUE on every iteration, ener the if for every element.
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
如果您想要每秒向数组添加一个值,那么您可以这样做(请注意,这不会停止/stall/delay 执行和之后的代码这仍将每隔 运行 执行一次。如果不需要,您必须单独处理):
timer(IN := vCount <> 801, PT := T#1S); // timer is TON
IF (timer.Q) THEN
timer(IN := FALSE); // reset the timer so it starts counting again nextr run
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount + 1; // increment the counter
END_IF
我正在尝试创建一个具有时间延迟的 FOR TO 循环。但它似乎无法正常工作我无法弄清楚错误在哪里,但似乎循环 运行s 完全没有考虑时间延迟。
FOR vCount := 0 TO 800 DO
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
所以我预计这个循环会占用 801 秒。因此,每一秒都有一个新值被添加到数组中。但是当我 运行 代码在短时间后(例如 1 秒)我已经在数组中有 801 个值,所以计时器不工作。
我已经用 TON 尝试过代码,现在我在这个论坛上找到了 FB Blink,但它仍然不起作用。
谁能帮帮我
BINK
和 TON
不像“等待”或“延迟”那样工作,程序将卡在上面直到到达时间)。当时间到时,将触发输出位(Q、OUT、OUTPUT 或其他取决于您使用的库),但您应该在每个程序周期处理它,连续地等待输出。
更好的处理PLC程序的方法是它永远不应该停止,它应该总是运行,然后在流程中做出决定。
因此,由于这个延迟,FOR
不是最好的方法...状态机是您可以使用的一个好概念。
由于您没有指定程序的启动方式,它包含一个 bStart
位来控制何时开始循环。
VAR
bStart : BOOL;
vVsample : ARRAY [0 .. 800] OF REAL;
vVin : WORD;
fbTon : TON;
bStartTimer : BOOL := FALSE;
vCount : INT := 0;
vState : INT := 0;
END_VAR
//The timer is processed continuously
fbTon(IN := bStartTimer, PT := T#1S);
//State Machine
CASE vState OF
0 : //Start the Timer
IF bStart THEN
bStartTimer := TRUE;
//Go to State 10 (Wait Timer)
vState := 10;
END_IF
10 : //Wait for the timer
IF fbTon.Q AND vCount <= 800 THEN
//Set value and increment counter
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount + 1;
//Reset the timer in the next cycle
bStartTimer := FALSE;
//Return to state 0
vState := 0;
END_IF
//Checks if reached the end of the array
IF vCount > 800 THEN
//reset flags
bStartTimer := FALSE;
bStart := FALSE;
vCount := 0;
//Return to state 0
vState := 0;
END_IF
END_CASE
您似乎对 CODESYS 运行 代码的使用方式存在误解。与 C/C++ 等代码从上到下执行一次的语言不同,在 codesys 中,代码每秒执行多次,只要控制器有电(在我工作的 PLC 上,它被执行每 20 毫秒,换句话说,每秒 50 次)。
因此,您无法拥有 stall/delay 执行的函数。计时器在 CODESYS 中的实际作用是,它们会记住您第一次调用它们的时间,然后在每次调用时它们只会检查经过了多少时间(它们不会停止!)。一旦设定的时间过去,他们会在他们的输出上升起一个标志,这样你就可以执行一些任务。
所以让我们分解一下当您 运行 您的代码时会发生什么:
// first run:
FOR vCount := 0 TO 800 DO
// on first itewration (vCount = 0) this will remember the current time,
// however it won't stop here and it will continue to the next line.
// on next iterations (vCount >= 1) the timer will check the elapsed time,
// which will be 0, so it will do nothing and continue to the next line.
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
// the timer just started so bSignal is FALSE
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
// second run:
FOR vCount := 0 TO 800 DO
// the timer will compare current time to the recorded first time.
// the elapsed time is below the target, so skip to the next line.
// this will be repeated 800 times for no good reason...
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
// the timer hasn't reached target time so bSignal is FALSE
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
// the above will reapeat for another 48 cycles
// 50th run:
FOR vCount := 0 TO 800 DO
// the timer will compare current time to the recorded first time.
// the elapsed time has reached the target 1 second (TIMELOW := T#1s),
// so it will raise the OUT flag to TRUE.
// the comparison will happen on every 800 iterations, and every time
// it will be set to TRUE.
fbBlink(ENABLE := TRUE, TIMELOW := T#1s, TIMEHIGH := T#1s, OUT => bSignal);
// since bSignal is TRUE on every iteration, ener the if for every element.
IF bSignal THEN
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_IF
END_FOR
如果您想要每秒向数组添加一个值,那么您可以这样做(请注意,这不会停止/stall/delay 执行和之后的代码这仍将每隔 运行 执行一次。如果不需要,您必须单独处理):
timer(IN := vCount <> 801, PT := T#1S); // timer is TON
IF (timer.Q) THEN
timer(IN := FALSE); // reset the timer so it starts counting again nextr run
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount + 1; // increment the counter
END_IF