Siddhant Kumar
Project 092 · Robotics

Obstacle-Avoiding Rover.

A rover that drives itself around a room, sensing obstacles ahead and steering toward the clearest path — reactive autonomy without a map.

Beginner 8–14 hours 27 min read RobotUltrasonicAutonomy
Jump to source Bill of materials
Obstacle-Avoiding Rover — reference build illustration
Difficulty
Beginner
Build time
8–14 hours
Indicative cost
₹1,400 – ₹2,600
Platform
Arduino Uno R3 (ATmega328P)
Category
Robotics
Last updated
28 July 2026
Contents — 26 sections

Project Overview

A rover that drives itself around a room, sensing obstacles ahead and steering toward the clearest path — reactive autonomy without a map.

The simplest form of free-roaming autonomy is not to plan a route but to react: drive forward, and whenever something is in the way, turn toward the clearer side. An obstacle-avoiding rover does exactly that — it wanders a space on its own, using a distance sensor to detect what is ahead and steering around it — and in doing so it demonstrates the foundation of mobile robotics: sense the world, decide, and act, in a tight loop, fast enough to stay out of trouble. No map, no localisation; just continuous reaction to what the sensors see right now.

The rover measures distance ahead with an ultrasonic (or time-of-flight) sensor, usually mounted on a small servo so it can look left and right as well as straight ahead. The behaviour is a state machine: while the path ahead is clear, drive forward; when an obstacle comes within a threshold, stop, scan left and right to compare clearances, and turn toward the more open direction before resuming. This "sense–scan–steer" reaction, repeated many times a second, lets the rover thread its way around furniture, walls and people without ever knowing where it is.

It is the ideal first mobile robot because it teaches the whole reactive-autonomy loop honestly and cheaply, and its limits are as instructive as its behaviour: a purely reactive rover can get stuck in corners or oscillate between two obstacles (it has no memory or plan), ultrasonic sensing has blind spots and struggles with soft or angled surfaces, and it avoids obstacles rather than navigating to a goal. Real autonomous robots add mapping, localisation and path planning on top. But as a self-driving, obstacle-avoiding rover built on differential drive and a scanning distance sensor, it is both a satisfying autonomous machine and the clearest introduction to the sense–decide–act loop at the heart of all robotics.

A small wheeled line-following robot on a track
An obstacle-avoiding rover explores a space on its own using a fast sense–decide–act loop — reactive autonomy without a map. Photograph sourced from Wikimedia Commons — Line following robot.jpg. Reused under the licence stated on that page; please check it before republishing.

What this project does

  • Drives itself around a space avoiding obstacles
  • Measures distance ahead with an ultrasonic/ToF sensor
  • Scans left/right (servo) to compare clearances
  • Steers toward the more open direction
  • Runs a fast sense–decide–act reaction loop
  • Needs no map or localisation (reactive autonomy)
  • Demonstrates the foundation of mobile robotics

Real-World Applications

SettingHow it is used
Robotics educationThe sense–decide–act loop and reactive autonomy in one build.
Roaming / patrol demosA robot that explores a space on its own.
Behaviour-based roboticsA base for layered reactive behaviours (wander, avoid, seek).
Sensor/actuator integrationLearning distance sensing, servos and differential drive together.

Deployment contexts where a build of this kind earns its keep.

Features & Capabilities

  • Ultrasonic distance sensing (scanning)
  • Reactive obstacle-avoidance state machine
  • Differential-drive steering
  • Stuck/oscillation handling (basic)
  • Adjustable stop distance and turn behaviour
  • Cheap, robust first autonomous robot
  • Honest about the limits of purely reactive navigation

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelBeginner
Estimated completion time8–14 hours
Indicative build cost₹1,400 – ₹2,600
Primary disciplineRobotics
Reference platformArduino Uno R3 (ATmega328P)

Skills you should have (or will pick up)

  • Ultrasonic/ToF distance sensing (and scanning with a servo)
  • Reactive state-machine behaviour design
  • Differential-drive steering
  • Handling reactive failure modes (stuck/oscillation)
  • Sensor–actuator loop timing

Bill of Materials

Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.

