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 endpointEquipment LibraryControl 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 (read-only)

The faceplate shows ISA-88 mode. In Manual mode an operator can write the setpoint directly. In Automatic mode a recipe step owns it.

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 carries no role and renders as a 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/write setpoint Setpoint. Operator or recipe writes this.
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) 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.

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. There is no anti-windup or output rate limiting in this template. If you need those, 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.

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.
  • Anti-windup — the integral term keeps growing while CV is saturated against the 0–100 % limits, then overshoots wildly on the way back. The base pid-loop doesn't have anti-windup. You'll see a slow recovery after long saturation events. Derive a new template with a back-calculation or clamping anti-windup if this is hurting you.
  • Bumpless transfer on Manual/Auto — switching between Manual and Auto causes a CV jump because the integrator hasn't been keeping up. The default template doesn't preset the integrator on operator mode change. (Bumpless transfer on device-interlock release is already built in. The integrator is back-calculated from the output's actually-written value via TRK/TRK_VAL. See "How it works".)
  • 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 oscillationkp too high or ki too high
  • Slow drift toward setpointki 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 CVkd 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. Processriverbendpharma-areasim-cellmix-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