Obstacle Avoiding Car Using Arduino

Published  October 30, 2023   0
Arduino Obstacle Avoiding Car

Avoiding obstacles is a key job in robotics, where autonomous robots aim to reach their destination without bumping into things. One type of autonomous robot that's pretty clever is the real-time Arduino obstacle avoiding car. It can spot obstacles and figure out new paths to move without running into them. Previously, we have built many robots using Arduino, including an Obstacle Avoiding Robot using Arduino Uno and an Ultrasonic Sensor. You can also check them out if you are interested. This thorough guide will teach you how to build an obstacle-avoiding vehicle using readily available components. An obstacle avoiding robot car autonomously navigates its environment by detecting obstacles with sensors and intelligently changing direction to avoid collisions.

In this comprehensive guide, I will explain the process of constructing your very own obstacle avoiding car using Arduino. This innovative vehicle employs a servo-mounted ultrasonic sensor to detect objects situated both in front and on either side of the car. Additionally, it employs an L298N DC motor driver, which serves as the driving force for four geared motors. You also need an Arduino obstacle avoiding car kit for this project. In this detailed obstacle avoiding car project, you'll learn to build a fully functional autonomous robot that uses an HC-SR04 ultrasonic sensor mounted on a servo motor for 180-degree environmental scanning. This tutorial provides the complete Arduino obstacle avoiding car code, a detailed obstacle avoiding car circuit diagram, and step-by-step assembly instructions.

What is an Arduino Obstacle Avoiding Car?

An Arduino obstacle avoiding car is an autonomous mobile robot that's designed to identify obstacles that are in its way and make decisions to navigate around them without the need for human involvement. This robot uses an ultrasonic distance sensor along with a distance-measured ultrasonic distance sensor to detect the proximity of nearby objects. The information is processed and compiled together in an Arduino microcontroller to direct two DC motors to move away from an obstacle. This technology provides the foundations for autonomous vehicles, robotic vacuum cleaners, autonomous machines and educational robotic systems.

Some of the main components of an obstacle avoiding robot car are as follows: a brain (opto-isolated Arduino Uno microcontroller), a sensory system to detect the proximity of obstacles (an HC-SR04 ultrasonic sensor on a rotating servo mount), a motor control system (an L298N dual H-bridge driver), a propulsion system (four DC geared motors), power management (a battery: 12V Li-ion batteries with voltage regulation circuit) and a power supply. When combined, these systems created an intelligent machine capable of decision making, judgment, and autonomous navigational control with few restrictive obstacles in its way.

Components Required for Obstacle Avoiding Car Project

To build this obstacle avoiding car project, you'll need the following components. These parts are readily available online through electronics retailers, and many suppliers offer complete obstacle avoiding car kits that include all necessary components.

  • Arduino Uno 
  • MG 90 metal gear Servo motors (1x)
  • HC-SR04 Ultrasonic Sensor
  • RGB Led(3x)
  • L298N motor driver
  • 2WD Arduino car kit, Laser cut Chassis 
  • 12V Li-ion battery
  • LM2596 DC-DC buck converter
  •  Switch
  • Jumper wires
  • Breadboard or PCB (Printed Circuit Board)
  • Screws, nuts, spacers

Arduino Obstacle Avoiding Car Circuit Diagram 

The complete circuit diagram for this 2WD obstacle avoiding robot is given below. As you can see, it uses an Ultrasonic sensor to take measurements in all three directions with the help of a servo motor. Based on the distance measurements, the motor takes actions to move forward or turn left and right. The complete obstacle avoiding car circuit diagram is shown below.

Arduino obstacle avoiding car circuit diagram showing HC-SR04 ultrasonic sensor, L298N motor driver, servo motor, RGB LEDs, and power supply connections with labeled pins and wire connections

Understanding the Circuit Design

The HC-SR04 ultrasonic sensor plays a crucial role in this Arduino obstacle avoiding car. It transmits 40kHz ultrasonic pulses that reflect off objects and return as echoes. The sensor plays a crucial role in this project. It sends out 40kHz ultrasonic signals that bounce back when they hit an object. By analysing the returning echoes, the sensor calculates distances between the car and obstacles in real-time. When an obstacle is detected, the car autonomously changes direction. Once our Arduino car for obstacle avoidance is built, it should look like something as shown in the image below. 

Assembled Arduino obstacle avoiding robot car showing component placement on chassis, professional wiring organization, ultrasonic sensor mounted on servo motor at front, L298N driver secured to upper deck, battery placement, and breadboard connections

The L298N motor driver controls the four DC motors that propel the obstacle avoiding robot car. We have used an off-the-shelf Robotic Car chassis kit to build the body of our robot. There are many versions of the Arduino robot kit available on the market. You can purchase the now of your choice. But we personally selected this kit because it looks more like a car with a front bumper, spoiler, etc. Previously, we have also used the same kit to build other projects like the Human Following Robot and Pick and Place Arduino Robot Car. You can also check them out if you are interested. 

Step-by-Step Wiring Connections for Obstacle Avoiding Car

Building the Arduino obstacle avoiding car requires careful attention to wiring connections. Follow these detailed instructions to ensure proper circuit assembly. To make things easy to understand, in the following paragraphs, we have explained how each component is connected to the Arduino Nano. You can also follow the circuit diagram for better understanding. 

