RC Car with Arduino

Hi guys, good evening!

In your opinion, is it possible to use Arduino components to make an RC Car model? :roll_eyes: :slight_smile:

Given that the R in RC stands for radio, and that the Arduino isn't a radio, it does not seem likely that the Arduino, by itself, can be used to make an RC car. By the time you add the transmitter and receiver, there isn't a whole lot left for the Arduino to do.

Yes, it it. You just have to decide on what components you want to use. Hobby motors, brushless motors (require an esc), motor drivers, servo for steering, and most of all, your communication. I made one last year, check it out if you're interested.

http://forum.arduino.cc/index.php?topic=154463

cwhummel:
Yes, it it. You just have to decide on what components you want to use. Hobby motors, brushless motors (require an esc), motor drivers, servo for steering, and most of all, your communication. I made one last year, check it out if you're interested.

Edit: RC car with RFM12B transceivers and Custom Controller - Exhibition / Gallery - Arduino Forum

It's nice the project, but is there something of more complex? :slight_smile:

How complex do you want to go?

I'd like to make "The Tumbler" from Batman, if that's what you mean. Other than that, I'm not sure how you can make it any harder, unless you want to add in other components like sonar and gps, etc...

Alex_Co:
Hi guys, good evening!

In your opinion, is it possible to use Arduino components to make an RC Car model? :roll_eyes: :slight_smile:

I've done it. All you do is remove the radio (R/C) receiver and use the Arduino to drive the servos and ESC for the motor(s). You also (may) need some filtering to keep motor current surges from crashing the Arduino (simple circuit: diode and 1000-some uF capacitor).

Then prepare for endless amounts of fun as you write and re-write your code, then add more parts (like ultrasonic sensors and lights) and add more code.

Running an RC car with an Arduino is coded like this:

while (1) {
    write code ();
    if (hit_wall_again ()) {
        repair_car ();
    }
    edit_code ();
    add_stuff_to_car ();
    if (leds_burn_out ()) {
        learn_ohms_law ();
        buy_resistors ();
        buy_more_leds ();
    }
    try_new_things ();
    edit_code ();
    batteries (4);
    charge_batteries ();
    chase_cat ();
}

uint8_t batteries (uint8_t how_many)
{
    uint8_t battery_count = 0;
    while (how_many--) {
        buy_more_battery_packs ();
        battery_count++;
    }
    if (!own_battery_charger) {
        buy_battery_charger ();
    }
    return battery_count;
}

void chase_cat (void)
{
    if (cat_direction == left) {
        steer_left ();
    }
    if (cat_direction == right) {
        steer_right ();
    }
    if (cat_stopped == TRUE) {
        motor_speed  (100);
    }
    if (cat == hiss) {
        return;
    }
}

:slight_smile:

Krupski:

while (1) {

write code ();
   if (hit_wall_again ()) {
       repair_car ();
   }
   edit_code ();
   add_stuff_to_car ();
   if (leds_burn_out ()) {
       learn_ohms_law ();
       buy_resistors ();
       buy_more_leds ();
   }
.
.
.
   chase_cat ();
}

void chase_cat (void)
{
.
.
.
   if (cat == hiss) {
       return;
   }
}

LOL!

It reminds me of a small UGV I made - strapped a camera to a toy RC car and chased my dog around the house with it (driving via the camera view). That was a fun time...

:smiley:

cwhummel:
How complex do you want to go?

I'd like to make "The Tumbler" from Batman, if that's what you mean. Other than that, I'm not sure how you can make it any harder, unless you want to add in other components like sonar and gps, etc...

Well cwhummel,
my idea is to build an RC Car with:

  • Brakes
  • Lights (including backup light when the car goes in reverse)

And other extra stuff. :smiley:

Lights are easy. I may not have posted it, but my whole truck is lit. Headlights, tail lights, brake lights, blinkers. I used a shift register for all the extra pins.

As for brakes, you can either use the code to use the motor as a brake, as motor drivers and esc's have a brake function., or , I guess you can try to add actual brakes. I'm not that familiar with rc parts, but it looks like rc brakes are only for gas rc cars, not electric.

