I have built and tested 2 RC cars recently. One is quite straight forward and the other is full to the brim. They both are controlled by BLE Controller app on my iPhone.
Car A:
- Arduino Uno R4 Wifi
- No skin yet
- 4 basic motors wired in pairs
- 4 wheels
- 2 P3 batteries
- Metal 2 tier chassis purchased online from various
- 1 L298n motor driver
- Connecting wires
Code A:
/*
This sketch is for 2 pairs of motors driven by 1 L298n module. (Right side & Left side).
Powered by 2 P3 batteries.
Using UNO R4 wifi, thus reducing wiring and need for modles, dividers etc.
Steering is acheived by motor control rather than servo.
Control is by 'BLE control' app on iPhone.
*/
#include <ArduinoBLE.h>
#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5
BLEService carService("180A");
BLECharacteristic commandChar("2A57", BLEWrite, 20);
void setup() {
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
if (!BLE.begin()) {
Serial.println("BLE init failed!");
while (1);
}
BLE.setLocalName("UnoR4Car");
BLE.setAdvertisedService(carService);
carService.addCharacteristic(commandChar);
BLE.addService(carService);
BLE.advertise();
Serial.println("BLE RC Car ready");
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
while (central.connected()) {
if (commandChar.written()) {
char cmd = commandChar.value()[0];
drive(cmd);
}
}
}
}
void drive(char cmd) {
if (cmd == 'F') { forward(); }
else if (cmd == 'B') { backward(); }
else if (cmd == 'L') { left(); }
else if (cmd == 'R') { right(); }
else if (cmd == 'O') { spin(); }
else { stopCar(); }
}
void forward() { digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); }
void backward() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4,HIGH); }
void left() { digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); }
void right() { digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); }
void spin() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); }
void stopCar() { digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); }
Car B:
- Arduino Uno R3
- 1/14 body skin online purchase
- 2 basic motors
- 2 basic wheels
- 2 RC car wheels
- 1 HC-10 module
- 1 Ackermann steering system
- 1 basic 180 deg Servo
- 2 steering wires
- 2 x 3.7v Li-ion batteries
- 2 P3 batteries
- 1 L298n motor driver
- 1 regulator for servo
- connecting wires
Code B:
/*
/*
Stitched together by Chris Mence aka Kristov48 Mar 2026
Utilises Uno R3, HM-10 BLE via iPhone, powered by L298n board 2WD at rear.
Steering via Ackermann geometry with servo.
Lights and horn included.
Please use as you wish. Have fun.
*/
#include <SoftwareSerial.h>
#include <Servo.h>
// if using servo as well as motors don't use pins 9 & 10
const int IN1 = 2; // Direction pin 1
const int IN2 = 3; // Direction pin 2
const int IN3 = 4; // Direction pin 3
const int IN4 = 5; // Direction pin 4
const int ENA = 6; // PWM pin to control speed
const int ENB = 12; // PWM pin to control speed
const int LED1 = 9;
const int LED2 = 10;
const int BUZZER = 13;
char cmd = ""; // variable to store the servo position
int pos = 100;
bool LED_STATE = 0;
SoftwareSerial mySerial(7,8); // Set pins to be used for tx, rx
Servo myservo; // create servo object to control a servo
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(BUZZER, OUTPUT);
Serial.begin(9600);
mySerial.begin(9600);
myservo.attach(11); // attaches the servo on pin 9 to the servo object
Serial.println("TURN ON BLE APP ON YOUR IPHONE:");
}
void loop() {
if (mySerial.available()) {
char cmd = mySerial.read();
delay(15);
if (cmd) {
//Serial.println(cmd);
if (cmd == 'F') { forward();}
else if (cmd == 'B') { backward();}
else if (cmd == 'L') { left(); }
else if (cmd == 'R') { right();}
else if (cmd == 'T') { straight();}
else if (cmd == 'S') { stopCar();}
else if (cmd == 'D') { lights();}
else if (cmd == 'H') { horn();}
}
}
}
void forward() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, 240); // Speed (0-255)
analogWrite(ENB, 240); // Speed (0-255)
// pos = 100;
// myservo.write(pos); // tell servo to go to position in variable 'pos'
// delay(15);
}
void backward() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, 240); // Speed (0-255)
analogWrite(ENB, 240); // Speed (0-255)
// pos = 100;
//myservo.write(pos); // tell servo to go to position in variable 'pos'
// delay(15);
}
void left() {
pos = 50;
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
void right() {
pos = 150;
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
void straight() {
pos = 100;
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15);
}
void stopCar() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
analogWrite(ENA, 0); // Speed (0-255)
analogWrite(ENB, 0); // Speed (0-255)
}
void lights() {
LED_STATE = !LED_STATE;
if (LED_STATE >0) {
digitalWrite(LED1, HIGH); digitalWrite(LED2, HIGH); }
else
digitalWrite(LED1, LOW); digitalWrite(LED2,LOW);
}
void horn() {
tone(BUZZER, 200); // Turn on the buzzer
delay(500); // Wait for 1 second
noTone(BUZZER); // Turn off the buzzer
delay(500);
}
Msg me for more info or pics.
I hope this helps somebody on their way.


