learn · South Africa
Function block diagram (FBD) — PLC programming basics
A practical function block diagram tutorial. FBD vs ladder, common blocks like AND OR TON SR, building a PID loop, and worked examples in a free simulator.
Function block diagram is the second graphical language defined in IEC 61131-3, and on most projects with any analog content it ends up being the language of choice for the parts ladder logic struggles with. Where ladder is a ledger of contacts and coils that reads like a relay schematic, FBD is a wiring schematic of pre-built logic boxes — AND, OR, timers, edge detectors, set/reset latches, scaling blocks, PID controllers — connected by signal lines that carry boolean, integer, real, or structured data. The same program logic can usually be written in either language; the question is which one makes the program easier to read three years from now when somebody else has to fix it. This tutorial walks the FBD basics — the blocks you will use weekly, the connection rules that trip up new programmers, how to build a control loop, EN/ENO discipline, encapsulation into derived blocks, and a worked start-stop example you can copy into the simulator.
One opinion stated outright. If your ladder rung has more than three contacts in a single branch, you have already left the territory where ladder is the clearer language. Switch to FBD before the rung becomes unreadable. The cost of switching languages mid-project is a half-day of refactoring; the cost of leaving a tangled rung in production is a maintenance technician staring at it at 02:00 trying to work out which contact represents which physical condition. Pick the right language for the job.
Try the simulator →What FBD is
Function block diagram is a graphical PLC programming language standardised in IEC 61131-3 alongside ladder, structured text, instruction list, and sequential function chart. The visual idiom is direct — boxes are function blocks, lines are signal flow between them, the diagram reads left to right top to bottom in the same scan order ladder does. Each block has named input and output pins. Pins are typed — BOOL, INT, DINT, REAL, TIME, STRING — and the editor will refuse a connection where the source and destination types do not match. The output of one block becomes the input to the next, the same way a wire on a panel runs from one terminal to another.
Programmers coming from ladder sometimes describe FBD as "ladder turned on its side." That is misleading. Ladder is fundamentally a representation of relay logic — current flows from a left rail through contacts to a coil on the right rail, and the program is a series of those rungs. FBD has no rails and no current flow. It has signals propagating through a directed graph of blocks. The two languages happen to compile to similar bytecode on most platforms but the mental model is different, and the cleaner FBD looks the more it pulls away from being ladder-with-different-symbols.
The reference standard is IEC 61131-3, available from the IEC at iec.ch/standards/iec-61131-3. Every major platform — Siemens TIA Portal, Rockwell Studio 5000, CODESYS, Beckhoff TwinCAT, Schneider EcoStruxure — implements an FBD editor that conforms in the broad strokes to the standard with platform-specific extensions. The blocks and connection rules below are the IEC subset that is portable across all of them.
When FBD beats ladder
Three categories of logic where FBD is clearly the better choice.
Analog-heavy logic. Anything where the dominant data type is REAL — flow rates, pressures, temperatures, levels, weights — pulls the program away from boolean ladder rungs and toward block-based math. A scaling block, a low-pass filter, a deadband comparator, a high-low alarm — each of these is one box in FBD, with three or four typed pins. The same logic in ladder is half a screen of MOV, MUL, DIV, GEQ, LEQ instructions inside a rung that nobody enjoys reading.
Control loops. PID, cascade, ratio, feed-forward — every closed-loop control structure is a graph of blocks with signals flowing between them. That is what FBD draws natively. Ladder can host a PID instruction in a single rung, but the surrounding context — which input feeds the process variable, which output drives the manipulated variable, where the setpoint comes from, what the alarm logic does — is much clearer as a wired diagram than as a stack of rungs.
Math-heavy derived logic. Volume calculations, mass-balance closures, heat-transfer estimates, fuel consumption integrators. Anything where the program is doing arithmetic to produce derived values for an HMI or a report. FBD's typed pins and explicit data flow are easier to verify against the formula on the engineer's notepad than a sequence of ladder math instructions.
The fourth case worth mentioning is reusability. If you find yourself writing the same eight-rung pattern (a debounce, a fault-latch with reset, a runtime accumulator) on twenty motors, encapsulating it as a derived function block — section 7 below — turns it into a single FBD instance you drop in twenty times. That kind of factoring is awkward in ladder and natural in FBD.
The basic blocks
The blocks every FBD programmer uses every week. Pin names follow the IEC 61131-3 convention; platform-specific names may differ slightly but the signatures are the same.
AND OR NOT
___ ___ ___
| | | | | |
-| & |- -|>=1|- -| 1 |o-
-| | -| | |___|
|___| |___| (single input, inverted output)
BOOL→BOOL BOOL→BOOL BOOL→BOOL
R_TRIG (rising-edge) F_TRIG (falling-edge)
_________ _________
| | | |
| CLK Q |--- | CLK Q |---
|_________| |_________|
BOOL→BOOL BOOL→BOOL
(Q is true for one scan (Q is true for one scan
on rising edge of CLK) on falling edge of CLK)
TON (on-delay timer) TOF (off-delay timer)
_________ _________
| | | |
| IN Q |--- | IN Q |---
| PT ET |--- | PT ET |---
|_________| |_________|
IN: BOOL Q: BOOL IN: BOOL Q: BOOL
PT: TIME ET: TIME PT: TIME ET: TIME
SR (set-dominant latch) RS (reset-dominant latch)
_________ _________
| | | |
| S1 Q1 |--- | S Q1 |---
| R | | R1 |
|_________| |_________|
S1, R: BOOL S, R1: BOOL
Q1: BOOL Q1: BOOL
(S1 wins if both true) (R1 wins if both true)
CTU (count-up) CTD (count-down)
_________ _________
| | | |
| CU Q |--- | CD Q |---
| R CV |--- | LD CV |---
| PV | | PV |
|_________| |_________|
CU, R: BOOL CD, LD: BOOL
PV: INT Q: BOOL CV: INT PV: INT Q: BOOL CV: INT
Eleven blocks. Memorise these signatures and you can read 80% of the FBD in any production program. The remaining 20% is platform-specific extensions (motion blocks, communication blocks, drive control blocks) which all follow the same pin-and-signal pattern once you know the basic shape.
Connection rules — the part everyone gets wrong
Block-to-block wiring on a real FBD editor enforces three rules that new programmers regularly fight with.
Data type matching. Pins are typed. A BOOL output cannot connect to a REAL input. A REAL input cannot connect to a TIME pin. The editor will refuse the connection with a red marker. The fix is either to choose a different block (some blocks have BOOL and REAL input variants) or to insert a type conversion block — BOOL_TO_INT, REAL_TO_DINT, INT_TO_REAL. Conversion blocks are explicit on purpose; an implicit cast from a 32-bit float to a 16-bit integer can lose precision or overflow silently, and IEC 61131-3 requires the program to ask for it.
Fan-out is fine; fan-in is not. A single block output can feed many block inputs — drag the wire from the output, branch it, end it on as many inputs as needed. That is fan-out, and it works because each destination is reading the same source value. The reverse is forbidden — multiple block outputs cannot connect to a single input. There is no hardware analogue of two voltage sources driving the same node; in software it would be an undefined value. If you need to combine two outputs, you have to insert an OR (for booleans), an ADD (for numerics), or some other arbitration block that takes two inputs and produces one output.
Feedback loops require care. A feedback loop — block A's output feeding block B, block B's output feeding back into block A — is allowed but introduces a one-scan delay. The block that reads the fed-back signal sees the value from the previous scan, not the current scan. Most platforms mark feedback connections with a special arrow style to make this visible. Use feedback for accumulators, integrators, state machines that genuinely need last-scan state. Do not use it accidentally — if the same value is computable in the current scan, route the wire forward not backward.
A subtler trap is execution order. The compiler determines block execution order by topological sort of the wiring graph. Most of the time it gets the answer you wanted. But if you have two parallel sub-graphs with no wires between them, the order in which they execute is not guaranteed unless you constrain it — most editors let you set explicit execution numbers on each block. If you have side effects (a write to a global variable, a fault flag) that depend on order, set the order explicitly.
Building a simple control loop in FBD
A pressure control loop in FBD reads naturally as a chain of blocks left-to-right.
+-----+ +-----+ +------+ +-----+ +-----+
AI | | | | | | | | | |
PV-|SCALE|---PV-| GE |--OK--| PID |--CV--|SCALE|--CV--| AO |
| | | | | | | | | |
SP-| | | | SP--| | | | | |
+-----+ +-----+ +------+ +-----+ +-----+
raw→eng PV≥0? compute eng→raw drive
The flow. Analog input raw counts come in as an INT — say 0 to 27648 on a Siemens analog module, or 4000 to 20000 (representing 4–20 mA in milli-amps × 1000) on a Rockwell module. The first SCALE block converts those raw counts to engineering units — bar, kPa, psi, whatever the process variable is measured in. That scaled REAL becomes the process variable input to the PID block. The setpoint comes from the HMI (or a recipe, or a fixed value) in the same engineering units. The PID computes its control output as a REAL between 0.0 and 100.0 — percent of valve travel, typically. A second SCALE block converts that 0–100% back into raw counts for the analog output card, which drives the valve positioner.
A GE comparison block on the PV is a sanity check — if the scaled PV reads less than zero, the analog input is faulted (broken wire, sensor failure) and the PID should hold last output rather than slamming the valve open. The GE output gates the PID's manual/auto bit.
PID block names by platform. On Siemens TIA Portal with an S7-1500 the standard block is PID_Compact, documented at support.industry.siemens.com — a single FB instance with PV, SP, manipulated variable, and an extensive parameter set for tuning. On Rockwell Studio 5000 with a ControlLogix or CompactLogix processor the equivalent is PIDE (Process PID, Enhanced) — an Add-On Instruction with similar pins and a built-in autotune. On CODESYS the standard PID block is PID from the Util library or the more featureful PID_FIXCYCLE for fixed-cycle execution. The signatures differ in detail, the structure is the same — PV in, SP in, CV out, plus a stack of tuning parameters and mode bits.
EN / ENO chains
EN (enable) and ENO (enable output) are pins on most function blocks that act as a software circuit breaker. EN is a BOOL input — if EN is true (the default when the pin is not wired), the block executes normally; if EN is false, the block does not execute and its outputs hold their last values. ENO is a BOOL output — true when the block executed successfully, false when the block was disabled (EN was false) or failed internally.
The pattern is to wire ENO of one block to EN of the next, building a chain that short-circuits on fault. If a SCALE block fails (input out of range, conversion error), its ENO goes false, and every block downstream that takes its EN from that ENO also stops executing. The PID holds its last output. The analog output stays where it was. The HMI shows a fault. Nothing dangerous happens.
The most common bug with EN/ENO is leaving EN unwired and assuming the block is always disabled. The opposite is true. An unwired EN pin is implicitly true — the block runs every scan. If you want a block to run only when a permissive is true, wire that permissive to EN explicitly. The default-true behaviour is a deliberate choice in IEC 61131-3 — it means most blocks just work without ceremony — but it bites programmers who expect the opposite.
A second pattern is using EN to skip expensive blocks. A heat-transfer estimator that runs a 50-iteration solver every scan is wasteful if the inputs have not changed. Wire EN to a "inputs-changed" flag — true when any input has changed since last scan — and the block only re-solves when it needs to. The savings on a high-scan-rate program can be significant.
Encapsulation — derived function blocks
The best feature of FBD is the ability to roll your own blocks. A pattern you find yourself wiring over and over — a debounce, a fault-latch with reset and acknowledge, a runtime accumulator with reset — can be wrapped into a derived function block with named input and output pins, and reused everywhere.
The platform-specific names. On Siemens TIA Portal, a derived block is an FB (Function Block) with an instance Data Block (DB) that holds its persistent state. Each call to the FB needs its own instance DB so the state of one motor's runtime accumulator does not collide with another's. On Rockwell Studio 5000, the equivalent is an Add-On Instruction (AOI) — defined once, instanced many times, with each instance carrying its own backing tag. On CODESYS and other IEC-conforming platforms, it is a FUNCTION_BLOCK POU (Program Organisation Unit) declared in the project tree with a typed interface.
The discipline. A good derived block has a small interface — five to ten pins is plenty, twenty is too many. The internal logic is encapsulated so the calling program does not need to know how it works, only what the pins do. Document the pins. Type them strictly. If the block has internal state (a timer, an accumulator) that needs to survive across scans, make sure the platform's instance mechanism is providing isolated storage per call.
The trap is over-encapsulation. A two-block derived FB that wraps an AND and an OR saves nothing — the call overhead and the indirection cost more than the inline version. Encapsulation pays off when the encapsulated logic is at least five or six blocks deep, called at least three or four times in the program, or has parameters that vary per instance (different timer presets, different fault thresholds). Below that threshold, just inline it.
FBD vs ladder — when to switch
The empirical rule. If your ladder rung has more than three contacts in a branch, FBD is clearer. If you find yourself stacking MOV, ADD, GEQ instructions inside a rung, FBD is clearer. If the logic is closed-loop control or analog math, FBD is clearer. If the logic is discrete IO with seal-in latches and interlocks — start-stop, reversing, sequencing — ladder is usually clearer because the ladder idiom matches the relay schematic the panel was designed from.
Many real projects mix languages within one program. The motor-control rungs stay in ladder because the maintenance team can read ladder fluently and the rungs map directly to the panel drawings. The analog scaling and the PID loops sit in FBD because that is where they read cleanly. The supervisory sequence sits in SFC because state machines belong in SFC. IEC 61131-3 supports this mixing explicitly — different POUs in the same project can be in different languages — and most platforms render the languages side-by-side in the editor. Use the right language per piece of logic, not one language for the whole program.
The migration cost is low. Translating a ladder rung to FBD is mechanical: contacts become AND or OR boxes, coils become assignment connectors, timers and counters keep the same pins. The reverse is the same. If you start a piece of logic in the wrong language, switching is a half-hour job. Do not stay in the wrong language out of inertia.
A worked example — start-stop in FBD
The same start-stop seal-in rung from the motor control tutorial, expressed as FBD. The diagram is a four-block graph.
+-----+ +------+
Start --+--------| | | |
| | OR |--------+-------| |
| +-----| | | | AND |--+--- MotorRun
| | +-----+ | | | |
| | | +----| | |
| | | | +------+ |
| | +------------+ | | |
| | | feedback | | | |
| +--| (1 scan) |----+ | |
| +------------+ | |
| | |
| +--------+ | |
Stop----| NOT |------------+ |
| | |
+--------+ |
|
MotorRun ------------------------------(feedback)-+
(the AND output is also wired back into the OR via the seal-in path above)
The OR block has two inputs — the start button and the seal-in feedback from MotorRun. Either one true makes its output true. The AND block has two inputs — the OR output and the inverted Stop. As long as Stop is not pressed, the AND passes whatever the OR is producing. The AND output is MotorRun, and it also feeds back as the second input to the OR, which is the seal-in.
Adding overload protection is one more AND input — the overload-not-tripped signal goes into a third input of the AND, and if it goes false the rung breaks the same way Stop does. Adding a runtime accumulator is dropping a derived FB next to the MotorRun output that takes MotorRun as its input pin and outputs accumulated runtime hours. Adding a fault-latch is dropping an SR block driven by overload-tripped on the S input and a reset button on the R input.
The full IEC 61131-3 standard text covering this language and its semantics is published by the IEC at iec.ch/standards/iec-61131-3. Section 4 of part 3 is the FBD reference; section 2 is the common element types (data types, variable declarations) that apply to all the languages.
Practice in the simulator
Open the simulator and choose the FBD editor. The first exercise is the start-stop graph above — drag an OR block, an AND block, a NOT block; wire Start and the MotorRun feedback into the OR; wire the OR output and the inverted Stop into the AND; assign the AND output to MotorRun. Toggle the inputs and confirm the latch behaviour matches what the ladder version of the same logic does.
The second exercise is a TON timer. Drop a TON block, wire MotorRun to the IN pin, set PT to T#5s, watch ET count up while MotorRun is true and Q assert at five seconds. That is the runtime-detection foundation for fault-latches that ride on minimum-on times.
The third is a small control loop. Drop a SCALE block (or use the built-in scaling on the simulator's analog input), wire the scaled PV into a PID block, give it a fixed setpoint, route the PID output through another SCALE to a simulated analog output. Step the setpoint and watch the loop respond. This is where FBD earns its keep — the same logic in ladder is half a screen of math; in FBD it is five blocks and four wires.
The fourth is your own derived block. Take the start-stop graph, package it as a function block with three inputs (Start, Stop, OverloadNotTripped) and one output (MotorRun), and instance it three times for three motors. Confirm each instance latches independently. That is encapsulation working.
A full afternoon of FBD practice and the language becomes as natural as ladder. The next tutorial covers structured text — the third IEC language, text-based, where the math-heavy logic that FBD draws as graphs gets compressed into a few lines of code. The three languages are complementary; the strong PLC programmer is fluent in all three and picks the right one per piece of logic. FBD is the middle stop on that path. Build the reflex layer here.
Try the simulator →