RF controlled 4WD Rover

Hello everyone,

I am new to the Arduino community and I just finished my first project. The kids loved it!

I though I would share the code so it can inspire other newbies. Basically, an arduino driven shift register is coordinating 2H-Bridge motor drivers. Depending on speed, it uses differential or skid steering. Comments are welcome.

The Rover

/* --------------------------------------------- 
Controling 4WD RC vehicule

PARTS
- 2 Arduino Uno
- 2 H-bridge IC (SN754410)
- 1 Shift Register (74HC595)
- 2 2.4Ghz rf transivers (nRF24L01)
- 1 Joystick
- 1 4wd chassis (DAGU robot)

PRINCIPLE
Shist register pins QA-QH are connected to all
8 h-bridge A pins (1A-2A,3A-4A).

TIPS
PWM Enable Pins must be filtered (Low Pass Filtering) for 
nice tork and smooth control of the speed.

--------------------------------------------- */

// H-bridge Enable pins
const int EN1=5;
const int EN2=6;

// Shift Register pins
const int SER = 8;
const int LATCH = 7;
const int CLK = 4;

// Initializing constants
int valSpeed = 0;
int valSteer = 0;
int velocity = 0;  
int steer = 0; 

/* - CONNECTIONS: nRF24L01 Modules See:
 http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo
   1 - GND
   2 - VCC  => 3.3V
   3 - CE => pin 9
   4 - CSN => pin 10
   5 - SCK => pin 13
   6 - MOSI => pin 11
   7 - MISO => pin 12
   
*/   
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#define CE_PIN   9
#define CSN_PIN 10

// NOTE: the "LL" at the end of the constant is "LongLong" type
const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
int joystick[2];  // 2 element array holding Joystick readings


void setup()
{
    //Serial.begin(9600);
    delay(1000);
    //Serial.println("Nrf24L01 Receiver Starting");
  // Enable pins
    pinMode(EN1, OUTPUT);
    pinMode(EN2, OUTPUT);
    
    // Shift Register
    pinMode(SER, OUTPUT);
    pinMode(LATCH, OUTPUT);
    pinMode(CLK, OUTPUT);

    radio.begin();
    radio.openReadingPipe(1,pipe);
    radio.startListening();;
    
    brake(); //Initialize with motor stopped
}

void loop()
{
   //RADIO TRANSMISSION
   if ( radio.available() )
  {
    // Read the data payload until we've received everything
    bool done = false;
    while (!done)
    {
      // Fetch the data payload
      done = radio.read( joystick, sizeof(joystick) );
    }
  }
  else
  {    
      //Serial.println("No radio available");
  }
    
      valSpeed = joystick[1];
      valSteer = joystick[0];
      /*Serial.print("valSeed = ");
      Serial.print(valSpeed);
      Serial.print(" valSteer = ");      
      Serial.println(valSteer); */
      Serial.println( " Hello World!");
      
    //go forward
    if (valSpeed > 562)
    {
        velocity = map(valSpeed, 563, 1023, 0, 255);   
        forward(velocity,valSteer);
    }
 
    //go backward
    else if (valSpeed < 462)
    {
        velocity = map(valSpeed, 461, 0, 0, 255);
        reverse(velocity,valSteer);
    }
 
    //brake
    else if (valSteer > 562 || valSteer < 462)
    {
        velocity= 255;
        skid(valSteer,velocity);      
    }
    else
    {
        brake();
    }
}

//Motor goes forward at given rate (from 0-255)
void reverse (int rate,int valsteer)
{
    digitalWrite(EN1, LOW);
    digitalWrite(EN2, LOW);
    
    digitalWrite(LATCH,LOW);
    shiftOut(SER,CLK,MSBFIRST,B01010101);
    digitalWrite(LATCH,HIGH);

    // Sterring Left
    if (valsteer > 562)
    {
        steer = map(valsteer, 563, 1023, 200, 0);   
        analogWrite(EN1, rate);
        analogWrite(EN2, steer);
    }
 
    // Sterring Right
    else if (valsteer < 462)
    {
        steer = map(valsteer, 461, 0, 200, 0);
        analogWrite(EN1, steer);
        analogWrite(EN2, rate);
    }
  
     
    // Same speed on both sides
    else
    {
      analogWrite(EN1, rate);
      analogWrite(EN2, rate);
    } 
}

//Motor goes backward at given rate (from 0-255)
void forward (int rate, int valsteer)
{
    digitalWrite(EN1, LOW);
    digitalWrite(EN2, LOW);
    
    digitalWrite(LATCH,LOW);
    shiftOut(SER,CLK,MSBFIRST,B10101010);
    digitalWrite(LATCH,HIGH);
   // Sterring Left
    if (valsteer > 562)
    {
        steer = map(valsteer, 563, 1023, 200, 0);   
        analogWrite(EN1, rate);
        analogWrite(EN2, steer);
    }
 
    // Sterring Right
    else if (valsteer < 462)
    {
        steer = map(valsteer, 461, 0, 200, 0);
        analogWrite(EN1, steer);
        analogWrite(EN2, rate);
    }
 
    // Same speed on both sides
    else
    {
      analogWrite(EN1, rate);
      analogWrite(EN2, rate);
     }
}

