The fear of FOR TO and WHILE loops

andepand

Member
Join Date
Jan 2017
Location
Amsterdam
Posts
72
Hi everybody,

For a while I’ve been wondering, in every plc forum where the use of loops come to discussion I find most people answering that it’s best to stay away from them and that there are better, easier and mostly less scan time demanding solutions out there. Why is that?

I mostly program in ST and in many projects I make use of lots of arrays combined with lots of FOR TO loops and in my experience they’re the next best thing.

Why would referencing data from an array of 40 Dwords using a FOR X:= 0 TO 40 DO loop be any more scan time demanding then the PLC scanning through 40 rungs of statments?

Just curious if I’m missing something here.

Cheers
 
Last edited:
Hi everybody,

For a while I’ve been wondering, in every plc forum where the use of loops come to discussion I find most people answering that it’s best to stay away from them and that there are better, easier and mostly less scan time demanding solutions out there. Why is that?

I mostly program in ST and in many projects I make use of lots of arrays combined with lots of FOR TO loops and in my experience they’re the next best thing.

Why would referencing data from an array of 40 Dwords using a FOR X:= 0 TO 40 DO loop be any more scan time demanding then the PLC scanning through 40 rungs of statments?

Just curious if I’m missing something here.

Cheers

If you mess up and put your PLC into an infinite loop, you trigger a watchdog timeout and hard fault the whole process. In the olden days, that situation could even lock you out of communicating with the PLC, you might even have to use a keyswitch and put the thing in stop mode the "break" the infinite loop.

If you use a concise and elegant solution with looping, it can be difficult to troubleshoot, since it might be difficult the see a single instance of the contained logic executing "live" on your monitoring screen.

The execution of the loop will be slightly slower than the brute force method of 40 nearly identical rungs. Not a big deal on modern fast machines, but could add several (or dozens of) milliseconds to the scan time of an old PLC. If the execution of the entire loop is conditional, this can create a scan cycle that is inconsistent, with large spikes that occur in the scan time only when that code is executed. This is not usually an issue with modern controllers, but depending on the other functions of the machine, could create problems with older, slower CPUs.

Trying to enter 40 nearly identical rungs can lead to a mistake, where it is less likely if you re-use the exact logic inside a loop.

Using loops can save the programmer a lot of time developing logic, but that time will often be paid back triple explaining it to others.

I use loops occasionally, for data handling purposes, almost never for actual machinery logic.
 
Last edited:
If the situation allowed I always tried to create a loop with on itiration per scan. If I needed slightly faster response I created logic to allow up to x iterations in a single scan. Though slightly more complex to code the impact on scan became minimal.


In general the triggering information for a lookup loop was available well before the answer was needed. In another system the very complex information buried in a QR code was extracted with many string operations taking place one per scan. The result was available with no observable delay in the process.
 
Sure, a simple loop is ok in ST.
Your programmer makes a mistake and puts
Code:
I : SINT; //-128 to 127

FOR I := 0 TO 255 DO
  ARRAY1[I] := I;
END_FOR;

never ending loop? Out of array bounds?
And then maintenance tries to troubleshoot sensor 12, and sees it is written to from ARRAY1[12], but there are no references anywhere in the code to ARRAY1[12].

You also might have a loop that is of variable length, perhaps a WHILE statement that waits for something. During commissioning this loop might take only 500μs, but might grow to 50ms when you increase the size of the loop.

You might want to look at scripting some of your code creation. In Rockwell you can copy and paste rungs into Excel or notepad, copy them and then use Excel to change the array elements automatically. CODESYS will let you use python scripts to generate code.

And as to your question about speed
Try writing the assembly equivalent of my above code example but with a UDINT now so you don't have those issues.

