Project tutorial
Hacking A RC Car To Control It Using An Android Device

Hacking A RC Car To Control It Using An Android Device © GPL3+

Let's disassemble one RC toy car, racking its main parts, replacing the original embedded electronics by an Arduino.

  • 23,907 views
  • 0 comments
  • 43 respects

Components and supplies

Apps and online services

About this project

Background

Whenever I walk into a toy store and see remote control cars in the window, I think to take take them home, maybe because as a kid I adored this kind of toy, but for lack of options and money (they were much more expensive than today), I had not. To compensate and have an excuse to buy it, we will disassembly one of these, racking its main parts, replacing the original embedded electronics by an Arduino controlled remotely thru an Android device. This way, will be very easy to add new features to the toy, like sensors for example. Racking a RC car toy, is a very inexpensive way to build a robot for educational use.

The video below shows the finished project:

Step 1: General Bill of Materials ( see "Things" tab for detail)

  • A RC car toy w/ Battery
  • Arduino UNO
  • H-Bridge L-293D
  • HC-06 Bluetooth slave
  • Buzzer
  • LEDs (3X)
  • Battery 9V
  • Breadboard and cables

Step 2: Knowing the RC car

The first step will be to disassembly the car to get an idea of how it works, what part will be used and what should be added.

In the bottom chassi are the two motors (front and rear), the battery (rechargeable, 5V) and the electronic module. At the top of the housing, it is the antenna (copper plate connected to a black cable) and the 4 LEDs that function as the front and rear headlights. Each LED is connected separately by a wire pair. With this arrangement, you can:

  • Light headlights (light the two front LEDs)
  • Give flashes (light the LEDs left or right)
  • Flag a breaking (the two rear light LEDs)

The original electronics block diagram is shown above.

Step 3: Mobility system

Regarding mobility, the most common robots use the technique of "Differential Steering" where varying the direction of wheel's spin, vary the direction of robot, but here you can see that the car, although also have two DC motors, has a different configuration:

The front motor has no speed control being used only to flip the cart "right" or "left", moving simultaneously all wheels / front axle set (more or less like an automobile). In general the car always move forward in a straight line and the motor is off, thus leaving the wheels free. A command to "turn left" for example, will turn the motor, causing the gear mechanism as a whole move to the left. While the motor is powered, the car will continuously "turning left". The rear motor is coupled to a speed reducer gear system in order to provide variable torque to the rear wheels. The rear wheels always run together at same speed and direction.

Step 4: Hacking the eletronics

Once you learned how the car works, it's time to remove the original electronics, leaving only the motors and battery cables (probably you will need to add some extension to the original cables). Once I will not be using the upper housing for now, I will not worry with the original LEDs.

In place of the electronic's module, we will use an Arduino Uno, which will be responsible for logic processing, triggering motors, LEDs and Buzzer. The remote control was previously achieved by a 27MHz RF receiver system that will now be replaced by the HC-06 module, which will communicate with the Android device. The original car battery will be kept exclusively for the original DC Motors via the H-Bridge L293D. As DC motors consume enough power and generate noise due to their brushes, this will help isolating the power system. By the way, the front motor consumes a lot of energy at the time it receives a command to turn to one side, because its axis is locked and the current consumption is maximun (like a "short circuit"). For the Arduino we will use a 9V battery (connected to its Vin), and the HC-06 module will be powered by the 5V Arduino's output. Above you can see the new block diagram for circuit implementation.

At this point, it is important to test the motors individually. Using a battery, feed each one of the the DC motors and see which way it rotates. Invert the battery and repeat the test taking notes of the colors of the wires:

In the case of my car, we have:

Front Motor:

  • Yellow: LEFT
  • White: RIGHT

Rear Motor:

  • Green: BACKWARD
  • Blue: FORWARD

Step 5: ​FINAL ASSEMBLY

Above you can see the circuit diagram (please note that the colors of the motor wires are not real ones).

The new HW for your remote controled car is ready for its first test. Now, it is time to implement the SW and the Android application.

Step 6: ​THE ANDROID APPLICATION

To control the car, we will use an App that I developed, using the MIT AppInventor 2: "MJRoBot BT Remote Control". The app can be downloaded for free from the Google store via the link:

App: MJRoBot BT Remote Control.

