Skip to content
Constell Shop
Obstacle-avoiding robot 3D

Project guides

Obstacle-avoiding robot

An ultrasonic “eye” on a servo measures the distance ahead; when something gets close, the robot stops, looks left and right, and turns towards the open side.

Difficulty
Medium
Time
~150 min
Parts
12 parts
Step by step
4 steps
  • Measuring distance with an HC-SR04
  • Turning a servo
  • Making decisions from sensor readings

Parts

You'll also need

  • — A computer with the Arduino IDE (free from arduino.cc)
  • — A USB cable for the UNO (the UNO SMD “+ USB cable” option)
  • — A small Phillips screwdriver

Step by step

  1. 01

    Build the car

    Build the chassis, motors, L298N and power exactly as in the Robot car guide — the pins are the same.

  2. 02

    Mount the servo and sensor

    Fix the SG90 at the front. The code centres the servo at 90° on start — after that, mount the HC-SR04 on its bracket facing straight ahead.

  3. 03

    Wire the sensor and servo

    The extra rows in the table: TRIG → D12, ECHO → D11, servo signal (orange) → D3, both powered from 5V and GND.

  4. 04

    Upload and test

    The sketch uses the Servo library, which comes with the Arduino IDE. Upload, insert the cells and let it go. Serial Monitor (9600) shows the distance.

Wiring

  • Power (+)
  • Ground (−)
  • Signal pin
  • I²C / SPI bus
L298N ⟷ UNO8 wires
  1. L298NENA→UNOD5 remove the jumper on ENA
  2. L298NIN1→UNOD7
  3. L298NIN2→UNOD8
  4. L298NIN3→UNOD2
  5. L298NIN4→UNOD4
  6. L298NENB→UNOD6 remove the jumper on ENB
  7. L298NGND→UNOGND common ground — required
  8. L298N5V→UNO5V powers the UNO from the driver
L298N ⟷ Left motor1 wire
  1. L298NOUT1OUT2→Left motor
L298N ⟷ Right motor1 wire
  1. L298NOUT3OUT4→Right motor
Battery ⟷ L298N2 wires
  1. Battery+(2×18650)→L298N12V
  2. Battery−→L298NGND
HC-SR04 ⟷ UNO4 wires
  1. HC-SR04VCC→UNO5V
  2. HC-SR04GND→UNOGND
  3. HC-SR04TRIG→UNOD12
  4. HC-SR04ECHO→UNOD11
SG90 ⟷ UNO3 wires
  1. SG90signal(orange)→UNOD3
  2. SG90red→UNO5V
  3. SG90brown→UNOGND

The code

sketch.ino
#include <Servo.h>

// motors (L298N)
const int ENA = 5, IN1 = 7, IN2 = 8;   // left
const int ENB = 6, IN3 = 2, IN4 = 4;   // right

void motors(int left, int right) {     // -255 … 255
  digitalWrite(IN1, left >= 0);  digitalWrite(IN2, left < 0);
  digitalWrite(IN3, right >= 0); digitalWrite(IN4, right < 0);
  analogWrite(ENA, abs(left));   analogWrite(ENB, abs(right));
}

void setupMotors() {
  int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
  for (int p : pins) pinMode(p, OUTPUT);
  motors(0, 0);
}

const int TRIG = 12, ECHO = 11;
Servo neck;

long distanceCm() {
  digitalWrite(TRIG, LOW);  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  long us = pulseIn(ECHO, HIGH, 25000);   // ~4 m max
  return us ? us / 58 : 400;              // nothing heard = far away
}

long look(int angle) {
  neck.write(angle); delay(350);
  return distanceCm();
}

void setup() {
  Serial.begin(9600);
  setupMotors();
  pinMode(TRIG, OUTPUT); pinMode(ECHO, INPUT);
  neck.attach(3);
  neck.write(90);
  delay(1500);
}

void loop() {
  long ahead = distanceCm();
  Serial.println(ahead);
  if (ahead > 25) {
    motors(170, 170);
    delay(40);
    return;
  }
  motors(0, 0);
  motors(-150, -150); delay(250);   // a step back
  motors(0, 0);
  long left = look(160), right = look(20);
  neck.write(90); delay(200);
  if (left > right) motors(-170, 170); else motors(170, -170);
  delay(380);                       // about a quarter turn
  motors(0, 0);
}

If something doesn't work

  • Distance is always 0 or 400: TRIG and ECHO may be swapped.
  • Motor speed doesn't change: make sure ENA/ENB aren't on D9/D10 — the Servo library takes them over.
  • The servo jitters and the UNO resets: weak cells — charge the 18650s.
  • It doesn't see a wall: soft surfaces (curtains, sofas) swallow ultrasound — that's normal.

Where to go from here

  • Add a second sensor to watch the sides
  • Change speed smoothly with distance