Skip to content

21Structured programs

Writing a function block

A complete FUNCTION_BLOCK for a motor with Start, Stop, Feedback and Fault inputs, Run and Alarm outputs, an internal timer, plus instances and VAR_IN_OUT.

Lesson 21 of 3413 minIEC 61131-3

Why a block, not a function

Every motor in the plant needs the same things: a seal-in, a check that the contactor auxiliary came back, a latched fault, and an acknowledge. The check needs a timer, the timer needs memory, and memory means a function block, not a function.

Write it once, use it for thirty motors.

Declaring one

FUNCTION_BLOCK FB_Motor
VAR_INPUT
  Start    : BOOL;   (* start pulse *)
  Stop     : BOOL;   (* stop pulse, always wins *)
  Feedback : BOOL;   (* contactor auxiliary contact *)
  Ack      : BOOL;   (* fault acknowledge *)
  FbTime   : TIME;   (* how long to wait for feedback *)
END_VAR
VAR_OUTPUT
  Run   : BOOL;      (* to the contactor *)
  Alarm : BOOL;      (* latched fault *)
END_VAR
VAR
  FbTimer : TON;     (* memory, private to each instance *)
END_VAR

(* Seal-in; stop and fault both win *)
Run := (Start OR Run) AND NOT Stop AND NOT Alarm;

(* Commanded to run but no feedback within the allowed time *)
FbTimer(IN := Run AND NOT Feedback, PT := FbTime);

IF FbTimer.Q THEN
  Alarm := TRUE;     (* latched: it holds after the cause clears *)
END_IF;

IF Ack THEN
  Alarm := FALSE;
END_IF;

END_FUNCTION_BLOCK

The instance is the whole point

VAR
  M101 : FB_Motor;
  M102 : FB_Motor;
  M103 : FB_Motor;
END_VAR

M101(Start := Btn1, Stop := StopAll, Feedback := Aux1, Ack := AckBtn, FbTime := T#2s);
M102(Start := Btn2, Stop := StopAll, Feedback := Aux2, Ack := AckBtn, FbTime := T#2s);
M103(Start := Btn3, Stop := StopAll, Feedback := Aux3, Ack := AckBtn, FbTime := T#5s);

K101     := M101.Run;
K102     := M102.Run;
AnyFault := M101.Alarm OR M102.Alarm OR M103.Alarm;

Three instances, each with its own timer and its own fault latch. Fix the logic once in the block and all thirty motors are fixed.

Call every instance every scan

An instance only advances when it is called. Put M101(...) inside an IF that is sometimes skipped and its internal timer freezes, leaving the fault stuck on a stale state. Call all instances every scan and steer behaviour through the inputs.

Read the outputs after the call

M101(Start := Btn1, ...);
K101 := M101.Run;      (* correct: this scan's value *)

Read M101.Run before the call and you get last scan's value. Not always wrong, but a one-scan lag that is painful to explain inside a sequence.

VAR_IN_OUT

VAR_INPUT copies a value in, VAR_OUTPUT copies one out. VAR_IN_OUT gives the block the variable itself: it reads and writes it, and the change shows up in the original.

FUNCTION_BLOCK FB_RunHours
VAR_INPUT
  Running : BOOL;
END_VAR
VAR_IN_OUT
  Hours : REAL;      (* an hours counter the program owns and the block updates *)
END_VAR

Use it when the block must update something large or retained that lives outside it: a run-hours total, a logging buffer. Do not use it to save a line. A plain output is clearer, and VAR_IN_OUT hides who writes what.

Not runnable in the lab

The lab does not support declaring a FUNCTION_BLOCK. The lab program below writes the same logic inline with a TON for a single motor, so you can watch the seal-in, the feedback check and the fault latch work.

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 and press START: the motor starts in star and moves to delta after 4 s.
  2. Turn on OVERLOAD TRIP: Fault latches and the motor stops. Turn it off and press START to reset.
  3. Change Feedback := KMain; to Feedback := FALSE; and download again: after one second the fault appears, because the feedback never came.

People find this lesson by searching

FUNCTION_BLOCK structured textmotor function block plcwrite a function block IEC 61131-3function block instanceVAR_IN_OUT structured textmotor feedback fault plcreusable function block

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