Loops in TwinCAT: Breaking Down Struc­tured Text Iterations

Iteration is a core concept in programming, and Structured Text (ST) provides a variety of loop types to implement it. However, when working with TwinCAT, understanding the behavior of loops—especially the FOR-loop—can be trickier than it seems. This article offers a concise introduction to TwinCAT loops and their peculiarities.

FOR-Loop

The FOR-loop is an entry-controlled loop that executes statements repeatedly until the <counter> meets the specified end condition:

  • Without a <step size expression>: Loop stops when the <counter> is greater than the <end condition expression>.
  • With a positive <step size expression>: Loop stops when the <counter> exceeds the <end condition expression>.
  • With a negative <step size expression>: Loop stops when the <counter> is below the <end condition expression>.

The following components must be or return an integer:

  • <counter>, <initial expression>, <end condition expression>, and <step size expression>:
    • ANY_BIT: BYTE, WORD, DWORD, LWORD, __XWORD
    • ANY_INT: SINT, USINT, INT, UINT, DINT, UDINT, LINT, ULINT, __XINT, or __UXINT

After each execution of the loop’s <instructions>, the <counter> is automatically incremented by the value of the <step size expression>. If no step size is specified, the default step size is 1.

noun-information-6735183-FFFFFF_edited
The <end condition expression> must not match the upper or lower limits of the <counter> data type, as this could result in an endless loop due to overflow.
noun-information-6735183-FFFFFF_edited
The EXIT-statement is used to jump out of a loop.
noun-information-6735183-FFFFFF_edited
The CONTINUE-statement interrupts the current iteration and proceeds with the next iteration of the loop.

Syntax

FOR <counter> := <initialization expression> TO <end condition expression> [BY <step size expression>] DO
<instruction>
[CONTINUE;]
[EXIT;]
[<instructions>]
END_FOR

noun-information-6735183-FFFFFF_edited
The parts in square brackets are optional.

Flowchart

Flowchart of a FOR-loop
noun-information-6735183-FFFFFF_edited
The <step size expression> is evaluated three times per loop cycle because of a fully evaluated OR. The <end condition expression> is evaluated once per cycle without <step size expression> and twice per cycle with <step size expression>.

Examples

Simple Examples
VAR
	i :LINT;
	squares :ARRAY[0..20] OF LINT;
END_VAR
VAR
	FIRST_SQUARE :LINT := LOWER_BOUND(squares,1);
	LAST_SQUARE :LINT := UPPER_BOUND(squares,1);
END_VAR
FOR i := FIRST_SQUARE TO LAST_SQUARE DO	
	squares[i] := i*i;
END_FOR
Example with Pointer Operations
VAR
	foo : T_MaxString := 'Hello foo';
	bar : POINTER TO BYTE;
	baz : PVOID;
	inverseFoo : T_MaxString;
END_VAR
(* clean the memory before we start *)
Tc2_System.MEMSET(ADR(inverseFoo),0,TO_UDINT(Tc2_Standard.LEN(foo)+1));
(* store the inverse content of foo in inverseFoo *)
FOR baz := bar := ADR(foo) + TO___UXINT(MAX(Tc2_Standard.LEN(foo)-1,0)) TO ADR(foo) BY -1 DO
	bar := baz;
	inverseFoo := Tc2_Standard.CONCAT(inverseFoo, CHR(bar^));
END_FOR
Example with a Reference
VAR
	foo :REFERENCE TO UDINT;
	baz :ARRAY[0..25] OF UDINT;
	bar :UDINT := TO_UDINT(LOWER_BOUND(baz,1));
	barz :UDINT := 12;
END_VAR
(* The array baz will only once initialize until the value of bar is set to 0 again *)
FOR foo REF= bar TO TO_UDINT(UPPER_BOUND(baz,1)) DO
	baz[foo] := barz * foo;
END_FOR
Example with EXIT and CONTINUE
VAR
	actBit :DINT;
	bar :WORD;
	highestSetBit :DINT(-1..15);
END_VAR
(* For loop finds the number of the highest set bit *)
FOR actBit := 15 TO 0 BY -1 DO
	IF (bar = 0) THEN
		highestSetBit := -1;
		EXIT;
	END_IF
	IF ((bar AND SHL(1,actBit)) = 0) THEN
		CONTINUE;
	END_IF
	highestSetBit := actBit;
	EXIT;
END_FOR
Example with Complex Expressions
VAR
	values :ARRAY[0..20] OF WORD;
	a,b,c,d  :WORD;
