Robotics and Embedded Systems

Lesson 4: Control, Autonomy and Simple AINew-age

Sensors and motors give a robot a body. Control is the set of rules that turns readings into behaviour — and the difference between a robot that merely moves and one that moves *well*. This lesson builds the ladder of control ideas: reactive rules, feedback, proportional control worked with real numbers, the full PID controller, state machines, and where simple AI takes over. It ends with the part no competition rubric grades but every real deployment demands: safety and responsibility.

Reactive control: rules that react

The simplest controller is a list of reactions. If the obstacle is closer than 20 cm, stop and turn; otherwise drive forward. If the left line sensor sees the line, steer left. Reactive control is easy to write, easy to predict and surprisingly robust — insects run on little more. Its limits are just as clear: it has no memory (it cannot notice it has turned in a circle four times), no smoothness (every decision is full on or full off), and no sense of *how much* — an obstacle at 19 cm and one at 2 cm trigger the same panicked swerve. The greenhouse fan in Lesson 2 was reactive control with one refinement, hysteresis; keep that in mind as the first rung.

Feedback: closing the loop

Open-loop control acts without checking the result: "drive forward for 3 seconds" assumes the floor, battery and wheels all behave as imagined. Feedback (closed-loop) control measures the outcome and corrects continuously: "drive until the distance sensor reads 50 cm" works on any floor, with any battery, because the sensor — not the assumption — decides when to stop. Almost everything reliable in robotics is a feedback loop running the sense–decide–act cycle many times per second. The central question of feedback design is: given the error — the gap between what you measure and what you want — how hard should you correct?

Proportional control, worked with real numbers

The proportional (P) controller answers: correct in proportion to the error. command = Kp × error, where Kp is a gain you choose. Watch a robot approach a wall, aiming to stop at a target distance of 50 cm, checking and moving every 100 ms. Its rule: each step, move towards the wall by Kp × (distance − 50) cm.

StepDistance, Kp = 0.3Distance, Kp = 1.2
Start150.0150.0
1120.030.0
299.054.0
384.349.2
474.050.2
566.850.0

With Kp = 0.3 the robot glides in — 30 cm, then 21, then 14.7 — each step closing 30% of the remaining gap. It never overshoots, but it also never quite arrives: the closer it gets, the smaller the steps, so it creeps the last few centimetres. With Kp = 1.2 each step closes 120% of the gap: step 1 overshoots to 30 cm (too close), step 2 corrects back to 54, step 3 settles near 49.2 — fast, with one overshoot and a small oscillation that dies away. Now try Kp = 2.0: step 1 commands 200 cm of travel from 150 cm out, which puts the robot at −50 cm — *inside* the wall. On paper it oscillates forever; in the workshop, the experiment ends at step 1. Gain is not a detail. Too small and the robot is timid and late; too large and it oscillates or crashes. Tuning — choosing gains from measured behaviour — is the practical core of control engineering, and it is done by logging real runs, not by guessing.

A P controller in Arduino style, building directly on Lesson 3's distance function, shows where each idea lives:

const int TARGET_CM = 50;
const float KP = 0.30;

void loop() {
  float d = readDistanceCm();            // Lesson 3: median-filtered
  if (d < 0) { stopMotors(); return; }   // no echo: fail safe, stop
  float error = d - TARGET_CM;
  float cmd = KP * error;                // cm to move this step
  if (cmd > 30) cmd = 30;                // clamp: never command a lurch
  if (cmd < -30) cmd = -30;
  drive(cmd);                            // positive = towards the wall
  delay(100);                            // 10 control steps per second
}

Read the safety features, because they are the lesson: a missing echo stops the robot rather than letting it drive blind; the clamp bounds every command no matter what the sensor claims; and the loop runs at a fixed, known rate, which the tuning numbers were measured against.

From P to PID: fixing what P leaves behind

P control alone leaves two known defects, and the full PID controller adds a term for each. The integral (I) term accumulates past error: if the robot consistently stops 3 cm short — say one motor is weaker, so equal commands do not produce equal motion — the P term alone can never fix it, because at 3 cm short the correction is tiny and stays tiny. The integral keeps growing while any error persists, slowly adding the extra push that cancels the bias. (Its failure mode is *windup*: during a long period where correction is impossible — the robot is being carried across the room — the integral grows huge and the robot lurches on release. Real code clamps the integral too.) The derivative (D) term responds to how fast the error is changing: approaching the wall quickly, it brakes early, damping the overshoot that Kp = 1.2 showed. Its weakness is noise — differentiating jittery sensor data amplifies the jitter — which is why Lesson 3's filtering comes first.

Line following ties it together. Two reflectance sensors straddle the line; ours return higher values over the dark line. Suppose the left sensor reads 850 and the right 350: the line sits under the left sensor, so the robot must turn left. error = left − right = 500; with Kp = 0.05 the correction is 0.05 × 500 = 25; around a base speed of 150, set left wheel PWM = 150 − 25 = 125 and right wheel PWM = 150 + 25 = 175. The robot veers left, the error shrinks, the correction shrinks with it — smooth, proportional steering instead of the zigzag of reactive on/off rules. Production line followers add I and D; competition robots are won and lost on this tuning.

State machines: behaviour with memory