Servo Motor Connection with Arduino

To connect the servo motor to the Arduino, simply attach the signal wire to any PWM control pin, connect the power wire to the 5V output from a DC-DC converter, and link the ground wire to one of the Arduino's ground pins.

Connecting Arduino Car to Ultrasonic Sensor

Connect the sensor to the Arduino like this: VCC to 5V, GND to GND, TRIG to a digital pin 2, and ECHO to another digital pin 4 of. This setup allows the Arduino to interact with the sensor. Further, we will also be writing an arduino car ultrasonic sensor code to enable our robot to read the distance of objects ahead of it and control the wheels accordingly. More details on that can be found in the code section. 

RGB LEDs Connection with Arduino

Connect all the RGB LEDs' ground (cathode) to a ground rail on the breadboard. Then, link each RGB LED's red terminal to an analog pin on the Arduino(A1, A2&A3) and the green terminal to a digital pin on the Arduino(5,6&13). This configuration allows the Arduino to control the RGB LEDs.

LED PositionGround (Cathode)Red AnodeGreen AnodeFunction
Right LEDGround railPin A3 (220Ω resistor)Pin 9 (220Ω resistor)Right turn indicator
Center LEDGround railPin A2 (220Ω resistor)Pin 13 (220Ω resistor)Forward/stop indicator
Left LEDGround railPin A1 (220Ω resistor)Pin 10 (220Ω resistor)Left turn indicator

L298N Motor Driver Connection with Arduino

Arduino's GND to breadboard GND rail, Arduino's Vin to breadboard positive rail, LM2596 5V out to positive rail, LM2596 GND out to GND rail. For the DC motor, 1  L298N IN1 and IN2 to Arduino pins 7 and 8. For the DC motor, 2  L298N IN3 and IN4 to Arduino pins 12 and 11. Enable PWM motor control by connecting L298N ENA to Arduino PWM pin 9 and ENB to PWM pin 10, enabling independent control of two DC motors using Arduino.

Power Supply Connections and Distribution

Connect the 12V Li-ion battery's positive terminal to the LM2596's Vin input and link the battery's negative terminal to the breadboard's ground rail. Also, connect the battery's positive terminal to the L298N motor driver's 12V input and connect the battery's negative terminal to the L298N's GND.

Important: Always turn off the Arduino power switch and remove the external Vin supply when you upload the code.

Power supply wiring diagram for Arduino obstacle avoiding car showing 12V Li-ion battery connections, LM2596 buck converter input and output, power switch placement, charging socket, and battery level indicator connections

Secure all components to the car frame using screws, nuts, and spacers as needed. Ensure that all connections are secure and free from loose wires or potential short circuits. Always double-check your connections before powering on the circuit.

Additionally, I incorporated several enhancements to the car's design. These include the addition of a power on/off switch, a 12V DC charging socket, and a Li-ion battery level indicator located on the back side of the vehicle. Furthermore, I included a slider switch near the DC socket, which serves the purpose of monitoring the battery level when the primary power switch is off. When it comes to charging the battery, you simply slide the switch upwards. Conversely, if you wish to check the charging status of the battery, you can easily slide the switch back down. Do note that, when the switch is slid down, it will not charge the battery.

power connection of Obstacle Avoiding Car Using Arduino

Arduino Obstacle Avoiding Car Code Explained

The Arduino obstacle avoiding car code below provides complete functionality for autonomous navigation. Now that the obstacle avoiding car connection is complete, let’s have a look at the Arduino obstacle avoiding car code. The complete Arduino code for obstacle avoiding car is given at the end of this page. The program will include setting up the HC-SR04 module and outputting the signals to the Motor Pins to move the motor direction accordingly. Copy the complete obstacle avoiding car code provided below.

You can make some personal changes in the code, like the threshold distance as per your requirement and motor speed control. Install the required libraries and upload the code given above. 

#include <Servo.h>
This block includes the Servo library, which is necessary for controlling the servo motor.
// Ultrasonic sensor pins
#define trig 2
#define echo 4
// RGB led pins 
#define LR 9        // Led Right
#define LC 13        // Led Center 
#define LL 10       // Led Left
#define LRR A3     // Led Right Red      
#define LCR A2     // Led Center Red  
#define LLR A1     // Led Left Red

In this block, various pin constants are defined for components such as the Ultrasonic sensor and RGB LEDs. These constants are used to specify which pins on the Arduino are connected to each component.

// Motor control pins
#define LEFT_MOTOR_PIN1 8
#define LEFT_MOTOR_PIN2 7
#define RIGHT_MOTOR_PIN1 12
#define RIGHT_MOTOR_PIN2 11
#define ENA 6 // Enable A pin for motor speed control
#define ENB 3 // Enable B pin for motor speed control

These lines define digital pins of Arduino (pin7,pin8,pin12 and pin11) for the L298N motor driver inputs to control the DC motors. The pins in1 and in2 control one motor, and the pins in3 and in4 control the other motor. Ena and Enb control the speed of the motor.

// Distance thresholds for obstacle detection
#define MIN_DISTANCE_BACK 12

This block defines threshold values. MIN_DISTANCE_BACK represents the minimum distance required from an obstacle to stop.

void setup() {
  // Set motor control pins as outputs
  pinMode(LEFT_MOTOR_PIN1, OUTPUT);
  pinMode(LEFT_MOTOR_PIN2, OUTPUT);
  pinMode(RIGHT_MOTOR_PIN1, OUTPUT);
  pinMode(RIGHT_MOTOR_PIN2, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(LR, OUTPUT);
  pinMode(LC, OUTPUT);
  pinMode(LL, OUTPUT);
  pinMode(LRR, OUTPUT);
  pinMode(LCR, OUTPUT);
  pinMode(LLR, OUTPUT);
  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);
  digitalWrite(LL, LOW);
  analogWrite(LRR, 0);
  analogWrite(LCR, 0);
  analogWrite(LLR, 0);
  servoLook.attach(5);
  //Set the Trig pins as output pins
  pinMode(trig, OUTPUT);  
  //Set the Echo pins as input pins
  pinMode(echo, INPUT);
  analogWrite(ENA, 53.5); //  speed for motor A  0-LOW speed, 255-Full speed
  analogWrite(ENB, 45); //  speed for motor B
  // Initialize the serial communication for debugging
  Serial.begin(9600);
}

In the setup() function, various initialisations take place. This includes configuring motor control pins, LED pins, and sensor pins as either OUTPUT or INPUT. It also sets the initial states for LEDs and RGB LEDs to LOW or 0. Additionally, the Servo motor is attached to pin 5, motor speed is adjusted using analogWrite() for ENA and ENB, and serial communication is initiated for debugging (though this part is optional).

void loop()
{
  servoLook.write(90);
  delay(750);
  int distance = getDistance();
  if (distance >= MIN_DISTANCE_BACK)
{ 
    moveForward(); 
    Serial.println("forward");  } 
   while(distance >= MIN_DISTANCE_BACK)   
{
    distance = getDistance();
    delay(50); 
 }
   Stop(); 
   int turnDir = checkDirection();
   Serial.println(turnDir);
   switch(turnDir)
   {
    case 0:                            //Turn left
    Serial.println("Left");
      turnLeft();
      delay(425);
      Stop();
      break;
    case 2:                            //Turn right
    Serial.println("Right");
      turnRight();
      delay(415);
      Stop();
      break;   
    case 3:                             //move forward
    Serial.println("Forward");
     moveForward();
      break; 
 }
}

This is the main loop of the code, executed continuously. The servo motor is set to look straight ahead, and there's a delay for it to settle. The getDistance() function is used to measure the distance using the Ultrasonic sensor. If the measured distance is greater than or equal to MIN_DISTANCE_BACK, the robot is instructed to move forward. While the distance is above the threshold, it continues moving forward. When the distance becomes less than MIN_DISTANCE_BACK, the Stop() function is called to stop the robot.The checkDirection() function is used to determine if there's an obstacle in the left, right, or front direction. Based on the detected direction, the robot will turn left, turn right, or move forward. Serial messages are printed to help with debugging.

int getDistance()                   //Measure the distance to an object{
  unsigned long pulseTime;    //Create a variable to store the pulse travel time
  int distance;              //Create a variable to store the calculated distance
  digitalWrite(trig, HIGH);                 //Generate a 10 microsecond pulse
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  pulseTime = pulseIn(echo, HIGH);    //Measure the time for the pulse to return
  distance  = pulseTime / 29 / 2;   //Calculate the object distance based on the                                                   
                                                   pulse time
  Serial.println(distance);
  return distance;

This function measures the distance to an object using the Ultrasonic sensor. It generates a trigger pulse and measures the time for the pulse to return. Calculate and return the distance based on the measured time.

int checkDirection()  //Check the left, Front and right directions and decide which way to turn

  int distances [3] = {0,0,0};       //Left ,right and Front distances
  int turnDir;        //Direction to turn, 0 left, 1 turn around, 2 right, 3 forward
  servoLook.write(180);                         //Turn servo to look left
  delay(500);
  distances [0] = getDistance();            //Get the left object distance
  servoLook.write(90);                         //Turn servo to look front
  delay(500);
  distances [3] = getDistance();            //Get the front object distance
  servoLook.write(0);                        //Turn servo to look right
  delay(1000);
  distances [1] = getDistance();             //Get the right object distance
  if (distances[0]<=25 && distances[1]<=25)   //If both directions are blocked, move forward
    turnDir = 3;                                             
  else if (distances[0]>=distances[1])   //If left has more space, turn left
    turnDir = 0;  //left
  else if (distances[0]<distances[1])   //If right has more space, turn right
    turnDir = 2;  //right
   //else if (distances[0]<=50 && distances[1]<=50 && distances[3]<=50)    //If All directions are blocked, turn around
    //turnDir = 1;  
  return turnDir;
}

This section of the code handles the obstacle-avoidance strategy for the car's movement. It continually monitors obstacle distances in three directions: left, right, and front by utilising a servo motor. After each scan, it calculates the distances to nearby obstacles. If both the left and right directions have close obstacles, the car proceeds forward. If there's more space on the left side, it steers the car left, and if the right side is more open, it directs the car to the right. If all three directions (front, left, and right) have obstructions nearby, the car is instructed to perform a U-turn. These directions are communicated by returning specific values: 0 for left, 2 for right, 3 for forward, and 1 for turning around.

// Motor control functions
void moveForward() { 
  analogWrite(ENA, 60.5); //  speed for motor A
  analogWrite(ENB, 52); //   speed for motor B
  digitalWrite(LR, HIGH);
  digitalWrite(LC, HIGH);      // All Green light turn on
  digitalWrite(LL, HIGH);
  analogWrite(LRR, 0);
  analogWrite(LCR, 0);       // All Red light turn off
  analogWrite(LLR, 0); 
  digitalWrite(LEFT_MOTOR_PIN1, LOW);
  digitalWrite(LEFT_MOTOR_PIN2, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN1, LOW);
  digitalWrite(RIGHT_MOTOR_PIN2, HIGH);
}
void moveBackward() {
  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);        // All Green light turn off
  digitalWrite(LL, LOW);
  analogWrite(LRR, 255);
  analogWrite(LCR, 255);       // All Red light turn on
  analogWrite(LLR, 255); 
  digitalWrite(LEFT_MOTOR_PIN1, HIGH);
  digitalWrite(LEFT_MOTOR_PIN2, LOW);
  digitalWrite(RIGHT_MOTOR_PIN1, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN2, LOW);
}
void turnRight() {
  analogWrite(ENA, 100); //  speed for motor A
  analogWrite(ENB, 90); //  speed for motor B  
  digitalWrite(LR, HIGH);
  digitalWrite(LC, LOW);            // right side Green light turn on
  digitalWrite(LL, LOW);
  analogWrite(LRR, 0);
  analogWrite(LCR, 255);         // Left and Middle Red light turn on
  analogWrite(LLR, 255);  
  digitalWrite(LEFT_MOTOR_PIN1, HIGH);
  digitalWrite(LEFT_MOTOR_PIN2, LOW);
  digitalWrite(RIGHT_MOTOR_PIN1, LOW);
  digitalWrite(RIGHT_MOTOR_PIN2, HIGH);
}
void turnLeft() {
  analogWrite(ENA, 100); //  speed for motor A
  analogWrite(ENB, 90); //  speed for motor B
  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);         // left side Green light turn on
  digitalWrite(LL, HIGH);
  analogWrite(LRR, 255);
  analogWrite(LCR, 255);         // right and Middle Red light turn on
  analogWrite(LLR, 0);
  digitalWrite(LEFT_MOTOR_PIN1, LOW);
  digitalWrite(LEFT_MOTOR_PIN2, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN1, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN2, LOW);
}
void Stop() {
analogWrite(ENA, 0); //  speed for motor A
  analogWrite(ENB, 0); //  speed for motor B
  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);
  digitalWrite(LL, LOW);
  analogWrite(LRR, 255);
  analogWrite(LCR, 255);
  analogWrite(LLR, 255);
  analogWrite(ENA, 0); //  speed for motor A
  analogWrite(ENB, 0); //  speed for motor B
  digitalWrite(LEFT_MOTOR_PIN1, LOW);
  digitalWrite(LEFT_MOTOR_PIN2, LOW);
  digitalWrite(RIGHT_MOTOR_PIN1, LOW);
  digitalWrite(RIGHT_MOTOR_PIN2, LOW);
}

These blocks are used in the main Arduino obstacle avoiding car code 2WD to control the car's movement and direction based on obstacle detection and the desired action.

moveForward() This function makes the car move forward. It sets the motor speeds for both sides to move forward, turns on green lights (indicating forward movement), and turns off red lights (indicating stopping or backward movement).

moveBackward() This function makes the car move backwards. It turns off the green lights and turns on the red lights to indicate reverse motion. It also sets the motor speeds for backward movement.

turnRight() This function makes the car turn right. It adjusts the motor speeds to execute a right turn, turns on the right-side green light, and turns on the left and middle red lights to indicate the right turn.

turnLeft() This function makes the car turn left. It adjusts the motor speeds to execute a left turn, turns on the left-side green light, and turns on the right and middle red lights to indicate the left turn.

Stop(). This function brings the car to a complete stop. It turns off all lights (indicating a stop), sets both motor speeds to zero, and stops all motor movement.

Common Issues and Troubleshooting

Problem

Solutions

The The Car doesn't move when powered on

  • Verify battery voltage is above 11V using a multimeter

  • Check all motor driver connections (IN1–IN4, ENA, ENB)

  • Ensure the power switch is ON and the connections are secure

  • Test motors individually by directly connecting to the battery

  • Confirm Arduino is receiving 5V from the LM2596 buck converter

Ultrasonic sensor gives erratic readings

  • Add a delay(50) after each distance measurement for stabilisation

  • Ensure sensor is mounted firmly without vibration

  • Check TRIG and ECHO pin connections are correct

  • Verify sensor is pointing perpendicular to obstacles (not angled)

  • Replace the sensor if it consistently reads 0 or the maximum distance