void skid (int valsteer, int rate) {

    digitalWrite(EN1, LOW);
    digitalWrite(EN2, LOW);
    
    digitalWrite(LATCH,LOW);
    
    if (valsteer > 562)
    {
         shiftOut(SER,CLK,MSBFIRST,B10100101);
    }
    else if (valsteer < 462)
    {
        shiftOut(SER,CLK,MSBFIRST,B01011010);
    }
    
    digitalWrite(LATCH,HIGH);
    
    analogWrite(EN1,rate);
    analogWrite(EN2,rate); 

    
}

//Stops motor
void brake ()
{
    digitalWrite(EN1, LOW);
    digitalWrite(EN2, LOW);
    
    analogWrite(EN1, 0);
    analogWrite(EN2, 0);
 }

The Joystick

/* YourDuinoStarter Example: nRF24L01 Transmit Joystick values
 - WHAT IT DOES: Reads Analog values on A0, A1 and transmits
   them over a nRF24L01 Radio Link to another transceiver.
 - SEE the comments after "//" on each line below
 - CONNECTIONS: nRF24L01 Modules See:
 http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo
   1 - GND
   2 - VCC 3.3V !!! NOT 5V
   3 - CE to Arduino pin 9
   4 - CSN to Arduino pin 10
   5 - SCK to Arduino pin 13
   6 - MOSI to Arduino pin 11
   7 - MISO to Arduino pin 12
   8 - UNUSED
   - 
   Analog Joystick or two 10K potentiometers:
   GND to Arduino GND
   VCC to Arduino +5V
   X Pot to Arduino A0
   Y Pot to Arduino A1
   
 - V1.00 11/26/13
   Based on examples at http://www.bajdi.com/
   Questions: terry@yourduino.com */

/*-----( Import needed libraries )-----*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define CE_PIN   9
#define CSN_PIN 10
#define JOYSTICK_X A1
#define JOYSTICK_Y A2

// NOTE: the "LL" at the end of the constant is "LongLong" type
const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe


/*-----( Declare objects )-----*/
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
/*-----( Declare Variables )-----*/
int joystick[2];  // 2 element array holding Joystick readings

void setup()   /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(pipe);
}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  joystick[0] = analogRead(JOYSTICK_X);
  joystick[1] = analogRead(JOYSTICK_Y);
  
  radio.write( joystick, sizeof(joystick) );

}//--(end main loop )---

/*-----( Declare User-written Functions )-----*/

//NONE
//*********( THE END )***********

IMG_1742.JPG

Here are the images attached to the top post so others don't have to download them.

534c456d076b2e88973e7aa709dfadb90b5d3bb2.jpg

It would be nice if there were a simple way to insert uploaded images but I don't know of one. This is the work around I came up with.

Thanks for sharing your project.

I noticed several "magic numbers" in the program. You might want to consider changing code like this:

if (valSpeed > 562)
    {
        velocity = map(valSpeed, 563, 1023, 0, 255);   
        forward(velocity,valSteer);
    }

To:

if (valSpeed >= FORWARD_THRESHOLD)
    {
        velocity = map(valSpeed, FORWARD_THRESHOLD, 1023, 0, 255);   
        forward(velocity,valSteer);
    }

Of course the constant "FORWARD_THRESHOLD" needs to be defined. I'm not sure if I used a good name or not.

const int FORWARD_THRESHOLD = 563;

You could do the same for the other magic numbers.

Now that I can see the pictures (by clicking "Preview" in the editor) I can see how cool the robot and remote look.

If you shoot some video, I hope you share it too.

Thanks DuaneDegn,

Will convert magic values to constants. Thanks!

To your knowledge, what is the most common schematic software out there that is free and easy to use?

Seb

sebmichel:
To your knowledge, what is the most common schematic software out there that is free and easy to use?

Sorry, I don't have anything to suggest.

I use DipTrace for circuit board design. DipTrace includes a schematic program but I wouldn't recommend using it for generic schematic use. It doesn't make very pretty schematics.

Here's a schematic of an early version of PCBs used with my RGB LED arrays.

I think you'll agree, it doesn't look very nice. There is a free version of DipTrace which I think is great PCB design software but not so great schematic rendering software.

Hopefully someone else will have a suggestion.

Eagle from www.cadsoft.de
http://www.cadsoftusa.com/download-eagle/freeware/