Some tasks are sequences, not set-points, and rules alone tangle. A state machine organises behaviour into named states with explicit transitions:

StateBehaviourMoves on when
SEARCHRotate slowly, scanning sensorsObject detected within 60 cm → APPROACH
APPROACHP-control towards the objectDistance under 12 cm → GRAB
GRABClose gripper, liftGrip sensor confirms hold → RETURN
RETURNFollow the line back to baseHome marker seen → SEARCH

One more transition completes the design: from *any* state, a low-battery warning or an emergency-stop input leads to a SAFE STOP state. State machines debug beautifully — when the robot misbehaves you can ask "what state was it in, and what transition fired?" — and they scale: adding a CHARGE state touches nothing else. Reactive rules are state machines with one state; PID is what a state uses while it works.

Adding simple AI — and knowing where rules end

Rules and PID handle the physics: distances, speeds, angles. They cannot answer "is that a ripe tomato?" Perception questions are where small learned models earn their place: a camera plus a lightweight neural network on a single-board computer can classify objects, read gestures or spot defects, and hand the *result* to an ordinary state machine ("if class = ripe, go to GRAB"). The Alpha School Deep Learning course builds those models; the robotics lesson to carry forward is architectural — keep the learned component in the perception seat, and keep deterministic, testable control around it, so the parts you cannot fully test never hold the parts that must not fail.

Responsible robotics: the non-negotiables

  • Emergency stop. A physical, obvious way to halt the machine that does not depend on the software being alive.
  • Speed and force limits appropriate to the space and the people in it.
  • Fail safe on bad data. Sensor timeout, impossible reading, lost connection: the default action is the safe action (our wall-approach code stops).
  • Privacy. A robot with a camera in a home, school or hospital is a recording device; what it captures, keeps and sends is a design decision with owners.
  • Accountability. When a machine causes harm, someone designed, deployed or approved it. "The robot decided" is never a complete answer.

Common mistakes

  • Tuning by vibes. Changing Kp without logging the run means you cannot tell better from different. Print the distances; compare tables like the one in this lesson.
  • Unclamped integral (windup). The robot lurches after being blocked or carried. Clamp the integral, and reset it on state changes.
  • Differentiating raw noise. D on unfiltered sensor data is a jitter amplifier. Filter first (Lesson 3).
  • No fail-safe. A control loop that treats "no reading" as "no obstacle" will eventually demonstrate the difference at full speed.
  • Blocking code in the loop. A delay() in a control loop is a period of flying blind (Lesson 2). Keep the loop fast and even.
Key idea. Measure, correct in proportion, clamp everything, fail safe — and tune from logged data, never from hope.
Try it. Using the wall-approach rule with Kp = 0.3 and a target of 50 cm, the robot starts at 90 cm. Calculate its distance after three steps, and explain why it will approach 50 cm ever more slowly without ever overshooting.

Real-World Challenge

The task. A warehouse robot must drive up to a shelving unit and stop with its scanner exactly 40 cm from the shelf face. It starts 200 cm away and uses proportional control, moving every step by Kp × (distance − 40) cm. You may choose Kp = 0.8 or Kp = 1.5. (a) Calculate the distance after each of the first four steps for Kp = 0.8, and state after how many steps the robot is within 2 cm of the target. (b) Calculate the first step for Kp = 1.5 and explain the outcome. (c) The sensor occasionally returns no echo. State the rule the code must contain for that case, and the clamp you would place on the commanded movement, with reasons.

Worked solution. (a) With Kp = 0.8, each step removes 80% of the remaining error. Start 200 cm, error 160, move 128 → 72.0 cm. Error 32, move 25.6 → 46.4 cm. Error 6.4, move 5.12 → 41.28 cm. Error 1.28, move 1.02 → 40.26 cm. The robot is within 2 cm of the target after 3 steps (41.28 cm) and within 0.3 cm after 4 — fast *and* smooth, with no overshoot, because Kp is below 1. (b) With Kp = 1.5, the first step commands 1.5 × 160 = 240 cm of travel from a start 200 cm away: the robot arrives at −40 cm, which is to say it drives 40 cm *into* the shelving unit. Gain above 1 overshoots by construction; at 1.5 with this much starting error, the overshoot is a collision. Kp = 0.8 is the choice. (c) If the echo times out, the reading is not "infinitely far", it is "unknown" — the code must treat it as a stop command (if (d < 0) { stopMotors(); return; }), because driving on unknown distance is how robots hit things that were there all along. And clamp every command to a sane maximum for the space: a single corrupted reading of 400 cm would otherwise command a 0.8 × 360 = 288 cm lurch. The genuine first step in this aisle is 128 cm, so clamping step commands at, say, 160 cm costs nothing on good data and caps the damage from bad data.

Extension. On a sloping loading bay the robot consistently stops 3 cm short of the target, whichever Kp you choose. Explain why proportional control alone cannot remove this steady-state error, then calculate the integral term's contribution after 10 steps if Ki = 0.02 per step and the error stays at 3 cm (the integral sums the error each step). Describe the risk this term introduces if the robot is picked up and carried to another aisle mid-task, and the one-line code change that prevents it.

✅ Check your understanding

Quick recall check, generated from this lesson’s key terms. It is practice only and is not graded.

Keep reading to complete this lesson