Skip to content

Control Module: pid-loop

A single-loop PID controller. Reads a process variable from an analog input, holds the setpoint in an operator- or recipe-writable register, computes a PID control output, and writes that output to an analog output. Use this template for any self-contained regulatory control loop where the setpoint comes from an operator or a recipe step.

For cascade control where the setpoint is driven by another controller or a supervisory system, use the pid-cascade template instead.

Where to find it

System endpoint → Equipment Library → Control Modules tab → select pid-loop.

pid-loop FBD: AI process variable, REAL_CONST setpoint, PID controller, AO output

pid-loop ST: IEC 61131-3 program reading PV from the AI, holding SP, computing the PID output (kp/ki/kd) into CV, and writing CV to the AO

What you see on the faceplate

Clicking a pid-loop instance on the unit detail view opens a faceplate with:

Element Meaning
PV Process variable (read-only)
SP Setpoint (writable in Manual mode)
CV Control output percentage, 0-100 (writable in Manual mode)

The faceplate shows ISA-88 mode. In Manual mode an operator can write the setpoint directly, or drive CV directly for the commissioning workflow below. In Automatic mode a recipe step owns the setpoint and the PID block owns CV. Both writes are refused.

Tags

The template declares deviceClass: controller and a role on each tag (ADR 0016). The HMI renders from these declarations and never infers meaning from moduleType or tag names. SP (role: setpoint) fills the HMI setpoint bar. PV (role: feedback) fills the feedback bar and, with no role: state tag, is the card's prominent value. CV (role: command) renders as the commanded output.

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/write setpoint Setpoint. Operator or recipe writes this.
CV Float read/write command Control output (0-100%) driven to the analog output. Writable only in Manual mode — see "How it works" for what a write does.
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.
PV_BAD Boolean read alarm true while the process variable is not trusted: the driver reported bad quality, the read failed, or the raw value fell outside the fail band. PV holds its last trusted reading while this is set, and the loop holds its output. A TagTrue AlarmDefinition on this is worth having on any loop whose instrument can fail.

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) Process variable 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.
rawFailLow / rawFailHigh (blank — no band) Raw counts outside which the input reading is rejected and PV_BAD is raised. Both or neither. Leave blank wherever the driver already reports quality of its own, which is OPC UA, simulation, and a Modbus card whose range diagnostic this product knows — see "How it works" for what a band can and cannot detect.

Setting interlockAddress on an instance enables the device interlock. See Alarms and Interlocks → Pattern 0.

The scan interval is fixed at 100 ms, faster than other analog templates because closed-loop PID needs tighter response.

How it works

Each scan, the runtime:

  1. Reads the process variable from the analog input.
  2. Computes PID output against the current setpoint using kp, ki, kd.
  3. Writes the resulting CV to the analog output, clamped to 0-100%.

The PID block uses a standard parallel form. Tune gains in the detail view's Parameters section. The PID block also clamps its own output to outMin/outMax (0-100% by default) and, whenever that clamp engages, backs the current scan's error back out of the integral. The integrator stops growing once CV saturates. This clamping anti-windup is built into the block itself. There is no output rate limiting in this template. If you need that, derive a new template from this one.

When the device interlock is enabled (see interlockAddress above) and trips, the analog output is forced to its safe value. The template wires the output block's interlock state into the PID's TRK input (freezing the integrator) and the output block's actually-written value into the PID's TRK_VAL input (back-calculation output tracking). While forced, the PID tracks the value the device really sees. When the interlock releases, the loop resumes from the real output, a bumpless transfer. Without the tracking it would resume from a wound-up state. This is inert unless the interlock is enabled, so existing instances are unaffected.

A process variable the block cannot trust holds the loop. A broken 4-20 mA wire is still a successful read of a register, and the register holds a value near the bottom of span. Scaled naively that is an ordinary reading of about 0 %, the error against any setpoint above it is close to maximal, and the loop answers by driving the valve to the opposite rail. So the input block does not publish a reading it does not stand behind. It holds PV at the last trusted value, raises PV_BAD, and faults itself so the control program reports Degraded with the block named. The template wires PV_BAD into the PID, which holds its output at the value it actually wrote and resumes bumplessly when the instrument comes back.

Two things decide whether a reading is trusted. The driver may report it, which needs no configuration. That happens on OPC UA, in simulation, and on a Modbus card whose own range diagnostic this product knows. A WAGO 750-454 states a broken wire in the low bits of the same word that carries the measurement, and the driver reports the bit the card set. Or the raw value may fall outside rawFailLow and rawFailHigh, which is what remains where the driver reports nothing.

A band is not a rule of thumb, and it is not always available. It separates a dead transmitter from a live one only where the values a failure produces lie outside the interval genuine readings occupy. A card that maps 4 mA onto raw zero does not do that. The 750-454 carries its measurement in the top thirteen bits, so a genuine reading is a multiple of eight. Its broken-wire code is raw 3, which falls strictly between the genuine readings 0 and 8. A band accepts a closed interval, so no pair of bounds rejects the fault while accepting both of its neighbours. The band cannot express the condition at any setting. That card needs none, because the driver already reports its bits. Set a band only from numbers measured on the specific card, and only where those numbers separate. Full reasoning: ADR 0074 and its #1740 amendment.