ComponentKey specificationQtyApprox. cost
Arduino Uno R3 (ATmega328P)
2 KB of SRAM is the real constraint — keep strings in PROGMEM.
16 MHz AVR, 32 KB flash, 2 KB SRAM, 1 KB EEPROM, 14 digital I/O (6 PWM), 6× 10-bit ADC1₹700
HC-SR04 ultrasonic distance sensor
Echo pin outputs 5 V — divide it down before feeding a 3.3 V ESP32.
2–400 cm, ±3 mm, 15° beam, 40 kHz, 10 µs trigger pulse1₹90
SG90 9 g micro servo
Stall current hits 700 mA — never power servos from the board 5 V rail.
1.8 kg·cm at 4.8 V, 0.1 s/60°, 180° travel, plastic gears, 50 Hz PWM1₹130
BO gear motor 300 rpm + wheel
No two BO motors run at the same speed — closed-loop or trim in software.
3–12 V, 300 rpm at 6 V, 0.8 kg·cm, plastic dual-shaft gearbox1₹150
L298N dual H-bridge motor driver
Bipolar transistors drop ~2 V per side — TB6612FNG is far more efficient.
2 × 2 A continuous, 5–35 V motor supply, 4.9 V logic regulator on board1₹180
18650 Li-ion cell 3400 mAh + holder
Never charge below 0 °C; always use a protected cell or a BMS.
3.7 V nominal, 4.2 V full, 3400 mAh, ~12.6 Wh, 2 C discharge1₹450
Ultrasonic sensor
Mount on a servo to scan
HC-SR04 (or VL53L0X ToF) distance ahead1₹120
Scan servoSG90 to pan the sensor left/right1₹120
Chassis + motors + wheels2-wheel differential-drive rover1₹700
BatteryLi-ion pack + holder1₹300

Estimated total: ₹2,940, excluding tools, shipping and consumables.

Tools and consumables

  • Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
  • Digital multimeter — continuity, DC volts and current ranges
  • Wire strippers, flush cutters and a small set of precision screwdrivers
  • Heat-shrink tubing and a heat gun (or a lighter, carefully)
  • A laptop with a USB port and the toolchain listed above

Hardware Specifications

PartSpecificationSupplyInterfaceReference
Arduino Uno R3 (ATmega328P)16 MHz AVR, 32 KB flash, 2 KB SRAM, 1 KB EEPROM, 14 digital I/O (6 PWM), 6× 10-bit ADC5 V logic, 7–12 V barrel inUART, SPI, I²CDatasheet
HC-SR04 ultrasonic distance sensor2–400 cm, ±3 mm, 15° beam, 40 kHz, 10 µs trigger pulse5 VTrigger/Echo digitalDatasheet
SG90 9 g micro servo1.8 kg·cm at 4.8 V, 0.1 s/60°, 180° travel, plastic gears, 50 Hz PWM4.8–6 VPWM 500–2400 µsDatasheet
BO gear motor 300 rpm + wheel3–12 V, 300 rpm at 6 V, 0.8 kg·cm, plastic dual-shaft gearbox3–12 VPWM + H-bridgeDatasheet
L298N dual H-bridge motor driver2 × 2 A continuous, 5–35 V motor supply, 4.9 V logic regulator on board5–35 VIN1–IN4 + 2 PWMDatasheet
18650 Li-ion cell 3400 mAh + holder3.7 V nominal, 4.2 V full, 3400 mAh, ~12.6 Wh, 2 C discharge3.0–4.2 VHolder / spot-welded tabsDatasheet

Consolidated electrical and interface specifications for every active part in the build.

Power Budget & Supply Sizing

Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.

LoadSupply railTypical current (mA)Notes
Arduino Uno R3 (ATmega328P)5 V logic, 7–12 V barrel in452 KB of SRAM is the real constraint — keep strings in PROGMEM.
HC-SR04 ultrasonic distance sensor5 V15Echo pin outputs 5 V — divide it down before feeding a 3.3 V ESP32.
SG90 9 g micro servo4.8–6 V200Stall current hits 700 mA — never power servos from the board 5 V rail.
BO gear motor 300 rpm + wheel3–12 V200No two BO motors run at the same speed — closed-loop or trim in software.
L298N dual H-bridge motor driver5–35 V36Bipolar transistors drop ~2 V per side — TB6612FNG is far more efficient.