The Servo motor jitters or doesn't rotate smoothly

  • Power servo from dedicated 5V supply, not Arduino's 5V pin

  • Add a 100µF capacitor across the servo power terminals to filter noise

  • Increase delay after servoLook.write() to 500ms minimum

  • Check signal wire connection to PWM pin 5

  • Test servo separately with simple sweep code to isolate issues

The Car gets stuck in corners or against walls

  • Increase  MIN_DISTANCE_BACK threshold from 12cm to 20–25cm

  • Add  moveBackward() function before turning when an obstacle is detected

  • Implement side distance checking (not just front detection)

  • Reduce motor speed near obstacles for better control

  • Add timeout logic to escape from stuck situations after 5 seconds

Real-World Applications of Obstacle Avoiding Robots

  • Autonomous Vacuum Cleaners: Commercial products like Roomba use similar ultrasonic and IR sensors combined with algorithms to clean homes efficiently while avoiding furniture, stairs, and obstacles.
  • Warehouse Automation: AGVs (Automated Guided Vehicles) transport inventory using obstacle avoidance for collision-free navigation in dynamic warehouse environments with human workers and forklifts.
  • Agricultural Robots: Autonomous field robots monitor crop health, spray pesticides, and harvest produce while navigating around plants, irrigation systems, and terrain obstacles.
  • Healthcare Delivery: Hospital robots deliver medications, meals, and supplies between departments, using obstacle avoidance to safely navigate corridors with patients and staff.
  • Security Surveillance: Patrol robots autonomously guard facilities, detecting intrusions while avoiding obstacles during their patrol routes both indoors and outdoors.
  • Assistive Technology: Mobility aids for visually impaired individuals use obstacle detection to provide audio warnings about nearby obstacles, stairs, and navigation hazards.
  • Hazardous Environment Exploration: Robots explore dangerous areas (chemical spills, disaster zones, nuclear sites) where human presence risks injury, using advanced obstacle avoidance for safe navigation.
  • Educational Robotics: Schools and universities use obstacle avoiding robots to teach programming, electronics, mechanics, and AI concepts through hands-on project-based learning.

Technical Summary and GitHub Repository 

The Technical Summary provides an overview of the project’s hardware design, circuit connections, and working principles. You can also explore the complete source code, schematics, and resources in the linked GitHub repository for hands-on implementation.

Code and schematic Download Zip

 

How the Obstacle Avoiding Car Works: Operating Principle

The obstacle avoiding robot car operates on a continuous sense-think-act cycle. The central component that makes the Arduino obstacle avoiding car work is the HC-SR04 Ultrasonic sensor. This sensor relies on sound waves to figure out how far away objects are in front of it. It's a handy sensor used in many projects that need to quickly and affordably measure distances. It's small and can be put anywhere on the car's body.

There are six main parts to this project: an Arduino obstacle avoiding 2WD kit, an Arduino Uno, the Ultrasonic Sensor, DC motors, a Servo motor, and an L293D motor driver. When you connect power to the Arduino, the Servo motor starts turning and checking the distance in three directions: left, right, and front. Whichever direction has the most space, the car moves in that direction.

As soon as the car gets close to an obstacle, there's a set distance programmed into the Arduino. If the obstacle is closer than this distance, the ultrasonic sensor tells the Arduino. Once the Arduino gets this signal, it tells the motor driver to stop the motors from turning. Then, the servo motor starts checking distances again in all three directions. Based on what it finds, it signals the motor driver to turn the car either left or right, and the car turns accordingly. After that, the car goes forward again until it encounters another obstacle. This whole process keeps happening until you turn off the power.

Obstacle avoiding car in operation showing RGB LED indicators illuminated green for forward movement, navigating around obstacles with ultrasonic sensor mounted on servo scanning ahead

Additionally, I've added three RGB LEDs on the underside of the car to indicate its movement. When the car stops, all the LEDs turn red. When it moves forward, they all turn green. If the car takes a right turn, the right-side LED glows green while the other two stay red, and the same goes for a left turn.

Obstacle Avoiding Car Using Arduino

In this project, we successfully designed and built an obstacle avoiding car using Arduino project that can navigate its environment autonomously and solve the Maze. The car utilises an HC-SR04 ultrasonic sensor for distance measurement, a servo motor for scanning the surroundings, and an L298N motor driver for controlling four geared motors.

In summary, this obstacle avoiding car demonstrates the fundamental principles of autonomous robotics, making it an excellent educational tool and a fun project for those interested in robotics and electronics. Building upon this foundation, there are many advantages of obstacle avoiding car that can be expanded and adapted for more complex tasks like food delivery, warehouse management, telemetric robots, etc, highlighting the exciting possibilities of robotics in various applications. If you want to build more such exciting robots, you can check out other Robotics Projects that we built previously.  

Frequently Asked Questions on Arduino Obstacle Avoiding Car

⇥ How far does the HC-SR04 ultrasonic sensor range?
The HC-SR04 ultrasonic sensor has a useful measuring range of 2cm to 400cm (0.8 inches to 13 feet) with an accuracy of ±3mm. In obstacle-avoiding car projects, the useful detection range is usually 10-50cm, so that there is enough reaction time for the robot to brake and move around. The sensor performs best on flat, perpendicular surfaces; sloping or surface materials like fabric and foam can decrease accuracy or give invalid readings.

