← Articles
SCADA/8 min read/ views

Why Your PID Loop Overshoots Every Time the Valve Hits a Limit

Reset windup is why a well-tuned loop overshoots after saturation or a manual-to-auto swap. What anti-windup and external reset actually fix in a PLC.

SCADAControlPLCTroubleshootingCommissioning

The loop is fine until something clamps the output

A level loop that tracks setpoint to within half a percent all day will, once in a while, sail past setpoint by ten percent and take two minutes to crawl back. It almost always happens after the same handful of events: the control valve drove fully open on a big demand, an operator held the loop in Manual for a while and then flipped it to Auto, or the plant just came off a cold start with the setpoint ramping up from zero.

The tuning is not the problem. The problem is the integrator. When the output can't move but the error won't go away, the integral term keeps accumulating against a wall, and that stored-up demand has to be unwound before the output comes back into the controlling range. That's reset windup, and it's the single most common reason a "well-tuned" loop misbehaves at exactly the moments you care about.

Where the integral goes when the output is stuck

Take a plain textbook PID in positional (absolute) form. The integral term is a running sum of error times time. As long as the output — call it the controller output, CV, 0–100% to the valve — is somewhere between its limits, that sum settles wherever it needs to hold the valve steady with zero error. Normal.

Now saturate it. Suppose the level is far below setpoint, the loop calls for more than 100% output, and the valve is already wide open. Physically the loop can do nothing more. But the error is still large and positive, so the integrator keeps piling up, second after second. The internal CV might climb to 140%, 180%, whatever the code lets it reach. The valve doesn't care — it's pinned at 100%.

Then the level finally crosses setpoint. Error flips sign. A healthy loop would start closing the valve immediately. This one can't, because the integrator is sitting at 180% and error has to spend a long time negative just to drag that sum back down under 100% before the valve moves off its stop at all. During that whole unwind, the valve stays wide open and the level keeps climbing. That's your overshoot. The loop isn't sluggish — it's digging out of a hole it dug while the output was saturated.

The same trap springs on any output limit, not just 0/100%. Output rate limits, a downstream "valve can't open past 80% during startup" clamp, a cascade secondary that's maxed out — anywhere the CV the controller computes can't reach the actuator, the integrator can wind up against the gap.

Anti-windup: stop integrating into a wall

Every serious controller solves this. The differences are in how gracefully they let go.

Clamping / conditional integration is the crude one. When the output is saturated, you simply stop updating the integrator — freeze it — or you only allow integration in the direction that would bring the output out of saturation. It's a few lines: if (CV >= CV_max && error > 0) hold_integral; and the mirror case at the low limit. It works, it's cheap, and it's what a lot of homebrew PLC PID blocks do. The weakness is that it's binary. The integrator sits frozen at whatever value it had when it hit the limit, which may still be well above what's needed, so you get a smaller version of the same delayed recovery.

Back-calculation is the one I reach for when the vendor block offers it. Instead of freezing, you feed the difference between the limited output and the unlimited output back into the integrator through a gain, so the integrator is continuously pulled toward a value consistent with the saturated output. The tuning knob is a tracking time constant, Tt — how fast the integrator gets desaturated. A common starting point is Tt near the integral time Ti, or the geometric mean of Ti and derivative time Td when there's derivative action. Smaller Tt unwinds faster but can make the exit from saturation twitchy. The payoff is that when the output comes off the limit, the integrator is already sitting at a sane value, so the loop hands control back smoothly instead of lurching.

External reset (a.k.a. reset feedback) is the same idea done through the loop structure rather than a bolt-on. The integral is implemented as a positive feedback of a filtered output signal, and you feed back the actual actuator or downstream measurement as that signal. If the valve is stuck at 100%, the fed-back value is 100%, and the integrator naturally can't demand more than that. DeltaV and Foxboro-style controllers lean on this heavily, and it's the correct backbone for cascade — the primary's external reset comes from the secondary's measured PV, so the primary automatically stops winding up whenever the secondary can't keep up. If you build cascade with two independent windup-clamped blocks and no reset feedback between them, you've rebuilt the windup problem one level up.

If you're writing the loop yourself and you get to pick, the velocity (incremental) form sidesteps the worst of this for free. Instead of computing an absolute output, you compute the change in output each scan and add it to the previous output. Because there's no explicit integrator sum being stored, there's nothing to wind up — when the output is clamped at the limit, the accumulated position simply doesn't advance past it. You still want limit handling, but the ugly unwind-from-180% behavior is gone by construction. IEC 61131-3 doesn't standardize a PID block, so what you get depends entirely on the platform's library; it's worth knowing which form is under the hood before you trust it.

Manual-to-Auto is the same bug wearing a different hat

The overshoot after an operator flips Manual → Auto is windup's twin. In Manual, the operator is moving the output directly and the integrator isn't controlling anything. If the block keeps integrating the error the whole time it sits in Manual, then at the instant of transfer the integrator can be at some wild value that has nothing to do with the current output, and the CV jumps — a "bump."

The fix is bumpless transfer, and the mechanism is the same tracking machinery as anti-windup: while the loop is in Manual (or being forced/overridden), you make the integrator track so that the computed auto output equals the current manual output. Then at the moment of transfer, auto picks up exactly where manual left off, zero jump, and the loop eases from there. Any block that claims bumpless transfer is doing output tracking internally, and the same feature usually covers "output forced by interlock" and "downstream took control" as well as the plain Manual/Auto case.

A few things I check at commissioning, because vendors implement this unevenly:

  • Force the output to a limit and watch the unwind. Drive the PV so the loop saturates, hold it, then release. If the valve doesn't start moving the instant PV crosses setpoint, windup handling is off or misconfigured. This is a two-minute test and it catches the exact failure operators complain about.
  • Bump Manual → Auto at several output levels, not just at 50%. Do it with the PV on setpoint and with the PV off setpoint. The output should not jump; if it does, tracking isn't wired.
  • Check the startup case. A setpoint ramping from zero on a cold start is a slow-motion saturation — confirm the loop doesn't wind up during the ramp and dump the whole stored demand the moment the process comes alive.
  • On cascade, break the secondary. Put the secondary in Manual or drive it to its limit, then watch the primary. With proper external reset the primary should stop winding up; without it, the primary quietly saturates while looking healthy on the faceplate.

The knob people reach for is usually the wrong one

When a loop overshoots, the reflex is to detune — drop the gain, lengthen the reset. Sometimes that's right. But if the overshoot only shows up after saturation or a mode change and the loop is otherwise crisp, detuning is treating a symptom. You'll make the loop sluggish everywhere to paper over misbehavior that only happens at the limits, and the overshoot won't fully go away because the integrator is still unwinding from wherever it wound up to. Fix the windup first — turn on back-calculation or reset feedback, verify bumpless transfer — and then judge whether the tuning actually needs to change. Most of the time it doesn't.

One more thing worth knowing before you trust a block: put the derivative on the measurement, not on the error. Derivative on error gives you a giant spike (derivative kick) every time an operator moves the setpoint, and on a valve that spike is a physical slam. Nearly every industrial block defaults to derivative-on-PV for this reason, but it's a settable option often enough that it's worth confirming rather than assuming — same as everything else in a PID block, which is far less standardized than its three-letter name suggests.