Schematex

Ladder logic

About ladder logic diagrams

Ladder logic is the graphical programming language used to describe control programs in Programmable Logic Controllers (PLCs) — the industrial computers that run factory automation, HVAC systems, conveyor lines, and process equipment worldwide. The name comes from the diagram's appearance: two vertical power rails (rails) connected by horizontal rungs, each rung expressing one condition-to-action rule. Electricians and controls engineers adopted it because it mirrors the relay-contact schematics they already knew.

Schematex follows IEC 61131-3:2013, the international standard for PLC programming languages, with Allen-Bradley (Rockwell) tag-address-name naming conventions common in North American industrial practice. This page documents what the parser accepts today.

ladder·§ IEC 61131-3
↘ preview
100%
Motor Start/Stop PLC ladder logic diagram with 4 rungs Motor Start/Stop Rung 001 — Seal-in circuit — Rung 002 — Mode select with Set/Reset — Rung 003 — Run timer — Rung 004 — Alarm on cycle complete — Start Button START_PB IN 1.0 Aux Contact MOTOR_AUX BIT 3.0 Stop Button STOP_PB IN 1.1 Motor Command MOTOR_CMD OUT 2.0 Auto Mode Button AUTO_HMIPB BIT 5.10 System Fault SYS_FAULT BIT 3.0 S System Auto Mode SYS_AUTO BIT 3.1 R System Manual Mode SYS_MANUAL BIT 3.2 MOTOR_CMD TON PT=5000 RUN_TMR Cycle Done CYCLE_DONE BIT 4.0 / Alarm Output ALARM_OUT OUT 2.5
UTF-8 · LF · 23 lines · 734 chars✓ parsed·5.2 ms·10.6 KB SVG

1. Your first ladder diagram

The smallest useful ladder program: one rung, two contacts, one coil.

ladder·§ IEC 61131-3
↘ preview
100%
First Rung PLC ladder logic diagram with 1 rung First Rung Rung 001 — Start when button pressed, stop on fault — START_PB FAULT MOTOR_RUN
UTF-8 · LF · 5 lines · 110 chars✓ parsed·0.6 ms·3.3 KB SVG

Four rules cover 80% of usage:

  1. Start with ladder, optionally followed by a quoted title.
  2. Each rung begins with rung N "optional comment": on its own line. The trailing colon is optional.
  3. Elements are listed one per line, indented under the rung — left to right means series (AND logic).
  4. A parallel: / branch: block introduces OR logic. Every branch holds its own element list.

Comments may start with #, //, or Mermaid-style %% on their own line.


2. Contacts

Contacts represent input conditions — they pass power when the associated bit matches the contact type.

TypeNamePasses power when…
XICExamine If ClosedTag bit = 1 (normally open)
XIOExamine If OpenTag bit = 0 (normally closed)
ONSOne-Shot RisingTag transitions 0 → 1 (rising edge, one scan)
OSFOne-Shot FallingTag transitions 1 → 0 (falling edge, one scan)

Syntax:

XIC(tag)
XIC(tag, "address")
XIC(tag, "address", name="Description")
XIC(tag, address="address", name="Description")
  • tag — required. The PLC tag name (displayed below the contact symbol).
  • "address" — optional positional second argument. The I/O address (e.g. "IN 1.0", "BIT 3.1").
  • name="…" — optional key-value. Human-readable description (displayed above the symbol).
ladder·§ IEC 61131-3
↘ preview
100%
Contact types PLC ladder logic diagram with 1 rung Contact types Rung 001 — All four contact types — Start Button START_PB IN 1.0 Emergency Stop NC E_STOP IN 1.5 One-Shot Rising PULSE_IN BIT 5.0 One-Shot Falling RESET_SIG BIT 5.1 Output Relay OUT_RLY OUT 2.0
UTF-8 · LF · 7 lines · 293 chars✓ parsed·0.8 ms·5.7 KB SVG

3. Coils

Coils represent output actions — they act on a tag bit when the rung has power flow.