⇥ Can I substitute an Arduino Uno for an Arduino Nano for an obstacle-avoiding car?  
Yes, the Arduino Nano is fully compatible with the project of building an obstacle-avoiding robot car while providing advantages, such as a smaller size (45mm × 18mm vs 68.6mm × 53.4mm), a lighter weight (7g vs 25g), and cheaper ($3-5 vs $10-15). Also, both have the same ATmega328P processor with a 16MHz clock speed. While the pin layout is not the same, all the pins you will need (digital I/O, PWM, analog) are present on the Nano. You will just have to change the PIN definitions in your code to represent the Nano layout instead. Both boards operate with 5V logic levels.  

⇥ Why does my obstacle-avoiding car spin in circles or not go straight?  
This typically occurs due to mismatched motor speeds based on manufacturing tolerances. Resolution: (1) In the method moveForward(), adjust the ENA and ENB PWM levels; if the car is turning to the right, add to the ENA (left motor velocity); if the car is turning left, add to the ENB (right motor velocity), (2) Ensure all four wheels are oriented correctly against the ground and not slipping on the motor shafts, (3) Use a multimeter to confirm both motor drivers get the same voltage (in this case, 12V), (4) Confirm all connections to each motor are tight, and that there are not any loose wires. Typical mismatched speed is approximately 5-15 points apart (i.e. ENA = 60 & ENB = 52) for moving straight.

⇥ What is the minimum distance for obstacle detection?
The code automatically sets the threshold for MIN_DISTANCE_BACK to 12cm, meaning that the car will brake when an obstacle is detected within 12cm. This minimum threshold can and will change dramatically depending on your needs. If your vehicle is travelling at higher speeds or you want your vehicle to be at higher speeds, you can increase the threshold to 20 to 30cm so there is enough space and time to stop the vehicle. If you want the vehicle to navigate in tight areas or maze finding, then you can reduce the distance to say 8 to 10cm, so the vehicle has a more tight and precise spot to turn. You should take into account the momentum from your vehicle, the response time from your motor, and the turn circle when adjusting the MIN_DISTANCE_BACK parameter.

⇥ How long will the battery last for an obstacle avoidance vehicle?
Generally, the 12V 2200mAh Li-ion battery will offer between 45-90 minutes in unbroken operation, depending on the load of the motors, roughness of terrain, or how many components are running. Analysis of current consumption: 4 DC motors, 200-400mA when cruising (each) + Arduino (50-100mA) + servo motor (100-500mA while moving) + ultrasonic (15mA) + LED's (60mA) = total 900-1800mA. If you use a larger 3000mAh battery, then you will receive an additional 1.5-3 hours of battery life. Keep in mind, you can always change some parameters to extend battery life (slow down motor, reduce servo motion), while also trying to reduce the number of DC motors on during obstacle avoidance.

⇥ What are some real-world applications of obstacle-avoiding robots? 
There are numerous commercial and industrial implementations of obstacle avoiding technology, including autonomous vacuum cleaners ($4.4 billion global market for iRobot Roomba), robots that manage inventory in warehouses (300% productivity increases with Amazon Robotics), agricultural robots that monitor crops and spray with precision (90% reduction in herbicide use), hospital and hotel delivery robots, surveillance or security robots that patrol autonomously 24/7 and monitor areas continuously, robots that explore hazardous environments, and devices that assist visually impaired persons. The applications range from school projects to industrial automation systems with complex sensor fusion systems that may use ultrasonic, LiDAR, cameras, or radar.

⇥ How would I put Bluetooth control on my obstacle-avoiding car? 
Yes, by interfacing an HC-05 or HC-06 Bluetooth module (dual-mode), which will allow you to run it autonomously, the built-in obstacle avoiding program, or to control it manually with your smartphone. Connect the TX from the module to Arduino pin 0 (RX), and the RX from the module to Arduino pin 1 (TX), and connect it to power (5V rail). You will have to incorporate some program logic to toggle between modes (control and autonomous) by reading incoming commands using Serial.available(). There are app options to use, like Arduino Bluetooth Controller or similar apps to communicate with your Arduino. In order to switch from autonomous operation to control all you need to add is a button (on the app) or a toggle switch that will convert between manual and autonomous operation without skipping a beat while it is in movement. 
 

Conclusion

This tutorial will take you through the process of designing and building an Arduino obstacle avoiding car that is capable of navigating autonomously in a yet unknown environment. This obstacle avoiding car project demonstrates simple concepts in robotics such as sensor integration, real-time decision-making algorithms, motor control, and embedded programming with simple and inexpensive hardware.

The finished obstacle avoiding robot car has an HC-SR04 ultrasonic sensor for distance measurement with a range from 2-400 cm at a ±3 mm accuracy (which meets the criteria for measuring distance), a servo motor with a 180-degree servo scan of the environment, and a set of four geared motors that allow for complete omnidirectional movement when incorporating an L298N motor controller. Whether you are a student learning about robotics for the first time or an educator developing STEM curriculum, a hobbyist learning new skills, or a professional who prototypes autonomous systems, an Arduino obstacle avoiding car offers a solid base. 

