Schematex

Block diagram

About block diagrams

A block diagram models a system as a set of functional blocks connected by directed signal lines. Each block represents a component whose behavior is captured by a transfer function or a descriptive label; signals flow through the blocks in a defined direction. Control engineers use them to design feedback loops, signal-processing engineers use them to document filter chains, and systems engineers use them to decompose complex architectures. The defining visual elements — rectangular blocks and circular summing junctions — are conventions drawn from control systems analysis (Ogata, Franklin, Nise) and carried into every datasheet and textbook that describes a feedback system.

Schematex follows the Laplace-domain transfer-function convention used in control systems textbooks: blocks are labeled with their transfer functions, summing junctions carry explicit +/ polarity signs, and a discrete flag on signals renders a dashed line for sampled-data paths. This page documents what the parser accepts today. Authoritative references: Ogata (2010) Modern Control Engineering; Franklin, Powell & Emami-Naeini (2018) Feedback Control of Dynamic Systems.

blockdiagram·§
↘ preview
100%
Audio dynamics processor Block diagram with 6 blocks, 1 summing junctions, 7 signals Audio dynamics processor Input + gated compressed Output Noise gate Compressor 3-band EQ Limiter Level detect in in
UTF-8 · LF · 26 lines · 623 chars✓ parsed·3.6 ms·4.6 KB SVG

1. Your first block diagram

The smallest useful block diagram: one controller, one plant, one feedback loop.

blockdiagram·§
↘ preview
100%
Temperature control Block diagram with 4 blocks, 1 summing junctions, 5 signals Temperature control Setpoint + T_measured + PID Heater Thermocouple in in
UTF-8 · LF · 14 lines · 339 chars✓ parsed·1.6 ms·3.6 KB SVG

Four rules cover 80% of usage:

  1. Start with blockdiagram, optionally followed by a quoted title.
  2. Declare each component with ID = block("label"), each summing junction with ID = sum(+a, -b), and each named signal with ID = signal("label").
  3. Connect components with ->. Chain multiple hops on one line: A -> B -> C.
  4. Optionally annotate connections with a trailing label: A -> B ["E(s)"].

Comments must start with # on their own line.


2. Blocks

A block represents any functional element — controller, plant, filter, actuator, sensor. The label is typically a transfer function or a descriptive name.

Syntax: ID = block("label") [role: X]

AttributeValuesEffect
role: plantplant, controller, sensor, actuator, reference, disturbance, genericVisual color coding; generic is the default
route: aboveabove, belowRouting hint for feedback and feedforward blocks

ID rules. Must start with a letter or underscore, followed by letters, digits, or underscores: [A-Za-z_]\w*.

blockdiagram·§
↘ preview
100%
Block roles Block diagram with 6 blocks, 0 summing junctions, 5 signals Block roles r(t) C(s) Actuator G(s) H(s) d(t)
UTF-8 · LF · 12 lines · 339 chars✓ parsed·0.7 ms·3.5 KB SVG

3. Summing junctions

A summing junction combines multiple signals into one, with explicit polarity for each input. It renders as a circle with +/ signs — the standard control-systems symbol.

Syntax: ID = sum(+a, -b, +c, …)

  • Each input is a signed ID: +x adds signal x, -y subtracts signal y.
  • An input without a sign is treated as positive.
  • The summing junction ID is then used as the target of connection lines, just like a block ID.
blockdiagram·§
↘ preview
100%
Error with disturbance rejection Block diagram with 4 blocks, 2 summing junctions, 6 signals Error with disturbance rejection r (setpoint) + y_m u(t) + + PI C(s) G(s) H(s) in in
UTF-8 · LF · 20 lines · 519 chars✓ parsed·0.6 ms·4.0 KB SVG

4. Signals

A signal declaration creates a named signal node that the parser inlines as an edge label. Signals are pass-through: when the parser sees A -> sig and sig -> B, it merges them into a single edge from A to B, labeling it with the signal's display text.

Syntax: ID = signal("label") [discrete]

  • Omit [discrete] for continuous signals (solid line).
  • Add [discrete] for sampled-data signals (dashed line).
e_sig = signal("E(s)")
u_sig = signal("U(s)") [discrete]

Signals are purely a labeling convenience — you can also label edges directly with a trailing attribute (see §5).


5. Connections

A connection line is from -> to. The -> operator always produces a directed, arrowed line.

Single hop: A -> B

Chain: A -> B -> C — equivalent to A -> B and B -> C. Both are written in one line.

With a signal label: append ["label text"] at the end of the chain. The label applies to the last hop only.

ctrl -> plant ["U(s)"]

With a discrete flag: append [discrete] to make the last-hop arrow dashed.

plant -> adc ["y"] [discrete]

Both label and discrete: use [label: "Y(s)", discrete] (comma-separated).

