Skip to main content

Arduino UNO Multi-Sensor Obstacle Avoidance & Bluetooth Controlled Robot Car Using L298N

Arduino UNO Obstacle Avoidance & Bluetooth Robot Car | MakeMindz
🤖 Advanced Robotics

Arduino UNO Obstacle Avoidance & Bluetooth Controlled Robot Car

A 4WD smart robot with 3 operating modes — autonomous obstacle avoidance, line following, and Bluetooth smartphone control. Full code, wiring & simulation included.

Arduino UNO HC-SR04 Ultrasonic HC-05 Bluetooth L298N Motor Driver SG90 Servo IR Sensors 4WD Platform Intermediate
🚗
Obstacle Avoidance
Send cmd 10 · Fully autonomous
↔️
Line Following
Send cmd 9 · IR sensor guided
📱
Bluetooth Control
Send cmd 8 · Manual via app
1

Project Overview

This project combines three intelligent operating modes in a single 4-wheel-drive robot. The Arduino UNO acts as the central controller, reading data from multiple sensors and switching between autonomous and manual operation based on Bluetooth or IR remote commands.

🔊

180° Scanning

SG90 servo sweeps the HC-SR04 ultrasonic sensor left and right to find the clearest path forward.

📡

Dual Input

Both Bluetooth (HC-05) and IR remote control are decoded simultaneously for flexible operation.

PWM Speed

Motor speed is set via analogWrite(enA/enB) PWM — adjustable from the app in real time.

🔋

18650 Li-ion

Rechargeable 18650 battery pack provides stable 7.4V–8.4V to the L298N motor driver.

2

Components List

🟦
Arduino UNO R3
ATmega328P
×1
🔊
HC-SR04
Ultrasonic sensor
×1
📡
HC-05
Bluetooth module
×1
⚙️
SG90 Servo
Sensor scanning
×1
🔴
IR Sensors
Line detection (×2)
×2
🔌
L298N Driver
Dual H-bridge
×1
🚗
DC Motors
TT gear motors
×4
🔋
18650 Battery
Li-ion 2-cell pack
×1
📻
IR Remote
NEC protocol
×1
🏗️
4WD Chassis
Acrylic robot frame
×1
📦
Install via Sketch → Manage Libraries: SoftwareSerial (built-in) · IRremote by shirriff · No additional libs needed for servo (manual PWM pulses used).
3

Wiring Diagram

All digital and analog pins are used. The servo is driven by manual PWM pulses on A4, and SoftwareSerial uses pins 2 (RX) and 3 (TX) for Bluetooth.

ARDUINO UNO D2 (BT RX) ● D3 (BT TX) ● D5 (enB) ● D6 (in4) ● D7 (in3) ● D8 (in2) ● D9 (in1) ● D10 (enA) ● ● A0 (IR Right) ● A1 (IR Left) ● A2 (Echo) ● A3 (Trigger) ● A4 (Servo) ● A5 (IR recv) 5V ● GND ● ATmega328P L298N MOTOR DRIVER OUT1/2 ● M1 (Right) OUT3/4 ● M2 (Left) ENA ● IN1 ● IN2 ● IN3 ● IN4 ● ENB ● GND ● +5V→Arduino ● M1 R M2 L HC-05 BLUETOOTH ANT VCC ● GND ● TXD ● RXD ● STATE ● BT TXD→D2 HC-SR04 ULTRASONIC Tx Rx VCC ● GND ● ● Trig ● Echo A2 Echo / A3 Trig SG90 SERVO ↑70° Signal ● VCC ● GND ● DUAL IR SENSORS LEFT IR A1 RIGHT IR A0 VCC ● GND ● IR RECEIVER 38kHz SIG→A5 VCC GND 5V rail GND rail LEGEND Motor control Servo / A4 Ultrasonic IR sensors IR receiver

Full Pin Reference

