简体   繁体   English

创建定时循环结构化文本

[英]Create Timed For Loop Structured Text

Im trying to create a FOR TO loop that has a time delay.我试图创建一个有时间延迟的 FOR TO 循环。 But it doesn't seem to work correctly I can't figure out where the error is, but it seems that the loop runs intirely and doesnt look to the time delay.但它似乎无法正常工作我无法弄清楚错误在哪里,但似乎循环完全运行并且没有考虑时间延迟。

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

So I would expect that this loop would take up 801 seconds.所以我预计这个循环会占用 801 秒。 And therefore each second a new value is added to the array.因此,每一秒都有一个新值被添加到数组中。 But when I run the code after a short time (eg 1 sec) I have allready 801 values in the array, so the timer doesnt work.但是当我在短时间(例如 1 秒)后运行代码时,数组中已经有 801 个值,所以计时器不起作用。

I have tried codes with TON and now I found on this forum the FB Blink but still it doesn't work.我已经尝试使用 TON 编写代码,现在我在这个论坛上找到了 FB Blink,但它仍然不起作用。

Could anybody help me out谁能帮帮我

BINK and TON do not work like a "Wait" or "Delay", where the program will be stuck on it until the time is reached). BINKTON不像“等待”或“延迟”那样工作,程序将停留在它上面直到到达时间)。 When the time is up an output bit will be triggered (Q, OUT, OUTPUT or other depending on the library you use), but you should be processing it every program cycle, continuously, waiting for the output.当时间到时,将触发 output 位(Q、OUT、OUTPUT 或其他取决于您使用的库),但您应该在每个程序周期连续处理它,等待 output。

A better way to handle a PLC program is that it should never stop, it should always be running, and then make decisions in the flow.处理 PLC 程序的更好方法是它永远不应该停止,它应该一直运行,然后在流程中做出决定。

So, because of this Delay, FOR would not be the best approach... A good concept for you to use is State Machine.因此,由于这种延迟, FOR不是最好的方法......您可以使用的一个好概念是 State 机器。

Since you didn't specify how your program starts, it includes a bStart bit to control when to start the loop.由于您没有指定程序如何启动,因此它包含一个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

You seem to have a misconception on how CODESYS runs the code.您似乎对 CODESYS 如何运行代码有误解。 Unlike languages such as C/C++ where the code gets executed once from top to bottom, in codesys the code is executed many times a second as long as theres power to the controller (on the PLC I work, it is executed every 20 milliseconds, or in other words 50 times a second).与 C/C++ 等代码从上到下执行一次的语言不同,在 codesys 中,代码每秒执行多次,只要 controller 有电(在我工作的 PLC 上,它每 20 毫秒执行一次,或者换句话说每秒 50 次)。

Because of that, you can't have functions that stall/delay execution.因此,您不能拥有停止/延迟执行的功能。 What timers actually do in CODESYS, is they remember the time you first called them, and then on every call they just check how much time passed (they don't stall.), Once the set time passes.计时器在 CODESYS 中的实际作用是,它们会记住您第一次调用它们的时间,然后在每次调用时它们只会检查经过了多少时间(它们不会停止),一旦设定的时间过去了。 they'll raise a flag on their output so you can perform some task.他们会在他们的 output 上竖起一面旗帜,这样您就可以执行一些任务。

So let's break down what happens when you run your code:因此,让我们分解一下运行代码时发生的情况:

// 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

If what you want is to add a value to the array once a second, then here's how you may do it (Do note, that this won't stop/stall/delay the execution and the code after this will still be executed every run. If that's undesired, you have to handle that separately):如果您想要每秒向数组添加一个值,那么您可以这样做(请注意,这不会停止/停止/延迟执行,此后的代码仍将在每次运行时执行. 如果这是不需要的,你必须单独处理):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM