Structured text
Structured Text (ST) is a high-level, textual programming language defined in the IEC 61131-3 international standard for programmable logic controllers (PLCs), designed to facilitate the development of sophisticated control algorithms and data processing tasks in industrial automation environments.[1] Modeled closely after structured languages like Pascal, ST employs familiar programming constructs such as assignment statements, conditional branching (e.g., IF-THEN-ELSE and CASE), and iteration loops (e.g., FOR, WHILE, and REPEAT), enabling engineers to write readable, modular code that supports reusability and maintainability.[2] As one of two textual languages in the standard—alongside Instruction List (IL)—ST complements graphical counterparts like Ladder Diagram (LD) and Function Block Diagram (FBD), allowing for a unified approach to PLC programming across vendors.[3]
The IEC 61131-3 standard, first published in 1993 and updated through editions like the 2025 version, standardizes syntax and semantics for these languages to promote interoperability, portability, and vendor independence in automation systems.[1] ST's case-insensitive syntax uses semicolons to terminate statements and supports the creation of Program Organization Units (POUs), including functions, function blocks, and programs, which can invoke standard or user-defined operations for tasks ranging from simple logic to advanced mathematical computations.[3] Its roots in languages like Ada, Pascal, and C provide a powerful foundation for handling complex scenarios, such as sequential control and real-time data manipulation, while integrating seamlessly with hardware configurations defined in the broader IEC 61131 framework.[2]
In practice, ST enhances productivity in industrial settings by allowing developers to express algorithmic logic more intuitively than low-level assembly-like code, reducing development time and errors in applications like manufacturing, process control, and robotics.[2] Organizations such as PLCopen extend the standard through technical committees, ensuring ST evolves to meet modern demands, including XML-based project exchanges and enhanced safety features.[1] This language's adoption has grown with the rise of integrated development environments (IDEs) that support multi-language mixing, making it a cornerstone for reliable, scalable automation software.[3]
Overview
Definition and purpose
Structured Text (ST) is a text-based, high-level programming language defined in the IEC 61131-3 standard for programmable logic controllers (PLCs).[4] It forms part of a unified suite of programming languages that includes both textual and graphical options, specifically alongside Instruction List (IL) as the other textual language, and graphical languages such as Ladder Diagram (LD), Function Block Diagram (FBD), and Sequential Function Chart (SFC).[4] This standardization ensures interoperability and consistency in PLC programming across vendors and applications in industrial automation.[1]
The primary purpose of Structured Text is to enable the expression of complex algorithms and control logic in a structured manner for managing industrial processes, such as manufacturing lines or process control systems.[5] Drawing from Pascal-like syntax, it prioritizes readability and maintainability, allowing programmers to write clear, hierarchical code that is easier to debug and modify compared to graphical representations, which may become unwieldy for intricate logic.[1] By supporting features like conditional statements and loops, ST facilitates the development of modular programs that can handle sophisticated decision-making and repetitive tasks in real-time environments.[1]
Key characteristics of Structured Text include its purely textual format, which is compiled into machine code for efficient execution on PLC hardware, ensuring deterministic performance critical for automation reliability.[6] It emphasizes modular programming through elements like functions and function blocks, promoting code reuse and organization for large-scale control systems.[5] Within the IEC 61131-3 framework, ST complements graphical languages by offering a high-level alternative suited to software engineers familiar with traditional programming paradigms, while maintaining compatibility with the standard's common data types and execution models.[4]
History and standards
Structured Text (ST) emerged in the 1990s amid the growing complexity of industrial automation systems, which necessitated standardized programming methods for programmable logic controllers (PLCs) to ensure portability and interoperability across vendors. This development was driven by a European initiative under PLCopen, culminating in the International Electrotechnical Commission (IEC) 61131 series of standards.[7][8]
The IEC 61131-3 standard, first published in December 1993, formally defined ST as a high-level, textual programming language within a suite of five languages for PLCs, drawing inspiration from structured languages like Pascal for its syntax and control structures, and incorporating elements reminiscent of C for expressions and operations. This initial edition established ST's role in enabling algorithmic programming suitable for complex logic, distinct from graphical languages in the standard.[9][10][11][12]
The standard evolved through subsequent editions to address practical needs in automation. The second edition, released in 2003, provided a technical revision with clarifications and minor enhancements to syntax and semantics. The third edition in 2013 introduced significant extensions, including improved data types (such as strings and wide characters), conversion functions, references, namespaces, and object-oriented features like classes and inheritance, which bolstered library reusability and system interoperability. A fourth edition followed in 2025, further refining these elements.[9][4][13][14][15]
Adoption of ST via IEC 61131-3 accelerated in the late 1990s, with major PLC vendors integrating it into their platforms to meet global standardization demands. Siemens incorporated full support for ST and the other IEC languages in its STEP 7 and later TIA Portal environments. Rockwell Automation's Logix 5000 controllers, including ControlLogix and CompactLogix, comply with the standard, enabling ST alongside ladder logic in Studio 5000. Beckhoff's TwinCAT system fully implements IEC 61131-3, including ST, for PC-based control applications. This widespread implementation by leading manufacturers has made ST a cornerstone of modern PLC programming.[16][17][18][19]
Language features
Data types
Structured Text, as defined in the IEC 61131-3 standard, supports a range of elementary data types that form the foundation for variable declarations and operations. These include basic types such as BOOL for boolean values (true or false, occupying 1 bit), INT for 16-bit signed integers (range -32768 to 32767), DINT for 32-bit signed integers (range -2147483648 to 2147483647), REAL for 32-bit single-precision floating-point numbers, and STRING for variable-length text strings (up to 254 characters by default, or configurable up to 65535).[20]
Additionally, time-related elementary types handle temporal data: TIME represents time intervals (e.g., T#1h30m for 1 hour and 30 minutes), TIME_OF_DAY (TOD) denotes time of day with millisecond precision (range 00:00:00.000 to 23:59:59.999), and DATE_AND_TIME (DT) combines date and time (range 1601-01-01-00:00:00.000 to 9999-12-31-23:59:59.999).[20]
Derived data types build upon elementary types to create more complex structures. Arrays group elements of the same type, declared as ARRAY[lower_bound..upper_bound] OF base_type, such as ARRAY[1..10] OF [INT](/page/INT) for a 10-element integer array; multi-dimensional arrays like ARRAY[1..5, 1..3] OF REAL are also supported, with elements accessed via indices in square brackets (e.g., MyArray[1]).[21] Structures (STRUCT) aggregate heterogeneous elements into a single unit, using the syntax:
TYPE StructName :
STRUCT
member1 : type1;
member2 : type2;
END_STRUCT
END_TYPE
TYPE StructName :
STRUCT
member1 : type1;
member2 : type2;
END_STRUCT
END_TYPE
For example, a machine status structure might be defined as:
TYPE Machine :
STRUCT
speed : REAL;
status : BOOL;
END_STRUCT
END_TYPE
TYPE Machine :
STRUCT
speed : REAL;
status : BOOL;
END_STRUCT
END_TYPE
Members are accessed with dot notation (e.g., MyMachine.speed).[22]
Enumerated types provide named integer values for improved readability, declared via:
TYPE EnumName : (value1, value2, ...);
END_TYPE
TYPE EnumName : (value1, value2, ...);
END_TYPE
Values default to sequential integers starting from 0 (e.g., TYPE [State](/page/State) : (Idle, Running, [Error](/page/Error)); END_TYPE assigns Idle=0, Running=1, Error=2), or can be explicitly set (e.g., TYPE [State](/page/State) : (Idle := 0, Running := 1, [Error](/page/Error) := 2); END_TYPE). They can be prefixed for disambiguation (e.g., State#Running).[23]
Variables of any data type are declared within sections using keywords that define scope and access: VAR for local variables, VAR_INPUT for inputs, VAR_OUTPUT for outputs, VAR_IN_OUT for bidirectional parameters, and VAR_GLOBAL or VAR_EXTERNAL for globals. The syntax is name : type [:= initial_value];, enclosed in VAR ... END_VAR, such as:
VAR
counter : INT := 0;
message : STRING(20) := 'Hello';
END_VAR
VAR
counter : INT := 0;
message : STRING(20) := 'Hello';
END_VAR
Initial values are optional and set at startup; constants use VAR CONSTANT ... END_VAR. Declarations ensure type safety within their scope.[24]
Type conversions occur implicitly in compatible cases, such as widening INT to DINT without loss, but narrowing (e.g., DINT to INT) or floating-point to integer requires explicit handling to avoid undefined behavior. Explicit conversions use standard functions like TO_DINT(value) or INT_TO_REAL(value), which follow IEC 60559 rounding rules (e.g., 3.5 rounds to 4, 2.5 to 2 using banker's rounding). Overflow in integer conversions or precision loss in floating-point operations may trigger runtime errors or truncation, depending on the implementation.[25]
Operators and expressions
Structured Text (ST) supports a variety of operators for performing computations on operands such as variables, constants, and function calls, forming expressions that evaluate to a result of a compatible data type. Expressions follow the syntax and semantics defined in the IEC 61131-3 standard, with evaluation proceeding from left to right for operators of equal precedence, and parentheses used to override the default order.[26][27]
Arithmetic operators in ST include addition (+), subtraction (-), multiplication (*), division (/), and modulo (MOD), applicable to numeric types like INT, DINT, REAL, and LREAL. For integer types, division truncates the result toward zero, such that 5 / 2 yields 2, while for REAL types, it produces a floating-point result like 2.5. The modulo operator returns the remainder of integer division, as in 15 MOD 4 equaling 3. Exponentiation (**) is also supported for numeric types, computing powers such as 2 ** 3 resulting in 8. Unary negation (-) applies to numeric operands, inverting their sign.[28][29][26]
Logical operators operate on BOOL types and include AND, OR, XOR, and unary NOT, yielding a BOOL result. For example, TRUE AND FALSE evaluates to FALSE, while NOT TRUE is FALSE. These operators do not support short-circuit evaluation, meaning both operands are always computed regardless of the left operand's value. Bitwise operations on bit-string types (e.g., BYTE, WORD) use symbols like & for AND, | for OR, and ^ for XOR, but the core standard emphasizes word-based logical operators for BOOL without bitwise symbols in primary expressions.[28][27][26]
Comparison operators return a BOOL based on relational evaluations between compatible types, including equality (=), inequality (<>), less than (<), greater than (>), less than or equal (<=), and greater than or equal (>=). For instance, 93.9 >= 100.0 is FALSE, and 5 <> 3 is TRUE. These apply to numeric, string, and time types, with string comparisons being lexicographical.[28][30]
Operator precedence in ST is hierarchical to determine evaluation order without parentheses: unary NOT and negation (-) have the highest precedence, followed by exponentiation (**); then multiplication (*), division (/), and modulo (MOD); then addition (+) and subtraction (-); next come relational comparisons (<, >, <=, >=); equality (=, <> ) follows; then logical AND; XOR; and OR has the lowest precedence. Operators of equal precedence are evaluated left-to-right. A compound expression like a := b * (c + d) first computes the parenthesized sum, then multiplies, and assigns the result.[28][26][30]
The assignment operator (:=) forms statements by binding an expression's value to a variable, as in var1 := var2 + 10, which is side-effect free except for the assignment itself. String concatenation uses the || operator, appending strings like "Hello" || " World" to yield "Hello World". Expressions must be type-compatible, with implicit or explicit conversions applied where possible, but overflow or underflow behavior depends on the target PLC hardware. Vendor extensions may add operators like short-circuit AND_THEN or OR_ELSE, but these are not part of the core IEC 61131-3 standard.[26][27][30]
Programming constructs
Control structures
Structured Text provides control structures for implementing conditional execution, selection based on values, and iteration over sequences or conditions, enabling algorithmic control flow in PLC programs as defined in the IEC 61131-3 standard.[28] These structures evaluate conditions that must resolve to the BOOL data type, ensuring precise branching and looping behaviors.[31] Nesting of control structures is permitted, allowing complex logic within proper scoping, while statements like BREAK are not supported outside loops.[32]
Conditional Statements
The IF-THEN-ELSIF-ELSE-END_IF construct handles conditional execution by evaluating a boolean expression and executing corresponding statements. The basic form is IF condition THEN statement; END_IF;, where the condition is a BOOL expression; if true, the statement executes, otherwise it is skipped.[28] Multiple alternatives use ELSIF clauses, such as IF condition1 THEN statement1; ELSIF condition2 THEN statement2; ELSE statement3; END_IF;, providing fallback execution in the ELSE branch if no prior condition holds.[31] For example, to control a pump based on valve states: IF ControlValve1_Closed = FALSE AND ControlValve1_Open = TRUE THEN Pump_Start := TRUE; ELSE Pump_Start := FALSE; END_IF;.[32] This structure supports nesting, as an inner IF can appear within the statements of an outer one, maintaining readability through indentation.
Selection Statements
The CASE selector OF ... END_CASE statement enables multi-way selection based on a numeric expression's value, comparing it against listed cases for execution. The syntax is CASE selector OF case1: statement1; case2: statement2; ... [ELSE](/page/The_Else) statement; END_CASE;, where the selector evaluates to an integer type, and the first matching case executes its statements.[28] Ranges are supported for concise handling of consecutive values, denoted as low..high, such as 1..5: statement;.[31] An ELSE clause provides default handling for unmatched values. For instance, managing motor states: CASE MotorState OF 0: MotorSpeed := 0; 1..2: MotorSpeed := 500; [ELSE](/page/The_Else) ErrorMessage := 'Invalid'; END_CASE;.[31] Only one case executes per evaluation, and the structure does not permit overlapping ranges.
Iteration Statements
Iteration in Structured Text includes FOR, WHILE, and REPEAT loops for repeating statements under controlled conditions. The FOR loop iterates a counter variable over a range: FOR index := start TO end DO statement; END_FOR;, where index increments from start to end (inclusive) in steps of 1 by default.[28] An optional BY clause specifies the step size, e.g., FOR i := 1 TO 10 BY 2 DO Result := Result + i; END_FOR;, allowing decrement (BY -1) or custom increments.[31]
The WHILE loop repeats while a BOOL condition remains true: WHILE condition DO statement; END_WHILE;, checking the condition before each iteration to prevent execution if initially false.[32] For example, WHILE Temperature < 100 DO HeatInput := TRUE; END_WHILE;.[31] In contrast, the REPEAT loop executes at least once before checking: REPEAT statement; UNTIL condition; END_REPEAT;, terminating when the BOOL condition becomes true. An example is REPEAT Counter := Counter + 1; UNTIL Counter >= 10; END_REPEAT;.[28]
Exit Statements
Loops support early termination via EXIT, which immediately ends the enclosing FOR, WHILE, or REPEAT loop upon execution.[31] Placed conditionally within the loop body, such as IF some_condition THEN [EXIT](/page/Exit); END_IF;, it skips remaining iterations without affecting outer structures.[28] EXIT is invalid outside loops, ensuring controlled flow. RETURN terminates execution of the POU and returns control to the caller with syntax RETURN;. For functions, the return value is the current assignment to the function name. It is usable in functions, function blocks, and programs.[32][33] These statements enhance flexibility without introducing unstructured jumps.
Functions and function blocks
In Structured Text (ST), functions represent pure procedures that encapsulate reusable operations and return a single value without maintaining internal state between calls. They are defined using the syntax FUNCTION <name> : <return_type>, followed by variable declarations such as VAR_INPUT for inputs and VAR_OUTPUT for outputs, the body of statements (with the return value assigned to the function name), optionally including a RETURN; statement to exit early, and END_FUNCTION.[33] This design ensures functions are deterministic and side-effect-free, promoting modularity in PLC programming.
Parameters in functions are passed by value for VAR_INPUT (read-only) and by reference for VAR_IN_OUT (bidirectional), with no support for default values in the core IEC 61131-3 standard. Outputs via VAR_OUTPUT are assigned within the body and do not require explicit passing. Functions can be invoked directly in expressions, such as result := <function_name>(arg1, arg2), or using the CAL statement for more explicit calls like CAL <function_name>(arg1 := value1);.
Function blocks extend modularity by allowing reusable code with persistent internal state, making them suitable for modeling components like timers or counters. The syntax is FUNCTION_BLOCK <name>, including VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, and VAR sections for local variables, followed by the body and END_FUNCTION_BLOCK; state variables can be qualified with RETAIN to persist across power cycles. Unlike functions, function blocks require instantiation as objects, such as declaring my_instance : <block_type>;, and are called via instance_name(params), where parameters follow the same value/reference rules as functions without defaults.
Programs serve as top-level executable units in ST, organizing the overall application logic without a return value. They use the syntax PROGRAM <name>, with optional variable sections and a body of statements ending in END_PROGRAM, and can invoke functions and function blocks within their code. Programs are instantiated within PLC resources and executed cyclically or via tasks, facilitating the integration of modular elements into complete control applications.
For reuse across projects, functions, function blocks, and programs can be packaged into libraries using the LIBRARY declaration, which includes elements like standard functions (e.g., ADD) and user-defined blocks, enabling import and instantiation without redefinition. This library mechanism supports extensible inputs and outputs in standard blocks, enhancing interoperability in industrial automation systems.
Examples and applications
Basic program examples
Structured Text (ST) provides a textual, high-level programming language for PLCs, allowing developers to implement simple logic using familiar constructs like conditional statements and loops, as defined in the IEC 61131-3 standard.[34] Basic programs typically begin with variable declarations to define inputs, outputs, and local variables, ensuring type safety and scope control within program organization units (POUs).[28]
A fundamental example is a basic counter program, which demonstrates variable declarations and assignment. The following code snippet declares variables in a VAR block for a counter that increments on each scan when an input is active:
PROGRAM Counter_Example
VAR
Reset_Button : BOOL AT %IX0.0; (* Input for reset *)
Count_Enable : BOOL AT %IX0.1; (* Input to enable counting *)
Counter : INT := 0; (* Local counter variable *)
Output_Counter : INT AT %QW0.0; (* Output to display count *)
END_VAR
IF Reset_Button THEN
Counter := 0;
ELSIF Count_Enable THEN
Counter := Counter + 1;
END_IF;
Output_Counter := Counter;
PROGRAM Counter_Example
VAR
Reset_Button : BOOL AT %IX0.0; (* Input for reset *)
Count_Enable : BOOL AT %IX0.1; (* Input to enable counting *)
Counter : INT := 0; (* Local counter variable *)
Output_Counter : INT AT %QW0.0; (* Output to display count *)
END_VAR
IF Reset_Button THEN
Counter := 0;
ELSIF Count_Enable THEN
Counter := Counter + 1;
END_IF;
Output_Counter := Counter;
This program resets the counter to zero when the reset button is pressed or increments it when counting is enabled, assigning the value to an output for monitoring.[28]
For conditional logic, a simple IF statement can check a temperature threshold to set an alarm. Consider this example, where an analog input represents temperature:
IF Temperature > 100 THEN
Alarm := TRUE;
ELSE
Alarm := FALSE;
END_IF;
IF Temperature > 100 THEN
Alarm := TRUE;
ELSE
Alarm := FALSE;
END_IF;
Here, Temperature is assumed to be a REAL variable from an input, and Alarm is a BOOL output; the statement evaluates the condition sequentially during program execution.[34]
Iteration is handled via a FOR loop, useful for processing arrays, such as summing values in a fixed-size array:
Sum := 0.0;
FOR i := 0 TO 9 DO
Sum := Sum + Array_Values[i];
END_FOR;
Sum := 0.0;
FOR i := 0 TO 9 DO
Sum := Sum + Array_Values[i];
END_FOR;
In this case, Sum is a REAL accumulator, i is the loop index (INT), and Array_Values is an ARRAY[0..9] OF REAL; the loop runs from 0 to 9, adding each element without explicit bounds checking in the basic form.[34]
ST programs execute within the PLC's scan cycle, a repetitive process defined in IEC 61131-3 implementations, consisting of three main phases: reading input states, executing the program logic (including ST statements from top to bottom), and updating output states based on results. This cyclic execution ensures deterministic behavior, with the scan time typically in milliseconds, influenced by program complexity.[35]
Basic error handling in ST often involves explicit range validation using IF statements to prevent invalid operations, such as checking sensor values before processing:
IF Value >= 0.0 AND Value <= 100.0 THEN
Processed_Value := Value * 2.0;
Error_Flag := FALSE;
ELSE
Error_Flag := TRUE;
END_IF;
IF Value >= 0.0 AND Value <= 100.0 THEN
Processed_Value := Value * 2.0;
Error_Flag := FALSE;
ELSE
Error_Flag := TRUE;
END_IF;
This approach sets an error flag for out-of-range inputs (Value as REAL), avoiding runtime issues in simple applications without relying on advanced exception mechanisms.[28]
Advanced programming examples
Advanced programming in Structured Text (ST) often involves function blocks that encapsulate complex control algorithms, such as proportional-integral-derivative (PID) controllers, which maintain a process variable at a desired setpoint by adjusting an output based on error calculations. A PID function block typically declares inputs for the setpoint and process value, maintains an internal integral term for accumulated error, and computes an output control value using proportional, integral, and derivative terms. For instance, the following ST code defines a PID function block according to IEC 61131-3, where the integral term is handled via an INTEGRAL sub-block, and calculations occur cyclically without explicit loops, though WHILE loops can be incorporated for iterative tuning if needed.[36]
FUNCTION_BLOCK PID
VAR_INPUT
ACTUAL : REAL; (* Process value *)
SET_POINT : REAL; (* Setpoint *)
KP : REAL; (* Proportional gain *)
TN : REAL; (* Integral time *)
TV : REAL; (* Derivative time *)
Y_MANUAL : REAL;
Y_OFFSET : REAL;
Y_MIN : REAL;
Y_MAX : REAL;
MANUAL : BOOL;
RESET : BOOL;
END_VAR
VAR_OUTPUT
Y : REAL; (* Control value *)
LIMITS_ACTIVE : BOOL;
OVERFLOW : BOOL;
END_VAR
VAR
CLOCK : TON;
I : INTEGRAL; (* Internal integral state *)
D : DERIVATIVE;
TMDIFF : DWORD;
ERROR : REAL;
INIT : BOOL := TRUE;
Y_ADDOFFSET : REAL;
END_VAR
(* Calculations: Error computation and PID terms *)
ERROR := SET_POINT - ACTUAL;
I(IN := TRUE, X0 := ERROR, T := TN, Y => Y_ADDOFFSET); (* Integral accumulation *)
(* Additional proportional and derivative terms follow, with output limiting *)
IF MANUAL THEN Y := Y_MANUAL; ELSE Y := (KP * ERROR) + Y_ADDOFFSET + (D(Y)); END_IF;
IF Y > Y_MAX THEN Y := Y_MAX; LIMITS_ACTIVE := TRUE; END_IF;
IF Y < Y_MIN THEN Y := Y_MIN; LIMITS_ACTIVE := TRUE; END_IF;
END_FUNCTION_BLOCK
FUNCTION_BLOCK PID
VAR_INPUT
ACTUAL : REAL; (* Process value *)
SET_POINT : REAL; (* Setpoint *)
KP : REAL; (* Proportional gain *)
TN : REAL; (* Integral time *)
TV : REAL; (* Derivative time *)
Y_MANUAL : REAL;
Y_OFFSET : REAL;
Y_MIN : REAL;
Y_MAX : REAL;
MANUAL : BOOL;
RESET : BOOL;
END_VAR
VAR_OUTPUT
Y : REAL; (* Control value *)
LIMITS_ACTIVE : BOOL;
OVERFLOW : BOOL;
END_VAR
VAR
CLOCK : TON;
I : INTEGRAL; (* Internal integral state *)
D : DERIVATIVE;
TMDIFF : DWORD;
ERROR : REAL;
INIT : BOOL := TRUE;
Y_ADDOFFSET : REAL;
END_VAR
(* Calculations: Error computation and PID terms *)
ERROR := SET_POINT - ACTUAL;
I(IN := TRUE, X0 := ERROR, T := TN, Y => Y_ADDOFFSET); (* Integral accumulation *)
(* Additional proportional and derivative terms follow, with output limiting *)
IF MANUAL THEN Y := Y_MANUAL; ELSE Y := (KP * ERROR) + Y_ADDOFFSET + (D(Y)); END_IF;
IF Y > Y_MAX THEN Y := Y_MAX; LIMITS_ACTIVE := TRUE; END_IF;
IF Y < Y_MIN THEN Y := Y_MIN; LIMITS_ACTIVE := TRUE; END_IF;
END_FUNCTION_BLOCK
This block integrates seamlessly into larger programs, where persistent variables declared with VAR RETAIN maintain state across power cycles, ensuring the integral term does not reset during outages.[36]
In a main program, multiple function blocks are called with named parameters for clarity, often within control structures like CASE to select operational modes. For example, a motor control program might invoke a motor_control block based on a mode selector, processing inputs like target speed while integrating PID outputs for precise regulation. The CASE statement evaluates the mode and executes corresponding block calls or logic.[37][38]
PROGRAM MainProgram
VAR
Mode : INT;
TargetSpeed : REAL := 1500.0;
MotorFB : motor_control; (* Instance of motor function block *)
END_VAR
CASE Mode OF
0: (* Manual mode *)
MotorFB(Enable := TRUE, Speed := TargetSpeed);
1: (* Auto mode with PID *)
PID_Instance(SET_POINT := TargetSpeed, ACTUAL := CurrentSpeed);
MotorFB(Enable := PID_Instance.Y > 0, Speed := PID_Instance.Y);
ELSE (* Emergency stop *)
MotorFB(Enable := FALSE);
END_CASE;
END_PROGRAM
PROGRAM MainProgram
VAR
Mode : INT;
TargetSpeed : REAL := 1500.0;
MotorFB : motor_control; (* Instance of motor function block *)
END_VAR
CASE Mode OF
0: (* Manual mode *)
MotorFB(Enable := TRUE, Speed := TargetSpeed);
1: (* Auto mode with PID *)
PID_Instance(SET_POINT := TargetSpeed, ACTUAL := CurrentSpeed);
MotorFB(Enable := PID_Instance.Y > 0, Speed := PID_Instance.Y);
ELSE (* Emergency stop *)
MotorFB(Enable := FALSE);
END_CASE;
END_PROGRAM
ST's support for arrays and structures enables efficient processing of sensor data in machine monitoring applications, where a STRUCTURE defines a composite type for related measurements, and arrays store multiple instances for batch analysis. For instance, a sensor data structure might encapsulate temperature and pressure readings, with an array of such structures updated from inputs and processed to detect anomalies, such as averaging values over time for trend monitoring. This approach organizes complex data hierarchically, facilitating scalable control in industrial systems.[6][39]
TYPE SensorReading :
STRUCT
Temperature : REAL;
Pressure : REAL;
Timestamp : DT;
END_STRUCT
END_TYPE
VAR
Sensors : ARRAY[1..10] OF SensorReading; (* Array for multiple sensors *)
AvgTemp : REAL;
i : INT;
END_VAR
FOR i := 1 TO 10 DO
Sensors[i].Temperature := RealFromInput(%IW[i]); (* Read sensor data *)
Sensors[i].Timestamp := DT_NOW;
END_FOR;
AvgTemp := 0.0;
FOR i := 1 TO 10 DO
AvgTemp := AvgTemp + Sensors[i].Temperature;
END_FOR;
AvgTemp := AvgTemp / 10.0; (* Process for monitoring *)
IF AvgTemp > 80.0 THEN (* Trigger alarm */ END_IF;
TYPE SensorReading :
STRUCT
Temperature : REAL;
Pressure : REAL;
Timestamp : DT;
END_STRUCT
END_TYPE
VAR
Sensors : ARRAY[1..10] OF SensorReading; (* Array for multiple sensors *)
AvgTemp : REAL;
i : INT;
END_VAR
FOR i := 1 TO 10 DO
Sensors[i].Temperature := RealFromInput(%IW[i]); (* Read sensor data *)
Sensors[i].Timestamp := DT_NOW;
END_FOR;
AvgTemp := 0.0;
FOR i := 1 TO 10 DO
AvgTemp := AvgTemp + Sensors[i].Temperature;
END_FOR;
AvgTemp := AvgTemp / 10.0; (* Process for monitoring *)
IF AvgTemp > 80.0 THEN (* Trigger alarm */ END_IF;
These examples illustrate ST's capability for stateful, integrated programs that combine reusable blocks with data structures for real-world automation tasks.[36]
Comparisons and usage
Advantages and limitations
Structured Text (ST) offers high readability for complex algorithms due to its textual format, which allows for concise expression of mathematical operations, loops, and conditional logic using familiar syntax similar to high-level languages like Pascal or C.[40] This readability is enhanced by support for comments and optional indentation, making it suitable for algorithm-intensive tasks in industrial automation.[32] Additionally, ST supports structured programming paradigms, including procedures, functions, and modular code organization, which promote reusability and maintainability in large-scale applications.[41]
Debugging in ST is facilitated by its text-based nature, enabling use of standard editors for modifications and integration with integrated development environments (IDEs) that provide syntax highlighting and variable monitoring.[32] It is particularly efficient for mathematical computations, as it handles data types like arrays and real numbers with operators for arithmetic and logical operations, often outperforming graphical languages in execution speed for complex calculations by 15-25%.[42] The 2025 edition of IEC 61131-3 introduces enhancements to ST, including UTF-8 string support (USTRING and UCHAR types) for better international portability, synchronization primitives like mutexes and semaphores for concurrent execution in multi-core systems, and the ASSERT function for improved validation during development.[15] In industry, ST is preferred by software engineers for large-scale automation systems, such as process control in manufacturing, where its flexibility aids in developing sophisticated control strategies.[32]
Despite these strengths, ST presents a steep learning curve for non-programmers, such as electricians accustomed to relay-based or graphical representations, as it requires familiarity with textual syntax and programming concepts.[40] It is less intuitive for such users compared to visual languages, potentially hindering adoption in maintenance-heavy environments.[41] The absence of graphical aids increases the potential for syntax errors, such as missing semicolons or mismatched brackets, which can complicate troubleshooting without specialized tools.[40]
ST also has limited real-time guarantees inherent to the language itself, relying on vendor-specific tools and hardware for deterministic execution in time-critical applications. Compilation overhead is higher than for graphical languages due to the need for parsing and validating textual code, leading to longer build times in development cycles.[40] Although standardized under IEC 61131-3, portability across vendors remains challenging owing to proprietary extensions, environment dependencies, and differences in library implementations, often requiring code adjustments for full compatibility.[43][17]
Comparison to other PLC languages
Structured Text (ST), a high-level textual programming language defined in the IEC 61131-3 standard, differs from other PLC languages in its support for procedural constructs like loops and conditionals, making it suitable for algorithmic tasks, while graphical languages emphasize visual representation of control flows.[44] In contrast to Ladder Diagram (LD), which is graphical and mimics relay-based logic for discrete control and Boolean operations, ST excels in expressing complex algorithms and data manipulations through structured syntax similar to Pascal or Ada, though LD remains preferred for simple I/O mapping and troubleshooting due to its intuitive circuit-like visuals.[44][40]
Compared to Function Block Diagram (FBD), another graphical language focused on signal flows and interconnections between reusable blocks for process-oriented applications, ST offers greater flexibility for recursion and handling complex data structures without relying on visual wiring, though FBD provides clearer visualization of data dependencies in continuous control systems.[44][45] Versus Sequential Function Chart (SFC), which graphically models state machines through steps and transitions for sequential processes like batch operations, ST is better suited for detailed procedural code within those steps, such as calculations, while SFC prioritizes high-level sequencing and team communication.[44][46]
Relative to Instruction List (IL), a low-level textual language akin to assembly code that was part of earlier editions of the standard and produces compact instructions for time-critical logic, ST provides higher readability and abstraction through features like functions and variables, reducing error proneness in larger programs; however, IL was removed from IEC 61131-3 in the 2025 edition and is now considered legacy.[44][46][15] Hybrid usage of ST with other languages is common in modern PLC environments, where ST handles computational tasks invoked within LD rungs for relay logic or FBD sheets for modularity; for instance, Siemens TIA Portal integrates all IEC 61131-3 languages, allowing seamless mixing such as embedding ST function blocks in LD programs to leverage each language's strengths without vendor-specific limitations.[46][47]