Summed typical draw is 496 mA. With a 1.5× design margin the supply should deliver at least 800 mA continuously at the stated rail voltage.

Software Requirements & Development Environment

Reference toolchain: Arduino IDE 2.3.x (AVR core 1.8.6). Anything newer normally works; anything older may lack the board definitions used here.

  • Install the Arduino IDE 2.3.x (or PlatformIO if you prefer a real editor and dependency locking).
  • Select Tools → Board → Arduino AVR Boards and the matching board. Clone boards with a CH340 USB bridge need the CH340 driver on Windows and macOS.
  • Set the correct port under Tools → Port. On Linux add yourself to the dialout group: sudo usermod -aG dialout $USER and log out and back in.
  • Open the Serial Monitor at 115200 baud — every sketch here logs its state there.
  • Keep File → Preferences → Show verbose output during: compilation switched on while you are debugging build errors.

Required libraries

LibraryWhy it is neededInstall
ESP32Servo / Servo 3.0.x50 Hz PWM generation with correct pulse widths for hobby servos.Library Manager → "ESP32Servo" by Kevin Harrington
Preferences (NVS) bundledWear-levelled key/value storage in ESP32 flash for settings.Bundled with the ESP32 core

Block Diagram

The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.

Obstacle-Avoiding Rover — system block diagramFunctional block diagram of the Obstacle-Avoiding Rover system. SenseUltrasonicdistanceServo scanL/RDecideClear ahead?thresholdChoose sidemore openActForwardif clearTurnto open sideRecoverStuck?back+turnLoop fastreactrightrightnone
Obstacle-Avoiding Rover — system block diagram

Circuit Diagram & Wiring

Every signal line in the build is shown below, followed by a pin-by-pin connection table you can work through with a multimeter in hand.

Obstacle-Avoiding Rover — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsArduino Uno R3(ATmega328P)5 V logic, 7–12 V barrel inUltrasonicD9/D10Distance aheadScan servoD11Pan sensorMotor driver LD2/D4/D5Left wheelMotor driver RD3/D7/D6Right wheelBatteryVINPower
Obstacle-Avoiding Rover — wiring schematic
PeripheralPeripheral pinController pinSignal
UltrasonicTRIG/ECHOD9/D10Distance ahead
Scan servoPWMD11Pan sensor
Motor driver LIN1/IN2/ENAD2/D4/D5Left wheel
Motor driver RIN3/IN4/ENBD3/D7/D6Right wheel
Battery+VINPower

Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.

Wiring explanation

  • Mount the ultrasonic sensor on the scan servo at the front, level and looking ahead.
  • Wire the two motors through an H-bridge; ENA/ENB take PWM for speed.
  • Keep the sensor clear of the chassis so it does not see the robot itself.
  • Power motors and logic sensibly with a common ground.
  • Balance the rover so it does not tip when it stops/turns quickly.
An HC-SR04 ultrasonic distance sensor with its two transducers
The ultrasonic sensor on a scan servo compares left and right clearances so the rover steers toward open space. Photograph sourced from Wikimedia Commons — HC-SR04.jpg. Reused under the licence stated on that page; please check it before republishing.

System Architecture

Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.

Obstacle-Avoiding Rover — architecture stackLayered architecture from hardware to user interface. Hardware layerArduino Uno R3 (ATmega328P) · HC-SR04 ultrasonic distance sensorDriver layerservo · preferencesApplication logicsampling loop · filtering · thresholds · state machinePresentation layerlocal display · serial console · logged output
Obstacle-Avoiding Rover — architecture stack

Working Principle

There are two ways to make a robot move through a space without hitting things: plan a route (which needs a map and localisation) or react to what is immediately sensed. Reactive navigation is the simpler and older idea, and it is remarkably capable: a robot that simply drives forward and turns away from whatever is close can explore a cluttered room indefinitely without ever knowing where it is. This rover is the canonical reactive robot, and its value is that it demonstrates the sense–decide–act loop — the beating heart of all robotics — in its purest, most visible form.

The sense stage measures the world with a distance sensor. An ultrasonic sensor emits a pulse and times its echo to gauge how far away the nearest surface ahead is; a time-of-flight laser does the same with light. Crucially, one forward reading is not enough to choose a direction, so the sensor is usually mounted on a servo that pans it left and right — letting the rover build a coarse picture of where the space is open. This scanning is what turns blind "something ahead" detection into a decision between alternatives.