The app has a simple interface, allowing you to send commands to the BT module in both, TEXT mode or directly via pre-programmed buttons (each time a button is pressed, a character is sent):

  • s: Backward
  • d: Right
  • a: Left
  • f: Stop
  • p: ON / OFF
  • m: Manual / Automatic
  • +: Speed +
  • -: Speed-

There is also a text window for messages received from the BT module. This feature is very important during the testing phase, it can be used in the same way as the "Serial Monitor".

Above, the Block diagram of the project at MIT appInventor2.

Step 7: The ARDUINO CODE

The code of the main block is very simple:

void loop() 
{
  checkBTcmd();  // verify if a comand is received from BT remote control
  receiveCmd ();
  
  if (turnOn) manualCmd ();
  else stopRobot ();
}

The first thing to do is to check if there is any new BT command coming. The responsible is the function checkBTcmd () :

 void checkBTcmd()  
 { 
    if (BT1.available()) 
    { 
      command = BT1.read();
      BT1.flush();
    }
 } 

Once the BT device is checked, the receiveCmd () function is executed. It will be in charge of executing the command received by the previous function. The variable "turnOn" is used to turn on or off the car. Note that every time that the red button with the symbol of "POWER" is pressed on the Android device, the character "p" will be sent by the app and variable "turnOn" will change if value (from 1 to 0 and vice versa) :

void receiveCmd ()
{
  
  switch (command)
  {
    case 'p': 
      Serial.println("command ==> p"); 
      turnOn = !turnOn;
      command = 0;
      analogWrite(ledStatus, turnOn*128); // Robot ON - Led ON
      beep(outBuz, 1000, 100);
      BT1.print(" COMMAND ON/OFF");
      BT1.println('\n');
      delay(200); //Delay to call attention to mode change
      break;
      
   case 'm': //not used here
      break;
  }   
}

Returning to the main loop while the variable "turnOn" is HIGH, the manualCmd ()function executes a command depending on the received character.

void manualCmd()
{
  switch (command)
  {
    case 'f': 
      moveStop(); //turn off both motors
      state = command;
      break;
    case 'w':  
      moveForward(); 
      state = command;  
      break;
    case 'd':     
      moveRight();
      break;
   case 'a': 
      moveLeft();
      break;
    
    case 's':  
      moveBackward();
      state = command;
      break;
    case '+': 
      if (state == 'w')
      {
        motorSpeed = motorSpeed + 10;
        if (motorSpeed > MAX_SPEED) 
        { 
          motorSpeed = MAX_SPEED;
        }  
        command = 'w';
      } else {command = state;}
      break;
    case '-': 
      if (state == 'w')
      {
        motorSpeed = motorSpeed - 10;
      }     
      if (motorSpeed < MIN_SPEED ) 
      { 
        motorSpeed = MIN_SPEED;
      }
      Serial.println(motorSpeed); 
      command = state;
      break;
  }
}

For example, if the "w" command is received the specific function to move the car forward: moveForward () is executed.

void moveForward() // rear motor FW
{ 
  analogWrite(rearMtEne, motorSpeed);
  digitalWrite(rearMtFw, HIGH);
  digitalWrite(rearMtBw, LOW);
  
  digitalWrite(frontMtEne, LOW);
  digitalWrite(ledRed, LOW);
  delay(5);
}

If "PowerOn" is HIGH and the "POWER" key is pressed, the variable "PowerOn", will be "toggle" to LOW and stopRobot () function will be executed instead of manualCmd (). This function ensures that the rear motor is stopped, the LEDs off and variables zeroed.

void stopRobot ()
{
  digitalWrite(ledBlue, LOW);
  digitalWrite(ledRed, LOW);
  
  state = 0;
  moveStop(); //turn off both motors
}

In the next step we will go deeper on how the motor function works.

Step 8: ​Triggering DC MOTORS VIA H-BRIDGE

The front and rear motors are connected to H-bridge as shown in the above diagram, and each of the Arduino pins, which should be defined as an OUTPUT during setup, will have a variable assigned:

// Motor Drives
const int rearMtFw = 4;     // Rear Motor  - FW
const int rearMtBw = 7;     // Rear Motor  - BW
const int rearMtEne = 6;    // Rear Motor  - enable
const int frontMtLeft = 2;  // Front Motor - turn Left
const int frontMtRight = 3; // Front Motor - turn right 
const int frontMtEne = 5;   // Front Motor enable

For example, if we want to move the car forward, the moveForward () function will put the pin 4 in HIGH and pin 7 in LOW, this will cause the current to flow "clockwise" as shown in the second above diagram.

Pin 6 is the "enable" what means that only when it is in "HIGH", the bridge will allow current flowing to motors. Because this pin is a PWM type, the speed on which the motor will turn, depend on the value of "MotorSpeed" variable, at pin 6 (value range from 0 to 255).

The function should also ensure that the front engine "rotate freely" and for that, the pin 5 which is the pin "enable", should be LOW (the status of pins 2 and 3 do not matter, since the enable is LOW). The LED "ledRed" that emulates a "reverse gear light" should always be off when the car moves forward:

void moveForward() // rear motor FW
{ 
  analogWrite(rearMtEne, motorSpeed);
  digitalWrite(rearMtFw, HIGH);
  digitalWrite(rearMtBw, LOW);
  
  digitalWrite(frontMtEne, LOW);
  digitalWrite(ledRed, LOW);
  delay(5);
}

By analogy, it is obvious that to make the car "move back", the motor must rotate in the opposite direction. For this, the pin 4 must be LOW and HIGH pin 7. Note that in this case of the " reverse gear light" should be on. The function in this case will be:

void moveBackward() // rear motor BW
{ 
  analogWrite(rearMtEne, motorSpeed);
  digitalWrite(rearMtFw, LOW);
  digitalWrite(rearMtBw, HIGH);
  
  digitalWrite(frontMtEne, LOW);
  digitalWrite(ledRed, HIGH);
  delay(5);
}

The same reasoning can be used for the front engine, only that in this case there is no speed control. Putting the pin 2 (enable) HIGH enables the engine to "try to turn" to one side or the other depending on the status of pins 2 and 3:

void moveLeft() // front motor left
{ 
  digitalWrite(frontMtEne, HIGH);
  digitalWrite(frontMtLeft, HIGH);
  digitalWrite(frontMtRight, LOW);
  digitalWrite(ledRed, LOW);
  delay(10);
}
//******************************************************************************//  
void moveRight() // front motor right
{ 
  digitalWrite(frontMtEne, HIGH);
  digitalWrite(frontMtLeft, LOW);
  digitalWrite(frontMtRight, HIGH);
  digitalWrite(ledRed, LOW);
  delay(10);
}

To stop the car, just put all the bridge's outputs for the rear motor in LOW, what will "catch" the motor shaft . For the front motor, just put the enable pin in LOW):

void stopRobot ()
{
  digitalWrite(ledBlue, LOW);
  digitalWrite(ledRed, LOW);
  
  state = 0;
  moveStop(); //turn off both motors
}

Step 9: C​ONCLUSION

Congratulations! Your RC car is properly "hacked" and ready to win the world!

Now the sky is the limit! Start, for example adding sensors to avoid obstacles, an HC-04 (ultrasound) will work well, as we saw in the case my tutorial "Mars Rover Emulator". Create a new command and send the "character" via text or use the Man / Auto button, that already send the character "m", for the car to perform other functions (a horn, for example).

Other interesting idea is to improve the "drivability". The frontal DC motor could be replaced by a servo motor in order to obtaining variable turning angles. The above picture is an example that I found in the web, it is not exactly the mechanism of my car, but shows how it could be.

The updated project files can be found at GITHUB: https://github.com/Mjrovai/MJRoBot-AutoBot

That's all folks!

As always, I hope this project can help others find their way in the exciting world of electronics and robots!

For more projects, please visit my blog: MJRoBot.org

Saludos from the south of the world!

Thank you

Marcelo

Code

Code snippet #1Plain text
void loop() 
{
  checkBTcmd();  // verify if a comand is received from BT remote control
  receiveCmd ();
  
  if (turnOn) manualCmd ();
  else stopRobot ();
}
Code snippet #2Plain text
 void checkBTcmd()  
 { 
    if (BT1.available()) 
    { 
      command = BT1.read();
      BT1.flush();
    }
 }
 
