# Bluetooth robot car with an HC-05 and Arduino: design worksheet and code

> A ₹1,780 design worksheet for a phone-controlled robot car using an HC-05 Bluetooth module and an L298N, with the level-divider maths, single-character commands, a stop-if-silent failsafe and a test plan.

Canonical: https://roboticsengineering.in/projects/bluetooth-robot-car-hc05-arduino/ | Published: 2026-11-04 | Updated: 2026-11-04

**A ₹1,780 robot car you drive from a phone. An HC-05 Bluetooth module passes single characters from a phone’s serial-terminal app to an Arduino Uno, which drives two motors through an L298N. The page covers the one wiring detail that kills modules, the sketch, a failsafe that stops the car if the signal goes quiet, and a test plan.**

**Scope:** beginner to intermediate. This is a design worksheet with illustrative costs. It has not been bench-tested by this site. Module settings such as baud rate, pairing code and AT-command syntax differ between HC-05 versions and clones, so the values named here are common ones to check, not guarantees. The resistor-divider figure below is plain arithmetic and was checked.

## How it works

The HC-05 is a Bluetooth serial adapter. Once paired with your phone it behaves like a wire: characters you send from a serial-terminal or controller app come out of its TX pin, and characters the Arduino sends into its RX pin go to the phone. The sketch listens for single letters, F, B, L, R and S for forward, back, left, right and stop, plus a digit 0 to 9 for speed, and sets the L298N inputs to match.

Pairing is done once on the phone, with the module powered. The module usually shows up under a name beginning with HC-05, and the pairing code is commonly 1234 or 0000. Check your seller’s sheet, and change the code with the module’s AT commands, so a stranger within range cannot drive your car.

## Bill of materials

| Part | Qty | Unit | Total |
| --- | --- | --- | --- |
| Arduino Uno clone | 1 | ₹550 | ₹550 |
| HC-05 Bluetooth module | 1 | ₹350 | ₹350 |
| L298N motor driver | 1 | ₹180 | ₹180 |
| TT gear motor pair with wheels | 1 | ₹260 | ₹260 |
| 2WD chassis | 1 | ₹150 | ₹150 |
| 2×18650 holder with cells | 1 | ₹200 | ₹200 |
| 1 kΩ and 2 kΩ resistor pair | 1 | ₹10 | ₹10 |
| Switch | 1 | ₹30 | ₹30 |
| Jumper wire set | 1 | ₹50 | ₹50 |
| Parts total | ₹1,780 |  |  |

Scroll the table sideways to see every column.

Prices checked Nov 2026. Shipping and tools are not included.

Prices are illustrative figures for Indian sellers in November 2026, before shipping, and have not been checked against current listings. Bluetooth modules vary a lot in price and quality. A cheaper clone may need different AT commands.

## The one wiring detail that matters

The Uno drives its pins at 5 V. The HC-05’s RX pin is designed for 3.3 V logic. Many people connect it directly and get away with it for a while, but the safe way is a small resistor divider on that one wire. A 1 kΩ resistor from the Uno pin to the HC-05 RX, and a 2 kΩ resistor from the HC-05 RX to ground, gives 5 V × 2 / (1 + 2) = 3.33 V. The other direction needs nothing: the HC-05’s TX output is about 3.3 V, which an Uno reads as a high.

| Part | Arduino Uno | Note |
| --- | --- | --- |
| HC-05 TX | D10 (software RX) | Direct |
| HC-05 RX | D11 (software TX) | Through the 1 kΩ / 2 kΩ divider |
| HC-05 VCC / GND | 5V / GND | Check your board: many have an onboard regulator; some are 3.3 V only |
| L298N ENA / IN1 / IN2 | D5 / D7 / D8 | Left motor, ENA is PWM |
| L298N ENB / IN3 / IN4 | D6 / D9 / D4 | Right motor, ENB is PWM |
| Battery | L298N 12V input and Uno VIN | Check your pack voltage against the board’s limits |

*Pin numbers are one working layout. SoftwareSerial can use most free pins; keep the PWM pins for the motors.*

This layout uses SoftwareSerial on D10 and D11 so the USB serial port stays free for debugging, and the module never shares the pins used for uploading sketches.

## The sketch

```
// Bluetooth robot car: Uno + HC-05 + L298N
// Phone app sends one character: F B L R S, and 0-9 for speed.
// Design worksheet: check the module's baud rate (commonly 9600).

#include <SoftwareSerial.h>

SoftwareSerial bt(10, 11);          // RX, TX

const int L_EN = 5, L_IN1 = 7, L_IN2 = 8;
const int R_EN = 6, R_IN3 = 9, R_IN4 = 4;

const int PWM_MIN = 100;            // below this the motors may not turn
const int PWM_MAX = 255;
const unsigned long FAILSAFE_MS = 500;

int speedPwm = 170;
unsigned long lastCmd = 0;

void motors(int left, int right) {  // -255..255
  digitalWrite(L_IN1, left >= 0); digitalWrite(L_IN2, left < 0);
  digitalWrite(R_IN3, right >= 0); digitalWrite(R_IN4, right < 0);
  analogWrite(L_EN, abs(left));
  analogWrite(R_EN, abs(right));
}

void handle(char c) {
  if (c >= '0' && c <= '9') {
    speedPwm = map(c - '0', 0, 9, PWM_MIN, PWM_MAX);
    return;
  }
  switch (c) {
    case 'F': motors(speedPwm, speedPwm); break;
    case 'B': motors(-speedPwm, -speedPwm); break;
    case 'L': motors(-speedPwm, speedPwm); break;
    case 'R': motors(speedPwm, -speedPwm); break;
    case 'S': motors(0, 0); break;
    default: return;                // ignore anything else
  }
  lastCmd = millis();
}

void setup() {
  Serial.begin(115200);
  bt.begin(9600);
  pinMode(L_EN, OUTPUT); pinMode(L_IN1, OUTPUT); pinMode(L_IN2, OUTPUT);
  pinMode(R_EN, OUTPUT); pinMode(R_IN3, OUTPUT); pinMode(R_IN4, OUTPUT);
  motors(0, 0);
}

void loop() {
  while (bt.available()) {
    char c = bt.read();
    Serial.print(c);                // echo to the USB monitor for debugging
    handle(c);
  }
  if (millis() - lastCmd > FAILSAFE_MS) motors(0, 0);   // stop if silent
}
```