END_VAR
(*
for loop that calculates the fibonacci sequence up to 100.
- the init expression is called only once
	- the expression (a := c := d := 0) returns 0 so b is initailized with 1 and b is the counter varibale
- the condition expression is called twice per cycle
	- the expression (0 AND (c := (d := d + 1) / 2)) returns 0 because of the bitwise AND 0 but it increments d by two and c by one every loop cycle because it is called twice per loop cycle
- the step size expression will be called three times per loop cycle a is the (c-1)th fibonacci number and b is the (c+1)th fibonacci number   
*)
FOR b := 1 + (a := c := d := 0) TO 100 * 3 + (0 AND (c := (d := d + 1) / 2)) BY (a := b - a) DO	
	values[c - 1] := a;
END_FOR

WHILE-Loop

The WHILE-loop is an entry-controlled loop that executes statements repeatedly until the <condition expression> returns FALSE.

noun-information-6735183-FFFFFF_edited
The EXIT-statement is used to jump out of a loop.
noun-information-6735183-FFFFFF_edited
The CONTINUE-statement interrupts the current iteration and proceeds with the next iteration of the loop.

Syntax

WHILE <condition expression> D
<instruction>
[CONTINUE;]
[EXIT;]
[<instructions>]
END_WHILE

noun-information-6735183-FFFFFF_edited
The parts in square brackets are optional.

Flowchart

Flowchart of a WHILE-loop

Examples

Simple Example
VAR
	i :LINT;
	squares :ARRAY[0..20] OF LINT;
END_VAR
VAR
	FIRST_SQUARE :LINT := LOWER_BOUND(squares,1);
	LAST_SQUARE :LINT := UPPER_BOUND(squares,1);
END_VAR 
i := FIRST_SQUARE;
WHILE (i <= LAST_SQUARE) DO
	squares[i] := i*i;
	i := i+1;
END_WHILE
Example with CONTINUE and EXIT
VAR
	actBit :DINT;
	bar :WORD;
	highestSetBit :DINT(-1..15);
END_VAR
ctBit := 15;
(* While loop finds the number of the highest set bit *)
WHILE (actBit >= 0) DO
	IF (bar = 0) THEN
		highestSetBit := -1;
		EXIT;
	END_IF
	IF ((bar AND SHL(1,actBit)) = 0) THEN
		actBit := actBit -1;
		CONTINUE;
	END_IF
	highestSetBit := actBit;
	EXIT;
END_WHILE

REPEAT-Loop

The REPEAT -loop is a variant of the WHILE-loop. This loop will execute the code block once, before checking if the <condition expression> is TRUE. Then it will repeat the loop as long as the <condition expression> returns FALSE.

noun-information-6735183-FFFFFF_edited
The EXIT-statement is used to jump out of a loop.
noun-information-6735183-FFFFFF_edited
The CONTINUE-statement interrupts the current iteration and proceeds with the next iteration of the loop.

Syntax

REPEAT
<instruction>
[CONTINUE;]
[EXIT;]
[<instructions>]
UNTIL
<condition expression>
END_REPEAT

noun-information-6735183-FFFFFF_edited
The parts in square brackets are optional.

Flowchart

Flowchart of a REPEAT-loop

Examples

Simple Example
VAR
	i :LINT;
	squares :ARRAY[0..20] OF LINT;
END_VAR
VAR
	FIRST_SQUARE :LINT := LOWER_BOUND(squares,1);
	LAST_SQUARE :LINT := UPPER_BOUND(squares,1);
END_VAR
i := FIRST_SQUARE;
REPEAT
	squares[i] := i*i;
	i := i+1;
UNTIL
	(i > LAST_SQUARE)
END_REPEAT
Example with CONTINUE and EXIT
VAR
	actBit :DINT;
	bar :WORD;
	highestSetBit :DINT(-1..15);
END_VAR
actBit := 15;
(* While loop finds the number of the highest set bit *)
REPEAT
	IF (bar = 0) THEN
		highestSetBit := -1;
		EXIT;
	END_IF
	IF ((bar AND SHL(1,actBit)) = 0) THEN
		actBit := actBit -1;
		CONTINUE;
	END_IF
	highestSetBit := actBit;
	EXIT;
UNTIL
	(actBit < 0)
END_REPEAT
For more insights on this topic, check out our in-depth video on loops in TwinCAT on YouTube here.

@Ninjamonkeystutorials