Bluetooth Controlled 4WD Robotic Car Using Arduino

In this project, we will build a 4WD robotic car that can be controlled wirelessly using a smartphone. The car uses an Arduino Uno, HC-05/HC-06 Bluetooth module, Adafruit Motor Shield V1, and four DC geared motors.

The mobile phone sends commands through Bluetooth, and the Arduino controls the motors, headlights, rear lights, and horn.

Components Required

  • Arduino Uno
  • Adafruit Motor Shield V1 (L293D)
  • HC-05 or HC-06 Bluetooth module
  • 4 × DC geared motors
  • 4 × Wheels
  • 4WD robot chassis
  • Battery pack
  • 2 or more front LEDs
  • 2 or more rear LEDs
  • 220Ω–330Ω resistors
  • Buzzer
  • Jumper wires
  • On/Off switch

Motor Connections

MotorMotor Shield
Left FrontM1
Left RearM2
Right FrontM3
Right RearM4

The project uses the AFMotor library, which is compatible with the Adafruit Motor Shield V1.

Bluetooth Connections

HC-05/HC-06Arduino Uno
VCC5V
GNDGND
TXDD0 (RX)
RXDD1 (TX)

The Bluetooth module is configured for 9600 baud.

Important: Disconnect the Bluetooth TX/RX wires from D0 and D1 while uploading the Arduino code. Reconnect them after uploading.

Lights and Buzzer

ComponentArduino Pin
Front LightsD10
Rear LightsD13
BuzzerA0

Use a suitable current-limiting resistor with LEDs. For a larger buzzer, use a transistor driver circuit.

Power Supply

Connect the battery to the motor shield’s motor power input. Do not power the four motors from the Arduino 5V pin.

Make sure the Arduino and motor power system have a common GND.

Bluetooth Commands

The smartphone app should send the following characters:

CommandFunction
FForward
BBackward
GForward Left
IForward Right
HBackward Left
JBackward Right
LTurn Left
RTurn Right
SStop
WFront Lights ON
wFront Lights OFF
URear Lights ON
uRear Lights OFF
VHorn ON
vHorn OFF

The car uses differential drive. During diagonal movement, one side runs slower than the other, allowing the car to move in a curved direction. During left and right turns, the motors on opposite sides rotate in opposite directions, allowing the car to pivot in place.

Arduino Code:

#include <AFMotor.h>

// ---------- Motors (shield channels) ----------
AF_DCMotor motorLF(1);   // Left-front  -> M1
AF_DCMotor motorLR(2);   // Left-rear   -> M2
AF_DCMotor motorRF(3);   // Right-front -> M3
AF_DCMotor motorRR(4);   // Right-rear  -> M4

// ---------- Accessory pins ----------
const int FRONT_LIGHTS_PIN = 10;
const int REAR_LIGHTS_PIN  = 13;
const int BUZZER_PIN       = A0;

// ---------- Tuning ----------
int fullSpeed = 250;   // 0-255, current driving speed (adjustable via app's speed slider)
int slowSpeed = 120;   // 0-255, speed for the "slowed" side during a diagonal move

// ---------- Failsafe ----------
// If the car is moving and no new command arrives within this window,
// assume the Bluetooth link dropped and stop automatically.
const unsigned long COMMAND_TIMEOUT = 800; // ms
unsigned long lastCommandTime = 0;
bool isMoving = false;

void setup() {
  Serial.begin(9600);   // This IS the Bluetooth link now (D0/D1), not USB debug.
                          // Default HC-05/HC-06 baud rate is 9600.

  pinMode(FRONT_LIGHTS_PIN, OUTPUT);
  pinMode(REAR_LIGHTS_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);

  stopCar();
  digitalWrite(FRONT_LIGHTS_PIN, LOW);
  digitalWrite(REAR_LIGHTS_PIN, LOW);
  digitalWrite(BUZZER_PIN, LOW);
}

void loop() {
  if (Serial.available()) {
    char command = Serial.read();
    handleCommand(command);
    lastCommandTime = millis();
    // Note: no Serial.println() debug prints here on purpose -
    // this Serial line is shared with the Bluetooth module, so anything
    // printed here gets sent to the phone app instead of a USB debug console.
  }

  // Failsafe: if we're supposed to be moving but haven't heard from the
  // app in a while, the Bluetooth link likely dropped - stop the car.
  if (isMoving && (millis() - lastCommandTime > COMMAND_TIMEOUT)) {
    stopCar();
  }
}

