Control Module: pid-cascade¶
A PID controller whose setpoint is read from an external tag address, typically the output of an outer-loop controller or a supervisory system. Use this template for the inner loop of a cascade pair, for ratio control, or any situation where the SP does not come from an operator/recipe register.
For a single self-contained loop with an operator- or recipe-writable
setpoint, use pid-loop instead.
Where to find it¶
System endpoint → Equipment Library → Control Modules tab → select pid-cascade.


What you see on the faceplate¶
| Element | Meaning |
|---|---|
| PV | Process variable (read-only) |
| SP | Setpoint, sourced from an external AI (read-only) |
| CV | Control output percentage, 0–100 (read-only) |
Unlike pid-loop, the SP is read-only on the faceplate. If you need
to manually override the SP during commissioning, the right move is to
switch the outer loop's owner to Manual. That keeps the cascade
relationship explicit. Editing this inner loop directly would hide it.
Tags¶
The template declares deviceClass: controller and a role on each tag
(ADR 0016), matching
pid-loop: SP is the setpoint (read-only here, tracking the
external source), PV the feedback and the card's
prominent value, and CV a roleless generic row.
| Tag | Type | Access | Role | Description |
|---|---|---|---|---|
PV |
Float | read | feedback |
Measured process variable, scaled to engineering units. Shown as the card's prominent value. |
SP |
Float | read | setpoint |
Setpoint read from the external tag address. |
CV |
Float | read | — | Control output (0–100%) driven to the analog output. |
ILCK |
Boolean | read | interlock |
true while the device interlock is forcing the output to its safe state. Reserve a TagTrue AlarmDefinition for interlocks whose trip is abnormal in itself (why). The historian records every trip either way. |
Parameters¶
| Parameter | Default | What it does |
|---|---|---|
kp |
1.0 |
Proportional gain |
ki |
0.1 |
Integral gain |
kd |
0.01 |
Derivative gain |
eng_min / eng_max |
(blank) | PV and SP scale range |
eng_units |
(blank) | Display units for PV and SP |
interlockAddress |
(empty — interlock disabled) | Device address of a boolean trip signal, read by the output block every scan; while tripped (or unreadable — fail-safe) the output is forced to the safe value. |
interlockInvert |
false |
Trip while the signal is false (with the invert off, true trips). |
safeValue |
(empty) | Output value forced while interlocked. Empty means the output range minimum. |
Setting interlockAddress on an instance enables the device interlock.
See Alarms and Interlocks → Pattern 0.
Scan interval is fixed at 100 ms, matching pid-loop.
How it works¶
Each scan, the runtime:
- Reads
PVfrom thepvinput tag address. - Reads
SPfrom thespinput tag address (the outer-loop output, or a supervisory target). - Computes PID output against the error
SP − PV. - Writes
CV(0–100%) to theouttag address.
Tuning advice is identical to pid-loop. See its
tuning section. The cascade-specific pitfall is
windup when the outer loop is slow. If the inner loop saturates at
0% or 100%, the integrator keeps accumulating until the outer loop
catches up, then overshoots badly. If this hurts you, derive a new
template with back-calculation anti-windup.
As with pid-loop, when the device interlock is enabled and trips, the
template freezes the integrator (TRK) and back-calculates it from the
output's actually-written value (TRK_VAL). The inner loop tracks
what the device really sees and resumes bumplessly on release. The same
back-calculation mechanism is how a cascade inner loop initializes from
its real output. Wire the outer loop's TRK_VAL from the inner loop's
setpoint source so the outer loop hands off without a bump when it takes
over (see the wiring pattern below).
Cascade wiring pattern¶
Typical pairing:
- Outer loop —
pid-loopdriving the cascade setpoint.CVof the outer loop is written (via an analog output address, or directly via an internal tag) to the same tag address that the inner loop reads assp. - Inner loop —
pid-cascade, taking its SP from that address.
The outer-loop scan rate should be slower than the inner's, typically 2–10×. A reactor temperature / jacket temperature cascade might run the outer loop at 1 s and the inner at 100 ms.
Failure modes¶
- SP source tag goes stale / offline —
pid-cascadecontinues running with the last-read value, which may not be obvious to an operator. Wrap the SP source with an AlarmDefinition on IOModuleStateEquals: Offlineso the batch holds when the supervisory link fails. - Outer loop saturated long-term — SP pinned at its limit means the cascade can't deliver what the supervisory loop wants. Fix by revisiting outer-loop tuning or actuator sizing. Raising inner gains fixes nothing here.
Reference instances¶
| Deployment | Unit | Instance | Purpose |
|---|---|---|---|
| newark-plant | granulator-1 | jacket-temp-ctrl |
Granulator bowl jacket temperature tracks the recipe-driven SP written by the outer temperature loop |
The reference plant currently has no pid-cascade instances. It uses pid-loop
for its single closed loop (N2 blanket pressure). Add a pid-cascade
when demonstrating reactor-jacket cascade control.
Try it¶
On newark-plant:
- Process → newark-plant → granulator-1
- Click jacket-temp-ctrl on the unit detail view
- Observe
PV,SP, andCV— note thatSPis read-only on the faceplate - Write to the
Granulator1.JacketTempSPaddress (via the outer loop or an operator override) and watch the cascade track