Free version for 1 sheet schematics, 80x100 PCBs.
Can do a lot with that, before spending $49 for a version that can do more.

Yellow on black is hard to read. Wouldn't want to print that.

I doubt any PCB design software is the best choice for someone wanting to create a schematic for display purposes.

The schematic I posted was a screen grab. I'm pretty sure it's pretty common for PCB design software to have user configurable appearances.

If you're interested in the debate about which religion PCB design software is best, you can check out this thread.

I like expresspcb.com for schematics for posting here. Or Eagle.
Both can export a high res picture that is better for posting than a screen capture.
I often export, than insert into powerpoint, crop, maybe resize, then save as .jpg and post it as an attachment (and then modify the post to make it show up).
This is from eagle.

Personally I like to use fritzing. It can be used to design PCBs, schematics, and includes Arduino boards in its list of parts for design. To be honest you really can't go wrong in most cases when using PCB design software. Just try different ones and use the software that you like the most!

I hope this helps,
goodinventor

I think you'll find there are many people around here who do not like Fritzing.

I wonder why. Maybe it is because of the lack of a comprehensive parts database?

goodinventor:
I wonder why. Maybe it is because of the lack of a comprehensive parts database?

I'm sure the reason people don't like it is not because it's lacking in parts.

I think the main reason people don't like it is because it's not a schematic. The viewer is required to try to build a schematic in the mind.

When was the last time you used Fritzing? When I got it it had three windows total: one for prototyping (shows breadboard, controller, etc. in colors), one for electronic schematics, and one for PCB design.

goodinventor:
When was the last time you used Fritzing? When I got it it had three windows total: one for prototyping (shows breadboard, controller, etc. in colors), one for electronic schematics, and one for PCB design.

Right. I forgot about the PCB design part of Fritzing. You might be right about Fritzing making good schematics. The problem is people usually post the breadboard diagram rather than the schematic.

Thanks for clarifying. Some of us may be being judging Fritzing too harshly.

Thank you both for your suggestions. Will definitely look at Fritzing as I want to start with simple diagrams.

DuaneDegn:
Thanks for clarifying. Some of us may be being judging Fritzing too harshly.

For a long time.

I played around with it briefly a few years back; while I felt it could use some polish - I also felt it held great promise, especially for newbies to the world.

It has everything that made the Arduino a success: It's completely open-source, it has a good team behind it, and a community for support and expansion of the parts library (which grows on a regular basis - if you need a part, it's not that difficult to make one using inkscape and a text editor, for the most part).

Will it ever be EagleCAD or anything like that? No - it won't - and I don't think it is meant to be. It also won't replace gEDA (which has a cliff-like learning curve), nor KiCAD - both other open-source electronic design tools.

It is interesting though, in it's approach - because you can create and edit a circuit from one of the three windows: Breadboard, Schematic, and PCB Layout.

If your in your schematic, and you need to add a part - do it; the results will show up in the other windows (you'll definitely need to re-position the parts/layout on the other windows - it's not that smart). You can also do the same on the other windows as well; a change in one window is reflected in the others.

For newbies, it's the breadboard layout that they like - it may irk those of us who like to see schematics, but this software is meant, I believe, as a teaching and transitioning tool: A newbie can play, make changes on a physical structure they may have in front of them (the breadboard and parts), and do that same change on their breadboard - but then, at a later point (or in the process of making those changes) - they can look at the schematic and see how it changes, thus learning part symbols, connections, etc. They can then move parts around on the schematic - and notice how it doesn't change the breadboard or PCB, hopefully picking up the fact that the schematic is a model representation of the "real circuit" - and that it doesn't have to share the same layout with "the real thing" (in fact, it might be impossible or very difficult for it to, especially on more complex circuits). They can also learn how routing and such on the PCB does a similar thing, and how they might have to modify the routing and such to get parts to fit.

In short - for some people, it probably can help them understand the differences and similarities for how the virtual (schematic) affects the real (breadboard and PCB) - and vice-versa.

I've always thought it could be a powerful teaching tool - perhaps even one that would pair well with many beginning Arduino users. Instead, many of them - trying to show what they have set up - seemingly get "berated" for not using the "right tool" - instead of being guided on how to use the tool they are using to look at the schematic side of things, and understand how that relates to their "breadboard view".

...and, perhaps, maybe those of us who use more advanced tools might be able to help guide both the users and the developers of Fritzing to improve the system to make it more palatable for both newbies and more advanced users. We should be supportive of the open source efforts on these tools, IMHO - since our development platform arguably comes from the same kind of ideals.

How wise cr0sh! I am a beginner in electronics and Fritzing appears to be very much appropriate.

thanks for sharing, everyone :smiley:

Hello,

This project was great to get to the next level and go from a prototype to a nice looking homemade pcb.

I posted the code and the Fritzing file here:

Cheers!

S