How is Structured Text programming done in CoDeSys?

Variables, conditions and cyclic execution in a CODESYS Structured Text program

How do you program in Structured Text with CODESYS?

Structured Text (ST) is a PLC programming language that expresses control logic as text. It is defined within IEC 61131-3 and supported by the CODESYS platform. Conditions, calculations and block calls are written as statements. Learning ST involves more than syntax: you also need to understand how a task executes those statements repeatedly.

ST is one of the programming languages available in CODESYS. This guide follows the CODESYS Development System V3 layout; menu names can vary with the version and manufacturer package. When downloading CODESYS, check which version your device manufacturer supports. The following examples are intended for learning in simulation, with no variables mapped to physical outputs.

1. Prepare the project and ST program

Use File → New Project to select an appropriate project template. For a standard project, choose the target device and programming language. When creating a project for real hardware, you need a compatible controller and the appropriate device packages. Simulation can be used for the initial logic exercise.

Under Application, use Add Object → POU to add a program organisation unit. Select Program as its type and Structured Text (ST) as its language. If the project already contains an ST program named PLC_PRG, you can use it. An important point in PLC programming is that a program object can exist without being called. We will check its task connection separately.

2. Separate declarations from implementation

The ST editor has a declaration area for variables and an implementation area for executable statements. Keep the PROGRAM line created by the editor. Place the following VAR block in the declaration area, replacing an existing empty VAR block if necessary. Among the available data types, BOOL represents TRUE or FALSE.

Declaration area:

VAR
    xSwitch : BOOL := FALSE;
    xPermit : BOOL := FALSE;
    xLight  : BOOL := FALSE;
END_VAR

Implementation area:

IF xSwitch AND xPermit THEN
    xLight := TRUE;
ELSE
    xLight := FALSE;
END_IF;

xSwitch represents the switch request, xPermit a software permission, and xLight the result variable. The result is TRUE when both inputs are TRUE. xPermit is only an educational variable here, not a safety circuit. Read the program by asking: which condition causes which value to be assigned?

Expected results for the first example
xSwitch xPermit xLight
FALSE FALSE FALSE
TRUE FALSE FALSE
FALSE TRUE FALSE
TRUE TRUE TRUE

3. “:=” assigns a value; “=” compares values

xLight := TRUE; assigns a value to the variable. xSwitch = TRUE is an equality comparison. AND requires both conditions to be true, OR requires at least one, and NOT gives the logical opposite. When learning ST statements and operators, distinguish these roles instead of transferring assumptions from another programming language.

The first example can also be expressed with the following single statement. Use it in place of the IF block:

xLight := xSwitch AND xPermit;

In the longer version, ELSE explicitly sets the result to FALSE when the condition is not satisfied. If ELSE is removed and nothing else assigns the variable, xLight can retain its previous TRUE value. A condition becoming false does not automatically reset a variable.

4. Connect the program to a cyclic task

Under Task Configuration, a Cyclic task must include your program in its Program Calls list. Select it using Add Call if necessary; do not add a duplicate of an existing call. Task scheduling determines when the program executes.

For this small simulation exercise, an interval such as T#20ms can be used. The condition is evaluated on each call. This interval is not a universal recommendation for real machines. Waiting inside a WHILE loop for a sensor is also different from cyclic execution: a long or endless loop occupies the task and can trigger its execution-time monitoring.

5. Run the simulation and observe the result

Use Build → Generate Code, or F11, to generate the application code. Resolve errors shown in the message view. Then enable Online → Simulation, use Online → Login to log in to the simulated device, and confirm creation of the simulated application if prompted. Debug → Start, or F5, puts the application into RUN.

During debugging, prepare values for xSwitch and xPermit in the declaration area's Prepared Value column. Apply them with Debug → Write Values, or Ctrl+F7. First set only xSwitch to TRUE, then set xPermit to TRUE as well. Check that xLight follows the table, then set the permission variable back to FALSE.

Write Values performs a one-time write; a variable assigned by the program may change again on the next call. Change the input variables for this exercise and let the program produce the result. Simulation does not operate real I/O channels or send fieldbus telegrams: testing the logic and verifying the hardware are separate stages.

6. A second example: Count sensor transitions, not sensor states

In projects such as part counting, increasing a counter on every task call while the sensor is TRUE can count one item repeatedly. The CTU block counts a FALSE → TRUE transition at its CU input. Function blocks are used through instances that retain their own state.

Create a separate Program POU, for example PRG_CountDemo, select ST and add it to the cyclic task. Check that the Standard library is present in Library Manager. Place the following sections in that program's declaration and implementation areas.

Counter program declarations:

VAR
    xSensor        : BOOL := FALSE;
    xReset         : BOOL := FALSE;
    xBatchComplete : BOOL := FALSE;
    fbCounter      : CTU;
END_VAR

Counter program implementation:

fbCounter(CU := xSensor, RESET := xReset, PV := WORD#5);
xBatchComplete := fbCounter.Q;

fbCounter.CV is the count; Q becomes TRUE when CV reaches or exceeds the target. PV specifies the target, and RESET resets the count. With xReset FALSE, set xSensor to TRUE and leave it there: the first transition counts once, while remaining TRUE does not represent another item. Write FALSE, then TRUE again in a later trial. After five transitions, xBatchComplete becomes TRUE.

7. What changes when you move to a real PLC?

Variables must be mapped to physical channels in the input and output modules. Assess the sensor's electrical signal, sampling interval and pulse duration separately; this simple program cannot recover short pulses missed between task calls. For network connections and data transfer, check device support, addresses and data types.

Configure the communication settings for the real target and assess how the download or online change options shown at login will affect its existing application. CODESYS security also involves access permissions and project backups. Before connecting a physical output, verify the expected behaviour, task call and I/O mapping individually.

Official technical references: Program object, IF statement, simulation and the CTU counter block.