PCBGOGO Mike
Published

Arduino RC Car

Fastest Arduino RC Car using Coreless DC Motors and nRF24L01 RF module

IntermediateFull instructions provided885
Arduino RC Car

Things used in this project

Hardware components

PCB
×1

Software apps and online services

Visual Studio Code Extension for Arduino
Microsoft Visual Studio Code Extension for Arduino

Hand tools and fabrication machines

AMS1117-3.3V
3.3V Arduino Pro Mini
NRF24L01 – 2pcs
Joystick Module
1N5819 Diode
Connecting wires

Story

Read more

Custom parts and enclosures

3D Printing Wheels and Motor Mount

Schematics

Fabricating PCB for Arduino RC Car

Arduino RC Car Circuit Diagram

Code

Programming the Arduino

Arduino
The complete program (both Arduino nano and pro mini) for this project can be found at the bottom of this page. The explanation of your RC program is as follows

Then inside the setup function, we initialize our nRF24L01 module. We have used the 115 bands since it is not congested and has set the module to operate with low power, you can also play around with these settings.

Next in the main loop function, we will only execute the ReadData function with which we will be constantly reading the value sent from our Transmitter joystick module. Note that the pipe address mentioned in the program should be the same as the one mentioned in the transmitter program. We have also printed the value that we receive for debugging purposes. Once the value is successfully read we will execute the Control Car function to control our RC car based on the value received from the Rf module.

We start the program by including the required header file. Note that, the nRF24l01 module requires a library to be added to your Arduino IDE, you can download RF24 Library from Github using this link. Apart from that, we have already defined the minimum speed and maximum speed for our robot. The minimum and maximum range are 0 to 1024 respectively.

Then inside the setup function, we initialize our nRF24L01 module. We have used the 115 bands since it is not congested and has set the module to operate with low power, you can also play around with these settings.

Next in the main loop function, we will only execute the ReadData function with which we will be constantly reading the value sent from our Transmitter joystick module. Note that the pipe address mentioned in the program should be the same as the one mentioned in the transmitter program. We have also printed the value that we receive for debugging purposes. Once the value is successfully read we will execute the Control Car function to control our RC car based on the value received from the Rf module.

Inside the Control Car function, we will control motors connected to the PWM pins using the analog write function. In our transmitter program we have converted the Analog values from A0 and A1 pin of Nano to 1 to 10, 11 to 20, 21 to 30 and 31 to 40 for controlling the car in forward, reverse, left and right respectively. The below program is used to control the robot in a forward direction

Similarly, we can also write three more functions for reverse, left, and right control as shown below.
#define min_speed 200
#define max_speed 800
#include <SPI.h> 
#include "RF24.h"
RF24 myRadio (7, 8);

void setup() {
  Serial.begin (9600);
  myRadio.begin();
  myRadio.setChannel(115);  //115 band above WIFI signals
  myRadio.setPALevel(RF24_PA_MIN); //MIN power low rage
  myRadio.setDataRate( RF24_250KBPS ) ;  //Minimum speed
}

void ReadData()
{
  myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Which pipe to read, 40 bit Address
  myRadio.startListening(); //Stop Transminting and start Reveicing
  if ( myRadio.available())
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
    }
    Serial.print("\nReceived:");
    Serial.println(data.msg);
    received = data.msg;
    Control_Car();
  }
}

if (received>=1 && received <=10) // Move Forward
  {
    int PWM_Value =  map (received, 1, 10, min_speed, max_speed);
    analogWrite(R_MR,PWM_Value);
    analogWrite(L_MR,PWM_Value);
  }
  
  if (received>=11 && received <=20) // Break
  {
    int PWM_Value =  map (received, 11, 20, min_speed, max_speed);
    analogWrite(R_MR,0);
    analogWrite(L_MR,0);
  }
    if (received>=21 && received <=30) // Turn left
  {
    int PWM_Value =  map (received, 21, 30, min_speed, max_speed);
    analogWrite(R_MR,PWM_Value);
    analogWrite(L_MR,0);
  }
      if (received>=31 && received <=40) // Turn Right
  {
    int PWM_Value =  map (received, 31, 40, min_speed, max_speed);
    analogWrite(R_MR,0);
    analogWrite(L_MR,PWM_Value);
  }

Code

Arduino
After you are done with the code, upload it to your pro-mini-board. Remove the battery and your board through the FTDI module for testing. Launch your code, open serial battery and you should receive the value from your transmitter Joystick module. Connect your battery and your motors should also start to rotate.

The complete working of the project can be found in the video linked at the bottom of this page. If you have any questions leave them in the comment section. You can also use our forums to get quick answers for your other technical questions.
RF Remote Joystick

/*Code to transmit RF values to Arduino 
 * 
 * Pin Conections
 *  CE - 7
    MISO - 12
    MOSI - 11
    SCK - 13
    CS - 8
    A0 - JoyX
    A1 - JoyY
*/
#include <SPI.h>  
#include "RF24.h"
RF24 myRadio (7, 8);
struct package
{
  int msg = 0;
};
byte addresses[][6] = {"0"};
typedef struct package Package;
Package data;
void setup()
{
  Serial.begin(9600);
  myRadio.begin();  
  myRadio.setChannel(115);  //115 band above WIFI signals
  myRadio.setPALevel(RF24_PA_MAX); //MAX power long rage
  myRadio.setDataRate( RF24_250KBPS ) ;  //Minimum speed
  delay(500);
  Serial.print("Remote Initialized");
}
  int forward; 
  int reverse; 
  int left; 
  int right; 