The decide stage is a small state machine. While the forward distance exceeds a threshold, the decision is trivial: keep driving. When an obstacle comes within the threshold, the rover stops, scans left and right, compares the clearances, and decides to turn toward the more open side. If both sides are blocked, it backs up and turns — a recovery from a dead end. The whole intelligence is a few rules over the sensed distances, and its elegance is that complex-looking wandering emerges from simple reactions. The act stage executes the decision through differential drive: forward when clear, a pivot toward the open side when not, exactly as in any two-wheeled robot.

What makes this an honest teaching robot is that its limitations are as clear as its behaviour, and they motivate everything more advanced. Because it is purely reactive — no map, no memory, no goal — it can get stuck in a corner or oscillate between two obstacles, repeating the same reaction forever; basic recovery (back up, turn a random extra amount) mitigates but does not solve this, because the real fix is memory and planning. Ultrasonic sensing has its own honest flaws: blind spots, poor returns from soft or steeply angled surfaces, and a wide beam that blurs fine detail. And fundamentally it avoids obstacles rather than navigating to a goal — going somewhere specific needs localisation and path planning layered on top. Those limits are precisely why real autonomous robots add mapping (SLAM) and planning. But as a first robot, the obstacle-avoiding rover delivers the essential lesson intact: a fast, tight sense–decide–act loop is enough to produce genuine autonomous behaviour, and everything else in mobile robotics is built on that foundation.

The maths behind it

Ultrasonic distance

plainUltrasonic distance
distance = (echo_time × speed_of_sound) / 2

  ≈ echo_time_µs / 58   → distance in cm

(÷2 because the pulse travels out AND back.)

Reactive decision

plainReactive decision
if forward > D_stop:            drive forward
else:
  scan left, right
  if max(left, right) > D_stop: turn toward the more open side
  else:                        back up, then turn (dead end)

Complex wandering emerges from these few rules.

Loop-rate vs stopping

plainLoop-rate vs stopping
To stop before hitting an obstacle:

  D_stop  >  v × (t_loop + t_react)

The faster the rover, the larger the stop distance and the
faster the loop must run. Reactive safety = fast loop.

Program Flowchart

The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.

Obstacle-Avoiding Rover — firmware flowchartControl flow through the main program loop. Measure distance aheadObstacle within threshold?Stop + scan L/RDrive forwardDrive forwardStop + scan L/RWhich side is clearer?Turn toward open sideBoth blocked → back up + turnTurn toward open sideBoth blocked → back up + turnResume
Obstacle-Avoiding Rover — firmware flowchart

Assembly Instructions

Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.

  1. Build the rover and scanner

    Assemble the differential-drive chassis, mount the H-bridge and battery, and put the ultrasonic sensor on the scan servo at the front, level and clear of the body.

  2. Verify sensing and drive

    Confirm the distance readings are sane across the range and that the rover drives straight and pivots cleanly.

  3. Tune the avoidance behaviour

    Set the stop distance for the speed, tune scan angles/turn amounts, and add stuck/oscillation recovery.

