How to Build a Bluetooth Robotic Rover with Arduino
Description
This project is a Bluetooth-controlled Arduino car built with an Arduino board, a Bluetooth serial module, a motor driver, and two DC motors. The robot receives movement commands from a smartphone or computer through Bluetooth and uses them to move forward, backward, left, right, or stop. The code also uses PWM speed pins to set different speeds for the two motors, which is useful for balancing the car if one motor is stronger or faster than the other. This project is useful for learning wireless control, SoftwareSerial communication, motor driver logic, PWM speed control, and basic Arduino robotics.
Required components and Schematic:
CODE:
// https://nemiatools.com
#include <SoftwareSerial.h> // Imports software serial library
SoftwareSerial bluetooth(9, 12); // Creates Bluetooth serial port
// Motor control pins
const int leftMotorForwardPin = 3; // Defines left forward pin
const int leftMotorBackwardPin = 2; // Defines left backward pin
const int rightMotorForwardPin = 5; // Defines right forward pin
const int rightMotorBackwardPin = 4; // Defines right backward pin
const int rightMotorSpeedPin = 6; // Defines right speed pin
const int leftMotorSpeedPin = 11; // Defines left speed pin
char command = 'S'; // Stores current Bluetooth command
unsigned long lastCommandTime = 0; // Stores last command time
void setup() {
pinMode(rightMotorForwardPin, OUTPUT); // Sets right forward output
pinMode(leftMotorForwardPin, OUTPUT); // Sets left forward output
pinMode(leftMotorBackwardPin, OUTPUT); // Sets left backward output
pinMode(rightMotorBackwardPin, OUTPUT); // Sets right backward output
pinMode(leftMotorSpeedPin, OUTPUT); // Sets left speed output
pinMode(rightMotorSpeedPin, OUTPUT); // Sets right speed output
analogWrite(rightMotorSpeedPin, 110); // Sets right motor speed
analogWrite(leftMotorSpeedPin, 97); // Sets left motor speed
bluetooth.begin(9600); // Starts Bluetooth communication
Serial.begin(9600); // Starts serial communication
Serial.println("START"); // Prints startup message
}
void stopMotors() { // Stops both robot motors
digitalWrite(rightMotorForwardPin, LOW); // Disables right forward
digitalWrite(leftMotorForwardPin, LOW); // Disables left forward
digitalWrite(rightMotorBackwardPin, LOW); // Disables right backward
digitalWrite(leftMotorBackwardPin, LOW); // Disables left backward
}
void driveForward() { // Drives robot forward
digitalWrite(leftMotorForwardPin, HIGH); // Enables left forward
digitalWrite(rightMotorForwardPin, HIGH); // Enables right forward
digitalWrite(leftMotorBackwardPin, LOW); // Disables left backward
digitalWrite(rightMotorBackwardPin, LOW); // Disables right backward
}
void driveBackward() { // Drives robot backward
digitalWrite(leftMotorBackwardPin, HIGH); // Enables left backward
digitalWrite(rightMotorBackwardPin, HIGH); // Enables right backward
digitalWrite(leftMotorForwardPin, LOW); // Disables left forward
digitalWrite(rightMotorForwardPin, LOW); // Disables right forward
}
void turnRobotLeft() { // Turns robot left
digitalWrite(leftMotorForwardPin, HIGH); // Enables left forward
digitalWrite(rightMotorBackwardPin, HIGH); // Enables right backward
digitalWrite(leftMotorBackwardPin, LOW); // Disables left backward
digitalWrite(rightMotorForwardPin, LOW); // Disables right forward
}
void turnRobotRight() { // Turns robot right
digitalWrite(leftMotorBackwardPin, HIGH); // Enables left backward
digitalWrite(rightMotorForwardPin, HIGH); // Enables right forward
digitalWrite(leftMotorForwardPin, LOW); // Disables left forward
digitalWrite(rightMotorBackwardPin, LOW); // Disables right backward
}
void loop() {
if (bluetooth.available()) { // Checks for Bluetooth data
command = bluetooth.read(); // Reads Bluetooth command
Serial.print(command); // Prints received command
lastCommandTime = millis(); // Updates last command time
}
if(command == 'F') // Checks forward command
driveForward(); // Drives robot forward
else if(command == 'B') // Checks backward command
driveBackward(); // Drives robot backward
else if(command == 'L') // Checks left command
turnRobotLeft(); // Turns robot left
else if(command == 'R') // Checks right command
turnRobotRight(); // Turns robot right
else if(command == 'S') // Checks stop command
stopMotors(); // Stops both motors
if(millis() - lastCommandTime > 1000) { // Checks command timeout
command = 'S'; // Sets stop command
}
}
How it works:
This project controls a small robot car through Bluetooth. A Bluetooth module receives commands from an external device, such as a smartphone app, and sends them to the Arduino. The Arduino then controls the motor driver to move the car in the requested direction.
The line #include <SoftwareSerial.h> adds the SoftwareSerial library. This library allows the Arduino to create a second serial communication port using normal digital pins, instead of using only the hardware serial pins 0 and 1.
The line SoftwareSerial bluetooth(9, 12); creates a Bluetooth serial port. In this case, pin 9 is used as RX and pin 12 is used as TX. The Bluetooth module TX pin should be connected to Arduino pin 9, while the HC-05 RX pin should be connected to Arduino pin 12 through a voltage divider or a suitable 5 V-to-3.3 V level shifter, with a common ground.
The motor pins define how the Arduino controls the motor driver. The lines leftMotorForwardPin and leftMotorBackwardPin control the direction of the left motor, while rightMotorForwardPin and rightMotorBackwardPin control the direction of the right motor.
The pins rightMotorSpeedPin = 6 and leftMotorSpeedPin = 11 are used for motor speed control. These pins should be connected to the enable or PWM inputs of the motor driver. By using analogWrite(), the Arduino can control how much power is sent to each motor.
Inside setup(), all motor direction pins and speed pins are configured as outputs. This allows the Arduino to send HIGH, LOW, and PWM signals to the motor driver.
The lines analogWrite(rightMotorSpeedPin, 110); and analogWrite(leftMotorSpeedPin, 97); set the speed of the two motors. The values can go from 0 to 255, where 0 means stopped and 255 means maximum PWM output.
These speed values are very important in a real robot car because the two DC motors are often not perfectly identical. One motor may rotate faster than the other even with the same command. In this code, the right motor is set to 110 and the left motor to 97 to help balance the movement and make the car go straighter.
The user can change both the pin numbers and the speed values to adapt the project to their own wiring, motor driver, chassis, and motor behavior. If the car does not move straight, the user can slightly increase the speed of the slower motor or reduce the speed of the faster motor until the movement is balanced.
The line bluetooth.begin(9600); starts Bluetooth communication at 9600 baud. This value must match the baud rate of the Bluetooth module, such as an HC-05 or HC-06.
The function stopMotors() sets all direction pins LOW. This removes every forward and backward command from both motors, so the car stops.
The function driveForward() turns on the forward direction pins of both motors and turns off the backward direction pins. This makes the left and right motors rotate forward at the speed previously set by the PWM pins.
The function driveBackward() does the opposite. It turns on the backward direction pins and turns off the forward direction pins, so both motors rotate backward.
The functions turnRobotLeft() and turnRobotRight() rotate the motors in opposite directions. This makes the robot turn on the spot instead of simply moving in a wide curve.
Depending on how the motors are mounted and wired, the physical left and right movement may be reversed. If this happens, the user can swap the motor wires, change the pin definitions, or exchange the logic inside the turning functions.
Inside loop(), the condition if (bluetooth.available()) checks if a new Bluetooth command has arrived. If a command is available, command = bluetooth.read(); reads one character and stores it in the variable command.
The command characters define the movement. The character 'F' makes the robot move forward, 'B' makes it move backward, 'L' makes it turn left, 'R' makes it turn right, and 'S' stops the motors.
Every time a new Bluetooth command is received, the line lastCommandTime = millis(); saves the current time. The function millis() returns the number of milliseconds passed since the Arduino was powered on or reset.
The condition if(millis() - lastCommandTime > 1000) works as a safety timeout. If the Arduino does not receive any new Bluetooth command for more than one second, the code automatically sets command = 'S';, so the robot stops.
This timeout is useful because if the Bluetooth connection is lost or the controller app stops sending data, the robot will not continue moving forever with the last command.
Overall, the Bluetooth module receives movement characters, the Arduino interprets them, the motor driver powers the motors, and the PWM speed values help balance the two sides of the robot. By adjusting the pins and the speed values, the user can adapt the code to many different robot car layouts and make the movement more precise.
For real hardware, the motors should be powered through a suitable motor driver and an external power supply. The Arduino, Bluetooth module, motor driver, and motor power supply must share a common ground. If the Bluetooth module RX pin is not 5V tolerant, use a voltage divider or level shifter between Arduino TX and the module RX pin.