void loop()
{
 int xValue = analogRead(A0); //Read JoyX value
 int yValue = analogRead(A1); //Read JoyY Value 
 //Serial.print(xValue); Serial.print(" , "); Serial.println(yValue);
 if (xValue>560 && xValue<1000) // Filter JoyX for up 
 {
 forward = map (xValue, 560, 1000, 1, 10); //Convert Joyx-up to 0-10
 //Serial.print("F="); Serial.println(forward);
 data.msg = forward; WriteData(); delay(50);
 }
 if (xValue<500 && xValue > 10) // Filter JoyX for break 
 {
 reverse = map (xValue, 10, 500, 20, 11); //Convert JoyX-down to 11-20
 //Serial.print("B="); Serial.println(reverse);
 data.msg = reverse; WriteData(); delay(50);
 }
 else if (yValue>600 && yValue<1000) // Filter JoyY for right  
 {
 right = map (yValue, 600, 1000, 21, 30); //Convert JoyY-right to 21-30
 //Serial.print("R="); Serial.println(right);
 data.msg = right; WriteData(); delay(50);
 }
 else if (yValue<450 && yValue > 10) // Filter JoyY for left 
 {
 left = map (yValue, 10, 450, 40, 31); //Convert JoyY-left to 31-40
 //Serial.print("L="); Serial.println(left);
 data.msg = left; WriteData(); delay(50);
 }
/* else
 {
  Serial.println("Rest");
  data.msg = 0; WriteData(); delay(50);
 }
*/
}
void WriteData()
{
  myRadio.stopListening();  //Stop Receiving and start transminitng 
  myRadio.openWritingPipe( 0xF0F0F0F0AA); //Sends data on this 40-bit address
  myRadio.write(&data, sizeof(data)); 
  //Serial.print("\nSent:");
  //Serial.println(data.msg);
  delay(50);
}
void ReadData()
{ 
myRadio.openReadingPipe(1, 0xF0F0F0F066); // Which pipe to read, 40 bit Address
  myRadio.startListening(); //Stop Transminting and start Reveicing 
  if ( myRadio.available()) 
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
    }
    Serial.print("\nReceived:");
    Serial.println(data.msg);
  }
}

BLDC Motor

/*CE - 7
MISO - 12
MOSI - 11
SCK - 13
CS - 8
Recently tested with nano
*/
/*PIN DEFANITIONS*/
#define R_IR 3
#define L_IR 4
#define L_MR 5
#define R_MR 6
#define min_speed 200
#define max_speed 800
#include <SPI.h>  
#include "RF24.h" 
RF24 myRadio (7, 8); 
struct package
{
  int msg;
};
typedef struct package Package;
Package data;
byte addresses[][6] = {"0"}; 
void setup() { 
  pinMode(R_IR, INPUT);
  pinMode(L_IR, INPUT);
  pinMode(L_MR, OUTPUT);
  pinMode(R_MR, OUTPUT);
  Serial.begin (9600);
  myRadio.begin(); 
  myRadio.setChannel(115);  //115 band above WIFI signals
  myRadio.setPALevel(RF24_PA_MIN); //MIN power low rage
  myRadio.setDataRate( RF24_250KBPS ) ;  //Minimum speed
}
int received; 
void loop() {
ReadData();
}
void Control_Car()
{
  if (received>=1 && received <=10) // Move Forward
  {
    int PWM_Value =  map (received, 1, 10, min_speed, max_speed);
    analogWrite(R_MR,PWM_Value);
    analogWrite(L_MR,PWM_Value);
  }
    if (received>=11 && received <=20) // Break
  {
    int PWM_Value =  map (received, 11, 20, min_speed, max_speed);
    analogWrite(R_MR,0);
    analogWrite(L_MR,0);
  }
    if (received>=21 && received <=30) // Turn Right 
  {
    int PWM_Value =  map (received, 21, 30, min_speed, max_speed);
    analogWrite(R_MR,PWM_Value);
    analogWrite(L_MR,0);
  }
      if (received>=31 && received <=40) // Turn Right 
  {
    int PWM_Value =  map (received, 31, 40, min_speed, max_speed);
    analogWrite(R_MR,0);
    analogWrite(L_MR,PWM_Value);
  }
}
void ReadData()
{
  myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Which pipe to read, 40 bit Address
  myRadio.startListening(); //Stop Transminting and start Reveicing 
  if ( myRadio.available()) 
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
    }
    Serial.print("\nReceived:");
    Serial.println(data.msg);
    received = data.msg;
    Control_Car();
  }
  else  //If not data from RF
  {
  //analogWrite(R_MR,0);
  //analogWrite(L_MR,0);
  }
}
void WriteData()
{
  myRadio.stopListening(); //Stop Receiving and start transminitng 
  myRadio.openWritingPipe(0xF0F0F0F066);//Sends data on this 40-bit address
  myRadio.write(&data, sizeof(data)); 
  Serial.print("\nSent:");
  Serial.println(data.msg);
  delay(300);
}

Credits

Aswinth Raj

Posted by PCBGOGO Mike

Comments

Please log in or sign up to comment.