Blog · 2026-07-05 · PID

How to Tune a PID Controller: A Step-by-Step Method That Works

Tuning by randomly poking three numbers is how people decide PID "doesn't work." Here is the systematic version: one gain at a time, in the right order, with a known symptom to watch for at each step.

This article assumes you know what the three terms do — if not, ten minutes with PID Control Explained Simply first will make everything below land harder. Tuning is where that theory meets your specific robot: the gains that balance one machine send another into violent oscillation, because gains encode the plant's mass, friction, motor strength and sensor scaling. There is no universal answer, but there absolutely is a universal procedure.

Before touching a gain: the pre-flight checks

More "impossible to tune" systems are broken than mistuned. Verify four things first. Sign: a positive error must produce a correction in the direction that reduces it — flipped motor wiring or sensor sign makes the loop push the wrong way, and no gain fixes backwards. Loop rate: run the controller at a fixed, consistent interval (100 Hz is ample for hobby robots); an irregular dt corrupts both I and D. Sensor quality: plot the measurement at rest — if it's jumping around, filter it now, because D will amplify every jump later. Actuator authority: confirm the motor, sized properly (the Motor Sizing Calculator exists for this), can physically produce the correction; a controller commanding torque that isn't there just winds up its integral.

The manual method: one gain at a time

Step 1 — Zero everything, raise Kp until it rings

Set Ki = Kd = 0. Start Kp small — small enough that the response is obviously sluggish — and command a step change in setpoint. Double Kp and repeat. The response sharpens with each doubling until, at some value, the system overshoots and oscillates continuously around the target. That gain is your critical gain — write it down (call it Ku) along with the oscillation period (Tu, seconds per cycle); both feed the shortcut method below. Then retreat: set Kp ≈ 0.5 × Ku. You now have a brisk response that probably overshoots a little and — if any constant disturbance exists — settles slightly off target.

Step 2 — Add Kd to kill the overshoot

Raise Kd from zero in small steps, repeating the step test. Watch the overshoot shrink and the response snap crisply to target. Stop when overshoot is acceptable (10–15% is fine for most robots; some jobs want zero). Two warnings: too much Kd makes the response sluggish again — D is a brake, and you can drag it — and if the output starts buzzing or chattering, D has found your sensor noise: filter the derivative or reduce Kd. On clean systems it's common to end near Kd ≈ Kp × Tu ÷ 8.

Step 3 — Add Ki, last and least

If the response settles offset from the target, raise Ki from zero until the offset drains away over a second or so after each step. More Ki removes it faster but reintroduces overshoot and, past a point, a slow wallowing oscillation — the integral fighting itself. Use the minimum Ki that kills the offset in acceptable time, and always clamp the integral term (more below). If there's no steady-state error to fix — common in line followers — leave Ki at zero and enjoy a simpler controller.

Step 4 — Confirm with realistic tests

A tune that looks perfect on one gentle step can fall apart elsewhere. Test big steps and small ones, disturbances (tap the arm, put the robot on carpet), and battery states — a LiPo at 12.6 V gives the motors more authority than at 10.5 V, which effectively changes your gains mid-match. Tune at mid-charge, verify at both ends.

Ziegler–Nichols: the shortcut with your Ku and Tu

The classic 1942 recipe converts the critical gain and period you recorded into a full gain set:

ControllerKpKiKd
P0.50 × Ku
PI0.45 × Ku0.54 × Ku ÷ Tu
PID0.60 × Ku1.2 × Ku ÷ Tu0.075 × Ku × Tu

Treat the output as a starting point, not gospel — Z-N deliberately tunes aggressive (about quarter-amplitude decay), and most robots feel better with the resulting Kp and Ki backed off 20–30%. Its real value is skipping the wilderness: it lands you in the right order of magnitude in one experiment.

Integral windup: the bug every real controller must handle

Your robot is blocked, error persists, and the integral term quietly accumulates a mountain of correction; when the blockage clears, the controller dumps the mountain — a huge, slow overshoot that looks like madness. Three standard defenses, best used together: clamp the integral to a sane range (the one-liner from the previous article); freeze integration when the output is saturated — if the motor is already at 100%, accumulating more demand is pure fiction; and reset the integral on large setpoint changes or mode switches. You can reproduce windup safely in the PID Tuning Visualizer — the "Windup" preset shows the signature fat overshoot, and sliding Ki down shows the cure.

Symptom → fix table

You seeIt meansDo this
Fast, constant oscillationKp too high (or Kd noise feedback)Reduce Kp 30–50%
Slow wallowing oscillationKi too high / windupReduce Ki, add clamp + saturation freeze
Overshoots then settlesDamping short for this KpRaise Kd (or trim Kp)
Sluggish, never arrivesGains too low / too much KdRaise Kp; trim Kd
Settles off targetNo integral vs constant disturbanceAdd small Ki
Output chatter / motor buzzD amplifying sensor noiseFilter measurement, reduce Kd
Perfect on bench, wild on floorPlant changed (load, friction, voltage)Retune under real conditions

Hardware realities the textbooks skip

Derivative-on-measurement: compute D from the sensor value instead of the error and setpoint changes stop producing derivative "kick" — a free upgrade in most firmware. Output limits: always clamp the final output to your actuator's real range, and remember mechanical dead zones (a motor that doesn't move below 15% PWM) look like steady-state error and tempt you into excess Ki; feed-forward or a minimum-output offset is the honest fix. Backlash in cheap gearboxes creates a dead zone the loop hunts across — sometimes the correct tuning fix is a better gearbox, a trade covered in Gear Ratios Explained. Change one thing at a time and keep a log; tuning amnesia ("was 4.0 better than 6.0?") wastes more sessions than any technical mistake.

Quick answers

How long should tuning take?

With this procedure and a repeatable step test: 20–60 minutes for a typical hobby loop. Days of frustration usually indicate a pre-flight failure (sign, noise, loop rate), not difficult dynamics.

Can software auto-tune for me?

Relay auto-tuners (the method in 3D printer firmware's M303) automate exactly the Ku/Tu experiment above and work well on well-behaved plants. Knowing the manual method is what lets you judge — and fix — their output.

Do these gains transfer to my next robot?

The gains, no — they encode this machine. The procedure, the symptom table and your trained eye transfer completely, and that's the durable asset. Sharpen the eye for free in the PID Tuning Visualizer before your next build.

Tuning cascaded loops: inner first, always

Balance bots, drones and position-controlled drives use nested PIDs — a fast inner loop (motor speed, or tilt rate) commanded by a slower outer loop (position, or tilt angle). The tuning rule is absolute: tune the inner loop first, alone, to be fast and well-damped; only then close the outer loop around it, treating the tuned inner loop as part of the plant. An outer loop wrapped around a sloppy inner loop produces coupled oscillations that no amount of outer-gain fiddling untangles, and the debugging experience is miserable because two loops' symptoms superimpose. Keep the loops separated in bandwidth too — the inner loop should be several times faster than the outer — or they fight over the same frequencies. When a cascaded system misbehaves after tuning, open the outer loop (command the inner loop directly) and re-verify the inner response before touching anything else; nine times out of ten the fault localizes immediately.

Why your gains are magic numbers (and how to make them less so)

Gains carry hidden units: Kp converts error units into output units, so a controller reading degrees and writing PWM counts has gains meaningless to a controller reading radians and writing volts. This is why copied gains from a forum never work and why normalizing helps portability: scale error and output into −1…+1 ranges and gains become dimensionless, comparable across robots, and typically land in humane ranges (Kp of 0.5–5 rather than 47,000). It also makes the Visualizer's intuition transfer more directly — its plant is normalized the same way.