Skip to content

Control Modules

Reusable function-block wrappers for the smallest addressable pieces of equipment: valves, sensors, modulating outputs, and PID loops. Every phase template binds its role names (solvent_valve, agitator, …) to instances of these modules at recipe execution.

New here?

If you're coming from a class-based DCS library or a ladder/AOI environment, read Mental Models first. It maps these modules onto concepts you already know.

The canonical library is the set of templates below. Control modules publish raw diagnostic tags (PV, MISMATCH, FAULT). Thresholds, debounce, severity, and exception actions live in AlarmDefinition CRs (see the pattern). The one exception is vfd, which carries an in-network fault interlock for hardware-fast drive disable.

Every template declares a deviceClass (valve, actuator, sensor, controller, other) and a per-tag role (state, setpoint, command, feedback, alarm, interlock) that tell the HMI how to render its cards and faceplates (ADR 0016). The meaning is declared, and the HMI never infers it from moduleType or tag names. Tags without a role render as generic rows.

Derived device state

A device whose state has more than two words (a dual-limit-switch valve that can be Fault / Open / Closed / Traveling) computes its state word in the template's FB network with the DEVSTATE block (ADR 0018): a priority encoder whose Boolean inputs IN1IN8 are evaluated in order, params state1state8 name the word for each, the first true input wins, and the required default param names the word when none is true. The block's string OUT backs an ordinary template tag declared role: state, dataType: String, accessLevel: read. That declaration makes the state word a real tag: readable from phase logic (READ('feed-valve.STATE') = 'Traveling'), historized as text, published on MQTT, and rendered verbatim by the HMI card and faceplate. The enumeration lives in the block params, schema-visible and change-controlled. No lookup table inside a renderer carries it.

The derived tag is read-only at every layer: external writes are rejected by the tag's access level, and the runtime refuses output overrides on the block itself. Alarm duty stays on Boolean companion tags computed from the same subnetwork (e.g. MISMATCH), because alarm conditions evaluate Boolean/numeric tags. A single-feedback device (e.g. discrete-valve) keeps its Boolean state tag with trueLabel/falseLabel. There is nothing to synthesize. The worked example is solenoid-valve.

Discrete / binary

Module Purpose
discrete-valve Recipe-driven binary on/off valve with single feedback.
solenoid-valve Binary on/off valve with dual-limit-switch feedback.

Analog sensing

Module Purpose
analog-sensor Read-only analog input with raw → engineering scaling. Alarms via AlarmDefinition.

Modulating control

Module Purpose
analog-control Modulating analog output with feedback and deviation alarm.
pid-loop Single-loop PID controller — PV, SP, CV with mode handling.
pid-cascade PID with external (supervisory) setpoint for cascade control.

Motor / drive

Module Purpose
vfd Variable-frequency drive with run/speed and hardware-fast fault interlock.