TypeNameEffect on tag bit
OTEOutput EnergizeSets bit = 1 while rung is true; clears to 0 when rung is false
OTLOutput LatchSets bit = 1; retains even after rung goes false (latches)
OTUOutput UnlatchClears bit = 0; retains even after rung goes false
OTNOutput NegateSets bit = 0 while rung is true; sets to 1 when rung is false
RESResetRockwell / Allen-Bradley counter or timer reset coil

Syntax: identical to contacts — OTE(tag), OTE(tag, "address"), OTE(tag, "address", name="…").

OTL and OTU are used in pairs to build Set/Reset flip-flops. The last rung to write wins.

ladder·§ IEC 61131-3
↘ preview
100%
Set-Reset latch PLC ladder logic diagram with 2 rungs Set-Reset latch Rung 001 — Set on start — Rung 002 — Reset on stop or fault — Start START_PB IN 1.0 S Motor Latch MOTOR_ON BIT 3.0 Stop STOP_PB IN 1.1 E-Stop E_STOP IN 1.5 R Motor Latch MOTOR_ON BIT 3.0
UTF-8 · LF · 11 lines · 319 chars✓ parsed·0.9 ms·5.5 KB SVG

4. Function blocks

Function blocks perform timer, counter, math, and comparison operations. They appear inline in a rung and have keyword parameters after the mandatory tag argument.

4.1 Timers

TypeNameKey parameters
TONTimer On-DelayPT= preset time in milliseconds
TOFFTimer Off-DelayPT= preset time in milliseconds
TPTimer PulsePT= preset time in milliseconds
TON(timer_tag, PT=5000)

The timer tag stores elapsed time. The timer's Q bit (done output) is accessed by tag name in downstream contacts.

4.2 Counters

TypeNameKey parameters
CTUCount UpPV= preset value (integer)
CTDCount DownPV= preset value
CTUDCount Up/DownPV= preset value
CTU(cycle_counter, PV=100)

4.3 Math

TypeOperation
ADDAdd
SUBSubtract
MULMultiply
DIVDivide
MOVMove (copy)
ADD(result_tag, IN1=setpoint, IN2=offset)
MOV(dest_tag, IN1=source_tag)

4.4 Comparisons

TypeMeaning
EQUEqual
NEQNot equal
GRTGreater than
LESLess than
GEQGreater than or equal
LEQLess than or equal
EQU(compare_tag, IN1=speed_actual, IN2=speed_setpoint)
ladder·§ IEC 61131-3
↘ preview
100%
Timer and counter PLC ladder logic diagram with 3 rungs Timer and counter Rung 001 — Start run timer — Rung 002 — Count completed cycles — Rung 003 — Alarm when batch complete — Motor Running MOTOR_CMD BIT 3.0 TON PT=10000 RUN_TIMER Cycle Sensor CYCLE_SENSOR IN 2.0 CTU PV=500 PART_COUNT Count Done PART_COUNT Batch Complete Alarm BATCH_ALARM OUT 3.0
UTF-8 · LF · 10 lines · 359 chars✓ parsed·1.0 ms·5.6 KB SVG

5. Parallel branches

A parallel: block introduces OR logic — the rung has power if any branch conducts. Each branch is a branch: sub-block with its elements indented below it.

parallel:
  branch:
    XIC(LOCAL_START)
  branch:
    XIC(REMOTE_START)

Branches in a parallel: are evaluated simultaneously. The block closes when indentation returns to the level before parallel:.

Rules:

  • parallel: must appear inside a rung.
  • branch: must appear inside a parallel: — using it alone throws LadderParseError.
  • Each branch holds one or more elements.
  • Elements after the parallel: block are series with it (AND logic).
ladder·§ IEC 61131-3
↘ preview
100%
Parallel OR logic PLC ladder logic diagram with 1 rung Parallel OR logic Rung 001 — Start from either local or remote — Local Start LOCAL_START IN 1.0 Remote Start REMOTE_START BIT 5.2 Stop All STOP_ALL IN 1.5 Conveyor Run CONVEYOR OUT 2.0
UTF-8 · LF · 9 lines · 292 chars✓ parsed·0.7 ms·4.5 KB SVG

