What you will learn
  • Assemble a complete differential-drive rover.
  • Match low-current motors to a documented driver.
  • Wire sensor, logic and motor power separately.
  • Explain forward, turning and fault states.
  • Verify stop behavior before testing navigation.

Before you begin

Complete the sensor, actuator and communication lessons. Read ROB06 for stopping distance and blind spots before enabling wheels on the floor.

Define a small, supervised robot

This rover drives slowly on a clear, level floor while you hold a run button. A front ultrasonic sensor checks distance. Below 30 cm the rover turns left; above 40 cm it resumes forward motion. A missing or implausible reading stops it, and an unsuccessful turn stops after 800 milliseconds.

The behavior is programmed automation, not machine learning. One front sensor cannot detect every obstacle, drop or moving person. Use large cardboard obstacles in an enclosed test area, keep stairs, pets and feet away, and supervise every run. The turn is deliberately bounded because the sensor does not see the whole swept area.

All sensing and decisions run on the Uno. The driver switches motor power. No cloud connection, Raspberry Pi or external command stream is used. The sensor read has a timeout, and the held run switch acts as a local permission signal: release or a broken run wire disables motion.

HC-SR04 distance → Uno state logic → TB6612FNG → Wheels
Run button → Motion permission       Wheels → New distance

Parts and exact connections

Use two Pololu 100:1 Micro Metal Gearmotor LP 6V, product 992 motors, with their documented 0.36 A stall-current estimate at 6 V. These are the low-power variant, not the higher-current HP variant. Use the Pololu TB6612FNG carrier, product 713, whose documented continuous limit is 1 A per channel under suitable conditions.

With all supplies disconnected, mount the motors opposite each other on a small two-wheel chassis, fit compatible 3 mm D-shaft wheels and add a caster. Secure the Uno, driver and forward-facing HC-SR04. Keep the sensor clear of the wheels and above the floor.

Motor power comes from four AA alkaline cells in a covered holder with a switch and a suitable inline fuse, feeding VMOT and driver GND. The Uno uses a separate USB power bank. Join driver GND, sensor GND and Uno GND. Do not join battery positive to Uno 5V. Use secure connections for motor current; do not route it through thin breadboard power contacts.

Connection or partExact arrangement
TB6612FNG logic powerVCC → Uno 5V; GND → common GND
Motor power4×AA positive through switch/fuse → VMOT; negative → GND
Left motorAO1/AO2; PWMA → D5; AIN1 → D7; AIN2 → D8
Right motorBO1/BO2; PWMB → D6; BIN1 → D9; BIN2 → D10
Driver standbySTBY → D4; extra 10 kΩ from STBY to GND
SparkFun HC-SR04 5 V moduleVCC → 5V; GND → GND; TRIG → D11; ECHO → D12
Normally open held-run buttonD2 → switch → GND
Mechanical partsSmall chassis, two compatible wheels, caster, mounts and insulated wiring
Uno supplyUSB power bank and cable, tested to remain on at the board’s load

Complete firmware

Upload with motor battery power off. This Arduino C/C++ program uses only the core API. pulseIn measures the returning pulse with a 20,000-microsecond timeout. Sound travels out and back, so the approximate distance formula divides by two.

cpp
const byte enablePin = 4, runPin = 2;
const byte triggerPin = 11, echoPin = 12;
bool fault = false, turning = false;
unsigned long lastPing = 0, turnStarted = 0;

void stopMotors() {
  analogWrite(5, 0);
  analogWrite(6, 0);
  digitalWrite(enablePin, LOW);
}

void drive(bool turn) {
  digitalWrite(7, turn ? LOW : HIGH);
  digitalWrite(8, turn ? HIGH : LOW);
  digitalWrite(9, HIGH);
  digitalWrite(10, LOW);
  analogWrite(5, 95);
  analogWrite(6, 95);
  digitalWrite(enablePin, HIGH);
}

void setup() {
  for (byte pin = 4; pin <= 11; pin++) pinMode(pin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(runPin, INPUT_PULLUP);
  stopMotors();
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(runPin) == HIGH) {
    stopMotors();
    fault = false;
    turning = false;
    return;
  }
  if (fault) { stopMotors(); return; }
  if (turning && millis() - turnStarted >= 800) {
    fault = true;
    stopMotors();
    return;
  }
  if (millis() - lastPing < 60) return;
  lastPing = millis();
  digitalWrite(triggerPin, LOW);
  delayMicroseconds(2);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);
  unsigned long duration = pulseIn(echoPin, HIGH, 20000);
  float distanceCm = duration * 0.0343f / 2;
  Serial.println(distanceCm);
  if (duration == 0 || distanceCm < 2 || distanceCm > 300) {
    fault = true;
    stopMotors();
    return;
  }
  if (distanceCm < 30 && !turning) {
    turning = true;
    turnStarted = millis();
  }
  if (distanceCm > 40) turning = false;
  drive(turning);
}