ModuleModule PinArduino PinNotes
HC-05 BluetoothVCC5V
HC-05 BluetoothGNDGND
HC-05 BluetoothTXDD2 (SoftSerial RX)HC-05 TX → Arduino D2
HC-05 BluetoothRXDD3 (SoftSerial TX)Use voltage divider for 3.3V
L298NENAD10 (PWM)Right motor speed
L298NIN1D9Right motor dir A
L298NIN2D8Right motor dir B
L298NIN3D7Left motor dir A
L298NIN4D6Left motor dir B
L298NENBD5 (PWM)Left motor speed
IR Sensor RightOUTA0Digital read
IR Sensor LeftOUTA1Digital read
HC-SR04EchoA2Input
HC-SR04TriggerA3Output
SG90 ServoSignalA4Manual PWM pulses
IR ReceiverOUTA5RECV_PIN for IRremote lib
⚠️
HC-05 RXD voltage: The HC-05's RXD pin is 3.3V logic. Use a voltage divider (1kΩ + 2kΩ) between Arduino D3 (TX) and HC-05 RXD to avoid damaging the module.

How It Works — Three Modes

Mode 2 · cmd=10 — Obstacle Avoidance (Autonomous)

  • Servo sweeps the HC-SR04 to scan forward continuously.
  • If front distance > 20 cm (set variable), robot moves forward.
  • Obstacle detected, robot stops, calls Check_side().
  • Servo rotates left (140°) reads distance_L, then right (0°) reads distance_R.
  • compareDistance(): turns toward the side with more space (350 ms turn). If both blocked, reverse and turn 600 ms.
  • Servo returns to 70° (centre) and resumes forward motion.

Mode 1 · cmd=9 — Line Following

  • Speed set to 130 (moderate) for smooth line tracking.
  • R_S=0, L_S=0 (both on white): forward()
  • R_S=1, L_S=0 (right on black): turnRight()
  • R_S=0, L_S=1 (left on black): turnLeft()
  • R_S=1, L_S=1 (both on black / end of track): Stop()

Mode 0 · cmd=8 — Bluetooth / IR Remote Manual Control

  • HC-05 or IR remote sends a numeric command (1–10).
  • If value > 20, it is treated as a new PWM speed value (0–255).
  • Commands 1–5: Forward / Backward / Left / Right / Stop.
  • Commands 6–7: Timed turns (voice control style, auto-stop after 400 ms).
  • Commands 8/9/10 switch mode: Stop / Line Follow / Obstacle Avoid.

Servo Sweep Logic — Manual PWM Pulse Generation

  • No Servo library used, pulses are generated manually via servoPulse(pin, angle).
  • Formula: pwm = (angle x 11) + 500 microseconds.
  • At 70° = 1270 µs, At 0° = 500 µs, At 140° = 2040 µs.
  • 50 ms delay between pulses provides the refresh cycle.
5

Bluetooth / IR Command Reference

Send these integer values from your Bluetooth app (e.g. Arduino Bluetooth Controller on Android). IR remote codes are mapped to the same numbers via IRremote_data().

1
Forward
Move ahead
2
Backward
Reverse
3
Left
Turn left
4
Right
Turn right
5
Stop
Halt motors
6
Timed Left
400 ms turn
7
Timed Right
400 ms turn
8
Manual Mode
mode = 0
9
Line Follow
mode = 1
10
Avoid Mode
mode = 2
>20
Set Speed
PWM 0–255
📱
Recommended app: "Arduino Bluetooth Controller" or "Bluetooth RC Car" on Android. Set button values to the integers above. For speed, send any number like 150 or 200.
6

Interactive Robot Simulator

🎮 Mini Control Demo

🧱
🧱
🧱
🤖
Mode: Manual · Status: Ready
7

Full Arduino Code

Arduino / C++
#include <SoftwareSerial.h>
SoftwareSerial BT_Serial(2, 3); // RX=D2, TX=D3

#include <IRremote.h>
const int RECV_PIN = A5;
IRrecv irrecv(RECV_PIN);
decode_results results;

