20Structured programs
Writing your own function
How to declare your own FUNCTION such as Scale4to20, what purity means, and why one declaration replaces twenty copies of the same equation.
The problem: the same equation in twenty places
On a station with twenty analogue transmitters you copy this line twenty times with different numbers:
Flow := (RawFlow - 4.0) / 16.0 * 250.0;
Pres := (RawPres - 4.0) / 16.0 * 10.0;In one of them you type 16.0 where 4.0 belonged, a reading is wrong, and you spend three days finding it. The fix is to write the equation once, in a function.
Declaring one
FUNCTION Scale4to20 : REAL
VAR_INPUT
Raw : REAL; (* 4.0 .. 20.0 mA *)
EngLo : REAL;
EngHi : REAL;
END_VAR
Scale4to20 := EngLo + (Raw - 4.0) / 16.0 * (EngHi - EngLo);
END_FUNCTIONThree things to notice:
- The type follows the name:
FUNCTION Scale4to20 : REALmeans it returns aREAL. - Inputs live in
VAR_INPUT: read-only inside the body. - You return by assigning to the function's own name:
Scale4to20 := .... That is the standard syntax; there is noreturnkeyword.
Calling it
Flow := Scale4to20(RawFlow, 0.0, 250.0);
Pres := Scale4to20(RawPres, 0.0, 10.0);
Temp := Scale4to20(RawTemp, -50.0, 200.0);Or by name, which reads better in review:
Flow := Scale4to20(Raw := RawFlow, EngLo := 0.0, EngHi := 250.0);Purity: no memory, no side effects
A function is pure: the same inputs always give the same result, and nothing is remembered between calls. That means:
- No timers and no counters inside it. A
TONneeds memory, so it belongs in aFUNCTION_BLOCK. - Local
VARvalues inside a function are undefined at the start of each call. Never rely on them. - Do not write to a global from inside a function. Some platforms let you, but it makes the result depend on the program's history, which is exactly what you were avoiding.
When do you need a FUNCTION_BLOCK instead? When the answer to "does it need to remember anything from the previous scan?" is yes.
Functions worth writing
Scale4to20andScaleRaw: engineering-unit conversion.DeadbandPct: a deadband around a setpoint.CelsiusToF,BarToPsi: unit conversion.ClampPct: hold a value between 0 and 100 and flag the overshoot.
Each is reviewed once, tested once, and correct everywhere after that.
Not runnable in the lab
The lab on this site runs a single PROGRAM and does not support declaring a FUNCTION. The examples above are code to read, not to run. The lab program below does the same maths inline so you can watch the numbers move.
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
- Run the program, press START and watch Percent, DegC and Bar follow the level.
- Notice the same formula written three times; on a real PLC it becomes FUNCTION Scale, called three times.
- Change the temperature span 120.0 to 200.0 in the second line only, and notice you edited one place out of three: that is the mistake a function prevents.
People find this lesson by searching
user defined function structured textFUNCTION declaration plcscale 4-20mA structured textVAR_INPUT functionstructured text function return valuepure function plcreusable plc code
Course outline
- 01What is Structured Text, and when to use it instead of ladder
- 02How a PLC runs your code: the scan cycle and the process image
- 03Program structure: POUs, PROGRAM, FUNCTION and FUNCTION_BLOCK
- 04Your first program: starting a pump with seal-in logic
- 05Data types: BOOL, INT, REAL, TIME and the rest
- 06Declaring variables: VAR, VAR_INPUT and RETAIN
- 07Literals and constants: 16#FF, 2#1010 and T#5s
- 08Type conversion and scaling a 4-20 mA signal
- 09Assignment and arithmetic in ST: := and operator precedence
- 10Boolean logic, comparisons and bit operations
- 11Standard functions: ABS, SQRT, MIN, MAX, LIMIT, SEL, MUX
- 12IF, ELSIF and ELSE: the rules and when to avoid them
- 13The CASE statement and your first state machine
- 14The FOR loop and the watchdog
- 15WHILE, REPEAT, EXIT, CONTINUE and RETURN
- 16Edge detection: R_TRIG, F_TRIG and the "it fired every scan" bug
- 17Timers: TON, TOF and TP
- 18Counters: CTU, CTD and CTUD
- 19SR and RS flip-flops: which one wins
- 20Writing your own function
- 21Writing a function block
- 22Arrays in Structured Text
- 23Structs and enumerations
- 24References and pointers
- 25The state machine pattern: a batch sequence that cannot get stuck
- 26Alarm management to ISA-18.2: delay, deadband, latch, acknowledge, first-out
- 27Analogue signal processing: counts to engineering units, NE43 and filtering
- 28Closed-loop control in ST: hysteresis first, then a practical PID
- 29Motors and valves in practice: permissives, feedback and travel time
- 30The same ST on every platform: SCL, Studio 5000, CODESYS, TwinCAT
- 31Testing and debugging ST: the watch table, forcing and simulation
- 32An ST style guide: naming, comments, constants and version control
- 33Final project: a complete tank station with a state machine and alarms
- 3420 interview questions on ST and PLC programming, with answers