Schematex

Function Block Diagram (FBD)

About function block diagrams

Function Block Diagram (FBD) is one of the five PLC programming languages defined by IEC 61131-3:2013 — the international standard for industrial automation. It's the second-most-drawn PLC language in production code (after ladder), and the natural choice when a chunk of program is easier to read as data flow than as power-rail-and-rung relays. AND/OR logic, timers (TON/TOF/TP), counters (CTU/CTD), comparison (EQ/NE/GT/GE/LT/LE), math (ADD/SUB/MUL/DIV/MOVE), edge detectors (R_TRIG/F_TRIG), bistable latches (SR/RS) — all rendered as named-port boxes wired left-to-right.

Schematex follows the IEC 61131-3 §6.4 visual conventions with IEC 60617-12 distinctive symbols (& for AND, ≥1 for OR, =1 for XOR, 1 for NOT/BUF). Wires are colored by data type (BOOL black, INT blue, REAL orange, TIME magenta) following TIA Portal de-facto convention. Sister language to ladder (§6.3, rung-based) and sfc (§6.5, sequence-based); together they form the visual half of IEC 61131-3.

fbd·§
↘ preview
100%
FBD: Motor Control FBD with 2 network(s). 0 — Start/stop latch Start Latch Stop Latch OR ≥1 IN1 IN2 OUT AND & IN1 IN2 OUT 1 — Drive output Latch MotorOut MOVE IN OUT
UTF-8 · LF · 13 lines · 209 chars✓ parsed·1.6 ms·6.8 KB SVG

1. Your first FBD network

The smallest useful FBD network: one block, two inputs, one output.

fbd
network 0:
  Out = AND(A, B)

A and B are auto-declared as BOOL inputs (left-side terminals), and Out is auto-wired to the AND block's OUT port (right-side terminal). The block sits between them with port stubs and labels.


2. Variables

Declare variables before any networks. Each variable has a name, an IEC data type, and an optional initial value.

fbd "Tank Control"

var StartBtn: bool
var TankLevel: real
var SetPoint: real = 80.0
var DwellTimer: timer
var Pulse: counter

Supported types: bool, int, dint, uint, udint, real, lreal, time, date, tod, string, wstring, byte, word, dword, timer, counter. Any other identifier is treated as a user-defined function-block type.

Optional scope prefixes (default = local): var_input, var_output, var_in_out, var_global, var_external.


3. Networks

A network is one independent piece of data flow, evaluated left-to-right within itself; networks evaluate top-to-bottom across the program per scan.

network 0 "Start latch":
  ...

network 1:
  ...

The number is optional — networks are auto-numbered if absent. The title (in quotes) renders at the top-left of the network frame.


4. Block calls — inline expression notation

The clearest way to write a combinational network is as a single nested expression:

network 0:
  Out = OR(A, AND(B, ~C))

The parser builds the call tree: outer OR with A on input 1 and the AND result on input 2; the AND has B and the negated C. The renderer lays them out left-to-right (inputs at layer 0, AND at layer 1, OR at layer 2, output at layer 3).

~C adds a negation bubble (small open circle) at the input port — equivalent to inserting a NOT block on that wire, but cleaner.


5. Block calls — instance-named notation

When you need to reference a block's outputs from elsewhere, give it an instance tag:

network 0:
  Pulse = R_TRIG(CLK: Sensor)
  Count = CTU(CU: Pulse.Q, R: Reset, PV: 100)
  Done  = GE(IN1: Count.CV, IN2: 100)

Pulse.Q, Count.CV reference output ports of named instances. The instance tag renders italicized above the block header.

Argument lists accept named ports (CU: Pulse.Q) or positional (CTU(Pulse.Q, Reset, 100)) — named is recommended for readability and required when you skip a port.


6. Inline constants

Input ports can take literals directly — no wire needed:

network 0:
  Dwell = TON(IN: BottleSensor, PT: T#50ms)
  Cap   = LIMIT(MN: 0.0, IN: Setpoint, MX: 95.0)
  Mode  = SEL(G: ManualSwitch, IN0: AutoMode, IN1: ManualMode)

T#50ms, 0.0, 95.0 render as small yellow boxed text to the left of their port. Time literals follow IEC 61131-3: T#10ms, T#5s, T#3m20s, T#1h. Booleans are true / false (case-insensitive).


7. Standard block library

CategoryBlocks
BooleanAND, OR, NOT, NAND, NOR, XOR, XNOR, BUF
Edge detectR_TRIG, F_TRIG
BistableSR, RS
TimerTON, TOF, TP
CounterCTU, CTD
MathADD, SUB, MUL, DIV, MOD, ABS, NEG, MOVE
ComparisonEQ, NE, GT, GE, LT, LE
SelectionSEL, MUX, MAX, MIN, LIMIT

AND, OR, NAND, NOR, ADD, MUL, MAX, MIN accept any number of inputs (default 2). Pass extra positional args or use [inputs: N] to extend.

network 0:
  All4 = AND(A, B, C, D)
  Sum  = ADD(X, Y, Z)

8. Larger example — bottle counter

fbd "Bottle Counter"

var ConveyorRunning: bool
var BottleSensor: bool
var BatchDone: bool
var BatchSize: counter
var DwellTimer: timer

network 0 "Debounce sensor with 50ms dwell":
  Dwell = TON(IN: BottleSensor, PT: T#50ms)

network 1 "Count one bottle on rising edge of debounced signal":
  Pulse     = R_TRIG(CLK: Dwell.Q)
  BatchSize = CTU(CU: Pulse.Q, R: BatchDone, PV: 24)

network 2 "Batch done":
  BatchDone = MOVE(BatchSize.Q)

Three networks: debounce → edge-detect → count → flag. Each network is one DAG; the renderer routes wires through Manhattan paths.


9. v0.1 limitations

The current engine implements the standard-block subset most teams use day-to-day. The following are deferred and will be added in a follow-up:

  • EN/ENO power-flow rails ([en] block attribute, [rail: on] header) — adds a top-of-network enable rail, vendor convention from Studio 5000 / TIA Portal.
  • User-defined function blocks with pins_in: / pins_out: declarations — for custom motor controllers, PID instances, etc.
  • Page connectors (connector_out / connector_in) for wires that span multiple pages.
  • Bit-string blocks (SHL, SHR, ROL, ROR, AND_BIT, OR_BIT, etc.).
  • Extended math (SQRT, LN, LOG, EXP, SIN, COS, TAN, ASIN, ACOS, ATAN).
  • ANSI distinctive shape mode ([shape: ansi]) — the logic engine already provides this for pure-Boolean diagrams.
  • CTUD bidirectional counter, TP retentive timer (RTO).

If you need any of these now, open an issue or use the ladder engine for the full IEC 61131-3 LD subset.


Ready-to-use scenarios from the examples gallery:

fbd·§ IEC 61131-3:2013 §6.4 + §2.5
FBD: Motor Control FBD with 2 network(s). 0 — Start latch Start Latch Stop EmergencyStop Latch OR ≥1 IN1 IN2 OUT AND & IN1 IN2 IN3 OUT 1 — Drive output Latch MotorOut MOVE IN OUT
Motor start/stop latch (FBD)
Two-network FBD of the canonical PLC seal-in circuit — start-button rising edge sets a latch, stop and emergency-stop break it. Exercises declared variables, multi-network programs, inline expression notation, and negation bubbles.
manufacturing
fbd·§ IEC 61131-3:2013 §6.4 + §2.5
FBD: Bottle Counter FBD with 3 network(s). 0 — Debounce sensor with 50ms dwell BottleSensor TON IN PT T#50ms Q ET 1 — Count one bottle on rising edge of debounced signal BatchDone BatchSize R_TRIG CLK Q CTU CU R PV 24 Q CV 2 — Latch batch done BatchDone MOVE IN OUT
Bottle counter — debounce → edge → count (FBD)
Three-network FBD pipeline that debounces a bottle sensor with a 50ms TON, takes the rising edge with R_TRIG, counts up to 24 bottles per case with CTU, and self-resets when the case is full. A real production-line pattern that exercises timer + edge-detector + counter + named-instance references in sequence.
manufacturing
fbd·§ IEC 61131-3:2013 §6.4 + §2.5
FBD: Tank Level Setpoint Limiter FBD with 2 network(s). 0 — Clamp setpoint to safe range DesiredSetpoint SafeSetpoint LIMIT MN 0.0 IN MX 95.0 OUT 1 — Alarm on out-of-range request DesiredSetpoint Alarm OR ≥1 IN1 IN2 OUT LT IN1 IN2 0.0 OUT GT IN1 IN2 95.0 OUT MOVE IN OUT
Tank setpoint limiter + alarm (FBD)
Two-network FBD that clamps an operator-entered tank-level setpoint to the safe range [0, 95]% via LIMIT, and raises an alarm if the operator types an out-of-range value. Uses LT and GT comparison blocks, the LIMIT selection block, and demonstrates REAL (orange) and BOOL (black) wires carrying different data types in one diagram.
chemical-processing

Found this useful?

Schematex is free, fully open source, and zero-dependency. A star helps other developers discover it.