cwhummel:
Lights are easy. I may not have posted it, but my whole truck is lit. Headlights, tail lights, brake lights, blinkers. I used a shift register for all the extra pins.

As for brakes, you can either use the code to use the motor as a brake, as motor drivers and esc's have a brake function., or , I guess you can try to add actual brakes. I'm not that familiar with rc parts, but it looks like rc brakes are only for gas rc cars, not electric.

"use the motor as a brake, as motor drivers and esc's have a brake function" What do you mean? :open_mouth:
However the lights would be connected to the engine. I mean, when the RC Car starts to go in reverse the backup lights turn on, when the car brakes, the brake lights turn on. Everything like in a real car. While the headlights would turn on only if I push a button on the controller.

My idea for the brakes was just a small plastic rectangle (controlled by a button on the controller) that rests on the wheel (behind it), blocking it. But maybe this could force the motor overheating it.

Electric motors are most typically used to convert electrical into mechanical energy. But this process can be reversed: The motor can convert mechanical energy back into electrical energy (acting as a generator). That means that a motor in an RC car can both accelerate and brake the car. It all depends on the circuit driving the motor. All decent RC motor controllers implement this type of braking. You don't need a separate mechanical brake.

Also, this type of braking is fully controllable. It's not only full on or full off. Unless a car is extremely slow, suddenly blocking a wheel will lead to a loss of control (and probably broken parts).

So you already have brakes with any standard RC setup. It seems overkill to use an Arduino just for lights. Separate circuits can be built for that.

As i said, the lights on my truck are totally controlled by the arduino. Even when powered up, the lights dont do anything until I say so. The rear lights come on full when the brake is applied (motor brake, no actual physical brake). when brake is taken off, the dim to just tail lights, and the front headlights come on (i use high intensity LED's, they're really freaking bright). When i turn, the blinkers come on. I havent added any reverse lights yet, but that will come this summer. check out my code below. The LED's are shown under the "ShiftPWM" names as I'm using a shift register for all extra pins the leds take up.

Also as stingray pointed out, your motor driver has the capacity to use the motors own energy to act as a brake. trust us. you can see that in the code as well. I hope i commented everything well enough.

//This is the reciever side. It's the RC Car! This car is built upon an old RC car that i found, ripped all the electronics out except for the motor,
//and replaced the steering system with a servo. It uses a dual 1A motor driver wired in series for 2A.
//credit to Glyn Hudson openenergymonitor.org for the RFM12B code

//http://arduino.cc/forum/index.php/topic,154463.0.html

const int ShiftPWM_latchPin=A3;

#define SHIFTPWM_NOSPI
const int ShiftPWM_dataPin = A4;
const int ShiftPWM_clockPin = A2;


// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false; 

// You can enable the option below to shift the PWM phase of each shift register by 8 compared to the previous.
// This will slightly increase the interrupt load, but will prevent all PWM signals from becoming high at the same time.
// This will be a bit easier on your power supply, because the current peaks are distributed.
const bool ShiftPWM_balanceLoad = false;
#define _useTimer1
#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

// Here you set the number of brightness levels, the update frequency and the number of shift registers.
// These values affect the load of ShiftPWM.
// Choose them wisely and use the PrintInterruptLoad() function to verify your load.
// There is a calculator on my website to estimate the load.

unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
int numRegisters = 1;
int numRGBleds = numRegisters*8/3;

#include <JeeLib.h>
#include <Servo.h>

#define myNodeID 30          //node ID of Rx (range 0-30) 
#define network     210      //network group (can be in the range 1-250).
#define freq RF12_433MHZ     //Freq of RF12B can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. Match freq to module

typedef struct
{ 
  int steer, tilt, pan, forward, reverse, brake, fire; // the data that we are recieving from the controller
} 
PayloadTX;      
PayloadTX rcCar;  

const int rcCar_NodeID=10;            //emonTx node 

Servo steerServo; // servo used to steer the car
const int servopin1 = 9; // steer servo pwm pin
const int motorpos = 5; // forward!
const int motorneg = 6; // reverse!
const int motorSpeed = 3; // the speed PWM pin
int center = 90; // center the steering to 90 degrees (this isnt actually center becouse i did a crappy job of installing the servo),
int forward;
int reverse;


