Home · Academy · Robotics & Coding · Robotic Systems · Project: Obstacle-Avoiding Robot

Project: Obstacle-Avoiding Robot

Build an autonomous robot that avoids obstacles using a distance sensor, two motors and a driver.

PROJECT COMPASS

What will you use this page for?

Core idea

In this project we build a small autonomous robot that uses an ultrasonic sensor, two motors and a motor driver to notice an obstacle in front of it, stop, turn and drive on toward the open direction.

Evidence to produce

Complete the page task with your own input, test conditions and reasoning.

Control trap

Forgetting the common ground If the GND terminals of the Arduino and the battery holder are not connected, the motors will not turn or will behave randomly. This is the most common mistake. Connecting the motor directly to the Arduino Arduino pins cannot drive a motor and get damaged when forced. A motor must always…

Next connection

Project: Line-Following Robot

Module sources: Python Tutorial · Arduino Learn

LevelBeginner
Age10–16
Duration45–75 min
PrerequisiteFault Analysis
ContentProject guide · 1,657 words
Last updated

One-sentence summary

In this project we build a small autonomous robot that uses an ultrasonic sensor, two motors and a motor driver to notice an obstacle in front of it, stop, turn and drive on toward the open direction.

Why does it matter?

Until now we learned about sensors, motors and Arduino separately. This lesson brings them together into one working machine. The robot now makes its own decision without a person steering it: "Is something in front of me? If so, stop and look another way."

This is the core idea behind autonomous systems. Robot vacuum cleaners, cars with parking sensors and warehouse robots all run the same three steps: sense, decide, act. When you build this project, you see that loop with your own hands. It also makes the next step easier: turning this robot into a line-following robot.

The robot's logic: sense, decide, act

Our robot runs a simple loop over and over. First it measures the distance, then it compares that to a threshold value, then it sends a command to the motors.

Pseudocode

Before writing code, let us write the logic in plain language. This makes the plan in our head clear.

Repeat forever:
  measure the distance
  If the distance is less than the threshold
    stop moving forward
    back up a little
    change direction (turn)
  Otherwise
    move forward

The threshold here is the boundary distance at which the robot says "too close now." We will start with 20 centimetres. If you choose it too small, the robot cannot stop before hitting the obstacle; too large, and the robot runs away from everything and never moves ahead.

Two example situations

Example 1 — Clear ahead: The sensor reads 60 cm. Since 60 is greater than the threshold (20), the robot drives straight.

Example 2 — Wall ahead: The sensor reads 12 cm. Since 12 is less than the threshold, the robot stops, backs up a little and turns right. Then it measures again. If the new direction is clear, it keeps moving.

Parts and wiring

Parts list

Why a separate motor driver and a separate battery?

Motors draw far more current than an Arduino pin can supply. If you connect a motor straight to the Arduino, you can damage the board. So we place a motor driver (L298N) in between: the Arduino gives the driver a weak signal such as "go forward," and the driver passes power from the separate battery holder to the motor.

One important rule: the negative terminals (GND) of the Arduino and the battery holder must be connected together — a common ground. Without a common ground, the driver cannot read the Arduino's signal correctly.

Wiring summary

Wiring summary table
PartConnection
HC-SR04 VCCArduino 5V
HC-SR04 GNDArduino GND
HC-SR04 TrigArduino pin 9
HC-SR04 EchoArduino pin 10
L298N IN1 / IN2Arduino pin 5 / 6 (left motor)
L298N IN3 / IN4Arduino pin 7 / 8 (right motor)
L298N motor powerSeparate battery holder (+)
Common GNDArduino GND + battery (−) together

Arduino code (split into functions)

We split the code into small parts. This way we can test and understand each part on its own.

1. Pins and setup

// Ultrasonic sensor pins
const int trig = 9;
const int echo = 10;

// Motor driver pins
const int in1 = 5, in2 = 6;   // left motor
const int in3 = 7, in4 = 8;   // right motor

const int threshold = 20;     // obstacle threshold (cm)

void setup() {
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(in1, OUTPUT); pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT); pinMode(in4, OUTPUT);
}

2. Function that measures distance

