Robotics
Build a delivery robot: follow, count, stop on a bump
To build an Arduino delivery robot, combine three skills in one loop(): proportional line following to steer, a wheel encoder to stop after a set distance, and a bumper that halts it for good if it hits anything. Order the code so the safety checks come first and the steering last, and use no delay(), so every tick and every bump is seen.
Wiring
- Two reflectance eyes on A0 (left) and A1 (right), watching the line
- The wheel encoder on pin 2, a tick every 6 cm of the left wheel
- A bumper on pin 4 with
INPUT_PULLUP, LOW when it hits something - Two wheels on PWM pins 9 and 10
The plan, in order
- Count ticks: the HIGH-to-LOW edge, every pass.
- The bumper: if it reads LOW, set
halted, and never clear it. - The stop: halted, or 12 ticks reached, means both wheels 0 and
return. - The steering: wheels at 180 ∓ diff ÷ 8, constrained.
The code
void loop() {
bool now = digitalRead(2);
if (now == LOW && last == HIGH) ticks = ticks + 1;
last = now;
if (digitalRead(4) == LOW) halted = true; // a bump: halt for good
if (halted || ticks >= 12) { // delivered, or blocked
analogWrite(9, 0); analogWrite(10, 0);
return;
}
int diff = analogRead(A1) - analogRead(A0);
analogWrite(9, constrain(180 - diff / 8, 0, 255));
analogWrite(10, constrain(180 + diff / 8, 0, 255));
}
Twelve ticks at 6 cm each is the drop point, 72 cm along the line.
Live experiment
Run the delivery
The finished program on its course: count tick edges, one every 6 cm of the left wheel; a bump halts it for good; halted or 12 ticks means both wheels 0; otherwise steer in proportion, base 180, gain 8. Press Deliver, press Bump on the way, and tick off the four checks.
“Project: Parcel run” is the project that ends Encoder Edge, Robotics World 2. Free with an account. Lessons unlock in order, so you’ll do the 13 before it first.
Test it like a checklist
- Floor under both eyes: both wheels at 180.
- Left eye half over the line: a gentle lean left, not a lurch.
- Twelve ticks: stopped.
- A bump after five ticks: stopped at once, and still stopped later, even though the bumper has been released.
Every input here is an edge or a moment: a tick lasts a few milliseconds, a bump a fraction of a second. That's why the loop must never wait. Once it runs, the same structure takes more stops, a list of legs, or a stall check without changing shape.
Free lesson
Now build it yourself
Each lesson comes in three short parts: see the idea, try it on a live board, then build it yourself, with quick checks as you go.
“Project: Parcel run” is the project that ends Encoder Edge, Robotics World 2. Free with an account. Lessons unlock in order, so you’ll do the 13 before it first.
Or start from the very first lesson, no account neededPractice questions
Three quick questions from the lessons. Pick an answer to check it.
Show the answer
Answer: Stop at once and stay stopped, whatever the count. A bump is a halt. A flag set by the bumper, cleared by nothing, and checked before anything drives.
- Why not “Finish the twelve ticks first”? A bump means something is in the way. Driving on for three more ticks would push into it.
- Why not “Ignore it: the count isn't done”? The bumper is checked before the count and wins over it, whatever the count says.
- Why not “Reverse”? This rover's job on a bump is to halt and stay halted, not to back off.
Show the answer
Answer: The bumper and the ticks must be read every pass; a delay would miss them. Every input in this program is an edge or a moment. A frozen loop misses ticks and bumps alike.
- Why not “The eyes need it”? The eyes need reading on every pass, which is exactly what a delay would prevent.
- Why not “delay is slow”? delay() isn't slow, it's blocking: nothing else runs while it waits, so ticks and bumps are missed.
- Why not “It saves memory”? delay() uses no meaningful memory. The problem is that it stops the loop reading its inputs.
Show the answer
Answer: Nothing else would be read for that second: no bumper, no eyes, no ticks. Timestamps let loop() keep running and checking everything while it waits.
- Why not “It can't be done”? delay(1000) works; it just freezes the program for that second.
- Why not “It uses more battery”? Battery use is about the same either way. What's lost is every reading during the wait.
- Why not “delay() is slower”? A delay(1000) lasts exactly as long as the timestamp version. The difference is what happens meanwhile.
“Project: Parcel run” is the project that ends Encoder Edge, Robotics World 2. Free with an account. Lessons unlock in order, so you’ll do the 13 before it first.
Questions people ask
How do I set how far the robot drives?
Divide the distance by the distance per tick. With a tick every 6 cm of wheel, a drop point 72 cm along the line is 12 ticks. Count tick edges, not levels, and stop when the count reaches it.
Why does the bump need its own variable?
The bumper is only pressed for a moment. If the stop just followed the switch, the robot would halt while it's pressed and drive on as soon as it's released. A flag set by the bumper, and cleared by nothing, remembers the bump.
Why does the stop come before the steering?
Because the last analogWrite to each wheel wins. With the stop first, ending the pass with return, nothing below it can set the wheels moving again. Put it after, and one added line later could quietly undo it.
Related topics
- How to tune a line follower's proportional steeringSteer by how far off the line you are, not just which side, and the zigzag turns into a glide.
- How a wheel encoder measures distanceCount the notches as the wheel turns, and you know how far the robot went.
- How to make a robot bump and turn with a bumper switchA switch on the nose, LOW on a bump, and a four-step escape: stop, pause, pivot, go.
- How a robot can tell it's stuck, with an encoderMotors on and no ticks coming means the wheels aren't turning: back off and try again.