void setup() {

  rf12_initialize(myNodeID,freq,network);   //Initialize RFM12 with settings defined above  
  Serial.begin(9600); 
  //  Serial.println("RF12B demo Receiver - Simple demo"); //pointless memory waste
  //  Serial.print("Node: "); 
  //  Serial.print(myNodeID); 
  //  Serial.print(" Freq: "); 
  //  if (freq == RF12_433MHZ) Serial.print("433Mhz");
  //  Serial.print(" Network: "); 
  //  Serial.println(network);
  steerServo.attach(servopin1);
  steerServo.write(center);
  pinMode(motorpos, OUTPUT);
  pinMode(motorneg, OUTPUT);
  pinMode(motorSpeed, OUTPUT);
  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);

  // SetPinGrouping allows flexibility in LED setup. 
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  //ShiftPWM.SetPinGrouping(3); //This is the default, but I added here to demonstrate how to use the funtion

  ShiftPWM.Start(pwmFrequency,maxBrightness);
  // Turn all LED's off.
  ShiftPWM.SetAll(0);
}

void loop() {
ShiftPWM.SetAll(0);
  if (rf12_recvDone()){    
    if (rf12_crc == 0 && (rf12_hdr & RF12_HDR_CTL) == 0)
    {
      int node_id = (rf12_hdr & 0x1F);		  //extract nodeID from payload

      if (node_id == rcCar_NodeID)  {             //check data is coming from node with the corrct ID
        rcCar=*(PayloadTX*) rf12_data;            // Extract the data from the payload 
        
        forward = digitalRead(motorpos);
        reverse = digitalRead(motorneg);
        
        if(rcCar.brake == 1)
        {
          digitalWrite(motorpos, HIGH); // Engage the Brake for Channel A
          digitalWrite(motorneg, HIGH);
          steerServo.write(center); // centers steering
          ShiftPWM.SetOne(7, 255); //right taillight (on full brightness as brakelights)
          ShiftPWM.SetOne(6, 255); //left taillight (on full brightness as brakelights)
        }
        else if(rcCar.brake == 0) // if the brake is off, start driving!
        {
          steerServo.write(rcCar.steer); // steering control
          ShiftPWM.SetOne(6, 100);  //left taillight
          ShiftPWM.SetOne(7, 100);  //right taillight
          ShiftPWM.SetOne(0, 255);  //left headlight
          ShiftPWM.SetOne(1, 255);  //right headlight
          if(rcCar.steer <= 82)
          {
            ShiftPWM.SetOne(2, 255); // front right blinker
            ShiftPWM.SetOne(5, 255); //rear right blinker
          }
          else
          {
            ShiftPWM.SetOne(2, 0);
            ShiftPWM.SetOne(5, 0);
          }
          if(rcCar.steer >= 84)
          {
            ShiftPWM.SetOne(3, 255); //front left blinker
            ShiftPWM.SetOne(4, 255); //rear left blinker
          }
          else
          {
            ShiftPWM.SetOne(3, 0);
            ShiftPWM.SetOne(4, 0);
          }

          if(rcCar.forward < 30 && rcCar.reverse < 30) // the motor doesnt do well with a speed below 30
          {
            digitalWrite(motorpos, LOW); // Engage the soft Brake for Channel A
            digitalWrite(motorneg, LOW);
          }
          else if(rcCar.forward > 30) // 
          {
            //forward
            digitalWrite(motorpos, HIGH); // lets go forward!
            digitalWrite(motorneg, LOW);  
            analogWrite(motorSpeed, rcCar.forward); // speed
          }
          else if(rcCar.reverse > 30)
          {
            //backward
            digitalWrite(motorpos, LOW); // lets go backward!
            digitalWrite(motorneg, HIGH);  
            analogWrite(motorSpeed, rcCar.reverse);   //speed
           
          }
        }
      }
    }
  }

}