Code snippet #3Plain text
void receiveCmd ()
{
  
  switch (command)
  {
    case 'p': 
      Serial.println("command ==> p"); 
      turnOn = !turnOn;
      command = 0;
      analogWrite(ledStatus, turnOn*128); // Robot ON - Led ON
      beep(outBuz, 1000, 100);
      BT1.print(" COMMAND ON/OFF");
      BT1.println('\n');
      delay(200); //Delay to call attention to mode change
      break;
      
   case 'm': //not used here
      break;
  }   
}
Code snippet #4Plain text
void manualCmd()
{
  switch (command)
  {
    case 'f': 
      moveStop(); //turn off both motors
      state = command;
      break;

    case 'w':  
      moveForward(); 
      state = command;  
      break;

    case 'd':     
      moveRight();
      break;

   case 'a': 
      moveLeft();
      break;
    
    case 's':  
      moveBackward();
      state = command;
      break;

    case '+': 
      if (state == 'w')
      {
        motorSpeed = motorSpeed + 10;
        if (motorSpeed > MAX_SPEED) 
        { 
          motorSpeed = MAX_SPEED;
        }  
        command = 'w';
      } else {command = state;}
      break;

    case '-': 
 
      if (state == 'w')
      {
        motorSpeed = motorSpeed - 10;
      }     
      if (motorSpeed < MIN_SPEED ) 
      { 
        motorSpeed = MIN_SPEED;
      }
      Serial.println(motorSpeed); 
      command = state;
      break;
  }
}
Code snippet #5Plain text
void moveForward() // rear motor FW
{ 
  analogWrite(rearMtEne, motorSpeed);
  digitalWrite(rearMtFw, HIGH);
  digitalWrite(rearMtBw, LOW);
  
  digitalWrite(frontMtEne, LOW);
  digitalWrite(ledRed, LOW);
  delay(5);
}
Code snippet #6Plain text
void stopRobot ()
{
  digitalWrite(ledBlue, LOW);
  digitalWrite(ledRed, LOW);
  
  state = 0;
  moveStop(); //turn off both motors
}
Code snippet #7Plain text
// Motor Drives
const int rearMtFw = 4;     // Rear Motor  - FW
const int rearMtBw = 7;     // Rear Motor  - BW
const int rearMtEne = 6;    // Rear Motor  - enable
const int frontMtLeft = 2;  // Front Motor - turn Left
const int frontMtRight = 3; // Front Motor - turn right 
const int frontMtEne = 5;   // Front Motor enable
Code snippet #8Plain text
void moveForward() // rear motor FW
{ 
  analogWrite(rearMtEne, motorSpeed);
  digitalWrite(rearMtFw, HIGH);
  digitalWrite(rearMtBw, LOW);
  
  digitalWrite(frontMtEne, LOW);
  digitalWrite(ledRed, LOW);
  delay(5);
}
Code snippet #9Plain text
void moveBackward() // rear motor BW
{ 
  analogWrite(rearMtEne, motorSpeed);
  digitalWrite(rearMtFw, LOW);
  digitalWrite(rearMtBw, HIGH);
  
  digitalWrite(frontMtEne, LOW);
  digitalWrite(ledRed, HIGH);
  delay(5);
}
Code snippet #10Plain text
void moveLeft() // front motor left
{ 
  digitalWrite(frontMtEne, HIGH);
  digitalWrite(frontMtLeft, HIGH);
  digitalWrite(frontMtRight, LOW);
  digitalWrite(ledRed, LOW);
  delay(10);
}

//******************************************************************************//  

void moveRight() // front motor right
{ 
  digitalWrite(frontMtEne, HIGH);
  digitalWrite(frontMtLeft, LOW);
  digitalWrite(frontMtRight, HIGH);
  digitalWrite(ledRed, LOW);
  delay(10);
}
Code snippet #11Plain text
void stopRobot ()
{
  digitalWrite(ledBlue, LOW);
  digitalWrite(ledRed, LOW);
  
  state = 0;
  moveStop(); //turn off both motors
}
Github
https://github.com/Mjrovai/MJRoBot-AutoBot

Schematics

AutoBot electric diagram
CmW3o1EyPgq3esnkfUu3.fzz

Comments

Similar projects you might like

Turn your RC Car to Bluetooth RC car

Project tutorial by Prajjwal Nag

  • 11,968 views
  • 1 comment
  • 11 respects

Line Follower Robot - PID Control - Android Setup

Project tutorial by MJRoBot

  • 28,042 views
  • 7 comments
  • 33 respects

Control RC Car via Bluetooth with Android Smartphone

Project showcase by JoyDutta06

  • 7,319 views
  • 3 comments
  • 5 respects

Android Arduino RC Car

Project tutorial by RAFI RASHEED T C

  • 15,354 views
  • 2 comments
  • 38 respects

Arduino Bluetooth Robot for Android Device

Project showcase by aip06

  • 2,481 views
  • 1 comment
  • 10 respects
Add projectSign up / Login