Bluetooth-controlled RC car with Arduino and L298N
A Bluetooth-controlled RC car is a classic robotics project for getting comfortable with DC motors, H-bridges, and wireless communication — no custom app needed, just any off-the-shelf Bluetooth serial controller app and a few lines of Arduino code.
How it works
- Your phone pairs over Bluetooth with the HC-05 module (acting as a wireless serial port).
- The controller app sends a single command character each time a button is pressed:
F(forward),B(backward),L(left),R(right),S(stop). - The Arduino reads that character from
Serial(wired to the HC-05) and maps it to a combination of signals driving two DC motors through an L298N H-bridge. - Motor speed is set with a PWM signal on the L298N’s ENA/ENB pins.
Parts list
- Arduino Uno
- HC-05 Bluetooth module
- L298N H-bridge motor driver (drives 2 DC motors)
- 2 DC motors + wheels, a 2- or 4-wheel robot chassis
- A separate battery for the motors (18650 cell or a 9V-12V pack, not shared with the Arduino’s supply)
- Two resistors (1k ohm and 2k ohm) for a voltage divider on the HC-05’s RX pin
- Any Bluetooth serial controller app on your phone (e.g. “Arduino Bluetooth Controller” or “Serial Bluetooth Terminal”)
An important wiring detail
The HC-05 runs at 3.3V logic, but the Arduino Uno’s TX pin outputs 5V. Wiring Arduino’s TX directly into HC-05’s RX without stepping the voltage down can degrade or damage the module over time — use a voltage divider:
Arduino TX (5V) --[1k ohm]--+--[2k ohm]--- GND
|
HC-05 RX (~3.3V)
Sample code
#include <SoftwareSerial.h>
SoftwareSerial bluetooth(10, 11); // RX, TX wired to the HC-05
// L298N direction control pins
const int IN1 = 2, IN2 = 3; // left motor
const int IN3 = 4, IN4 = 5; // right motor
const int ENA = 9; // PWM speed for the left motor
const int ENB = 6; // PWM speed for the right motor
const int SPEED = 200; // 0-255
void goForward() {
digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}
void goBackward() {
digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH);
}
void turnLeft() {
digitalWrite(IN1, LOW); digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}
void turnRight() {
digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}
void stopCar() {
digitalWrite(IN1, LOW); digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}
void setup() {
bluetooth.begin(9600);
pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
pinMode(ENA, OUTPUT); pinMode(ENB, OUTPUT);
analogWrite(ENA, SPEED);
analogWrite(ENB, SPEED);
stopCar();
}
void loop() {
if (bluetooth.available()) {
char command = bluetooth.read();
switch (command) {
case 'F': goForward(); break;
case 'B': goBackward(); break;
case 'L': turnLeft(); break;
case 'R': turnRight(); break;
case 'S': stopCar(); break;
}
}
}
Pair the HC-05 with your phone first through Bluetooth settings (the default PIN is usually
1234or0000), then open your controller app and map its buttons to send theF/B/L/R/Scharacters.
Common pitfalls
- Skipping the voltage divider on RX: running the HC-05’s RX at 5V long-term can shorten its lifespan or damage it outright — always step it down as shown above.
- Sharing power between the Arduino and the motors: DC motors generate back-EMF spikes when starting or reversing suddenly, which can cause noise or reset the Arduino — power the motors from a separate battery and only share ground.
- Forgetting a common ground between the Arduino, HC-05, and L298N — this is the most common reason commands “send fine” but the car never moves.
SoftwareSerialpin conflicts: if you’re on a Mega or Leonardo instead of an Uno, consider using a hardwareSerial1port instead ofSoftwareSerialfor more reliable behavior at higher baud rates.
Where to go from here
Add an HC-SR04 ultrasonic sensor up front so the car automatically stops near obstacles, or swap the HC-05 for an ESP32 to control it over WiFi with a custom mobile app that has a virtual joystick instead of just five buttons.
Comments