void handleCommand(char command) {
  switch (command) {
    // ---- 8-direction movement ----
    case 'F': forward();       break;
    case 'B': backward();      break;
    case 'G': forwardLeft();   break;
    case 'I': forwardRight();  break;
    case 'H': backwardLeft();  break;
    case 'J': backwardRight(); break;
    case 'L': turnLeft();      break;
    case 'R': turnRight();     break;
    case 'S': stopCar();       break;

    // ---- Lights ----
    case 'W': digitalWrite(FRONT_LIGHTS_PIN, HIGH); break;
    case 'w': digitalWrite(FRONT_LIGHTS_PIN, LOW);  break;
    case 'U': digitalWrite(REAR_LIGHTS_PIN, HIGH);  break;
    case 'u': digitalWrite(REAR_LIGHTS_PIN, LOW);   break;

    // ---- Horn ----
    case 'V': digitalWrite(BUZZER_PIN, HIGH); break;
    case 'v': digitalWrite(BUZZER_PIN, LOW);  break;

    // ---- Speed slider (0-9 = 0%-90%, q = 100%) ----
    case '0': setSpeed(0);   break;
    case '1': setSpeed(28);  break;
    case '2': setSpeed(57);  break;
    case '3': setSpeed(85);  break;
    case '4': setSpeed(113); break;
    case '5': setSpeed(142); break;
    case '6': setSpeed(170); break;
    case '7': setSpeed(198); break;
    case '8': setSpeed(226); break;
    case '9': setSpeed(255); break;
    case 'q': setSpeed(255); break;

    default: break; // ignore unknown / newline characters
  }
}

// ---------- Speed ----------
void setSpeed(int newSpeed) {
  fullSpeed = newSpeed;
  slowSpeed = newSpeed * 0.6; // keep the diagonal-turn slowdown proportional

  // If the car is already moving, apply the new speed right away
  // instead of waiting for the next direction command.
  if (isMoving) {
    setLeftSpeed(fullSpeed);
    setRightSpeed(fullSpeed);
  }
}

// ---------- Helpers ----------
void setLeftSpeed(int speed)  { motorLF.setSpeed(speed); motorLR.setSpeed(speed); }
void setRightSpeed(int speed) { motorRF.setSpeed(speed); motorRR.setSpeed(speed); }

void leftForward()   { motorLF.run(FORWARD);  motorLR.run(FORWARD);  }
void leftBackward()  { motorLF.run(BACKWARD); motorLR.run(BACKWARD); }
void leftStop()      { motorLF.run(RELEASE);  motorLR.run(RELEASE);  }

void rightForward()  { motorRF.run(FORWARD);  motorRR.run(FORWARD);  }
void rightBackward() { motorRF.run(BACKWARD); motorRR.run(BACKWARD); }
void rightStop()     { motorRF.run(RELEASE);  motorRR.run(RELEASE);  }

// ---------- Movement ----------
void forward() {
  setLeftSpeed(fullSpeed);  setRightSpeed(fullSpeed);
  leftForward(); rightForward();
  isMoving = true;
}

void backward() {
  setLeftSpeed(fullSpeed);  setRightSpeed(fullSpeed);
  leftBackward(); rightBackward();
  digitalWrite(REAR_LIGHTS_PIN, HIGH); // reverse/brake indicator while backing up
  isMoving = true;
}

void forwardLeft() {
  // moving forward while veering left: slow the left side down
  setLeftSpeed(slowSpeed); setRightSpeed(fullSpeed);
  leftForward(); rightForward();
  isMoving = true;
}

void forwardRight() {
  // moving forward while veering right: slow the right side down
  setLeftSpeed(fullSpeed); setRightSpeed(slowSpeed);
  leftForward(); rightForward();
  isMoving = true;
}

void backwardLeft() {
  setLeftSpeed(slowSpeed); setRightSpeed(fullSpeed);
  leftBackward(); rightBackward();
  digitalWrite(REAR_LIGHTS_PIN, HIGH);
  isMoving = true;
}

void backwardRight() {
  setLeftSpeed(fullSpeed); setRightSpeed(slowSpeed);
  leftBackward(); rightBackward();
  digitalWrite(REAR_LIGHTS_PIN, HIGH);
  isMoving = true;
}

void turnLeft() {
  // pivot in place: left side backward, right side forward
  setLeftSpeed(fullSpeed); setRightSpeed(fullSpeed);
  leftBackward(); rightForward();
  isMoving = true;
}

void turnRight() {
  // pivot in place: left side forward, right side backward
  setLeftSpeed(fullSpeed); setRightSpeed(fullSpeed);
  leftForward(); rightBackward();
  isMoving = true;
}

void stopCar() {
  leftStop(); rightStop();
  digitalWrite(REAR_LIGHTS_PIN, LOW);
  isMoving = false;
}

Testing

After uploading the code:

  1. Connect the HC-05/HC-06 to the Arduino.
  2. Power the robotic car.
  3. Pair the phone with the Bluetooth module.
  4. Open a Bluetooth control app.
  5. Configure the buttons to send the commands listed above.
  6. Test forward, backward, left, right, lights, and horn.

If the car moves in the wrong direction, reverse the motor wires of the affected motor.