A tuning that is stable here can be unstable on the plant This simulates an ideal first-order-plus-dead-time process against an ideal controller. Real loops have valve stiction, actuator limits, measurement noise, drifting gain and neighbours that fight back, and none of that is modelled here. Never carry a gain set from this page to a live loop. Open for the full scope limits.
What this tool actually simulates
A first-order-plus-dead-time process driven by a parallel-form PID controller with zero-order hold and anti-windup, plus the classical tuning rules: Ziegler-Nichols, Cohen-Coon, AMIGO and lambda. It is a faithful simulation of that model, and it is a good way to build intuition for what each term does.
FOPDT is a deliberate idealisation. It is a useful caricature of a real process, not a description of one.
Not modelled, at all
- The valve. Stiction, backlash, dead band, hysteresis and non-linear installed characteristic are absent. Stiction in particular produces a sustained limit cycle that no amount of retuning fixes, and it is the most common cause of a loop that oscillates in service and behaves in simulation.
- Actuator limits. No stroke time, slew rate, or saturation beyond the anti-windup path. A controller that asks for a step the actuator cannot deliver is a different loop.
- Measurement reality. No sensor noise, no filter lag, no transmitter span or calibration error, no aliasing from a sample rate that is slow relative to the dynamics. Derivative action amplifies noise, and there is no noise here for it to amplify.
- A process that changes. Real gain and dead time move with throughput, composition, fouling and ambient. A tuning that is optimal at one operating point can be marginal at another.
- Non-linearity. No pH curves, no heat-transfer non-linearity, no split range, no integrating or open-loop-unstable processes.
- Interaction. One loop in isolation. Real plants have coupled loops, cascades, feedforward and constraint controllers that fight each other.
- Everything around the loop. No bumpless transfer, no mode handling, no output tracking, no failure or fallback behaviour, no interlocks.
The classical tuning rules are starting points, not answers. Ziegler-Nichols in particular is deliberately aggressive and is a poor choice for most real loops as published.
Never use this for
- Tuning, retuning or commissioning a live control loop.
- Any safety instrumented function or protective layer under IEC 61511 or IEC 61508.
- Process safety decisions, HAZOP or LOPA inputs, or alarm rationalisation.
- Sizing or selecting a valve, actuator or transmitter.
- Acceptance testing, validation, or any regulated qualification record.
A loop that is unstable on a running plant does not produce a bad graph. It produces a process excursion, and on the wrong unit that is a safety event.
Before touching a real controller
Identify the process from plant data rather than assuming a model. Detune from any classical rule and verify gain and phase margin. Test in manual and step cautiously, with the operator informed and an abort plan. Have the change reviewed by a control engineer who knows the unit, under the site's management of change process.
Ideal FOPDT model. No valve stiction, actuator limits, measurement noise, changing process gain or loop interaction. A tuning that is stable here can be unstable on the plant, so never carry these gains to a live loop. See the full disclaimer at the top of the page.
1Process Loop
A self-regulating first-order-plus-dead-time process under parallel-form PID control. Use the Process Narrative buttons to load realistic numbers for fast flow, jacketed temperature, heat exchanger, or composition loops, or stay on the normalized educational case. The dead time can be a non-integer multiple of the integration step; the delay buffer interpolates linearly between samples.
Physical Setup
Educational FOPDT
- What it is
- --
- What dominates
- --
- What to look for
- --
- Tuning recommendation
- --
- Cautions
- --
2Metrics; shift-click any underlined term for a glossary entry
3Process Variable
4Controller Output
5Open-Loop Frequency Response
Continuous-time loop L(s) = C(s) G(s) computed from the configured FOPDT plant and parallel-form PID gains. The sample-and-hold approximation is omitted; this is the textbook loop the discrete simulator is approximating.
Exports
Build metadata pending.
Method and Scope
Process model
The plant is a first-order-plus-dead-time (FOPDT) self-regulating process driven by a delayed manipulated variable plus an additive load disturbance:
tau * dPV/dt = -(PV - pv_baseline) + K * u(t - theta) + d(t)
The continuous solution under a piecewise-constant input is integrated exactly by zero-order hold each step:
PV[k+1] = PV[k] * exp(-dt/tau)
+ target * (1 - exp(-dt/tau))
target = pv_baseline + K * u_delayed + d
This is exact within floating-point precision and removes any Euler stability constraint on dt. Dead time is implemented as a delay buffer with linear interpolation between adjacent samples when theta is not an integer multiple of dt.
PID controller
Parallel form, evaluated at the controller sample time Ts and held with a zero-order hold between samples:
error = SP - measurement
P = Kp * error
I = I + Ki * error * Ts (with anti-windup, see below)
D = -Kd * filtered_derivative_of_measurement (derivative-on-measurement)
or
D = +Kd * filtered_derivative_of_error (derivative-on-error)
u_raw = bias + P + I + D
u = clamp(u_raw, u_min, u_max)
The derivative branch is the discrete equivalent of a first-order ISA-style filter D(s) = Kd s / (1 + Tf s). The discrete pole is alpha = exp(-Ts / Tf); Tf = 0 disables filtering. The equivalent ideal-form parameters are Ti = Kp / Ki and Td = Kd / Kp; both are shown live next to the gain inputs.
Anti-windup strategies
- Off. Integrator updates every sample regardless of saturation. Useful only to demonstrate windup behavior.
- Conditional (clamp). The integrator is frozen whenever the pre-integration command is already saturated and the proposed integral update would push it further into the limit. The other direction is allowed so the integrator can pull the actuator back into range.
- Back-calculation. Each tick adds
(u_clamped - u_raw) * Ts / Ttto the integral. When the controller is unsaturated this term is zero; when saturated, it drives the integrator back at a rate set by the tracking time Tt. This is the strategy used in most modern industrial PID blocks (Siemens, ABB, AB, Honeywell).
Tuning rules
The Tuning Rules panel applies open-loop FOPDT correlations to the configured K, tau, and theta. Each rule rewrites only the controller gains so you can compare them on the same plant:
- Ziegler-Nichols PI: Kc = 0.9 * tau / (K * theta), Ti = theta / 0.3.
- Ziegler-Nichols PID: Kc = 1.2 * tau / (K * theta), Ti = 2 * theta, Td = 0.5 * theta.
- Cohen-Coon PI/PID: classic 1953 correlations; less detuning needed for dead-time-dominated loops than Z-N.
- AMIGO PI/PID: Astrom-Hagglund robustness-focused rule derived from constrained optimization.
- Lambda PI: IMC tuning with closed-loop time constant lambda = tau. Decreasing lambda makes the loop faster but less robust.
The displayed Kp / Ki / Kd, plus the matching Ti and Td readouts, are exactly what the tuning rule produced; nothing is silently re-shaped.
Measurement noise
Noise is zero-mean Gaussian with standard deviation equal to the configured amplitude. The generator is Box-Muller built on a deterministic 32-bit LCG so that Rust and Python produce identical sequences from the same seed. Fixtures are reproducible bit-for-bit.
Frequency-domain analysis
The Bode plots evaluate the continuous-time open-loop transfer function on a fixed log frequency grid (1e-3 to 1e3 rad/s, 256 points):
C(s) = Kp + Ki/s + Kd * s / (1 + Tf * s)
G(s) = K * exp(-theta * s) / (1 + tau * s)
L(s) = C(s) * G(s)
S(s) = 1 / (1 + L(s))
- Phase margin (PM) is 180 deg + angle of L at the first omega where |L(jw)| = 1.
- Gain margin (GM) is -20 log10 |L(jwpc)| at the first omega where the unwrapped phase crosses -180 deg.
- Sensitivity peak Ms = max |S(jw)| over the grid. Industrial loops aim for Ms in 1.4-2.0; below 1.4 is conservative and slow, above 2.0 is fragile.
- Gain crossover wgc marks the closed-loop bandwidth and is annotated on both subplots.
The Bode plot is computed from the configured K, tau, theta, Kp, Ki, Kd, and Tf in closed form -- it updates instantly when any tuning rule or slider is moved, with no second simulation pass needed.
Metrics
- Overshoot is direction-aware (positive and negative steps both produce non-negative overshoot).
- Rise time is the 10% to 90% rise time of the PV trajectory after the setpoint step.
- Settling time is measured against a configurable tolerance band (default 2% of the step magnitude) and is the first time after which PV stays inside the band for the rest of the horizon.
- IAE / ISE / ITAE integrate absolute, squared, and time-weighted absolute error over the horizon. ITAE is weighted from the step time forward.
- Saturation percent is the fraction of samples where the actuator command was clamped.
- Max / Min PV / output are the extrema of the recorded trajectories.
- Settled is true when the loop reached the tolerance band before the horizon ended.
Verification boundary
The Python reference in verification/pid_reference.py is the numerical ground truth. It generates deterministic fixtures consumed by the Rust crate's regression test, and is also a readable side-by-side derivation of the controller and the integrator. The browser runtime uses the Rust/WASM port; passing tests mean Rust/Python agree to within 1e-8 absolute tolerance on every recorded series and metric.
Scope and limitations
Reference simulation only. FOPDT is a deliberate idealization; real plants have constraints, nonlinearity, valve hysteresis, and stochastic disturbances that this tool does not represent. Do not use these results for process-safety decisions or plant tuning without independent validation. The author makes no warranty as to fitness for any particular use.
Learning References
PID terms and response metrics
Anti-windup strategies
MathWorks: PID Controller block (clamping & back-calculation)
Tuning rules
OptiControls: Ziegler-Nichols and Cohen-Coon open-loop tuning
AMIGO and lambda tuning
Skogestad: Simple analytic rules for model reduction and PID controller tuning