Education › Robotics › Stage 3: Make it think

Control and PID

Open vs closed loop, feedback, and tuning a PID controller so the robot does what you meant.

Intermediate ~33 min read Module 10 of 16

Control is how a robot makes reality match intention — how it holds a speed, a heading, or a position despite friction, slope, and imperfect motors. The workhorse idea is feedback: measure the error between what you want and what you have, and act to shrink it. This lesson builds the PID controller from that single idea, one term at a time, and shows you how to tune it without the maths becoming a wall. Once you understand PID you can make a robot drive straight, hold a distance, or balance.

After this module you can
  • Explain the difference between open-loop and closed-loop control
  • Describe what the P, I and D terms each contribute
  • Implement a basic PID controller in code
  • Tune a PID controller and recognise overshoot and oscillation

Open loop vs closed loop

There are two ways to make a robot do something. Open loop means you send a command and hope: 'run the motor at 70% and it should go about the right speed.' It is simple but blind — if the robot hits a slope or the battery sags, it slows and nothing corrects it. Closed loop means you *measure the result* and adjust: read the actual speed, compare it to the target, and change the motor command to close the gap. The measured difference between what you want (the setpoint) and what you have (the measurement) is the error, and control is the art of driving that error to zero. Almost everything a robot does well — holding a speed, a distance, a heading — is closed-loop.

Note

The core loop of all feedback control: error = setpoint − measurement; then choose an action that reduces the error; then measure again. PID is just a good, general recipe for choosing that action.

P: react to the error now

The proportional term is the obvious one: push in proportion to how big the error is. Far from target, push hard; close to target, push gently. In code the correction is simply a gain Kp times the error. Proportional control alone gets you surprisingly far — a line follower that steers harder the further off the line it is works on P alone. But P has two weaknesses. If Kp is too small the robot responds sluggishly; too large and it overshoots and oscillates around the target. And P alone often settles just short of the target, leaving a small permanent steady-state error, because as the error shrinks so does the push, until it balances against friction before reaching zero.

I and D: kill the offset, damp the wobble

The other two terms fix P's weaknesses. The integral term accumulates the error over time, so a small error that persists keeps adding up until the controller pushes enough to eliminate it — this is what removes the steady-state offset that P leaves behind. Its danger is *windup*: if the error stays large for a while (say the robot is blocked), the integral grows huge and overshoots wildly once freed, so real controllers cap it. The derivative term looks at how fast the error is changing and pushes against rapid change, acting like a shock absorber that damps overshoot and oscillation. It is sensitive to noise, so it is often used gently. Put together — P reacts to the present error, I to the accumulated past, D to the predicted future — and you have PID, the most widely used controller in all of engineering.

python
class PID:
    def __init__(self, kp, ki, kd):
        self.kp, self.ki, self.kd = kp, ki, kd
        self.integral = 0.0
        self.prev_error = 0.0

    def update(self, setpoint, measurement, dt):
        error = setpoint - measurement
        self.integral += error * dt
        self.integral = max(-100, min(100, self.integral))  # anti-windup clamp
        derivative = (error - self.prev_error) / dt
        self.prev_error = error
        return self.kp * error + self.ki * self.integral + self.kd * derivative

# hold a target speed of 1.0
pid = PID(kp=2.0, ki=0.5, kd=0.1)
command = pid.update(setpoint=1.0, measurement=0.7, dt=0.02)

Tuning without the maths

You rarely calculate PID gains; you tune them, and there is a reliable recipe. Start with I and D at zero. Raise Kp until the robot responds briskly and just begins to overshoot and oscillate a little — that is your ceiling for P. Then add a little Kd to damp that overshoot so the response settles cleanly instead of ringing. Finally add a small Ki to erase any remaining steady-state offset — the robot settling just short of target. Change one gain at a time and watch the behaviour: sluggish means more P; overshoot and wobble means more D (or less P); never quite reaching the target means more I. This 'watch and adjust one thing' loop is how PID is tuned in practice, and it works without any equations.

  • Too slow to respond → increase Kp.
  • Overshoots and oscillates → increase Kd, or reduce Kp.
  • Settles just short of the target → increase Ki.
  • Oscillates slowly and grows → too much Ki (windup); reduce it and clamp.

Where you will use it

PID shows up everywhere on a robot. Wheel speed: hold each wheel at a target speed using its encoder, so the robot drives straight regardless of slope or battery — the closed-loop fix for the 'curves when going straight' problem from the motors lesson. Heading: use the IMU or the wheel difference to hold or reach a target heading. Line following: treat the line-sensor offset as the error and steer to zero it. Distance holding: keep a set distance from a wall using the ultrasonic reading. The same small controller, pointed at different errors, produces all of these behaviours — which is why learning PID once pays off across every robot you build.

Hands-on practice

Tune a speed controller

  1. Read one wheel's actual speed from its encoder and pick a target speed as the setpoint.
  2. Implement the PID update and use its output to set the motor PWM each loop.
  3. With Ki and Kd at zero, raise Kp until the wheel responds quickly and just starts to overshoot.
  4. Add Kd to damp the overshoot so the speed settles cleanly, then add a little Ki to remove any offset.
  5. Push against the wheel briefly and confirm the controller pushes back to hold the target speed.
Cheat sheet

Control and PID — at a glance

Main things to focus on

  • Open loop commands blindly; closed loop measures the result and corrects.
  • error = setpoint − measurement; control drives the error to zero.
  • P pushes proportional to the present error but leaves a small offset.
  • I accumulates past error to erase the offset (watch for windup).
  • D damps overshoot by reacting to how fast the error changes.
  • Tune by raising Kp to a slight overshoot, add Kd to damp, add Ki to remove offset.

The idea

Open loopcommand and hope; no correction
Closed loopmeasure result and adjust
setpointthe value you want
errorsetpoint minus measurement

The three terms

P (Kp·error)reacts to the present error
I (Ki·Σerror)erases persistent steady-state offset
D (Kd·Δerror)damps overshoot and oscillation
output = P + I + Dsum of the three corrections

Tuning

raise Kpfaster response, until slight overshoot
add Kddamp the overshoot so it settles
add Kiremove the remaining offset
anti-windup clampcap the integral so it can't blow up

Uses on a robot

wheel speedhold a target speed via encoder
heading holdreach or keep a target heading
line followingsteer to zero the line offset

Common pitfalls

  • Using open-loop commands and wondering why slope or a low battery throws the robot off.
  • Cranking Kp too high, causing overshoot and oscillation instead of a clean settle.
  • Leaving out I and never reaching the target, sitting at a steady-state offset.
  • Letting the integral wind up while blocked, then overshooting wildly once freed.
  • Using a large D term on a noisy signal, so noise makes the output jump around.
Quiz

Check your understanding

5 questions · 4 to pass · answers are explained as you go. Your best score is saved on this device only.

Progress and quiz scores are saved in this browser only. Back up or restore on the hub.

Was this lesson useful? Tell me what to improve →