← Back to Blog

Structured Text (ST) Tutorial: PLC Programming Guide

August 6, 2026·14 min read·Tutorial

Structured Text (ST) is a high-level PLC programming language that looks like Pascal or C. It's part of the IEC 61131-3 standard and is the language of choice for complex calculations, data handling, and algorithms that would be unwieldy in Ladder Logic.

Why Structured Text?

Ladder Logic works great for discrete on/off control. But when you need:

  • Math operations (PID, scaling, unit conversions)
  • String manipulation
  • Complex state machines
  • Array and data table operations
  • Recipe management
  • Communication protocol handling

Structured Text is dramatically more readable and maintainable than trying to build the same logic in rungs.

Basic Syntax

Variables and Data Types

VAR
    MotorRunning : BOOL := FALSE;
    Temperature  : REAL := 0.0;
    BatchCount   : INT := 0;
    TankLevel    : REAL;
    AlarmActive  : BOOL;
    RecipeName   : STRING(50) := 'Default';
END_VAR

Common data types:

  • BOOL: TRUE or FALSE
  • INT: Integer (-32768 to 32767)
  • DINT: Double integer (-2,147,483,648 to 2,147,483,647)
  • REAL: Floating point number
  • STRING: Text
  • TIME: Duration (T#5s, T#100ms)

IF/THEN/ELSE

IF Temperature > 250.0 THEN
    HeaterOn := FALSE;
    AlarmHigh := TRUE;
ELSIF Temperature < 200.0 THEN
    HeaterOn := TRUE;
    AlarmHigh := FALSE;
ELSE
    HeaterOn := FALSE;
    AlarmHigh := FALSE;
END_IF;

CASE Statement

CASE MachineState OF
    0: // Idle
        MotorRunning := FALSE;
        ValveOpen := FALSE;
    1: // Filling
        ValveOpen := TRUE;
        IF TankLevel >= 95.0 THEN
            MachineState := 2;
        END_IF;
    2: // Processing
        MotorRunning := TRUE;
        IF ProcessTimer.Q THEN
            MachineState := 3;
        END_IF;
    3: // Draining
        ValveOpen := TRUE;
        MotorRunning := FALSE;
        IF TankLevel <= 5.0 THEN
            MachineState := 0;
            BatchCount := BatchCount + 1;
        END_IF;
END_CASE;

FOR Loop

// Calculate average of 10 sensor readings
Sum := 0.0;
FOR i := 1 TO 10 DO
    Sum := Sum + SensorReadings[i];
END_FOR;
Average := Sum / 10.0;

WHILE Loop

// Find first empty slot in array
i := 1;
WHILE (i <= 100) AND (Slots[i] <> 0) DO
    i := i + 1;
END_WHILE;
NextEmptySlot := i;

Real Example: PID Temperature Controller

VAR
    Setpoint     : REAL := 250.0;  // Target temperature
    ProcessValue : REAL;            // Actual temperature
    Output       : REAL;            // Heater output 0-100%
    Error        : REAL;
    Integral     : REAL := 0.0;
    Derivative   : REAL;
    LastError    : REAL := 0.0;
    Kp           : REAL := 2.0;    // Proportional gain
    Ki           : REAL := 0.5;    // Integral gain
    Kd           : REAL := 0.1;    // Derivative gain
    dt           : REAL := 0.1;    // Scan time in seconds
END_VAR

// PID calculation
Error := Setpoint - ProcessValue;
Integral := Integral + (Error * dt);
Derivative := (Error - LastError) / dt;

Output := (Kp * Error) + (Ki * Integral) + (Kd * Derivative);

// Clamp output 0-100%
IF Output > 100.0 THEN
    Output := 100.0;
    Integral := Integral - (Error * dt); // Anti-windup
ELSIF Output < 0.0 THEN
    Output := 0.0;
    Integral := Integral - (Error * dt); // Anti-windup
END_IF;

LastError := Error;
HeaterOutput := Output;

Real Example: Batch Sequence

CASE BatchStep OF
    10: // Fill reactor
        InletValve := TRUE;
        IF ReactorLevel >= RecipeLevel THEN
            InletValve := FALSE;
            BatchStep := 20;
        END_IF;

    20: // Heat to temperature
        HeaterEnable := TRUE;
        TempSetpoint := RecipeTemp;
        IF ReactorTemp >= (RecipeTemp - 2.0) THEN
            BatchStep := 30;
            HoldTimer(IN := TRUE, PT := RecipeHoldTime);
        END_IF;

    30: // Hold at temperature
        HoldTimer(IN := TRUE);
        IF HoldTimer.Q THEN
            HeaterEnable := FALSE;
            BatchStep := 40;
        END_IF;

    40: // Cool down
        CoolingValve := TRUE;
        IF ReactorTemp <= 50.0 THEN
            CoolingValve := FALSE;
            BatchStep := 50;
        END_IF;

    50: // Drain
        DrainValve := TRUE;
        IF ReactorLevel <= 2.0 THEN
            DrainValve := FALSE;
            BatchComplete := TRUE;
            BatchStep := 10;
        END_IF;
END_CASE;

When to Use ST vs Ladder Logic

Use Structured TextUse Ladder Logic
PID and math calculationsMotor start/stop circuits
State machines with many statesSimple interlocks
Recipe and data managementSafety circuits
Communication protocolsDiscrete I/O control
Array/string operationsWhen electricians maintain code

Writing ST in Plaxio

Plaxio's AI can generate Structured Text from plain English descriptions. Try prompts like:

  • "PID controller for oven temperature, setpoint 250°C"
  • "Batch sequence: fill to 80%, heat to 90°C, hold 30 minutes, cool to 40°C, drain"
  • "Scale 4-20mA input to 0-100 PSI with alarm at 85 PSI"

The generated code follows IEC 61131-3 syntax and can be exported to any supported vendor format. You can test it immediately in the built-in simulator.

Try Structured Text in Plaxio

Write ST with AI assistance and test in the built-in simulator. Free download, no signup.

Download Plaxio →