Bluetooth-controlled car
What you’ll build
Your robot car, driven from a phone. The phone sends letters (Forward, Back, Left, Right, Stop) over Bluetooth; the Arduino reads them and drives the motors.
Parts
Your 2WD car from the previous projects, plus:
| Part | Notes |
|---|---|
| HC-05 or HC-06 Bluetooth serial module | Classic Bluetooth: works with Android “Bluetooth serial / RC car” apps |
| 1 kΩ and 2 kΩ resistors | Voltage divider for the module’s RX pin |
| A phone with a Bluetooth controller app | Many free “Arduino Bluetooth RC car” apps send single letters |
Wiring
| HC-05 pin | Connect to |
|---|---|
| VCC | 5V |
| GND | GND |
| TXD | Arduino pin 10 (SoftwareSerial RX) |
| RXD | Arduino pin 11 through a divider: pin 11 → 1 kΩ → RXD, and RXD → 2 kΩ → GND (its RX is 3.3 V) |
Pair the phone with the module (often PIN 1234 or 0000), then connect from the app.
Safety: a failsafe
If the connection drops, the car must stop. Stop the motors if no command arrives for 500 ms.
The program
#include <SoftwareSerial.h>const int ENA = 5, IN1 = 7, IN2 = 8, ENB = 6, IN3 = 9, IN4 = 10;
void setMotor(int en, int a, int b, int speed) { // speed -255..255 digitalWrite(a, speed > 0); digitalWrite(b, speed < 0); analogWrite(en, min(abs(speed), 255));}
void drive(int left, int right) { setMotor(ENA, IN1, IN2, left); setMotor(ENB, IN3, IN4, right);}
void setupMotors() { int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4}; for (int p : pins) pinMode(p, OUTPUT);}
SoftwareSerial bt(10, 11); // RX, TXunsigned long lastCmd = 0;
void setup() { setupMotors(); bt.begin(9600); // HC-05 default}
void loop() { if (bt.available()) { char c = bt.read(); lastCmd = millis(); if (c == 'F') drive(200, 200); else if (c == 'B') drive(-200, -200); else if (c == 'L') drive(-150, 150); else if (c == 'R') drive(150, -150); else if (c == 'S') drive(0, 0); } if (millis() - lastCmd > 500) drive(0, 0); // failsafe: no signal, stop}Many apps send the command repeatedly while a button is held, which keeps the failsafe happy. If yours only sends once, make the timeout longer.
Try it in the virtual Arduino
Press Start simulator, paste the sketch into sketch.ino (no extra wiring needed) and press ▶. Type a letter into the Serial Monitor box under the board and press Enter.
{ "version": 1, "author": "RoboLearn", "editor": "wokwi", "parts": [ { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} } ], "connections": [], "dependencies": {}}// In the simulator the Serial Monitor stands in for Bluetooth:// type F, B, L, R or S and press Enter.void setup() { Serial.begin(9600); Serial.println("Ready: send F B L R S");}
void loop() { if (Serial.available()) { char c = Serial.read(); if (c == 'F') Serial.println("forward -> drive(200, 200)"); else if (c == 'B') Serial.println("backward -> drive(-200, -200)"); else if (c == 'L') Serial.println("left -> drive(-150, 150)"); else if (c == 'R') Serial.println("right -> drive(150, -150)"); else if (c == 'S') Serial.println("stop -> drive(0, 0)"); }}Runs on Wokwi, free, no account needed.
Add a hornEasy
Add an H command that prints “beep” (on the real car: a buzzer tone()).
else if (c == 'H') Serial.println("beep");
Speed gearsMedium
Add commands 1, 2 and 3 that set a speed variable to 120, 180 and 255, used by the drive commands.
Add int spd = 180; then else if (c == '1') spd = 120; etc., and use drive(spd, spd) for F.
Test the failsafeHard
In the simulator version, print “STOP (failsafe)” when no command has arrived for 2 seconds after the last one.
Track lastCmd and a stopped flag so it prints only once.
Quick check
Finished this lesson?