// ── L298N Motor Driver Pins ──
#define enA  10  // Enable Right motors (PWM)
#define in1   9  // Right motor forward
#define in2   8  // Right motor backward
#define in3   7  // Left motor backward
#define in4   6  // Left motor forward
#define enB   5  // Enable Left motors (PWM)

#define servo   A4  // SG90 Servo signal
#define R_S     A0  // IR sensor Right
#define L_S     A1  // IR sensor Left
#define echo    A2  // HC-SR04 Echo
#define trigger A3  // HC-SR04 Trigger

int distance_L, distance_F = 30, distance_R;
long distance;
int set = 20;          // obstacle threshold (cm)
int bt_ir_data;
int Speed = 130;
int mode = 0;
int IR_data;

void setup() {
  pinMode(R_S, INPUT);  pinMode(L_S, INPUT);
  pinMode(echo, INPUT); pinMode(trigger, OUTPUT);
  pinMode(enA, OUTPUT); pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT); pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT); pinMode(in4, OUTPUT);
  pinMode(servo, OUTPUT);

  irrecv.enableIRIn();
  irrecv.blink13(true);

  Serial.begin(9600);
  BT_Serial.begin(9600);

  // Servo startup sweep (calibration)
  for (int a = 70; a <= 140; a += 5) servoPulse(servo, a);
  for (int a = 140; a >= 0; a -= 5)  servoPulse(servo, a);
  for (int a = 0; a <= 70; a += 5)   servoPulse(servo, a);
  delay(500);
}

void loop() {
  // Read Bluetooth
  if (BT_Serial.available() > 0) {
    bt_ir_data = BT_Serial.read();
    Serial.println(bt_ir_data);
    if (bt_ir_data > 20) { Speed = bt_ir_data; } // speed update
  }

  // Read IR Remote
  if (irrecv.decode(&results)) {
    bt_ir_data = IRremote_data();
    irrecv.resume();
    delay(100);
  }

  // Mode switching
  if      (bt_ir_data == 8)  { mode = 0; Stop(); }
  else if (bt_ir_data == 9)  { mode = 1; Speed = 130; }
  else if (bt_ir_data == 10) { mode = 2; Speed = 255; }

  analogWrite(enA, Speed);
  analogWrite(enB, Speed);

  if (mode == 0) {
    // ── Manual / Bluetooth control ──
    if      (bt_ir_data == 1) forword();
    else if (bt_ir_data == 2) backword();
    else if (bt_ir_data == 3) turnLeft();
    else if (bt_ir_data == 4) turnRight();
    else if (bt_ir_data == 5) Stop();
    else if (bt_ir_data == 6) { turnLeft();  delay(400); bt_ir_data = 5; }
    else if (bt_ir_data == 7) { turnRight(); delay(400); bt_ir_data = 5; }
  }

  if (mode == 1) {
    // ── Line Following ──
    if      (!digitalRead(R_S) && !digitalRead(L_S)) forword();
    else if ( digitalRead(R_S) && !digitalRead(L_S)) turnRight();
    else if (!digitalRead(R_S) &&  digitalRead(L_S)) turnLeft();
    else if ( digitalRead(R_S) &&  digitalRead(L_S)) Stop();
  }

  if (mode == 2) {
    // ── Obstacle Avoidance ──
    distance_F = Ultrasonic_read();
    if (distance_F > set) forword();
    else Check_side();
  }

  delay(10);
}

long IRremote_data() {
  if      (results.value == 0xFF02FD) IR_data = 1;
  else if (results.value == 0xFF9867) IR_data = 2;
  else if (results.value == 0xFFE01F) IR_data = 3;
  else if (results.value == 0xFF906F) IR_data = 4;
  else if (results.value == 0xFF629D || results.value == 0xFFA857) IR_data = 5;
  else if (results.value == 0xFF30CF) IR_data = 8;
  else if (results.value == 0xFF18E7) IR_data = 9;
  else if (results.value == 0xFF7A85) IR_data = 10;
  return IR_data;
}