// Returns distance from the sensor in cm
long measureDistance() {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  long duration = pulseIn(echo, HIGH);
  return duration * 0.034 / 2;   // convert using speed of sound
}

3. Movement functions

void forward() {
  digitalWrite(in1, HIGH); digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH); digitalWrite(in4, LOW);
}
void stopMotors() {
  digitalWrite(in1, LOW); digitalWrite(in2, LOW);
  digitalWrite(in3, LOW); digitalWrite(in4, LOW);
}
void turn() {                // turn right in place
  digitalWrite(in1, HIGH); digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);  digitalWrite(in4, HIGH);
}

4. Main loop

void loop() {
  long distance = measureDistance();
  if (distance < threshold) {  // obstacle close
    stopMotors();
    delay(200);
    turn();
    delay(400);                // a short turn
  } else {
    forward();                 // path is clear
  }
  delay(50);
}

Notice that the logic inside loop() is exactly the same as the pseudocode we wrote at the start. The language changed, but the decision logic stayed the same.

Mini activity

  1. Hold the robot with its wheels in the air and power it on. Move your hand in front of the sensor: does the motor direction change? If not, test here first.
  2. Set up a simple test course: place two cardboard boxes on the floor as obstacles, leaving enough space between them for the robot to pass.
  3. Put the robot on the floor and run it at low speed. When it nears an obstacle, does it stop and turn?
  4. Change the threshold in the code from 20 to 30. Does the robot now react to obstacles earlier? Observe the difference.

One bug and its fix

On my first try the robot stopped when it neared the obstacle but then drove forward again and hit it. The expected behaviour was: stop, turn, then head toward the open direction.

I looked at it step by step:

Expected: at obstacle stop -> turn -> drive in new direction
Actual:   at obstacle stopped -> immediately went forward again

The problem was that I gave no time for the turn after the turn() function. I had forgotten the delay(400) line, so as soon as the robot began turning, the loop restarted and gave the "forward" command again. When I added delay(400) after turn(), the robot really changed direction and headed toward the open side. One small missing line can break the whole behaviour.

Improvement ideas

Common mistakes

Forgetting the common ground

If the GND terminals of the Arduino and the battery holder are not connected, the motors will not turn or will behave randomly. This is the most common mistake.

Connecting the motor directly to the Arduino

Arduino pins cannot drive a motor and get damaged when forced. A motor must always be powered through the driver and a separate battery.

Choosing the wrong threshold

With too small a threshold the robot keeps hitting things; with too large a threshold it runs from everything. A range of 15–25 cm is a good start.

Not testing with the wheels in the air

Trying the code straight on the floor can cause damage if the robot falls off a table. First check the signals with the wheels in the air.

Safety note

A moving robot can pinch, fall or run into things. Before you build and run it, take care of these:

Lesson summary

Check questions

  1. What are the three basic steps the robot runs over and over?
  2. What is the "threshold" for, and what happens if it is chosen too small?
  3. Why do we connect the motor to a motor driver instead of directly to the Arduino?
  4. What can happen if the common ground is not connected?
  5. Why is it a good idea to run the first test with the robot's wheels in the air?

Answers

  1. Sense (measure the distance), decide (compare with the threshold) and act (command the motors).
  2. The threshold is the boundary distance at which the robot counts an obstacle as "too close." If it is too small, the robot cannot stop in time and hits the obstacle.
  3. Motors draw far more current than Arduino pins can supply; connecting directly damages the board. The driver passes power from a separate battery to the motor.
  4. The driver cannot read the Arduino's signal correctly; the motors will not turn or will behave randomly.
  5. With the wheels in the air the robot cannot fall or run away; you can safely check the signals and motor directions.

Source and verification note

For “Project: Obstacle-Avoiding Robot”, verification focuses on whether the relationship between The robot's logic: sense, decide, act and Two example situations remains consistent across examples. Robot behaviour cannot be explained by code alone; mechanical structure, power system, sensor placement and surface conditions must be evaluated together. Test results should be recorded over several runs on the same course.

Next lesson

Project: Line-Following Robot

Start QuizBack to Robotic Systems
QUESTION POOL

Reinforce this lesson with 10 questions

This lesson has a pool of 20 questions. Each attempt selects 10 and reshuffles the choices.