Step-by-Step Implementation Guide

Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.

  1. Sense, scan and decide

    Drive forward while clear; when an obstacle is within the stop distance, scan left and right and turn toward the more open side (or back up if both are blocked).

    cppavoid.ino
    #include <Servo.h>
    Servo scan;
    const int D_STOP = 25;                 // cm
    
    long ping();                           // HC-SR04 distance ahead
    
    long look(int angle){                  // pan sensor, then measure
      scan.write(angle); delay(180);
      long d = ping(); scan.write(90);     // recentre
      return d;
    }
    
    void loop(){
      long ahead = ping();
      if (ahead > D_STOP){ drive(FWD, FWD); return; }   // clear: cruise
    
      drive(0,0);                          // obstacle: stop
      long left  = look(150);
      long right = look(30);
    
      if (left < D_STOP && right < D_STOP){
        drive(REV, REV); delay(300);       // dead end: back up
        pivot(random(0,2) ? LEFT : RIGHT); // turn away
      } else if (left > right){
        pivot(LEFT);                       // steer to the more open side
      } else {
        pivot(RIGHT);
      }
    }
    if (ahead > D_STOP){ drive(FWD, FWD); return; } // clear: cruiseWhile the path ahead is clear the decision is trivial — keep driving. Most of the loop is this fast forward cruise.
    long left = look(150); long right = look(30);When blocked, the sensor pans to compare left and right clearances — turning blind detection into a choice between directions.
    if (left < D_STOP && right < D_STOP){If both sides are blocked the rover recognises a dead end and backs up before turning — basic recovery from getting boxed in.
    pivot(LEFT); // steer to the more open sideThe core reaction: turn toward the more open side. Complex wandering emerges from this simple rule.
  2. Handle stuck/oscillation and keep the loop fast

    Add recovery for getting stuck or oscillating (e.g. a random extra turn, or backing up further after repeated blocks), and keep the loop fast enough to stop in time.

Complete Source Code

The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.

cppobstacle_rover.ino
/* ═══════════════════════════════════════════════════════════════
   Obstacle-Avoiding Rover

   Reactive autonomy: drive forward while clear; when blocked, scan
   left/right and steer toward the more open side; back up from dead
   ends. A fast sense-decide-act loop — the foundation of mobile
   robotics — with honest handling of stuck/oscillation.
   ══════════════════════════════════════════════════════════════════ */

#include <Servo.h>
Servo scan;
const int D_STOP = 25, TRIG=9, ECHO=10;
int blockedStreak = 0;                  // detect being stuck

long ping(){
  digitalWrite(TRIG,LOW); delayMicroseconds(2);
  digitalWrite(TRIG,HIGH); delayMicroseconds(10); digitalWrite(TRIG,LOW);
  long us = pulseIn(ECHO, HIGH, 30000);
  return us ? us/58 : 400;              // cm; 400 = nothing in range
}
long look(int a){ scan.write(a); delay(180); long d=ping(); scan.write(90); return d; }

void drive(int l,int r){ setMotor(LEFT,l); setMotor(RIGHT,r); }
void pivot(int dir){ dir==LEFT ? drive(-180,180) : drive(180,-180); delay(300); }

void setup(){ scan.attach(11); scan.write(90); motorInit(); }

void loop(){
  long ahead = ping();

  if (ahead > D_STOP){                  // clear: cruise
    drive(200,200); blockedStreak=0; return;
  }

  drive(0,0);                           // obstacle: stop and scan
  long left = look(150), right = look(30);
  blockedStreak++;

  if (left < D_STOP && right < D_STOP){ // dead end
    drive(-200,-200); delay(400);       // back up
    pivot(random(0,2)?LEFT:RIGHT);
  } else {
    pivot(left > right ? LEFT : RIGHT); // toward the more open side
  }

  if (blockedStreak > 4){               // stuck/oscillating -> break out
    drive(-200,-200); delay(500);
    pivot(random(0,2)?LEFT:RIGHT);
    for (int i=0;i<3;i++) pivot(left>right?LEFT:RIGHT);
    blockedStreak = 0;
  }
}
return us ? us/58 : 400; // cm; 400 = nothing in rangeDistance is echo-time divided by 58 (out-and-back); a timeout means nothing is in range, treated as clear.
if (ahead > D_STOP){ // clear: cruiseThe forward-cruise state dominates: while clear, just drive. The reactive loop only does work when something is in the way.
pivot(left > right ? LEFT : RIGHT); // toward the more open sideThe central reactive rule — turn toward the more open side after comparing scanned clearances.
if (blockedStreak > 4){ // stuck/oscillating -> break outA run of repeated blocks means the rover is stuck or oscillating (its main failure mode), so it makes a larger random escape — honest handling of a memoryless robot's weakness.

Configuration & Calibration

Configuration steps

  • Configure the stop distance for the rover's speed.
  • Configure scan angles and turn/pivot amounts.
  • Configure dead-end and stuck/oscillation recovery.
  • Configure loop timing so it can stop before collision.

Calibration procedure

An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.

  1. Distance sensing

    Verify readings are accurate and sensible across the range; check for blind spots and false returns.

  2. Stop distance vs speed

    Set the stop distance so the rover halts before contact at its cruise speed; slow down if it clips obstacles.

  3. Turn amounts

    Tune pivot durations so turns are decisive but not excessive.

Mechanical Assembly & Motion

Mechanical assembly

  • Two-wheel differential-drive chassis with a castor, an H-bridge driver and battery.
  • A scan servo at the front carries the ultrasonic sensor, mounted level and clear of the chassis.
  • Low centre of mass so the rover does not tip when it stops or pivots quickly.

Motion logic

Motion is differential drive: forward with equal wheel speeds, and turns by pivoting (one wheel forward, one back or stopped) toward the open side.

The rover alternates between a fast forward "cruise" while clear and discrete stop–scan–turn manoeuvres when blocked, rather than steering continuously like a line follower.

StateLeft motorRight motorResult
Path clearForwardForwardCruise ahead
Obstacle, right clearerForwardReverse/stopPivot right
Obstacle, left clearerReverse/stopForwardPivot left
Both sides blockedReverseReverseBack up (dead end)
After backing upForwardReverseTurn away and retry
ScanningStopStopHold while servo pans

Sensor integration

  • Ultrasonic (or ToF) distance sensor on a scan servo: forward distance plus left/right clearances.
  • Optional side/rear sensors or bump switches for blind-spot and contact backup.

Actuator explanation

Two geared DC motors via an H-bridge, PWM-controlled, providing forward drive and pivots.

A servo pans the distance sensor to scan left and right so the rover can choose the more open direction.

Kinematics

The rover uses the same differential-drive relations as any two-wheeled robot; here the turn is usually a discrete pivot rather than a continuous arc.

plainkinematics
v     = (v_R + v_L)/2      # forward speed
omega = (v_R − v_L)/L      # turn rate

Pivot to open side:
  turn right:  v_L = +s, v_R = −s   (spin in place)
  turn left:   v_L = −s, v_R = +s

Testing Procedure & Expected Output

Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.

TestWhat you should see
Open floorCruises forward smoothly
Wall aheadStops, scans, turns to open side
CornerRecovers (backs up/turns) rather than jamming
Narrow gap between two objectsMay oscillate → escape behaviour breaks it out
Soft/angled surfaceNote ultrasonic blind spots; add margin
Increase speedLarger stop distance needed to avoid clipping

Bench-test checklist. If a row fails, stop and fix it before moving on.

Expected output

A rover that explores a space on its own, avoiding obstacles by scanning and steering toward open space.

plainrover-decision.txt
ahead: 22 cm  (< stop)
scan  left: 60 cm   right: 18 cm
decision: LEFT is clearer -> pivot left
state: AVOIDING -> resume cruise

The rover found the left side far clearer than the right and pivoted left — the sense–decide–act loop making a visible choice.

A brushed DC gear motor
Differential drive lets the rover pivot decisively toward the clearer direction when something blocks its path. Photograph sourced from Wikimedia Commons — DC motor.jpg. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

Clips obstacles

Likely cause. Stop distance too small / loop too slow / too fast

Fix. Increase stop distance; slow down; speed up the loop

Erratic readings

Likely cause. Sensor sees chassis/floor; angled surfaces

Fix. Mount level and clear; add margin; note blind spots

Gets stuck in corners

Likely cause. Purely reactive, no memory

Fix. Add dead-end back-up and random escape turns

Oscillates between two objects

Likely cause. No memory/plan

Fix. Detect repeated blocks; make a larger escape manoeuvre

Tips when stopping

Likely cause. High centre of mass

Fix. Lower the CoM; ease deceleration

The sketch will not upload — "Failed to connect" or "avrdude: stk500_recv()"

Likely cause. The bootloader is not being reached: wrong port, wrong board, a serial monitor holding the port open, or a USB cable that only carries power.

Fix. Close every serial monitor, confirm Tools → Board and Port, and swap to a known data-capable USB cable. On an ESP32 hold BOOT while the IDE prints "Connecting…", then release. If a peripheral is wired to the UART pins (GPIO 1/3 on ESP32, D0/D1 on Uno) unplug it — it fights the programmer.

The board resets in a loop, or the serial monitor prints "Brownout detector was triggered"

Likely cause. The supply cannot deliver peak current. Wi-Fi transmit bursts, relay coils and servos all pull far more than their average draw.

Fix. Power peripherals from a separate regulated supply with a common ground rather than from the board 5 V pin. Add a 470–1000 µF electrolytic capacitor across the supply near the load, and use a real power adapter rather than a laptop USB port.

Serial monitor shows garbage characters

Likely cause. Baud rate mismatch between Serial.begin() and the monitor, or a floating/shared UART line.

Fix. Set the monitor to 115200 to match the sketch. If it still garbles, the crystal or the USB bridge is being confused by noise — shorten the cable and keep motor wiring away from the USB lead.

Performance Optimisation

  • Keep the loop fast and the stop distance matched to speed.
  • Scan left/right to choose a direction, not just detect ahead.
  • Add dead-end and stuck/oscillation recovery for a memoryless robot.
  • Note ultrasonic blind spots; add sensors/margin where needed.
  • Replace every delay() with a millis() comparison — blocking delays are the single most common cause of dropped readings.
  • Sample sensors on a fixed cadence and publish on a slower one; you almost never need to transmit at the sampling rate.
  • Wrap constant strings in F("...") so they stay in flash — an Uno only has 2 KB of SRAM.
  • Use uint8_t / uint16_t where the range allows; on an 8-bit AVR a 32-bit add costs four times as much.
  • Profile before optimising — print micros() deltas around each stage and fix the slowest one first.

Safety Precautions

  • Keep speeds modest; a fast reactive rover can hit people or fall off edges.
  • Add an edge/cliff or bump backup if operating near drops or fragile objects.
  • Purely reactive avoidance is not a safety guarantee — do not rely on it where a collision could cause harm.
  • Secure the battery and wiring so nothing snags during quick turns.
  • Lithium cells vent and burn when abused. Only use protected cells or a proper BMS, never charge below 0 °C, and never leave a charging pack unattended on a wooden desk.
  • Moving parts pinch. Keep fingers, cables and hair out of gear trains and wheels, and always test motion with the drivetrain unloaded and the robot on blocks first.
  • Motors are inductive — always fit a flyback diode across a DC coil, or use a driver that already has one, or the back-EMF spike will destroy your GPIO.
  • Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
  • Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
  • Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.

Maintenance

  • Keep the sensor clean and correctly aimed; re-check after knocks.
  • Check wheels/motors for wear that causes drift.
  • Re-tune stop distance/turns if speed, battery or surface changes.
  • Verify the servo scan still sweeps freely.
  • Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
  • Log pack voltage. When resting voltage after a full charge drops below about 4.0 V, the cell is near end of life — replace it.
  • Listen for gear chatter. A servo that buzzes at rest is either stripped or fighting a mechanical bind — fix it before it burns out.
  • Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
  • Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.

Future Improvements & Upgrades

A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.

  • Add wheel encoders and odometry toward mapping.
  • Add multiple/side sensors or a ToF array for fewer blind spots.
  • Add SLAM and path planning to navigate to a goal, not just avoid.
  • Layer behaviours (wander, seek light, follow) on the reactive base.
  • Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
  • Add connectivity — an ESP32 and an MQTT publish turn a local gadget into something you can graph, alert on and analyse over months.
  • Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
  • Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
  • Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
  • Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.

Frequently Asked Questions

How does it navigate without a map?

It does not navigate to a place — it reacts. It drives forward and, whenever something is close, turns toward the clearer side. Complex-looking wandering emerges from that simple, fast sense–decide–act loop.

Why does the sensor scan left and right?

One forward reading only tells the rover something is ahead; scanning lets it compare clearances and choose the more open direction to turn toward. Scanning turns detection into a decision.

Why does it sometimes get stuck?

Because it is purely reactive — no memory, no plan — so in a corner or between two objects it can repeat the same reaction forever. Basic recovery (back up, random escape turn) helps, but the real fix is memory and planning, which is what more advanced robots add.

How fast can it safely go?

Only as fast as it can stop within its sensing. The stop distance must exceed speed times the loop-plus-reaction time — faster rovers need a larger stop distance and a faster loop.

What are the sensor's limits?

Ultrasonic sensing has blind spots, a wide beam that blurs detail, and weak returns from soft or steeply angled surfaces. Adding margin, extra sensors, or a time-of-flight laser improves robustness.

References & Learning Resources

These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.

  1. Mobile robotReference
  2. Obstacle avoidanceReference
  3. Behavior-based roboticsReference
  4. Ultrasonic ranging (HC-SR04)Reference
  5. Differential wheeled robotReference