JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

The PID Controller: Tuning P, I and D

Nine out of ten control loops on the planet — the cruise control holding your speed, the thermostat warming your room, the drone steadying in a gust — are some flavour of [[ee-pid-controller|PID]]. It is gloriously simple: three knobs that act on the **past, present and future** of a single error signal. But turn those knobs carelessly and your motor overshoots, oscillates, or drifts forever off target. This is the rung where you stop merely analysing loops and start **designing** one — squeezing out the [[ee-steady-state-error|steady-state error]] from rung 4 while keeping the system fast and stable.

One error, three points in time

Imagine you are steering a car back into the centre of your lane after a gust pushed you sideways. Your brain does three things at once. It looks at how far off you are right now and turns the wheel proportionally — drift a lot, turn a lot. It notices that you have been drifting *consistently* to the right for a while, so it adds a steady standing correction to cancel that bias. And it watches how fast the gap is closing, easing off before you slam past the centre line. Present error, accumulated past error, predicted future error. That is the whole of PID.

Formally, a controller in a feedback loop measures the error e(t) = setpoint − measurement, and produces a control signal u(t) — the throttle, the heater power, the motor voltage — that drives the plant. PID combines three terms, each weighted by a tunable gain: a Proportional term Kp·e, an Integral term Ki·∫e dt, and a Derivative term Kd·de/dt. Three numbers, three behaviours. The art of control engineering is choosing them.

        setpoint           error e          control u          output y
  r ───►(+)───────► e ───►[  PID  ]───► u ───►[ PLANT ]───┬───► y
        ▲ −                                                │
        │                                                  │
        └───────────────────[ SENSOR ]◄────────────────────┘
                          (measured output)

     u(t) = Kp·e(t)  +  Ki·∫e(t)dt  +  Kd·de(t)/dt
            └─PRESENT─┘  └──PAST────┘  └──FUTURE───┘
The classic single-loop PID. Error feeds three parallel terms; their sum drives the plant. P acts on the present, I on the accumulated past, D on the predicted future.

Proportional: fast, but it leaves a gap

Start with the simplest possible controller: pure proportional, u = Kp·e. The bigger the error, the harder you push. Crank Kp up and the system reacts faster and faster — the step response climbs steeply toward the target. So why not just use a huge Kp and be done? Two reasons, and both are the heart of why PID exists.

First, a proportional controller almost always leaves a permanent gap — the steady-state error you met in rung 4. Picture a motor-speed loop where the motor needs a steady 6 V to spin at the target 1000 rpm against friction. With pure P, the only way to keep producing 6 V of control is to keep the error non-zero: u = Kp·e means if u must be 6 V and Kp = 2, then e must settle at 3 rpm-equivalent forever. The controller needs a leftover error to justify its own output. Raise Kp to shrink the gap, but you can never reach zero — and pushing Kp too far brings on the second problem.

Second, a big Kp makes the loop oscillate and eventually go unstable. A real plant has lag — a motor's inertia, a heater's thermal mass — so the output reacts *after* you push. By the time the measurement catches up, the error has already reversed sign, and a strong controller over-corrects in the other direction. Push hard enough and the swings grow instead of shrinking. Stability, the criterion from rung 4, is the wall that caps how much P you can use.

  rpm           Kp too LOW: slow, big steady gap
 1000 ┤- - - - - - - - - - - - - - - - - setpoint
      │              ________________________
      │        _____/         ↑ leftover error
      │   ____/
    0 ┤__/
      └──────────────────────────────────► t

  rpm           Kp too HIGH: fast but rings, smaller gap
 1000 ┤- - - -/\- - - -/‾\- - - - - - - - setpoint
      │     /  \  /‾\ /   \___/‾‾‾‾
      │    /    \/   v
    0 ┤__/
      └──────────────────────────────────► t
Pure proportional control. Low Kp: sluggish with a large steady-state error. High Kp: snappy but oscillatory — and the error never quite reaches zero either way.

Integral kills the gap; Derivative tames the swing

The integral term is the cure for that stubborn leftover error. The I term outputs Ki·∫e dt — it accumulates the error over time. As long as *any* error persists, the integral keeps growing, pushing the control signal harder and harder, until the error is driven to exactly zero. At that point the integral stops changing and holds whatever standing value the plant needs — that 6 V for the motor. The genius is that the integral *remembers* the bias, so the controller no longer needs a live error to sustain its output. Mathematically, the integrator adds a pole at the origin (s = 0) to the loop, which by the rung-4 error analysis guarantees zero steady-state error for a step command.

But integral has a temper. Because it keeps pushing as long as error exists, it tends to overshoot — by the time the output finally reaches the setpoint, the integral has wound up a big stockpile of accumulated push that takes time to unwind, so the system sails past the target before coming back. Integral makes the loop more accurate but slower to settle and more prone to ringing. It is the term that trades speed for precision.

Enter the derivative term, the brakes. D outputs Kd·de/dt — it responds to how *fast* the error is changing. When the output is rushing toward the setpoint, the error is shrinking rapidly, de/dt is large and negative, and D pulls back on the control signal *before* the system arrives. It is pure anticipation: D acts on the predicted future, adding damping that suppresses overshoot and lets you safely use a higher Kp and Ki than you otherwise could. A well-tuned D term is what turns a wobbly, ringing loop into a crisp, well-damped one.

  EFFECT OF RAISING EACH GAIN (hold the others fixed):

          rise time   overshoot   settling time   steady-state err
  ↑ Kp    faster ↓    larger  ↑   small change     smaller ↓
  ↑ Ki    faster ↓    larger  ↑   longer  ↑         ELIMINATED ↓↓
  ↑ Kd    little      smaller ↓   faster  ↓         no effect

  (these are tendencies, not laws — the terms interact)