Manual mode drives CV directly. With the equipment in Manual mode, writing CV overrides the PID block's own output. The write reaches the analog output on the next scan, bypassing the PID computation entirely. Automatic mode refuses the write (ISA-88 Table 1: the control algorithm owns the equipment). The PID block tracks a Manual CV override the same way it tracks a device-forced value above, bumpless in both directions, with no separate mechanism. Switching back to Automatic hands control back to the loop's own computation with no extra step. The operator's last-driven value is what the loop resumes from.

Tuning

The pid-loop template ships with conservative default gains that work on the simulator but will need adjustment for any real loop. This section covers the practical commissioning workflow: the steps you'd actually follow on a new equipment area. It teaches no vendor-specific tuning method.

Parallel form

The template implements the standard parallel form:

CV(t) = kp·e(t) + ki·∫e(t)dt + kd·de(t)/dt

where e = SP - PV. This is different from the ideal (also called "dependent") form some vendors use, where ki and kd are expressed as time constants relative to kp (e.g. Ti = kp/ki, Td = kd/kp). If you're porting tuning constants from another system, check which form the source used and convert before pasting.

What each gain does, in isolation

Walk a new loop one gain at a time:

Gain Bump it up if Bump it down if
kp The PV is consistently short of setpoint The PV oscillates around setpoint
ki The PV reaches setpoint slowly and parks just below The PV overshoots and takes forever to settle
kd A step disturbance causes a long, slow recovery The PV jitters on noisy input

For most loops, start with kp only (ki = 0, kd = 0), get the loop to track without oscillating, then add a small ki to eliminate the steady-state offset, then add kd only if you genuinely need faster disturbance rejection. Many pharmaceutical loops never use kd.

Practical commissioning workflow

  1. Open the trend chart on this loop's PV, SP, and CV tags via the Data endpoint → Trends view. Keep all three on the same chart.
  2. Switch to Manual mode from the faceplate. The operator owns CV directly.
  3. Step the CV by 10–20 % and watch how PV responds:
    • Time to first response: how long before PV starts moving? That's your dead time.
    • Time to peak / steady state: how long until PV settles at a new value?
    • Process gain: by how much did PV change per 1 % of CV?
  4. Set initial kp to roughly 0.5 / process_gain and ki to 1 / (4 × time_to_steady_state). These are conservative starting values that almost never cause oscillation.
  5. Switch back to Auto from the faceplate. Set the recipe-driven setpoint and watch PV track. Use the trend chart to verify:
    • No sustained oscillation. A few cycles of damped oscillation after a setpoint change is fine. Never-decaying oscillation means kp is too high.
    • Reaches setpoint within a reasonable time. "Reasonable" depends on the process: minutes for a reactor jacket, seconds for a flow loop.
    • No persistent offset. If PV parks consistently above or below SP, you need more ki.
  6. Iterate in steps of ±25 % on each gain. Don't change two gains at once. You won't know which one caused the change.

When to escalate

The single-loop pid-loop template is intentionally simple. Move to a different template (or derive a new one) when you need:

  • Cascade control — outer-loop setpoint drives an inner-loop setpoint. Use pid-cascade instead. Common pattern: outer loop is reactor temperature, inner loop is jacket temperature. The outer-loop output becomes the inner-loop SP.
  • Output rate limiting — for loops driving slow actuators, a CV rate limit prevents the controller from commanding faster moves than the actuator can follow.
  • Feedforward — adding a measurable disturbance signal directly into the CV calculation, ahead of the feedback path.

For each of these, the right move is to derive a new control-module template. Keep the same pid-loop interface (PV, SP, CV) so existing phase templates that bind to a pid-loop role can use the new template without modification.

What good tuning looks like on the trend chart

A well-tuned loop, after a setpoint change, shows:

  • One small overshoot of 5–10 % of the SP step
  • Damped oscillation that disappears within 2–3 cycles
  • No persistent offset between PV and SP after settling
  • CV movement proportional to deviation, no rapid hunting

Bad signs to look for:

  • Sustained oscillation — kp too high or ki too high
  • Slow drift toward setpoint — ki too low
  • CV saturated at 0 % or 100 % for long periods — the loop is asking for more authority than the actuator can deliver. Either the process is undersized or there's a hardware fault. Adding more kp won't help. Fix the equipment or escalate to cascade with a faster inner loop.
  • Noisy CV — kd too high on a noisy PV signal. Try kd = 0 first. Add kd only once kp and ki are stable.

The faceplate trend view shows PV, SP, and CV together so you can diagnose all of these visually without exporting data.

Reference instances

Unit Instance Purpose
mix-tank-1 N2 blanket pressure controller Holds tank headspace pressure at target during fills and transfers

The reference plant uses only one pid-loop instance. Most temperature and agitator control in the reference plant is handled by analog-control (feedback + deviation alarm). Closed-loop PID is the exception there.

Try it

  1. Process → riverbend → pharma-area → sim-cell → mix-tank-1
  2. Click the N2 blanket pressure symbol on the unit detail view
  3. On the faceplate, write a new setpoint (SP) — e.g. change from 0.2 bar to 0.3 bar
  4. Watch PV converge on the new setpoint and CV settle at the steady-state output
  5. Open a trend chart with PV, SP, and CV on the same chart to see the loop response