adc -> ctrl [label: "y[k]", discrete]
blockdiagram·§
↘ preview
100%
Mixed continuous/discrete Block diagram with 5 blocks, 1 summing junctions, 7 signals Mixed continuous/discrete r[k] + u[k] u(t) y(t) Digital PID DAC G(s) ADC in in
UTF-8 · LF · 16 lines · 415 chars✓ parsed·0.5 ms·4.2 KB SVG

6. Labels & comments

  • Title: blockdiagram "My System" — first line, quoted.
  • Block label: the quoted string inside block("…") — appears inside the box.
  • Signal label: the quoted string inside signal("…") — appears on the merged edge.
  • Edge label: trailing ["text"] or [label: "text"] on a connection line — appears on that arrow.
  • Comments: # at the start of a line (after leading whitespace). Inline trailing comments are not supported.

7. Reserved words & escaping

Reserved at line start: blockdiagram (header).

Structural keywords (avoid as block/signal/sum IDs to prevent ambiguity): block, signal, sum.

in and out are conventional IDs for the external boundary of a diagram — the parser treats them as ordinary identifiers, but the renderer uses them as implicit source/sink nodes. Using in -> r and plant -> out is idiomatic.

Strings with spaces must be double-quoted in block("…") and signal("…") labels.


8. Common mistakes

You wroteParser saysFix
G = block(G(s)) (no quotes)Parse fails — label must be quotedG = block("G(s)")
err = sum(r, -ym) (no +)r treated as +r — works, but ambiguousWrite sum(+r, -ym) for clarity
ctrl -> plant, plant -> out (comma on one line), is not a separator — parse failsOne connection per line or use chain: ctrl -> plant -> out
s1 = signal("E(s)") [label: "E"]label: not valid on signal; use it on connectionsDrop label: from signal declaration
role: filterUnknown role — silently defaults to genericUse plant, controller, sensor, actuator, reference, disturbance, or generic
A -> B [discrete, label: "e"] — label first failsOrder of attrs inside […] doesn't matter, but bare "text" shorthand only works when it's the only itemUse [label: "e", discrete]

9. Grammar (EBNF)

document       = header (blank | comment | block-def | sum-def | signal-def | connection)*

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

block-def      = id WS "=" WS "block" "(" quoted-string ")" ( "[" block-attrs "]" )? NEWLINE
block-attrs    = block-attr ("," block-attr)*
block-attr     = "role:" role | "route:" ("above" | "below")
role           = "plant" | "controller" | "sensor" | "actuator"
               | "reference" | "disturbance" | "generic"

sum-def        = id WS "=" WS "sum" "(" sum-inputs ")" NEWLINE
sum-inputs     = sum-input ("," sum-input)*
sum-input      = ("+" | "-")? id

signal-def     = id WS "=" WS "signal" "(" quoted-string ")" ( "[" "discrete" "]" )? NEWLINE

connection     = id ("->" id)+ ( "[" conn-attrs "]" )? NEWLINE
conn-attrs     = quoted-string                          # shorthand: bare label only
               | conn-attr ("," conn-attr)*
conn-attr      = "label:" quoted-string | "discrete"

id             = [A-Za-z_] \w*
comment        = "#" any NEWLINE

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


10. Standard compliance

Schematex block diagrams follow the Laplace-domain transfer-function conventions from Ogata (2010) and Franklin et al. (2018) — the block, summing junction, and directed signal-line symbols found in every control systems textbook.

What is implemented today:

  • ✅ Rectangular blocks with transfer-function labels
  • ✅ Circular summing junctions with +/ polarity inputs
  • ✅ Named signal nodes (pass-through, merge to edge label)
  • ✅ Directed connections with chaining (A -> B -> C)
  • ✅ Edge labels — signal names on arrows
  • discrete flag — dashed line for sampled-data signals
  • ✅ Role annotations (plant, controller, sensor, actuator, reference, disturbance, generic)
  • route: above | below hint for feedback/feedforward placement
  • ⏳ Branch/pickoff point — explicit dot symbol where one signal fans out to two destinations
  • ⏳ Boundary box — dashed subsystem enclosure with label
  • ⏳ Bidirectional arrows — <-> for two-way signal exchange
  • ⏳ Bus notation — thick line representing a vector of signals

References:

  • Ogata, K. (2010). Modern Control Engineering, 5th ed. Prentice Hall.
  • Franklin, G.F., Powell, J.D. & Emami-Naeini, A. (2018). Feedback Control of Dynamic Systems, 8th ed. Pearson.


12. Roadmap

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

  • Branch/pickoff point symbol — explicit dot primitive where one output fans to multiple destinations (currently the renderer auto-inserts a branch when an ID is used as a source more than once, but there is no explicit syntax).
  • Subsystem boundary boxboundary "label" { … } block that draws a dashed rectangle enclosing the contained blocks, used for multi-loop and subsystem views.
  • Bidirectional connectionA <-> B for components with mutual information exchange (e.g. a bus interface).
  • Bus (vector signal) notation — thick line with a slash-and-count annotation //n indicating an n-wide signal bus.
  • Nested subsystems — a block whose interior is itself a block diagram, collapsible in the rendered output.

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