For a given I value you must:
Get the address of I.
Get the value at address I
Put the value on stack
Get address I again
Get the value at address I
Get the address of Array1
Add I to this address (maybe check here that you don't have array out of bounds)
Store stack value at this address
Get I address again
Get value of I
Add 1
Store at fixed address
Get I address again
Compare to 255
Conditional jump to previous code position

If you're not looping though:
Array1[12] := 12; //load 12. Store at fixed address
 
I use the for next loops in plc ladder logic for alarm messaging on displays.
if the word is blank, goto a label that increments the word and keep scanning.
if the bit is blank, do the same.
I do not loop back, I increment and keep scanning.
that way, the watch dog timer never triggers an error.

james
 
Hi everybody,

For a while I’ve been wondering, in every plc forum where the use of loops come to discussion I find most people answering that it’s best to stay away from them and that there are better, easier and mostly less scan time demanding solutions out there. Why is that?


1) Most people on most PLC forums are of the opinion that just about all code you write should be understandable by the electrician (not coder) who will be debugging the machine later on. In general, people recommend avoiding ST, and using LAD only (at least in the USA).



The fact that this recommendation is pretty much correct frustrates me to no end.


2) Loops have a lot of the same problems with jump statements and indirect addressing in LAD: it makes the machine much harder to for an electrician to troubleshoot, regardless how convenient it is for the programmer.
 
I use the for next loops in plc ladder logic for alarm messaging on displays.
if the word is blank, goto a label that increments the word and keep scanning.
if the bit is blank, do the same.
I do not loop back, I increment and keep scanning.
that way, the watch dog timer never triggers an error.

james

Isn’t the whole loop executed before the plc continues scanning the next statement?
That way it shouldn’t matter if you’re looping forward or backward, or am I wrong here?

Offcourse I see the problem of wrong use of a loop and the fact that monitoring isn’t as easy as with ladder logic (watch window helps though).

But I still don’t seem to understand why it apparently takes more time incrementing a loop and using it’s value in a bunch of statements instead of using the plc scan to execute the same statements written out and executed one by one.
 
But I still don’t seem to understand why it apparently takes more time incrementing a loop and using it’s value in a bunch of statements instead of using the plc scan to execute the same statements written out and executed one by one.

Under the hood, the PLC program must contain a label or marker of some sort to jump back to, keep track of the number of iterations, and perform a compare at each "Next" statement. Those little things are multiplied by the number of iterations, so maybe they total to a fraction of a millisecond in 2019, in 1998, that might have been an extra 8 milliseconds or more. In any case, that extra processing take an amount of time greater than zero, which is more than what the sequential rungs require if written out separately. So looping is less efficient for the CPU, but can be more efficient for the keyboard magician.
 
1) Most people on most PLC forums are of the opinion that just about all code you write should be understandable by the electrician (not coder) who will be debugging the machine later on. In general, people recommend avoiding ST, and using LAD only (at least in the USA).



The fact that this recommendation is pretty much correct frustrates me to no end.


2) Loops have a lot of the same problems with jump statements and indirect addressing in LAD: it makes the machine much harder to for an electrician to troubleshoot, regardless how convenient it is for the programmer.

In case of electricians troubleshooting the plc, that is a valid point.

Here in Holland, and in my experience in Germany also, electricians pretty much stay away from plc’s. Troubleshooting usually stops there and if necessary a software engineer is brought to the scene, or hardware is replaced.

It’s usually the department that created the software that troubleshoots the software.

Cultural differences I guess ;)


Lots of info so far btw, thanks folks
 
Last edited:
the way I write the for next loop is this.

