Learning Goals 5 min
Every L1–L3 motor control we've done was "open loop" — we told the motor what to do and hoped it complied. Real robots measure what actually happened and adjust. That's closed loop, and it's the whole reason robots can be precise. By the end of this lesson you will be able to:
- Define open-loop vs closed-loop control with one concrete example each.
- Identify the four parts of any feedback loop: setpoint, sensor, controller, actuator.
- Pick which type of loop suits a given build (servo position, robot speed, oven temperature, etc.).
Warm-Up 10 min
No new hardware today. Stand up, eyes closed.
Two ways to walk to a chair
- Open loop: You take 5 steps forward, eyes closed. You probably miss the chair.
- Closed loop: You open your eyes, see the chair, walk toward it, watch how you're getting closer, adjust your direction as you go.
Open loop = command without feedback. Closed loop = measure and correct.
Examples from your L3 builds
- L03-03 servo sweep: command angle, trust it gets there. Open loop (the servo internally is closed-loop, but our sketch doesn't verify).
- L03-10 robot car: drive forward for 2 s, hope you went 1 m. Open loop.
- L03-44 plant monitor: target moisture > 40% → water; reads sensor; reacts when low. Closed loop (sensor + decision + actuator + repeat).
New Concept · The four parts of a loop 25 min
| Part | Job | Example (oven) |
|---|---|---|
| Setpoint | The desired value | 180 °C |
| Sensor | Measures the actual value | Thermocouple — currently 165 °C |
| Controller | Compares setpoint to sensor, decides on action | "Below target — heat more" |
| Actuator | Acts on the world | Heating element |
The loop runs forever: sensor reads → controller decides → actuator acts → physical world changes → sensor reads again.
The error signal
error = setpoint − measurement. Positive = need more action; negative = need less. The controller's job is to drive error to zero.
Three flavours of controller
- Bang-bang: if error > 0, full action; if error < 0, none. Cheap, often jittery. Used in thermostats, water-heaters.
- Proportional only (P): action = Kp × error. Bigger error = bigger action. Quiet but may leave residual error.
- PID: P + integral + derivative terms. The industrial gold standard. We'll meet it tomorrow.
When open loop is fine
- Servo with internal feedback: the SG90's internal pot + control board is closed-loop already; your sketch just commands a target.
- Stepper at slow speed: it advances in known step amounts; missing steps unlikely.
- Short-duration moves: drive a robot forward for 200 ms; close enough.
When closed loop is mandatory
- Self-balancing robots (must continuously correct for gravity).
- Line-following cars (sensor feedback essential).
- Temperature control (heat element overshoots without it).
- Motor speed regulation (load changes cause speed changes).
- Drone altitude / orientation.
Three real loops
| System | Setpoint | Sensor | Controller | Actuator |
|---|---|---|---|---|
| Cruise control | Target speed (70 km/h) | Speedometer | PID | Throttle |
| Drone altitude hold | Target altitude (5 m) | Barometer / ultrasonic | PID | Motor RPM |
| Aircon | Target room temp (22 °C) | Room thermistor | Bang-bang | Compressor on/off |
Trade-offs of closed loop
- Pros: tracking, robust to load variation, can be more precise than the actuator alone.
- Cons: needs a sensor (more cost / complexity / failure points), needs tuning (gains), can oscillate or go unstable if tuned wrong.
Worked Example · Build a bang-bang oven (in code) 20 min
Imagine an oven with a TMP36 in the chamber and a relay-controlled heating element on D7. We want to hold the temperature at 80 °C.
Open-loop version (bad)
// Bad: just run the heater for some fixed duration.
digitalWrite(HEATER, HIGH);
delay(60000); // 1 minute on
digitalWrite(HEATER, LOW);Problem: we have no idea what temperature actually reached. With ice-cold air it's undershoot; with hot ambient it's overshoot.
Closed-loop version (bang-bang)
const float SETPOINT = 80.0;
const float HYSTERESIS = 2.0; // ±2 °C dead band
void loop() {
float temp = readTemp();
static bool heating = false;
if (temp < SETPOINT - HYSTERESIS) heating = true;
if (temp > SETPOINT + HYSTERESIS) heating = false;
digitalWrite(HEATER, heating ? HIGH : LOW);
delay(500);
}Four parts: setpoint = 80, sensor = readTemp(), controller = the if logic, actuator = digitalWrite. The hysteresis (±2 °C dead band) prevents rapid on/off cycling at the setpoint.
Trace the loop
- Oven at 22 °C. Heater on (22 < 78). Temp climbs.
- Reaches 78 °C → no change yet (still < 78 condition false). 80 °C → still heating. 82 °C → heater off.
- Temp drifts down. 80 °C → no change. 78 °C → still off. 77.9 °C → heater on.
- Cycle continues, holding 78–82 °C.
Average ~80 °C without ever overshooting badly. The first true control loop. Tomorrow we'll make it smoother with PID.
Basic 5 min
Turn the Worked Example into a full sketch you can run. Use a potentiometer on A0 as the "thermometer": map 0–1023 to 0–100 °C. Use an LED on D7 as the "heater".
- Setpoint 50 °C, hysteresis 2 °C.
- Print the temperature and the heater state each loop.
- Label the four parts of the loop with comments.
It works if the LED switches off as you pass 52 going up. It switches on as you pass 48 going down.
Challenge 1 5 min
Build a light-keeper. An LED on D9 (with 220 Ω) shines on an LDR. Wire the LDR from 5 V to A0, and 10 kΩ from A0 to GND. More light then gives a bigger reading. Cover both with a paper cup.
The sketch should hold the reading at 500. Instead, the LED races to fully on or fully off and stays there.
const int LDR_PIN = A0;
const int LED_PIN = 9;
const int SETPOINT = 500;
const float KP = 0.2;
int duty = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
int light = analogRead(LDR_PIN);
int error = light - SETPOINT;
duty = duty + KP * error;
duty = constrain(duty, 0, 255);
analogWrite(LED_PIN, duty);
Serial.println(light);
delay(20);
}Find the fault and fix it. Then lift the cup a little to let room light in.
It works if the reading settles near 500 in the Serial Plotter. The LED must dim when you let in room light.
Challenge 2 5 min
Use your fixed light-keeper from Challenge 1. Open the Serial Plotter.
- Raise
KPstep by step: 0.2, 0.5, 1, 2, 5. Find the first value where the reading wobbles and never settles. - Keep that
KP. Changedelay(20)todelay(200). Does it get better or worse? - Pick the largest
KPthat settles in under a second atdelay(20).
It works if you record the wobble value, the slow-loop result and your final KP. Take a Plotter screenshot of each.
Challenge 3 · Prove the dead band works 10 min
Real sensors are noisy. Change your Basic sketch so readTemp() adds noise, then count how often the heater switches.
float readTemp() {
float clean = analogRead(POT_PIN) * 100.0 / 1023.0;
return clean + random(-3, 4) * 0.5;
}- Add an
int switchCount. Add 1 each timeheatingchanges. - Every 60 seconds, print the count and reset it. Use
millis(). Shorten the loop delay to 50 ms. - Park the pot so the temperature reads about 50. Run one minute each with
HYSTERESISat 0, 1 and 2.
It works if you have three counts. Say how wide the dead band must be compared with the noise.
Recap 5 min
Open loop = act without measuring. Closed loop = measure → decide → act → repeat. Four parts: setpoint, sensor, controller, actuator. Bang-bang controller = simplest. Most L3 builds are open loop (or partial); pro robotics is closed-loop everywhere. Tomorrow we meet the PID algorithm — the smoother closed-loop controller used everywhere.
- Open-loop control
- Command without feedback. Simple, fast, but can't correct for disturbances.
- Closed-loop control
- Measure → decide → act → repeat. Robust, precise, but needs a sensor and tuning.
- Setpoint
- The target value the system tries to achieve.
- Process variable / measurement
- The actual value the sensor reports.
- Error
- setpoint − measurement. The signal the controller acts on.
- Controller
- The decision-making code: maps error to action. Bang-bang, P, PI, PID.
- Actuator
- The thing that physically changes the world (motor, heater, valve, servo).
- Hysteresis / dead band
- A gap around the setpoint where the controller doesn't react. Prevents rapid on/off cycling.
- Positive vs negative feedback
- Negative = error drives the system back toward setpoint (stable). Positive = error grows (unstable, runs away). Closed-loop controllers must be NEGATIVE feedback.
- Loop period
- How often the loop runs. Too slow = sluggish. Too fast = noisy / CPU-heavy. Match to the physical time constants.
Extra Mission 5 min
Part 1 — Design a gadget that corrects itself
Pick something that should hold steady by itself, such as a lamp that keeps a room evenly lit. Design its control loop on paper.
Your design must include:
- The four parts: setpoint, sensor, controller and actuator.
- Your controller type (bang-bang or proportional), and why.
- The dead band or gain you will start with.
- What should happen if the sensor fails or is unplugged.
Then look back at three of your Level 3 builds. Label each one open or closed loop.
Part 2 — Make it
Build your loop with the parts you have, such as an LDR, a TMP36, an LED or a servo. Tune it until it holds steady.
Bring back next class: the sketch, a photo of the circuit, and a Plotter screenshot of it holding its setpoint. Keep your Challenge 1 light-keeper built for ARD-L04-24.