cwhummel:
As i said, the lights on my truck are totally controlled by the arduino. Even when powered up, the lights dont do anything until I say so. The rear lights come on full when the brake is applied (motor brake, no actual physical brake). when brake is taken off, the dim to just tail lights, and the front headlights come on (i use high intensity LED's, they're really freaking bright). When i turn, the blinkers come on. I havent added any reverse lights yet, but that will come this summer. check out my code below. The LED's are shown under the "ShiftPWM" names as I'm using a shift register for all extra pins the leds take up.

Also as stingray pointed out, your motor driver has the capacity to use the motors own energy to act as a brake. trust us. you can see that in the code as well. I hope i commented everything well enough.

//This is the reciever side. It's the RC Car! This car is built upon an old RC car that i found, ripped all the electronics out except for the motor,

//and replaced the steering system with a servo. It uses a dual 1A motor driver wired in series for 2A.
//credit to Glyn Hudson openenergymonitor.org for the RFM12B code

//http://arduino.cc/forum/index.php/topic,154463.0.html

const int ShiftPWM_latchPin=A3;

#define SHIFTPWM_NOSPI
const int ShiftPWM_dataPin = A4;
const int ShiftPWM_clockPin = A2;

// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false;

// You can enable the option below to shift the PWM phase of each shift register by 8 compared to the previous.
// This will slightly increase the interrupt load, but will prevent all PWM signals from becoming high at the same time.
// This will be a bit easier on your power supply, because the current peaks are distributed.
const bool ShiftPWM_balanceLoad = false;
#define _useTimer1
#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

// Here you set the number of brightness levels, the update frequency and the number of shift registers.
// These values affect the load of ShiftPWM.
// Choose them wisely and use the PrintInterruptLoad() function to verify your load.
// There is a calculator on my website to estimate the load.

unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
int numRegisters = 1;
int numRGBleds = numRegisters*8/3;

#include <JeeLib.h>
#include <Servo.h>

#define myNodeID 30          //node ID of Rx (range 0-30)
#define network     210      //network group (can be in the range 1-250).
#define freq RF12_433MHZ     //Freq of RF12B can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. Match freq to module

typedef struct
{
  int steer, tilt, pan, forward, reverse, brake, fire; // the data that we are recieving from the controller
}
PayloadTX;     
PayloadTX rcCar;

const int rcCar_NodeID=10;            //emonTx node

Servo steerServo; // servo used to steer the car
const int servopin1 = 9; // steer servo pwm pin
const int motorpos = 5; // forward!
const int motorneg = 6; // reverse!
const int motorSpeed = 3; // the speed PWM pin
int center = 90; // center the steering to 90 degrees (this isnt actually center becouse i did a crappy job of installing the servo),
int forward;
int reverse;

void setup() {

rf12_initialize(myNodeID,freq,network);   //Initialize RFM12 with settings defined above 
  Serial.begin(9600);
  //  Serial.println("RF12B demo Receiver - Simple demo"); //pointless memory waste
  //  Serial.print("Node: ");
  //  Serial.print(myNodeID);
  //  Serial.print(" Freq: ");
  //  if (freq == RF12_433MHZ) Serial.print("433Mhz");
  //  Serial.print(" Network: ");
  //  Serial.println(network);
  steerServo.attach(servopin1);
  steerServo.write(center);
  pinMode(motorpos, OUTPUT);
  pinMode(motorneg, OUTPUT);
  pinMode(motorSpeed, OUTPUT);
  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);

// SetPinGrouping allows flexibility in LED setup.
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  //ShiftPWM.SetPinGrouping(3); //This is the default, but I added here to demonstrate how to use the funtion

ShiftPWM.Start(pwmFrequency,maxBrightness);
  // Turn all LED's off.
  ShiftPWM.SetAll(0);
}