6. Labels & comments

  • Title: ladder "Motor Control" — first line only, quoted string.
  • Rung number: required integer after rung.
  • Rung comment: optional quoted string after the rung number, before the optional colon: rung 3 "Run indicator": or rung 3 "Run indicator".
  • Tag: first argument inside the parentheses — displayed below the symbol.
  • Address: second positional argument (quoted): XIC(START_PB, "IN 1.0").
  • Name: name="…" keyword argument — human-readable description displayed above the symbol.
  • Line comments: #, //, or %% at the start of a line (after leading whitespace). The same markers also start trailing comments.

7. Reserved words & escaping

Reserved at line start (case-insensitive): ladder, rung, parallel:, branch:.

Element names are all uppercase ASCII: XIC, XIO, ONS, OSF, OTE, OTL, OTU, OTN, TON, TOFF, TP, CTU, CTD, CTUD, ADD, SUB, MUL, DIV, MOV, EQU, NEQ, GRT, LES, GEQ, LEQ.

Tag IDs — must match [A-Z][A-Z0-9_]* (the parser matches [A-Z][A-Z0-9_]* for the element name prefix). Lowercase tags are accepted inside the parentheses.

Quoted strings in address or name arguments must use double quotes "…".


8. Common mistakes

You wroteParser saysFix
rung 1 (no colon)Parsed correctlyThe trailing colon is optional
ONF(TAG)LadderParseError: unknown element type "ONF"Falling-edge contact is OSF, not ONF
parallel: without branch:Empty parallel block — rung has no elementAdd at least one branch: inside the parallel:
branch: before parallel:LadderParseError: branch: without parallel:Always open parallel: first
OTE() — no tagLadderParseError: element missing tagTag is required: OTE(MY_TAG)
var StartBtn: bool (variable declaration)LadderParseError: invalid element syntaxNo variable declarations — tags are used directly
Empty rung (no elements after rung N:)LadderParseError: Rung N: empty rungAdd at least one element to each rung
TON(T1, T#5s)LadderParseError: invalid element syntax (T# not a valid number)Use milliseconds integer: TON(T1, PT=5000)

9. Grammar (EBNF)

document      = header NEWLINE rung+

header        = "ladder" ( WS quoted-string )? NEWLINE
quoted-string = '"' any-char-but-quote* '"'

rung          = "rung" WS integer ( WS quoted-string )? ":"? NEWLINE
                  element+

element       = contact-line
              | coil-line
              | fb-line
              | parallel-block

contact-line  = contact-type "(" tag ( "," arg )* ")" NEWLINE
contact-type  = "XIC" | "XIO" | "ONS" | "OSF"

coil-line     = coil-type "(" tag ( "," arg )* ")" NEWLINE
coil-type     = "OTE" | "OTL" | "OTU" | "OTN" | "RES"

fb-line       = fb-type "(" tag ( "," arg )* ")" NEWLINE
fb-type       = "TON" | "TOFF" | "TP"
              | "CTU" | "CTD" | "CTUD"
              | "ADD" | "SUB" | "MUL" | "DIV" | "MOV"
              | "EQU" | "NEQ" | "GRT" | "LES" | "GEQ" | "LEQ"

arg           = quoted-string             // positional (address)
              | key "=" quoted-string     // keyword (e.g. name="…")
              | key "=" number            // keyword (e.g. PT=5000)

parallel-block = INDENT≥2 "parallel:" NEWLINE
                   ( INDENT branch-block )+

branch-block   = "branch:" NEWLINE
                   ( INDENT element )+

tag           = [A-Za-z][A-Za-z0-9_]*
key           = [A-Za-z][A-Za-z0-9_]*
integer       = [0-9]+
number        = [0-9]+ ( "." [0-9]+ )?
comment       = ( "#" | "//" | "%%" ) any NEWLINE

Authoritative source: src/diagrams/ladder/parser.ts. If this diverges from the parser, the parser wins — please open an issue.


10. Standard compliance

Schematex ladder logic follows IEC 61131-3:2013 Part 3 for the Ladder Diagram language and uses Allen-Bradley (Rockwell) tag-address-name conventions common in North American PLC practice.

What is implemented today:

  • ✅ Four contact types: XIC (NO), XIO (NC), ONS (rising edge), OSF (falling edge)
  • ✅ Five coil types: OTE (output), OTL (latch/set), OTU (unlatch/reset), OTN (negate), RES (counter/timer reset)
  • ✅ Three timer function blocks: TON, TOFF, TP with millisecond PT= parameter
  • ✅ Three counter function blocks: CTU, CTD, CTUD with integer PV= parameter
  • ✅ Math function blocks: ADD, SUB, MUL, DIV, MOV
  • ✅ Comparison function blocks: EQU, NEQ, GRT, LES, GEQ, LEQ
  • ✅ Parallel / branch blocks for OR logic
  • ✅ Tag, address, and name annotations per Allen-Bradley Studio 5000 conventions
  • ⏳ Retentive timer (RTO) — in the standard; not yet in the parser
  • ⏳ Jump (JMP) / Label (LBL) instructions
  • ⏳ Master Control Reset (MCR) zone
  • ⏳ Immediate I/O instructions (IIN, IOT)
  • ⏳ Structured Text or Function Block Diagram elements embedded in rungs

References:

  • IEC 61131-3:2013 — Programmable controllers, Part 3: Programming languages
  • NEMA ICS 1-2009 — General Standards for Industrial Control and Systems
  • Rockwell Automation Studio 5000 Logix Designer — Ladder Diagram Programming Manual

ladder·§ IEC 61131-3
Motor Start/Stop PLC ladder logic diagram with 1 rung Motor Start/Stop Rung 001 — Seal-in circuit — Start Button START_PB IN 1.0 Aux Contact MOTOR_AUX BIT 3.0 Stop Button STOP_PB IN 1.1 Motor Command MOTOR_CMD OUT 2.0
Motor start/stop seal-in circuit
Classic three-wire motor start/stop seal-in circuit in IEC 61131-3 ladder logic — the foundational pattern taught in every PLC certification course.
industrial & process
ladder·§ IEC 61131-3
System Mode Selection PLC ladder logic diagram with 2 rungs System Mode Selection Rung 001 — Set system Auto mode, reset Manual — Rung 002 — Set Manual, reset Auto (with Home seal-in) — Auto Mode HMI Pushbutton AUTO_HMIPB BIT 5.10 Manual Mode HMI Pushbutton MANL_HMIPB BIT 5.11 System Fault SYS_FAULT BIT 3.0 S System Auto Mode SYS_AUTO BIT 3.1 R System Manual Mode SYS_MANUAL BIT 3.2 Manual Mode HMI Pushbutton MANL_HMIPB BIT 5.11 System Home Command SYS_HOMECMD BIT 3.5 Auto Mode HMI Pushbutton AUTO_HMIPB BIT 5.10 System Fault SYS_FAULT BIT 3.0 S System Manual Mode SYS_MANUAL BIT 3.2 R System Auto Mode SYS_AUTO BIT 3.1
System mode selection (Set/Reset)
IEC 61131-3 ladder logic for HMI-driven Auto/Manual mode selection using Set/Reset (OTL/OTU) coils with system fault interlocks.
industrial & process

12. Roadmap

Planned — not yet parseable. Do not use these in generated DSL today; the parser will reject or ignore them.

  • Retentive Timer On (RTO) — timer that holds elapsed time through power loss; requires a separate reset contact.
  • Jump (JMP) / Label (LBL) — branch to a labeled rung to skip logic conditionally; used in large programs for performance.
  • Master Control Reset (MCR) zone — a bracketed zone that de-energizes all non-retentive outputs when the MCR input is false.
  • Structured text in rungs — inline expression evaluation (e.g., CALC(result = a * b + c)).
  • Immediate I/O (IIN / IOT) — force I/O scan mid-program for time-critical control.

Track in the GitHub issues if you need any of these sooner.