void servoPulse(int pin, int angle) {
  int pwm = (angle * 11) + 500;
  digitalWrite(pin, HIGH);
  delayMicroseconds(pwm);
  digitalWrite(pin, LOW);
  delay(50);
}

long Ultrasonic_read() {
  digitalWrite(trigger, LOW);  delayMicroseconds(2);
  digitalWrite(trigger, HIGH); delayMicroseconds(10);
  digitalWrite(trigger, LOW);
  distance = pulseIn(echo, HIGH);
  return distance / 29 / 2;
}

void compareDistance() {
  if      (distance_L > distance_R) { turnLeft();  delay(350); }
  else if (distance_R > distance_L) { turnRight(); delay(350); }
  else                               { backword();  delay(300); turnRight(); delay(600); }
}

void Check_side() {
  Stop(); delay(100);
  for (int a = 70;  a <= 140; a += 5) servoPulse(servo, a);
  delay(300); distance_L = Ultrasonic_read(); delay(100);
  for (int a = 140; a >= 0;   a -= 5) servoPulse(servo, a);
  delay(500); distance_R = Ultrasonic_read(); delay(100);
  for (int a = 0;   a <= 70;  a += 5) servoPulse(servo, a);
  delay(300); compareDistance();
}

// ── Motor Control Functions ──
void forword()   { digitalWrite(in1,HIGH); digitalWrite(in2,LOW); digitalWrite(in3,LOW);  digitalWrite(in4,HIGH); }
void backword()  { digitalWrite(in1,LOW);  digitalWrite(in2,HIGH);digitalWrite(in3,HIGH); digitalWrite(in4,LOW);  }
void turnRight() { digitalWrite(in1,LOW);  digitalWrite(in2,HIGH);digitalWrite(in3,LOW);  digitalWrite(in4,HIGH); }
void turnLeft()  { digitalWrite(in1,HIGH); digitalWrite(in2,LOW); digitalWrite(in3,HIGH); digitalWrite(in4,LOW);  }
void Stop()       { digitalWrite(in1,LOW);  digitalWrite(in2,LOW); digitalWrite(in3,LOW);  digitalWrite(in4,LOW);  }
9

Online Simulation

▶ Try it in CirkitDesigner

Simulate the full 4WD robot circuit online — test all three modes without any hardware. Use the serial monitor to send Bluetooth commands.

Open CirkitDesigner

Step-by-Step Simulation Guide

#Step
1Open CirkitDesigner, create a new project, add Arduino UNO.
2Add HC-SR04, SG90 Servo, 2× IR sensors, IR receiver, 4× DC motors, and L298N from the library.
3Wire all modules per the pin table above. Use the diagram.json to auto-import connections.
4Paste the code above into the Arduino editor. Install IRremote library.
5Click Simulate. Open Serial Monitor — type 10 to enter obstacle avoidance mode.
6Move a virtual object in front of the HC-SR04 to trigger avoidance. Watch servo sweep and motors respond.
7Type 9 to switch to line-following mode; toggle IR sensor inputs HIGH/LOW to test steering logic.
8Type 8 for manual mode, then 15 to drive forward/backward/turn/stop manually.
10

Applications & Upgrades

🏆Robotics competitions
🎓Final year projects
🏭Warehouse navigation
🔬Autonomous research
📦Object delivery bots
🌿Agricultural robots
🏠Smart home rover
🎪STEM exhibitions

Possible Upgrades

📷

ESP32-CAM

Add live video streaming to monitor the robot's path remotely from a browser.

🗺️

GPS Navigation

Add a NEO-6M GPS module for outdoor waypoint navigation and route tracking.

🎙️

Voice Control

Use Google Assistant via an ESP8266 + IFTTT bridge to control the robot with voice commands.

🧠

AI Object Recognition

Swap to a Raspberry Pi + camera and add TensorFlow Lite for real-time object detection.

© 2026 MakeMindz.com · Arduino, ESP32 & Robotics Project Tutorials

Comments

try for free