Stage 5 of 6 · Lab · about 30 minutes, plus the ladder
Tuning & the big loop
A PID with wrong gains is worse than no controller, and there is no formula that reads your plant's mind. Tuning is an ordered experiment with a written log, and this page is the method, plus the week's second act: lifting the loop off the board and onto the network, where the real architectural question of IoT control lives.
Tuning is a logged experiment
The manual recipe, one knob at a time, in this order, logging every trial:
- Zero everything but P. Raise Kp from small until the step response is brisk and just beginning to ring, then back it off to roughly half or two-thirds of that edge. You now have speed and a known offset.
- Add I until the offset dies politely. Raise Ki from small until ess reaches zero within a second or two of settling. Too far shows up as a slow, rolling overshoot after arrival.
- Add D only if overshoot needs shaving. Small doses of Kd; stop at the first sign of output shimmer. Kd = 0 is a finding, not a failure.
- Re-grade all four verification tests from the build page, both steps and both disturbances, because a tuning that only looks good on the test you tuned with is not tuned.
The log is the deliverable. docs/tuning.md gets one row per trial, gains, what you observed, what you changed and why, and Week 9's CSV logger rung becomes an instrument: log timestamp,sp,pv,u during each step test and the curve is yours to grade offline instead of squinting at a terminal.
Reading the curve
Experienced hands diagnose a loop from the shape alone. The three shapes you will actually meet:
| The curve shows | Diagnosis | Move |
|---|---|---|
| Slow crawl, settles short of SP | Too timid: Kp low; offset says Ki missing or tiny | Raise Kp; then bring in Ki |
| Brisk rise, one modest hump, settles clean at SP | About right | Log it and stop; resist one more "improvement" |
| Ringing that persists or grows | Too hot: gain past what the loop's delay tolerates | Cut Kp (and Ki); re-approach the edge slowly |
| Arrives, then a slow roll past SP and lazy return | Integral overdone or windup tail | Lower Ki; confirm anti-windup is active |
| Fuzzy, trembling output at rest | D amplifying noise | Lower Kd; confirm averaging; consider PI |
Ziegler–Nichols: the classical recipe
In 1942, Ziegler and Nichols published the tuning rules the industry still names first. The ultimate-gain method: with I and D off, raise Kp until the loop oscillates steadily, neither dying nor growing. Call that gain Ku and the oscillation's period Tu, then set:
| Controller | Kp | Ki | Kd |
|---|---|---|---|
| P | 0.5·Ku | — | — |
| PI | 0.45·Ku | 0.54·Ku/Tu | — |
| PID | 0.6·Ku | 1.2·Ku/Tu | 0.075·Ku·Tu |
Honesty about the classic: it was designed for fast disturbance rejection on sluggish industrial plants and lands deliberately aggressive, about a quarter-decay ringing per oscillation, so treat its numbers as a starting point to soften, not gospel. Its real value for you is conceptual: it names the edge (Ku, where your P-sweep went unstable) and scales every gain from two measured properties of your plant, which is the same empiricism as the manual recipe, formalized. Try it on the bench once; compare to your hand tuning in the log.
The big loop: control over the network
Everything so far ran on one board: sensor, controller and actuator sharing a chip, a local loop. The course architecture puts the control app on the Pi, so now the loop stretches across the bench, Week 9's channels carrying it:
Building it is Week 9 reuse: a LightController(LightMonitor) whose react() runs u = pid.update(sp, pv, dt) (with dt measured by time.monotonic() between messages) and publishes the duty on the cmd topic; the node's command handler applies it. It works, and it visibly works differently: with a 1 s sample period and network jitter, the central loop is softer and slower, and aggressive gains that the local loop tolerated will ring here. That comparison is the lab's point, not a defect.
Where should control live?
You have now run the same law in two places, which earns you the real question, one of the central architecture decisions of industrial IoT:
Local (on the node)
Milliseconds of loop delay, immune to network loss, keeps working unplugged from everything. This is why fast, safety-relevant loops, motor drives, flight controllers, your PLC's own PID blocks, run at the edge, next to the plant. The modern name for the principle is edge computing; your program has called it a PLC for two years.
Central (on the Pi)
Sees every node at once, coordinates across them, logs everything, retunes without reflashing. This is the supervisory layer, SCADA in industrial language, and it is the right home for slow decisions, coordination and oversight, exactly because it is the wrong home for fast ones.
Industry's standard answer uses both: fast loops local, supervision central, the supervisor adjusting the local loops' setpoints rather than their outputs. The ladder's rung 3 builds precisely that pattern on your bench, and it is the architecture your LIA project should default to.
The ladder
- Tune by the book. P, then PI, then (maybe) PID by the recipe, with a CSV log per step test and a
docs/tuning.mdrow per trial. Finish with the four verification tests and your final gains justified in one line each. - The Ziegler–Nichols detour. Find Ku and Tu on your plant, compute the table's PID gains, run the same step test, and write two sentences comparing it to your hand tuning. You have now tuned a loop two ways and can argue about it, which is the skill.
- Supervisory control. Node keeps its local PID; teach its command handler
sp:60so the Pi adjusts the setpoint over MQTT. Demonstrate the Pi walking the setpoint 30 → 60 → 45 while the local loop does the holding. This is the professional pattern from the cards above, running on your bench. - The fully central loop. Node falls back to publish-and-obey (Week 9's rung 3); Pi runs
LightControllerwith the PID. Grade it against the local loop with the same step test, and note what the 1 s sample period and the two hops cost in overshoot and settling. - Stretch: the step-test instrument. A small Pi script that publishes a setpoint step, logs
sp,pv,uto CSV for ten seconds, then computes rise time, overshoot and settling time from the data automatically. You have built the thing a loop-tuning consultant actually carries, and Week 11's dashboard will happily display its verdicts.