The standard PID cheat-sheet: how each gain trades off rise time, overshoot, settling and error. Integral is the only term that drives steady-state error to zero; derivative is the only one that purely damps.

A worked motor-speed loop

Let us put numbers on it. A DC motor driving a flywheel can be modelled as a first-order plant with transfer function G(s) = K/(τs + 1), where K is the steady gain (rpm per volt) and τ is the mechanical time constant (how long inertia takes to respond). Say K = 200 rpm/V and τ = 0.5 s, and we command a step from 0 to 1000 rpm. Watch the controller evolve term by term.

  Plant:  G(s) = 200 / (0.5 s + 1)      target = 1000 rpm

  (1) P only,  Kp = 0.01
      steady output settles at ~667 rpm   →  333 rpm SHORT.
      (loop gain Kp·K = 2, error = r/(1+2) = 333)

  (2) P + I,  Kp = 0.01, Ki = 0.05
      output now reaches 1000 rpm exactly, but OVERSHOOTS to
      ~1150 rpm and rings for ~3 s before settling.

  (3) P + I + D,  Kp = 0.01, Ki = 0.05, Kd = 0.004
      output reaches 1000 rpm, overshoot trimmed to ~3%,
      settles cleanly in ~1.2 s. Zero steady-state error.

         1150 ┤      ,-.        (2) PI: overshoot + ring
         1000 ┤----/---`-.__________  ← (3) PID: crisp
          667 ┤   /         (1) P-only floor (gap!)
            0 ┤__/
              └───────────────────────► t
Same plant, three controllers. P alone falls 333 rpm short. Adding I closes the gap but overshoots. Adding D damps the overshoot for a clean, fast, accurate response.

Read the first line carefully — it is the rung-4 error formula in action. With proportional gain alone, the loop gain is Kp·K = 0.01 × 200 = 2, and a first-order step settles to r·(loop gain)/(1 + loop gain) = 1000 × 2/3 ≈ 667 rpm. The 333 rpm shortfall is the steady-state error, baked in by the finite gain. The integral term in step (2) makes that error mathematically impossible: any residual error, given time, integrates up until the output sits exactly on target.

A tuning recipe you can actually use

Theory is lovely, but on the bench you tune by hand. Here is the manual recipe most engineers reach for first — it leans on the cheat-sheet above and respects the rung-4 stability limit at every step.

  1. Zero everything. Set Ki = 0 and Kd = 0. You are tuning pure P first.
  2. Raise Kp until the loop responds briskly and just begins to oscillate, then back off to about half that value. You now have a fast but slightly-short response.
  3. Add Ki to erase the steady-state gap. Increase it until the leftover error vanishes within an acceptable time. Too much Ki and overshoot/ringing creeps back in — ease off.
  4. Add Kd only if overshoot or ringing is still objectionable. A little derivative buys a lot of damping; increase until the response is crisp, but stop the moment the control signal starts looking jittery.
  5. Iterate. The terms interact — adding I may force you to nudge P, adding D may let you raise both. Verify the final step response meets your overshoot, settling-time and error targets.

For a more systematic start, the classic Ziegler–Nichols method gives you ballpark gains from a single experiment. Set I and D to zero and raise Kp until the loop oscillates with a steady, sustained amplitude — call that gain the ultimate gain Ku and the oscillation period Tu. Then read the gains straight off a table. It rarely lands perfectly (Z–N classically gives quite aggressive, overshoot-prone tuning), but it gets you into the right neighbourhood in minutes, ready for hand-trimming.

  ZIEGLER–NICHOLS (closed-loop / ultimate-gain method)

  Find Ku (gain at sustained oscillation) and Tu (its period).

  Controller │   Kp        Ki = Kp/Ti      Kd = Kp·Td
  ───────────┼──────────────────────────────────────────
     P        │ 0.50·Ku        —               —
     PI       │ 0.45·Ku    Ti = Tu/1.2         —
     PID      │ 0.60·Ku    Ti = Tu/2       Td = Tu/8

  (a starting point, not a final answer — always hand-trim)
The Ziegler–Nichols closed-loop table. One oscillation experiment yields Ku and Tu; the table converts them into starting gains for P, PI or PID.

Where PID bites back: windup and noise

Two real-world gremlins separate a textbook PID from one that survives in the field. The first is integral windup. Every real actuator saturates — a motor driver can only deliver so many volts, a valve can only open 100%. Suppose you command a big step and the output is limited at full throttle while still far from target. The error stays large, so the integral term keeps accumulating — winding up to an enormous value even though the actuator is already maxed out and pushing harder does nothing. When the output finally reaches the setpoint, that huge stored integral keeps driving the actuator hard, causing a massive, sluggish overshoot while it slowly unwinds.

The second gremlin lives in the derivative term. D responds to the *rate of change* of the error — and measurement noise is, by definition, a fast-changing signal. A sensor with even a little high-frequency hash can have a tiny but very rapid jitter, and de/dt amplifies exactly that. The result is a control signal full of violent spikes that hammer your actuator, waste energy, and can excite resonances. This is why pure textbook D is rarely used raw.

The cure is a filtered derivative: instead of pure Kd·s, real controllers implement Kd·s/(1 + s/N) — a derivative followed by a low-pass filter (typically N ≈ 8–20) that keeps the useful anticipation at the frequencies that matter while rolling off the high-frequency noise. Combined with anti-windup, this is what people mean by a 'practical PID', and it is exactly what runs inside the motion controllers, drone flight stacks and process loops you will design.