Thank you for following this comprehensive tutorial on how to make obstacle avoiding car using Arduino. We hope this guide provided clear instructions, helpful troubleshooting tips, and inspired you to continue exploring autonomous robotics. Happy building!
 

DIY Robotics Projects Using an Obstacle Avoidance System

We have previously implemented the obstacle avoidance system in several innovative robotics and automation projects. Explore the projects listed below to learn how this system is applied in real-world scenarios. Each project includes detailed circuit explanations, codes, and step-by-step tutorials to help you build your own version.

Obstacle Avoiding Robot using PIC Microcontroller

Obstacle Avoiding Robot using PIC Microcontroller

There are many ways to build an obstacle-avoiding robot in the project. We are going to use one Ultrasonic Sensor (front) and two IR sensors (Left/Right) so that our robot has eyes in all three directions. Here we are using the PIC Microcontroller PIC16F877A for this obstacle-avoiding robot.

Raspberry Pi Based Obstacle Avoiding Robot using Ultrasonic Sensor

Raspberry Pi-Based Obstacle-Avoiding Robot Using Ultrasonic Sensor

But today we are here with an Automatic Robot which moves autonomously without any external events, avoiding all the obstacles in its path, yes, we are talking about an Obstacle Avoiding Robot. In this project, we have used a Raspberry Pi and a Motor driver to drive the robot and an Ultrasonic sensor for detecting objects in the path of the Robot.

How does an HC-SR04 Ultrasonic Range Sensor Works and How to Interface with ESP32

How does an HC-SR04 Ultrasonic Range Sensor work, and how to interface with ESP32

In this project, we are going to interface an HC-SR04 Ultrasonic Distance Sensor module with ESP32, and we are going to know every little detail about the module, which is a key component of any obstacle avoidance or detection system. So, in this project, we are going to know every little detail about the HC-SR04 Ultrasonic Distance Sensor module, along with interfacing it with the ESP32. 

Complete Project Code

//Arduino Obstacle Avoiding Car Code
//by circuitdigest 


#include <Servo.h> 

// Ultrasonic sensor pins
#define trig 2
#define echo 4

// RGB led pins 
#define LR 9       // Led Right
#define LC 13     // Led Center
#define LL 10     // Led Left

#define LRR A3   // Led Right Red
#define LCR A2   // Led Center Red
#define LLR A1  // Led Left Red

// Motor control pins
#define LEFT_MOTOR_PIN1 8
#define LEFT_MOTOR_PIN2 7
#define RIGHT_MOTOR_PIN1 12
#define RIGHT_MOTOR_PIN2 11

#define ENA 6 // Enable A pin for motor speed control
#define ENB 3 // Enable B pin for motor speed control

// Distance thresholds for obstacle detection
//#define MAX_DISTANCE 80
#define MIN_DISTANCE_BACK 12

//float timeOut = 2*(MAX_DISTANCE+10)/100/340*1000000;
// Maximum and minimum motor speeds
#define MAX_SPEED 100
#define MIN_SPEED 75

Servo servoLook;

void setup() {
  // Set motor control pins as outputs
  pinMode(LEFT_MOTOR_PIN1, OUTPUT);
  pinMode(LEFT_MOTOR_PIN2, OUTPUT);
  pinMode(RIGHT_MOTOR_PIN1, OUTPUT);
  pinMode(RIGHT_MOTOR_PIN2, OUTPUT);

  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);

  pinMode(LR, OUTPUT);
  pinMode(LC, OUTPUT);
  pinMode(LL, OUTPUT);

  pinMode(LRR, OUTPUT);
  pinMode(LCR, OUTPUT);
  pinMode(LLR, OUTPUT);

  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);
  digitalWrite(LL, LOW);

  analogWrite(LRR, 0);
  analogWrite(LCR, 0);
  analogWrite(LLR, 0);

  servoLook.attach(5);
  //Set the Trig pins as output pins
  pinMode(trig, OUTPUT);
  
  //Set the Echo pins as input pins
  pinMode(echo, INPUT);

  analogWrite(ENA, 53.5); // speed for motor A  0-LOW speed, 255-Full speed
  analogWrite(ENB, 45); // speed for motor B
  
  // Initialize the serial communication for debugging
  Serial.begin(9600);
}

void loop() {

  servoLook.write(90);
  delay(750);
  int distance = getDistance();
  if (distance >= MIN_DISTANCE_BACK) {
    
    moveForward();
   
    Serial.println("forward");
  } 
   while(distance >= MIN_DISTANCE_BACK)
   {
    distance = getDistance();
    delay(50);
   }
   Stop(); 
   int turnDir = checkDirection();
   Serial.println(turnDir);
   switch(turnDir)
   {
    case 0:                                       //Turn left
    Serial.println("Left");
      turnLeft();
      delay(425);
      Stop();
      break;
    
    case 2:                                       //Turn right
    Serial.println("Right");
      turnRight();
      delay(415);
      Stop();
      break;
      
    case 3:                                       //move forward
    Serial.println("Forward");
     moveForward();
      break;
    }
}

