Capstone: Build the Line Follower
Chassis, two motors, two eyes, one PID — a robot that chases black tape across your floor, tuned by you, understood by you.
Builds on: 19.3 Encoders: Knowing Where You Are19.1 DC Motors & the H-Bridge14.2 PID Control12.1 Program the Night-Light
The mission
Build the classic first robot: two driven wheels, two downward-looking reflectance sensors, and firmware that steers so the black line stays between them. It is Lesson 14.2’s PID with wheels bolted on — and the moment it takes its first corner on its own, you will understand why people never stop building robots.
Shopping list (beyond Pico + breadboard kit)
| Part | Notes | ≈ Cost |
|---|---|---|
| 2WD robot chassis kit | two yellow “TT” gear motors, wheels, caster, plate — the universal starter chassis | $12–18 |
| DRV8833 driver module | dual H-bridge with interlocks; happier at 3.3 V logic than the old L298N | $3 |
| 2× TCRT5000 reflectance modules | IR LED + phototransistor — a divider output per sensor (2.2 again) | $3 |
| 4×AA battery holder | motor power — separate from the Pico’s USB/5V supply | $3 |
| Black electrical tape | the racetrack. Light floor, wide gentle curves to start | $2 |
The wiring
| # | From | To | Notes |
|---|---|---|---|
| 1 | Battery pack + / − | DRV8833 VM / GND | motor power stays off the Pico’s rail |
| 2 | Pico GND | DRV8833 GND & sensor GNDs | common ground — the scope capstone’s oldest law |
| 3 | GP2, GP3 | DRV8833 AIN1, AIN2 | left motor (PWM both for fwd/rev) |
| 4 | GP4, GP5 | DRV8833 BIN1, BIN2 | right motor |
| 5 | DRV8833 AOUT/BOUT | the two motors | swap a motor’s two wires if it runs backwards |
| 6 | Sensor AO (left / right) | GP26 / GP27 | the night-light’s ADC pins, now looking at the floor |
| 7 | Sensor VCC | Pico 3V3 | sensors sip; motors must not touch this rail |
| 8 | Sensors, mounted | ~15 mm apart, 3–8 mm above floor, ahead of the axle | height matters more than you think |
The firmware
from machine import Pin, PWM, ADC
from time import sleep_ms
# DRV8833: two PWM pins per motor (fwd / rev)
m_l_f, m_l_r = PWM(Pin(2)), PWM(Pin(3))
m_r_f, m_r_r = PWM(Pin(4)), PWM(Pin(5))
for m in (m_l_f, m_l_r, m_r_f, m_r_r):
m.freq(1000)
sens_l = ADC(26) # left line sensor
sens_r = ADC(27) # right line sensor
KP, KD = 28000, 900
BASE = 28000 # of 65535
last_err = 0
def drive(m_f, m_r, v):
v = max(-65535, min(65535, int(v)))
m_f.duty_u16(v if v > 0 else 0)
m_r.duty_u16(-v if v < 0 else 0)
while True:
l = sens_l.read_u16() / 65535
r = sens_r.read_u16() / 65535
err = r - l # +: line is to the right
steer = KP * err + KD * (err - last_err)
last_err = err
drive(m_l_f, m_l_r, BASE + steer) # line right -> left wheel faster
drive(m_r_f, m_r_r, BASE - steer) # -> robot turns right, toward the line
sleep_ms(10) # 100 decisions per secondThirty lines. The loop is the night-light’s superloop; the sensors are dividers into ADCs; the steering is 14.2’s PD law; the motors are Unit 8’s PWM through 19.1’s H-bridge. Tune KP exactly as the simulator taught you: too low corners wide, too high snakes down the straights, KD calms the snake. Then raise BASE until bravery fails.
If it misbehaves
| Symptom | Likely cause | Fix |
|---|---|---|
| Turns away from the line | sensors or steering sign swapped | swap GP26/GP27, or negate err — one change (15.2!) |
| One motor runs backwards | motor leads reversed | swap that motor’s two wires at the driver |
| Pico resets when motors kick | motor noise sagging the supply | separate battery pack for VM, common grounds, 100 µF across VM (15.1’s decoupling!) |
| Blind to the line | sensor height / ambient IR | 3–8 mm off the floor, shade from sunlight, check readings over tape vs floor in Thonny |
| Snakes violently | your Kp is shouting | halve KP, add KD — you rehearsed this exact tuning in the twin |
Where this road leads
Add encoders (19.3) and it knows its speed. Add an IMU and it can balance. Swap the tape for walls and a distance sensor: a maze solver. Everything else in robotics — SLAM, manipulators, autonomy — is more sensors, more loops, more math on the same skeleton you just built: sense → decide → act, at loop rates you now know how to choose, filter (13.3) and tune (14.2). Welcome to robotics. You came the long way, and it shows.
⚡ Lab — Digital Twin — Tune Before You Build
The exact robot, the exact control law, on a track that punishes bad tuning.
- Default tune: watch a clean lap. Now double the base speed and watch the corners bite.
- Set Kd to zero and find the speed where the straights start snaking.
- Find your fastest never-lost settings — then dial the same ratios into the real firmware.