The failsafe is the part to keep. If the phone goes out of range or the app closes, the sketch stops the motors after half a second instead of driving on. That means your app must keep sending the drive letter while a button is held; many controller apps do, some send once. Test yours. If the car stops after half a second every time, either the app sends only once or the failsafe time needs raising.

## Test plan

1. **Wheels off the ground:** prop the car up, send each command, and confirm the wheels turn the way you expect. Swap a motor’s two wires if one is reversed.
2. **Serial echo:** open the Serial Monitor and watch the letters arrive as you press the app’s buttons. If nothing arrives, check the baud rate, the TX/RX crossing and the pairing.
3. **Speeds:** try each digit and find the lowest that actually moves the car on your floor. Set PWM_MIN to that.
4. **Failsafe:** hold forward, then turn the phone’s Bluetooth off. The car should stop in about half a second.
5. **Range:** walk away in a straight line and note where commands begin to drop. Bluetooth range of this class is commonly quoted at about 10 m in the open, and walls cut it.
6. **Battery:** run until the car slows or the module resets. A weak pack can brown out the module before the motors stop.

## What other builders report

Builders have posted similar problems on the Arduino forum, for example in [this thread](https://forum.arduino.cc/t/hc-05-bluetooth-out-of-range-reset-stop/368907) and [this one](https://forum.arduino.cc/t/bluetooth-rc-car-hc05-will-not-be-connected-without-the-serial-cable/957491). The points below are a summary in our own words from search results. We could not open the threads to confirm which post said what, they are anecdotes rather than verified fixes, and none of it is our own measurement.

- Power sag is the most repeated cause of dropped links. Reports describe the battery voltage falling when the motors start, which leaves the Bluetooth board’s regulator short and resets the connection.
- Some builders report the link steadying once the Arduino and the motor driver run from separate supplies, and motor electrical noise on a shared supply is a suspected contributor.
- Common wiring slips named in these discussions: using the hardware serial pins 0 and 1 for the module, which clash with USB, and feeding the module from the 3.3 V pin. This worksheet avoids both by using SoftwareSerial on D10 and D11.
- To stop a car when the link drops, one suggestion is to read the module’s STATE pin where it is broken out. This worksheet uses a timeout instead, which works on any module.

What this means for the build: give the Bluetooth module and the motors separate supplies, or at least a strong shared one, and test with a nearly flat battery before you trust it.

## What usually goes wrong

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| Phone cannot find the module | Module not powered or already paired elsewhere | Check power, unpair from other devices |
| Pairs but no characters arrive | Wrong baud rate or swapped TX/RX | Match the baud rate, cross TX and RX |
| Garbage on the monitor | Baud mismatch | Try the module’s documented rate |
| Car stops after half a second | App sends the command once | Use an app that repeats, or raise FAILSAFE_MS |
| Module resets when motors start | Supply sag | Separate or better supply, add capacitance near the module |
| One wheel spins the wrong way | Motor wires swapped | Swap that motor’s two wires |

## Upgrades

- **Obstacle stop:** add an ultrasonic sensor and refuse forward commands when something is close.
- **Safer link:** change the pairing code and name using the AT commands for your module.
- **Proportional control:** send a speed and a turn value instead of single letters.
- **ESP32 version:** use Wi-Fi instead, as in the [ESP32 robot car](https://roboticsengineering.in/projects/esp32-robot-car/), and drop the module and the divider.

## Cost and parts notes

The ₹1,780 total is an illustration and does not include shipping. The Bluetooth module is the most variable line: check its voltage rating and whether it is a genuine HC-05 or a different chip. Use the [cost calculator](https://roboticsengineering.in/robotics-project-cost-calculator/) to compare sellers.

## Common questions

**Why does the HC-05 RX need a divider?**

The module’s RX input is designed for 3.3 V logic and the Uno outputs 5 V. A 1 kΩ and 2 kΩ divider brings 5 V to about 3.3 V.

**What baud rate does the module use?**

Commonly 9600 in data mode, and often 38400 in AT-command mode, but versions differ. Check your module’s sheet.

**Can anyone connect to my car?**

Anyone in range who knows the pairing code can. Change the default code on the module.

**Why does the car stop by itself?**

That is the failsafe. It stops the motors when no command has arrived for half a second.

Last reviewed: November 2026. This is a design worksheet with illustrative costs. It has not been bench-tested by this site; library names, pins and limits must be checked against your board and the current library versions, and measurements from your build are welcome.