int getDistance()                                   //Measure the distance to an object
{
  unsigned long pulseTime;                          //Create a variable to store the pulse travel time
  int distance;                                     //Create a variable to store the calculated distance
  digitalWrite(trig, HIGH);                         //Generate a 10 microsecond pulse
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  pulseTime = pulseIn(echo, HIGH);         //Measure the time for the pulse to return
  distance  = pulseTime / 29 / 2;         //Calculate the object distance based on the pulse time
  Serial.println(distance);
  return distance;
}

int checkDirection()                                            //Check the left and right directions and decide which way to turn
{
  int distances [3] = {0,0,0};                                    //Left ,right and Front distances
  int turnDir;                                               //Direction to turn, 0 left, 1 turn around, 2 right, 3 forward
  servoLook.write(180);                                         //Turn servo to look left
  delay(500);
  distances [0] = getDistance();                                //Get the left object distance

  servoLook.write(90);                                         //Turn servo to look left
  delay(500);
  distances [3] = getDistance();
  servoLook.write(0);                                           //Turn servo to look right
  delay(1000);
  distances [1] = getDistance();                                //Get the right object distance
  if (distances[0]<=25 && distances[1]<=25)                   //If both directions are blocked, move forward
    turnDir = 3;                                             
  else if (distances[0]>=distances[1])                          //If left has more space, turn left
    turnDir = 0;  //left
  else if (distances[0]<distances[1])                           //If right has more space, turn right
    turnDir = 2;  //right
   //else if (distances[0]<=50 && distances[1]<=50 && distances[3]<=50)    //If All directions are blocked, turn around
    //turnDir = 1;  
  return turnDir;
}

// Motor control functions
void moveForward() {
 
  analogWrite(ENA, 60.5); //  speed for motor A
  analogWrite(ENB, 52); //   speed for motor B

  digitalWrite(LR, HIGH);
  digitalWrite(LC, HIGH);      // All Green light turn on
  digitalWrite(LL, HIGH);

  analogWrite(LRR, 0);
  analogWrite(LCR, 0);       // All Red light turn off
  analogWrite(LLR, 0);
  
  digitalWrite(LEFT_MOTOR_PIN1, LOW);
  digitalWrite(LEFT_MOTOR_PIN2, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN1, LOW);
  digitalWrite(RIGHT_MOTOR_PIN2, HIGH);
}

void moveBackward() {
  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);        // All Green light turn off
  digitalWrite(LL, LOW);

  analogWrite(LRR, 255);
  analogWrite(LCR, 255);       // All Red light turn on
  analogWrite(LLR, 255);
  
 
  digitalWrite(LEFT_MOTOR_PIN1, HIGH);
  digitalWrite(LEFT_MOTOR_PIN2, LOW);
  digitalWrite(RIGHT_MOTOR_PIN1, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN2, LOW);
}

void turnRight() {
  analogWrite(ENA, 100); //  speed for motor A
  analogWrite(ENB, 90); //  speed for motor B
  
  digitalWrite(LR, HIGH);
  digitalWrite(LC, LOW);            // right side Green light turn on
  digitalWrite(LL, LOW);

  analogWrite(LRR, 0);
  analogWrite(LCR, 255);         // Left and Middel Red light turn on
  analogWrite(LLR, 255);
  
  
  digitalWrite(LEFT_MOTOR_PIN1, HIGH);
  digitalWrite(LEFT_MOTOR_PIN2, LOW);
  digitalWrite(RIGHT_MOTOR_PIN1, LOW);
  digitalWrite(RIGHT_MOTOR_PIN2, HIGH);
}

void turnLeft() {
  analogWrite(ENA, 100); //  speed for motor A
  analogWrite(ENB, 90); //  speed for motor B
  
  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);         // left side Green light turn on
  digitalWrite(LL, HIGH);

  analogWrite(LRR, 255);
  analogWrite(LCR, 255);         // right and Middel Red light turn on
  analogWrite(LLR, 0);
  
 
  digitalWrite(LEFT_MOTOR_PIN1, LOW);
  digitalWrite(LEFT_MOTOR_PIN2, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN1, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN2, LOW);
}

void Stop() {
  digitalWrite(LR, LOW);
  digitalWrite(LC, LOW);
  digitalWrite(LL, LOW);

  analogWrite(LRR, 255);
  analogWrite(LCR, 255);
  analogWrite(LLR, 255);
  
  analogWrite(ENA, 70.5); //  speed for motor A
  analogWrite(ENB, 60); //  speed for motor B
 
  digitalWrite(LEFT_MOTOR_PIN1, HIGH);
  digitalWrite(LEFT_MOTOR_PIN2, LOW);
  digitalWrite(RIGHT_MOTOR_PIN1, HIGH);
  digitalWrite(RIGHT_MOTOR_PIN2, LOW);
  delay(50);
  
  analogWrite(ENA, 0); //  speed for motor A
  analogWrite(ENB, 0); //  speed for motor B
  
  digitalWrite(LEFT_MOTOR_PIN1, LOW);
  digitalWrite(LEFT_MOTOR_PIN2, LOW);
  digitalWrite(RIGHT_MOTOR_PIN1, LOW);
  digitalWrite(RIGHT_MOTOR_PIN2, LOW);
}
Have any question related to this Article?

Add New Comment

Login to Comment Sign in with Google Log in with Facebook Sign in with GitHub