stopMotors() removes PWM and puts the driver in standby. drive() selects forward wheel directions or reverses only the left wheel for a left turn. Unsigned elapsed-time subtraction schedules a ping every 60 milliseconds. Faults latch until the button is released; the next press must still obtain a valid measurement. The 30/40 cm gap avoids rapid state changes. pulseIn briefly blocks, so release response can include that 20-millisecond wait.

Expected result: With wheels lifted, holding run and presenting a broad target 60 cm ahead spins both wheels forward. Moving it within 30 cm requests a left turn. Releasing run, withholding an echo, or remaining blocked through the turn timeout stops the motors.

Prove the subsystems before floor trials

First leave motor battery power off and inspect wiring. Power the Uno, open Serial Monitor at 9600 and hold run. Compare readings against a ruler at 20, 40 and 80 cm using a broad flat target. A zero indicates failure here, not free space. Release run between faulted tests.

Next raise both wheels off the surface, enable motor power and hold run with a valid distant target. Verify each wheel’s forward direction. If one is reversed, power everything off and swap that motor’s two output leads. Do not compensate by randomly changing several direction constants.

Test release, blocked-turn timeout and sensor failure before lowering the rover. Simulate signal failure only with power off: disconnect ECHO, then repower and verify no motion is enabled. Restore the sensor with power off. Keep the physical motor-power switch within reach.

On the floor, measure actual speed and stopping behavior. PWM 95 is a starting value, not a promised safe speed. If motion is too fast for the available clearance, reduce drive and retest. Increase the obstacle margin when measured stopping distance or sensor uncertainty requires it.

Limits and evidence

An angled surface can reflect sound away; cloth can absorb it; narrow legs can escape the sensor beam. A forward-facing sensor also cannot protect against a table edge. This project is an indoor demonstration, not a validated collision-prevention system.

A sensor timeout handles missing echoes, but it cannot recognize every falsely plausible measurement or a frozen processor. The power switch and supervision remain necessary. A later design can add a watchdog, bump switches, wheel encoders and independent motor shutdown.

Keep a trial log with distance, state, observed motion and stop reason. If the board resets on acceleration, inspect power and motor wiring. If neither motor moves, verify STBY, common ground and battery voltage. If one channel fails, isolate that channel with wheels lifted rather than increasing speed.

The build has not been bench-tested for this publication. Treat wiring and staged verification as required work, and record your actual board package and component revisions before reporting success.

Important terms

Differential drive
Steering by controlling left and right wheel motion separately.
Standby
A driver state that disables motor outputs.
Timeout
A maximum allowed wait before an operation is treated as failed.
Latched fault
A fault state retained until an explicit reset condition occurs.
Blind spot
An area the sensor does not observe.

Mini project: Complete a five-case acceptance test

  1. Check distance readings with motor power disabled.
  2. Verify both wheel directions with the chassis raised.
  3. Verify release stops, invalid-echo stops and the 800-millisecond blocked-turn stop.
  4. Run five supervised low-speed approaches to a large cardboard target on level floor.
  5. Finish only when your log shows repeatable stopping and no uncontrolled startup.

Common mistakes and debugging

  • Substituting high-current motors without checking stall specifications: reselect the driver or retain the specified low-power pair.
  • Powering motors from Uno 5V: use the separate switched battery supply.
  • Treating no echo as an empty path: the firmware treats it as a fault.
  • Testing at a table edge: the front sensor cannot detect the drop.

Independent challenge

Measure the shortest actual stopping distance over five trials, then the longest. Use the longest plus a justified margin to propose a new threshold; explain why average distance is insufficient.

Check your understanding: 10 questions

  1. Which device supplies the motor current?

  2. Why divide the ultrasonic travel calculation by two?

  3. What resets a latched fault?

  4. Why use different turn and resume thresholds?

  5. Is this rover guaranteed to avoid every collision?

  6. In your own words, what does “Differential drive” mean?

  7. In your own words, what does “Standby” mean?

  8. In your own words, what does “Timeout” mean?

  9. In your own words, what does “Latched fault” mean?

  10. In your own words, what does “Blind spot” mean?

Quiz answers

Reveal all 10 answers after your attempt
  1. The battery through the TB6612FNG driver, not an Uno GPIO pin.
  2. The pulse travels to the target and back.
  3. Releasing the run button; a later press still requires valid sensing.
  4. The hysteresis gap reduces repeated switching near one boundary.
  5. No. It has limited sensing, possible false readings and no complete coverage of its surroundings.
  6. Steering by controlling left and right wheel motion separately.
  7. A driver state that disables motor outputs.
  8. A maximum allowed wait before an operation is treated as failed.
  9. A fault state retained until an explicit reset condition occurs.
  10. An area the sensor does not observe.

Summary

A complete small robot combines wiring, firmware, mechanics and a testable stop policy. Its reliability comes from validating those parts and respecting what its sensor cannot see.

Continue learning

ARD10 helps choose the next skill based on what this build revealed.

Choose a connected learning path

Sources and further reading

Prepared 2026-09-18. Editorial draft; primary documentation consulted. Hardware build not bench-tested; code has not been executed on the reference board.