An obstacle avoiding robot is the first step into autonomous robotics — a machine that navigates its environment on its own, detecting and avoiding objects without any human input. Using an Arduino, HC-SR04 ultrasonic sensor mounted on an SG90 servo for scanning, and an L298N motor driver, you can build a fully autonomous obstacle-avoiding robot in a weekend. This guide covers every step from assembly to code to tuning, so your robot can confidently navigate any room.
Table of Contents
How Obstacle Avoidance Works
The ultrasonic sensor (HC-SR04) works like a bat: it emits a 40kHz sound pulse and measures how long it takes for the echo to return. The time-of-flight gives distance: distance = (time * 0.034) / 2. At 20cm, the echo returns in about 1.2ms.
By mounting the sensor on a servo, the robot can scan left and right without moving the whole chassis. The algorithm is simple and effective:
- Drive forward while distance ahead is greater than threshold (e.g. 20cm)
- When obstacle detected ahead: stop, look right, measure distance right
- Look left, measure distance left
- Return servo to centre
- Turn toward whichever side has more clearance
- Resume forward movement
This servo-scan approach is far superior to a fixed single sensor because the robot can see around corners before committing to a turn direction, avoiding dead-end traps.
Parts List
- Arduino Uno R3 — microcontroller
- HC-SR04 Ultrasonic Sensor — distance measurement (2cm–400cm)
- SG90 Servo Motor — rotates sensor for left/right scanning
- Ultrasonic sensor mounting bracket — mounts HC-SR04 to SG90 servo cleanly
- L298N Motor Driver Module — controls 2 DC motors
- 2x BO motors with wheels — or 4x for 4WD chassis
- Robot chassis (2WD or 4WD) — acrylic or aluminum
- Battery pack — 6V (4x AA) or 7.4V Li-ion
- Jumper wires
- Breadboard or PCB for connections
Assembly Steps
- Build the chassis base: Attach motors to chassis, fit wheels, and mount the caster ball (2WD) or rear motors (4WD).
- Mount the L298N: Place on chassis with M3 standoffs. Connect motor wires to OUT1/OUT2 and OUT3/OUT4.
- Mount the Arduino: On standoffs above or beside the motor driver. Leave USB port accessible for programming.
- Mount the SG90 servo: At the front centre of the chassis, oriented so rotation sweeps left-right (not up-down). The servo horn should point forward when at 90 degrees (centre).
- Attach HC-SR04 to servo: Use the mounting bracket to attach the ultrasonic sensor to the servo horn. The sensor should face forward at servo centre position.
- Mount battery pack: At the rear of chassis for balanced weight distribution (counter-balances the front sensor assembly).
- Wire everything: Follow the wiring section below before powering on.
Ultrasonic Sensor on Servo Mount
Mounting the HC-SR04 on a servo is the key feature that makes this robot significantly smarter than a fixed-sensor design. Wiring the sensor to the servo and connecting both to Arduino:
HC-SR04 connections:
- VCC → Arduino 5V
- GND → Arduino GND
- Trig → Arduino Pin A0
- Echo → Arduino Pin A1
SG90 Servo connections:
- Brown/Black → GND
- Red → 5V (use Arduino 5V for SG90, it draws only ~150mA)
- Orange/Yellow → Arduino Pin 10 (PWM pin for servo signal)
L298N to Arduino:
- ENA → Arduino Pin 5 (PWM), IN1 → Pin 2, IN2 → Pin 3 (Left motor)
- ENB → Arduino Pin 6 (PWM), IN3 → Pin 7, IN4 → Pin 8 (Right motor)
- GND → Arduino GND, 5V OUT → Arduino 5V (if battery is 6–12V)
The SG90 servo centre position is 90 degrees (facing forward). Scanning left = 160 degrees, scanning right = 20 degrees. These angles may need slight adjustment depending on how your servo bracket is oriented — check with the Serial Monitor if scans feel reversed.
Avoidance Algorithm
The algorithm runs as a state machine with four states: FORWARD, STOP_SCAN, DECIDE, TURN. Here is the logic flow:
State FORWARD:
Measure distance forward
If distance > SAFE_DIST (20cm): keep driving forward
Else: transition to STOP_SCAN
State STOP_SCAN:
Stop motors
Delay 200ms (let robot fully stop)
Scan right (servo to 20deg), measure distRight, delay 300ms
Scan left (servo to 160deg), measure distLeft, delay 300ms
Return servo to centre (90deg), delay 200ms
Transition to DECIDE
State DECIDE:
If distRight == 0 AND distLeft == 0: reverse + random turn (trapped)
Else if distRight > distLeft: turn RIGHT
Else: turn LEFT
Turn for 400–600ms
Transition to FORWARD
State FORWARD: (repeat)
Complete Arduino Code
The code uses the Servo library (built into Arduino IDE) and implements the full scanning algorithm described above.
#include <Servo.h>
// Ultrasonic sensor pins
const int TRIG_PIN = A0;
const int ECHO_PIN = A1;
// Servo
Servo scanServo;
const int SERVO_PIN = 10;
// Motor driver pins
const int ENA = 5, IN1 = 2, IN2 = 3; // Left motor
const int ENB = 6, IN3 = 7, IN4 = 8; // Right motor
// Tuning parameters
const int SAFE_DIST = 20; // cm - stop if obstacle closer than this
const int MOTOR_SPEED = 180; // 0-255 PWM
const int TURN_TIME = 500; // ms for each turn
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
scanServo.attach(SERVO_PIN);
scanServo.write(90); // Face forward
delay(500);
Serial.begin(9600);
Serial.println("Obstacle Avoiding Robot Ready");
}
long getDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout
if (duration == 0) return 400; // No echo = far away
return duration * 0.034 / 2;
}
void motorForward() {
analogWrite(ENA, MOTOR_SPEED); analogWrite(ENB, MOTOR_SPEED);
digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}
void motorStop() {
analogWrite(ENA, 0); analogWrite(ENB, 0);
digitalWrite(IN1, LOW); digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}
void motorTurnLeft() {
analogWrite(ENA, MOTOR_SPEED); analogWrite(ENB, MOTOR_SPEED);
digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); // Left backward
digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); // Right forward
}
void motorTurnRight() {
analogWrite(ENA, MOTOR_SPEED); analogWrite(ENB, MOTOR_SPEED);
digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); // Left forward
digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); // Right backward
}
void motorReverse() {
analogWrite(ENA, MOTOR_SPEED); analogWrite(ENB, MOTOR_SPEED);
digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH);
}
void loop() {
long distForward = getDistance();
Serial.print("Forward: "); Serial.print(distForward); Serial.println("cm");
if (distForward > SAFE_DIST) {
motorForward();
} else {
// Obstacle detected - stop and scan
motorStop();
delay(200);
// Scan right
scanServo.write(20);
delay(400);
long distRight = getDistance();
// Scan left
scanServo.write(160);
delay(400);
long distLeft = getDistance();
// Return to centre
scanServo.write(90);
delay(300);
Serial.print("Right: "); Serial.print(distRight);
Serial.print(" Left: "); Serial.println(distLeft);
// Decide direction
if (distRight < 15 && distLeft < 15) {
// Trapped - reverse and spin
motorReverse();
delay(500);
motorTurnRight();
delay(800);
} else if (distRight >= distLeft) {
motorTurnRight();
delay(TURN_TIME);
} else {
motorTurnLeft();
delay(TURN_TIME);
}
motorStop();
delay(100);
}
}
Distance Threshold Tuning
The SAFE_DIST constant is the most important tuning parameter. The right value depends on your robot size and motor speed:
- SAFE_DIST too small (e.g. 10cm): Robot drives too close to obstacles before stopping. At higher speeds it may collide before the stop takes effect.
- SAFE_DIST too large (e.g. 40cm): Robot stops far from obstacles and wastes navigable space. In narrow corridors it will stop when there is actually plenty of room.
- Recommended starting point: 20cm. Tune down to 15cm for slow robots on flat surfaces; tune up to 25–30cm for fast robots or uneven floors.
Also tune TURN_TIME: if the robot turns too far past obstacles, reduce it. If it does not turn far enough and immediately sees another obstacle in the new direction, increase it.
Use the Serial Monitor at 9600 baud to watch live distance readings while the robot moves — this makes tuning much faster than trial and error without feedback.
Adding Multiple Sensors for Better Detection
A single front sensor has blind spots — the robot cannot detect obstacles to its sides until they are directly ahead. Adding side sensors dramatically improves performance:
- Left and right fixed sensors: Add two HC-SR04 sensors pointing 45 degrees to the left and right. If a side sensor detects an obstacle while moving forward, the robot can start turning before hitting it.
- IR sensors for close range: HC-SR04 has a minimum range of 2cm and struggles with angled or very thin objects. IR proximity sensors (TCRT5000 or Sharp GP2Y) work better for nearby obstacles and thin objects like chair legs.
- Bottom IR sensors: Detect table edges or cliff drops — essential for table-top robots.
With three sensors (left, front, right) and the front servo-scan, your robot can detect obstacles in five directions: front, front-left, front-right, side-left, and side-right.
Speed Optimization
Higher speed means faster navigation but more collision risk. These techniques help:
- Proportional slowdown: Instead of full speed or stop, reduce
MOTOR_SPEEDproportionally as distance decreases. At 40cm, run at full speed. At 30cm, run at 70%. At 20cm, stop. This is smoother and reduces the stopping distance needed. - Reduce scan delay at high speed: At higher speeds, the
delay(400)servo scan time means the robot travels further while stopped. Reduce servo delays if your servo is fast (SG90 is fast — 0.1s/60 degrees — so 200ms scan delay is usually sufficient). - Non-blocking code with millis(): Replace
delay()withmillis()-based timing to allow sensor reading to continue even during turns. This is an advanced improvement for version 2.0 of your code.
Limitations and Improvements
Understanding the limitations helps you set expectations and plan upgrades:
- Glass and angled surfaces: HC-SR04 ultrasonic pulses reflect away from smooth surfaces at angles — the robot may not detect glass walls or diagonal obstacles. Use IR sensors for these surfaces.
- Soft materials: Carpet, foam, and thick curtains absorb ultrasonic energy and may not reflect a usable echo, giving false “clear” readings. Test on your specific environment.
- Narrow gaps: The HC-SR04 has about a 15-degree beam angle. The robot can pass through a gap only to get the body stuck even though the sensor saw clear. Widen the effective obstacle zone in your code.
- Corner traps: The basic algorithm can get stuck in U-shaped corners. The reverse-and-spin escape logic helps, but a more sophisticated algorithm (e.g., wall-following or potential field navigation) handles corners better.
- Improvement path: Add wheel encoders for measured turns, add a compass module (HMC5883L) for orientation tracking, and eventually implement a simple grid map for systematic room coverage.
Frequently Asked Questions
Q: Why does my robot keep turning in circles and not going straight?
Two possible causes: (1) Motor speeds are unequal — use analogWrite with different PWM values for each motor to compensate. (2) The HC-SR04 is getting false echoes from the chassis itself. Make sure the sensor is elevated above the chassis by at least 2–3cm on a bracket.
Q: The HC-SR04 reads 0 or random distances — what is wrong?
First check: Trig and Echo pins may be swapped. Trig is output (send pulse), Echo is input (receive). Second: make sure you have 5V on VCC, not 3.3V. Third: check for loose jumper connections — ultrasonic sensors are very sensitive to power supply noise. Add a 100µF capacitor across VCC and GND near the sensor.
Q: Can I use this code with a 4WD chassis?
Yes. For 4WD, wire the front-left and rear-left motors in parallel to OUT1/OUT2, and front-right + rear-right in parallel to OUT3/OUT4. If current draw exceeds 2A total (both channels), upgrade to the Cytron MD10C or use two L298N modules. The Arduino code stays the same.
Q: Can I add Bluetooth control AND obstacle avoidance?
Yes — this is a popular upgrade. Add HC-05 on SoftwareSerial. When Bluetooth commands are received, switch to manual mode (disable obstacle avoidance). When no command for 2 seconds, switch back to auto obstacle-avoidance mode. This gives you both autonomous and manual control.
Q: How accurate is the HC-SR04 for obstacle detection?
Accuracy is typically ±3mm at close range. However, the practical accuracy for robotics (where you need “is there something within 20cm”) is excellent. Main limitation is beam angle (about 15 degrees) and reflective surfaces. For precise distance measurement in a straight line, it is very reliable.
Start Your Autonomous Robot Build
Get Arduino Uno, HC-SR04, servo mounts, L298N motor driver, and robot chassis kits from Zbotic.in — all you need to build your obstacle avoiding robot. Fast delivery across India.
Add comment