Skip to content

23Structured programs

Structs and enumerations

Defining your own types with TYPE and STRUCT, enumerations for state names, and why State := Filling beats State := 1 every single time.

Lesson 23 of 3411 minIEC 61131-3

From loose variables to one thing

Every transmitter in the plant carries the same companions: a value, limits, a validity flag. With separate variables:

LT101_Value : REAL;
LT101_HiLim : REAL;
LT101_LoLim : REAL;
LT101_Bad   : BOOL;
LT102_Value : REAL;
LT102_HiLim : REAL;
(* ... and so on for forty transmitters *)

A hundred and sixty variables, and adding one field means editing forty places.

STRUCT

TYPE T_Analog :
STRUCT
  Value : REAL;
  HiLim : REAL;
  LoLim : REAL;
  Bad   : BOOL;
  HiAlm : BOOL;
END_STRUCT
END_TYPE

Then:

VAR
  LT101 : T_Analog;
  LT102 : T_Analog;
END_VAR

LT101.Value := RawLevel;
LT101.HiAlm := LT101.Value > LT101.HiLim;

Dot access, exactly like reading T1.Q from a timer. A fifth field is written once in the TYPE and appears on all forty.

Vendors call this a UDT, a user-defined type. It is also what lets a whole group of signals travel as one unit into a function block or out to the HMI.

Enumerations

This is where readability is really won. A state machine in numbers:

IF State = 2 THEN
  ...
ELSIF State = 5 THEN

What is 2? What is 5? You know today. You will not know in a year, and the technician opening the program at night never will. An enumeration gives the numbers names:

TYPE E_TankState : (
  Idle,
  Filling,
  Holding,
  Draining,
  Fault
);
END_TYPE

VAR
  State : E_TankState;
END_VAR

State := Filling;

CASE State OF
  Idle:
    ...
  Filling:
    ...
  Draining:
    ...
END_CASE;

Why the name beats the number

  • It reads itself. IF State = Draining needs no comment and no spreadsheet.
  • The compiler protects you. State := 7, or a value from a different enumeration, is rejected at build time instead of in the plant.
  • It extends cleanly. Adding a state breaks nothing, and some compilers warn you about a CASE that no longer covers them all.
  • It shows up by name in tools. The watch table says Draining, not 3.

You can pin the values when something external depends on them, such as a comms protocol:

TYPE E_Mode : (Manual := 0, Auto := 1, Service := 9); END_TYPE

If your compiler has no enumerations

Some older platforms do not. The acceptable fallback is named constants:

VAR CONSTANT
  ST_IDLE     : INT := 0;
  ST_FILLING  : INT := 1;
  ST_DRAINING : INT := 3;
END_VAR

You keep the readability and lose the compiler's protection against an invalid value. Still far better than a bare number in the middle of a CASE.

Not runnable in the lab

The lab supports neither TYPE, STRUCT nor enumerations. The lab program below uses an INT for the state with a comment explaining each number, which is the weakest form still worth accepting. Read it and notice how often you scroll back to that comment to follow the CASE.

Try it in the lab

The lab runs in your browser: an ST editor, a virtual process that suits the lesson, the same program as a live ladder diagram, a watch table, and export to Siemens SCL.

What to try

  1. Run the program, press OPEN and follow State in the watch table: 1 (OPENING), then 2 (OPENED).
  2. Press CLOSE, then turn on "car in doorway": the door reverses, because CLOSING moves to OPENING.
  3. Read the conditions aloud: the names explain the logic, while State = 3 says nothing.

People find this lesson by searching

STRUCT structured textTYPE END_TYPE plcenumeration structured textuser defined type plcUDT plc programmingenum state machine plcstruct vs separate variables plc

Course outline

  1. 01What is Structured Text, and when to use it instead of ladder
  2. 02How a PLC runs your code: the scan cycle and the process image
  3. 03Program structure: POUs, PROGRAM, FUNCTION and FUNCTION_BLOCK
  4. 04Your first program: starting a pump with seal-in logic
  5. 05Data types: BOOL, INT, REAL, TIME and the rest
  6. 06Declaring variables: VAR, VAR_INPUT and RETAIN
  7. 07Literals and constants: 16#FF, 2#1010 and T#5s
  8. 08Type conversion and scaling a 4-20 mA signal
  9. 09Assignment and arithmetic in ST: := and operator precedence
  10. 10Boolean logic, comparisons and bit operations
  11. 11Standard functions: ABS, SQRT, MIN, MAX, LIMIT, SEL, MUX
  12. 12IF, ELSIF and ELSE: the rules and when to avoid them
  13. 13The CASE statement and your first state machine
  14. 14The FOR loop and the watchdog
  15. 15WHILE, REPEAT, EXIT, CONTINUE and RETURN
  16. 16Edge detection: R_TRIG, F_TRIG and the "it fired every scan" bug
  17. 17Timers: TON, TOF and TP
  18. 18Counters: CTU, CTD and CTUD
  19. 19SR and RS flip-flops: which one wins
  20. 20Writing your own function
  21. 21Writing a function block
  22. 22Arrays in Structured Text
  23. 23Structs and enumerations
  24. 24References and pointers
  25. 25The state machine pattern: a batch sequence that cannot get stuck
  26. 26Alarm management to ISA-18.2: delay, deadband, latch, acknowledge, first-out
  27. 27Analogue signal processing: counts to engineering units, NE43 and filtering
  28. 28Closed-loop control in ST: hysteresis first, then a practical PID
  29. 29Motors and valves in practice: permissives, feedback and travel time
  30. 30The same ST on every platform: SCL, Studio 5000, CODESYS, TwinCAT
  31. 31Testing and debugging ST: the watch table, forcing and simulation
  32. 32An ST style guide: naming, comments, constants and version control
  33. 33Final project: a complete tank station with a state machine and alarms
  34. 3420 interview questions on ST and PLC programming, with answers