you have 21 words ( 20 words are used, #21 is a trap to keep from faulting the plc).

plc ladder logic

I do not use the sign bit !
if word x >= 21 then word = 1
if word x = 0 go to next-word
other plc ladder logic if the word <> 0

next-word label rung
word = word + 1

ladder logic
end of program

regards,
james
 
I'm using loops mainly for stuff like the script below. So, since I'm hardly a programming specialist, how would this translate to a non loop or non ST program?

Code:
FOR Loop1:= 0 TO 31 DO  (*Move camera data to folder register input*)
                               
   IF Production_mode AND NOT Cam_or AND Cycle_p_406mm_1 THEN  (*Camera must send error ("or" input) if no data is read*)

   	IF Camera_data_in[Loop1 *2]  = 49 THEN  (*Keyence camera sends ascii in two words, therefore loop variable *2  *)
        	Folder_reg_bit[Loop1]:= TRUE; (*Reg bit is a Bool array of the first word in the register*)
        ELSE Folder_reg_bit[Loop1]:= FALSE;
        END_IF;
   ELSE Folder_reg_bit[Loop1]:= FALSE;

   END_IF;
                
 END_FOR;
              
IF Cycle_p_203mm THEN (*160 DWORD shift register for 32 bit data*)
	
	FOR Loop2:= 160 TO 0 BY -1 DO
        Folder_register[(Loop2+1)]:= Folder_register[Loop2];
        
	END_FOR;
END_IF;
 
I'm using loops mainly for stuff like the script below. So, since I'm hardly a programming specialist, how would this translate to a non loop or non ST program?

Code:
FOR Loop1:= 0 TO 31 DO  (*Move camera data to folder register input*)
                               
   IF Production_mode AND NOT Cam_or AND Cycle_p_406mm_1 THEN  (*Camera must send error ("or" input) if no data is read*)

   	IF Camera_data_in[Loop1 *2]  = 49 THEN  (*Keyence camera sends ascii in two words, therefore loop variable *2  *)
        	Folder_reg_bit[Loop1]:= TRUE; (*Reg bit is a Bool array of the first word in the register*)
        ELSE Folder_reg_bit[Loop1]:= FALSE;
        END_IF;
   ELSE Folder_reg_bit[Loop1]:= FALSE;

   END_IF;
                
 END_FOR;
              
IF Cycle_p_203mm THEN (*160 DWORD shift register for 32 bit data*)
	
	FOR Loop2:= 160 TO 0 BY -1 DO
        Folder_register[(Loop2+1)]:= Folder_register[Loop2];
        
	END_FOR;
END_IF;

This is a pretty perfect example of what you would want to use a loop for. However if you find that the scan time is getting too bogged down with your loop, you can instead manually increment the loop variable each scan. Then you would be doing a single register per scan instead of all registers in one scan.
 
Code:
//FOR Loop1:= 0 TO 31                 
   Good := Production_mode AND NOT Cam_or AND Cycle_p_406mm_1;  (*Camera must send error ("or" input) if no data is read*)

Folder_reg_bit[0] := Good AND (Camera_data_in[0]  = 49);
Folder_reg_bit[1] := Good AND (Camera_data_in[2]  = 49);
//...
Folder_reg_bit[31] := Good AND (Camera_data_in[62]  = 49);

                
 //END_FOR;
              
IF Cycle_p_203mm THEN (*160 DWORD shift register for 32 bit data*)
  COP(Folder_register[0] , TempArray[0], 161);
  COP(TempArray[0], Folder_register[1] , 161);
END_IF;
 
Wouldn't let me edit, but here's an example of what i was talking about:
Code:
(*Move camera data to folder register input*)
IF Loop1 > 31 THEN Loop1 := 0; END_IF;                 

              
IF Production_mode AND NOT Cam_or AND Cycle_p_406mm_1 THEN  (*Camera must send error ("or" input) if no data is read*)
  IF Camera_data_in[Loop1 *2]  = 49 THEN  (*Keyence camera sends ascii in two words, therefore loop variable *2  *)
    Folder_reg_bit[Loop1]:= TRUE; (*Reg bit is a Bool array of the first word in the register*)
  ELSE Folder_reg_bit[Loop1]:= FALSE;
  END_IF;
ELSE Folder_reg_bit[Loop1]:= FALSE;
END_IF;
                
Loop1 := Loop1 + 1;
 

Similar Topics

Good Afternoon , My biggest fear came true. I lost a USB stick that had my RS Logix 5000 activation on it . What is the best way to get...
Replies
8
Views
7,144
Hello The plant is running and there is no shutdown nowadays therefore I can add 1734- AENTR and its card while PLC is in Run? I do not wanna...
Replies
8
Views
332
I have an issue with Power Flex 525 during running processing, the VFD stopped suddenly while the PLC and VFD connection ok, VFD does not have any...
Replies
1
Views
106
Hello! When trying to load the hardware configuration I get error 0050-133 2 2458, check the diagnostic buffer. When checking the buffer, it says...
Replies
4
Views
174
Can the following be made into a SINGLE Ladder so it could be incorporated with more ladder code and then made into an AOI? I have been trying...
Replies
26
Views
1,145
Back
Top Bottom