void loop() {
ShiftPWM.SetAll(0);
  if (rf12_recvDone()){   
    if (rf12_crc == 0 && (rf12_hdr & RF12_HDR_CTL) == 0)
    {
      int node_id = (rf12_hdr & 0x1F);   //extract nodeID from payload

if (node_id == rcCar_NodeID)  {             //check data is coming from node with the corrct ID
        rcCar=(PayloadTX) rf12_data;            // Extract the data from the payload
       
        forward = digitalRead(motorpos);
        reverse = digitalRead(motorneg);
       
        if(rcCar.brake == 1)
        {
          digitalWrite(motorpos, HIGH); // Engage the Brake for Channel A
          digitalWrite(motorneg, HIGH);
          steerServo.write(center); // centers steering
          ShiftPWM.SetOne(7, 255); //right taillight (on full brightness as brakelights)
          ShiftPWM.SetOne(6, 255); //left taillight (on full brightness as brakelights)
        }
        else if(rcCar.brake == 0) // if the brake is off, start driving!
        {
          steerServo.write(rcCar.steer); // steering control
          ShiftPWM.SetOne(6, 100);  //left taillight
          ShiftPWM.SetOne(7, 100);  //right taillight
          ShiftPWM.SetOne(0, 255);  //left headlight
          ShiftPWM.SetOne(1, 255);  //right headlight
          if(rcCar.steer <= 82)
          {
            ShiftPWM.SetOne(2, 255); // front right blinker
            ShiftPWM.SetOne(5, 255); //rear right blinker
          }
          else
          {
            ShiftPWM.SetOne(2, 0);
            ShiftPWM.SetOne(5, 0);
          }
          if(rcCar.steer >= 84)
          {
            ShiftPWM.SetOne(3, 255); //front left blinker
            ShiftPWM.SetOne(4, 255); //rear left blinker
          }
          else
          {
            ShiftPWM.SetOne(3, 0);
            ShiftPWM.SetOne(4, 0);
          }

if(rcCar.forward < 30 && rcCar.reverse < 30) // the motor doesnt do well with a speed below 30
          {
            digitalWrite(motorpos, LOW); // Engage the soft Brake for Channel A
            digitalWrite(motorneg, LOW);
          }
          else if(rcCar.forward > 30) //
          {
            //forward
            digitalWrite(motorpos, HIGH); // lets go forward!
            digitalWrite(motorneg, LOW); 
            analogWrite(motorSpeed, rcCar.forward); // speed
          }
          else if(rcCar.reverse > 30)
          {
            //backward
            digitalWrite(motorpos, LOW); // lets go backward!
            digitalWrite(motorneg, HIGH); 
            analogWrite(motorSpeed, rcCar.reverse);   //speed
           
          }
        }
      }
    }
  }

}

Thank you all for your help! I really appreciate it.

However I've decided to start with a easier project now. But, with your permission, I'll keep a copy of the codes that you shared in this post.

Now my 1st project will be another: the TIE Crawler (photo below) from the Star Wars Expanded Universe.
It'll move forward, backward, left and right. That's all.

What do you think about it? :slight_smile: :smiley:

TIE_Crawler.jpg

But, with your permission, I'll keep a copy of the codes that you shared in this post.

Go ahead. happy to share. i can post the transmitter code as well if you'd like. just keep in mind the communication is based on two RFM12B transceivers.

Now my 1st project will be another: the TIE Crawler (photo below) from the Star Wars Expanded Universe.
It'll move forward, backward, left and right. That's all.

What do you think about it?

Cool. I would recommend adding a speaker with an mp3/wav module to make that awesome noise they make in the movies, but that's just me :slight_smile:

cwhummel:

But, with your permission, I'll keep a copy of the codes that you shared in this post.

Go ahead. happy to share. i can post the transmitter code as well if you'd like. just keep in mind the communication is based on two RFM12B transceivers.

Now my 1st project will be another: the TIE Crawler (photo below) from the Star Wars Expanded Universe.
It'll move forward, backward, left and right. That's all.

What do you think about it?

Cool. I would recommend adding a speaker with an mp3/wav module to make that awesome noise they make in the movies, but that's just me :slight_smile:

Your idea of the MP3 sound effect is awesome! I didn't think about it! Thank you, I'll do it. :slight_smile:
Do you know if there are Arduino components that can do it?

However you can follow the project and read more informations about it here: My 1st project: TIE Crawler from the Star Wars Expanded Universe - Project Guidance - Arduino Forum