Introduction: Dagu Rover 5 - Arduino Mega 2560 - Xbee

Hi. This is my 1st robot platform and 1st Instructable post. I am a big believer of the sharing of knowledge and have learned a lot for the internet, so here is me adding to the collective knowledge. Sorry for the lack of early photos

Items needed for project

dagu rover 5 - I have the 4 motors/ 4 encoder model

rover 5 motor driver Board

arduino mega 2560

Xbees - I use XBee Series 1

XBee Explorer Dongle v2

XBee Explorer Regulated - plus pins and soldering stuff

Batteries - 6AA and 5v usb bank.

male to female jumper wires

Pololu RP5/Rover 5 Expansion Plate RRC07B (Wide) Transparent Clear

Step 1: Cut a Hole for the Motor Wire to Come Through

To attach the Pololu RP5/Rover 5 Expansion Plate to rover you have to cut out a hole in the middle for the wires from the motors and encoders to come through. I cut some to plastic bit with a sharp knife. then pull the wires through, this will allow for the plate to be mounted flat

Step 2: Wiring Part A

First attach the motor and encoder wires to the rover 5 motor driver Board. I have included a image of how i wired it but it doesn't show how I attach the motor and encoder wires. To wire these trace them back to the motor and then plug them into the right port. For the encoder wires i have plug them into bottom row of the pins label "INT ENC1 ENC2" . From left to right it is Red - Yellow - White - Black.

Step 3: Wiring Part B

Wire the rover 5 motor driver Board to the arduino mega 2560 should be easier if a little messy. The image I have included shows how I did it. Here is some arduino code of where to wires go.

#define encoderA 2
#define encoderB 3 // Only use one interrupt in this example
#define encoderC 19
#define encoderD 18 // Only use one interrupt in this example
volatile int Lcount;
volatile int Rcount;
int Lcountsaved;
int Rcountsaved;
int speedch1 = 9; // left front
int speedch2 = 10; // left back
int speedch3 = 11; // right front
int speedch4 = 12; // right back
// direction pins 
int dirch1 = 44; // left front
int dirch2 = 45; // left back
int dirch3 = 42; // right front
int dirch4 = 43; // right back
int curch1 = A1; // left front
int curch2 = A2; // left back
int curch3 = A3; // right front
int curch4 = A4; // right back

I have include the cur (current) pins but i never got them to work. I have use a breadboard for a common ground, this is probably wrong but it works. I will discuss Xbee in a separate step

Step 4: Platform to Hold Batteries

After wiring the lower platform, there is no room for batteries. So i created one for mine out of paper mache and wire. it is not very good, possible alternatives 3d print or shop bought box that fits. I attached the batteries via velcro.

Step 5: Coding Basic

This has been my first project so the code is rough. Here is a basic code for all four motor to spin for 5 seconds, there are no encoder or xbee in this code.

//ROBOT CAR CODE 001
int speedch1 = 9;
int speedch2 = 10;
int speedch3 = 11;
int speedch4 = 12;
int dirch1 = 44;
int dirch2 = 45;
int dirch3 = 42;
int dirch4 = 43;
int curch1 = A1;
int curch2 = A2;
int curch3 = A3;
int curch4 = A4;
void setup() {                
  // initialize the digital pin as an output.
pinMode(dirch1,OUTPUT);
pinMode(dirch2,OUTPUT);
pinMode(dirch3,OUTPUT);
pinMode(dirch4,OUTPUT);
pinMode(speedch1,OUTPUT);
pinMode(speedch2,OUTPUT);
pinMode(speedch3,OUTPUT);
pinMode(speedch4,OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
  delay(2000);
   digitalWrite(dirch1,LOW); // direction motor spins 
   digitalWrite(dirch2,HIGH); // 1 and 2 are on the same side but fight against each other.
   digitalWrite(dirch3,LOW);
   digitalWrite(dirch4,HIGH);
   analogWrite(speedch1,200); // speed PWM 0 - 255 
   analogWrite(speedch2,200);
   analogWrite(speedch3,200);
   analogWrite(speedch4,200);
   
   delay(5000);//how long the motors run
   
   analogWrite(speedch1,0); // stop
   analogWrite(speedch2,0);
   analogWrite(speedch3,0);
   analogWrite(speedch4,0);
}

Step 6: Encoders Code

Here is a simple code for the left encoder. I spend many hours confused over this. but found a linear encoder code that works. The code spins the left motors until the encoder (count) reaches 500. it also print it to the serial monitor. It the same for the other side just have to change the pins and names, but i will include a final code with everything at the end.

// Interrupt information // pins may be different on uno<br>// 0 on pin 2
// 1 on pin 3
#define encoderA 2
#define encoderB 3 // Only use one interrupt in this example
volatile int count;
int speedch1 = 9; // left front
int speedch2 = 10; // left back
int speedch3 = 11; // right front
int speedch4 = 12; // right back
// direction pins 
int dirch1 = 44; // left front
int dirch2 = 45; // left back
int dirch3 = 42; // right front
int dirch4 = 43; // right back
int curch1 = A1; // left front
int curch2 = A2; // left back
int curch3 = A3; // right front
int curch4 = A4; // right back
int TIME; //time the command is for
int SPEED;// 0 - 255 motor speed
void setup()
{
Serial.begin(9600);
count=0;
pinMode(dirch1,OUTPUT);
pinMode(dirch2,OUTPUT);
pinMode(dirch3,OUTPUT);
pinMode(dirch4,OUTPUT);
pinMode(speedch1,OUTPUT);
pinMode(speedch2,OUTPUT);
pinMode(speedch3,OUTPUT);
pinMode(speedch4,OUTPUT);
pinMode(encoderA, INPUT);
pinMode(encoderB, INPUT); attachInterrupt(0, handleEncoder, CHANGE);
}
void loop()
{
 delay(1000);
  (SPEED = 200);
   forward();
  if (count > 10) Serial.println(count); 
}
void handleEncoder()
{
if(digitalRead(encoderA) == digitalRead(encoderB))
{ count++;
}
else
{ count--;
}
}
void forward()
{  
     
   digitalWrite(dirch1,LOW);
   digitalWrite(dirch2,HIGH); 
   analogWrite(speedch1,SPEED);
   analogWrite(speedch2,SPEED);
   
   if (count > 500){ 
   
   analogWrite(speedch1,0);
   analogWrite(speedch2,0);
  }
}

Step 7: Xbee

The Xbees are the only place you will need to solder some pins. First get your xbees of choice and program them to take to each other on the same channel using XBee Explorer Dongle v2 and XCTU. unfortunately I managed to do this by what seems like blind luck. So i don't how much help I will be there. Here is what I know about the coding for sending for Processing to Xbee to Arduino mega 2560. choose the serial port for the xbee on the Arduino 2 or 3 and run this simple receiving code. The code turns led 13 on the board on when it receives (49) processing in next step.

int incomingByte = 0;   // for incoming serial data<

int led = 13;
void setup() {
  Serial2.begin(9600);  // change to the serial port /2/3
  pinMode(led, OUTPUT);        
}
void loop() {
        // send data only when you receive data:
        if (Serial2.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial2.read();
                
                if(incomingByte == 49) digitalWrite(led, HIGH);
                else if(incomingByte == 50) digitalWrite(led,LOW);
              }
}

Step 8: Processing

This is the other half. First import processing.serial. plug you other xbee to the XBee Explorer Dongle v2 and into your computer, I had found a usb extension lead useful. Pick which port you are attach too.Clicking and holding the mouse button it now should turn on led 13 on the board. This code was wrote in v2.1.1

import processing.serial.*;

Serial myPort;  // Create object from Serial class
void setup(){
  size(640, 360);
  println(Serial.list());// This will list serial ports
  String portName = Serial.list()[5];// port number
  myPort = new Serial(this, portName, 9600);
}
void draw(){
  if (mousePressed) {
    myPort.write(49);
  } else {
    myPort.write(50);
  }
}

Step 9: Final Code

Here is the Final code for the arduino mega 2560. I have created sub commands to make it easier.

//ROBOT CAR CODE 004
// commands
// forward()
// backward()
// rotate_left()
// rotate_right()
//notes 
//   FULL 360 rotate
//  (TIME = 12000);   //delay time
//  (SPEED = 200);   //speed 0-255
//  rotate_right(); 
int incomingByte = 0; //  for incoming serial data 
//speed pins 0 - 255 
#define encoderA 2
#define encoderB 3 // Only use one interrupt in this example
#define encoderC 19
#define encoderD 18 // Only use one interrupt in this example
volatile int Lcount;
volatile int Rcount;
int Lcountsaved;
int Rcountsaved;
int speedch1 = 9; // left front
int speedch2 = 10; // left back
int speedch3 = 11; // right front
int speedch4 = 12; // right back
// direction pins 
int dirch1 = 44; // left front
int dirch2 = 45; // left back
int dirch3 = 42; // right front
int dirch4 = 43; // right back
int curch1 = A1; // left front
int curch2 = A2; // left back
int curch3 = A3; // right front
int curch4 = A4; // right back
int TIME; //time the command is for
int SPEED;// 0 - 255 motor speed
int count;
int check1; //see if subcomand has run
int check2; //see if subcomand has run
int check3; //see if subcomand has run
int check4; //see if subcomand has run
int check5; //see if subcomand has run
void setup() {                
Lcount=0;
Rcount=0;
  // initialize the digital pin as an output.
pinMode(dirch1,OUTPUT);
pinMode(dirch2,OUTPUT);
pinMode(dirch3,OUTPUT);
pinMode(dirch4,OUTPUT);
pinMode(speedch1,OUTPUT);
pinMode(speedch2,OUTPUT);
pinMode(speedch3,OUTPUT);
pinMode(speedch4,OUTPUT);
pinMode(encoderA, INPUT);
pinMode(encoderB, INPUT); attachInterrupt(0, LhandleEncoder, CHANGE);
pinMode(encoderC, INPUT);
pinMode(encoderD, INPUT); attachInterrupt(5, RhandleEncoder, CHANGE);
Serial2.begin(9600);
Serial.begin(9600);
analogWrite(speedch1,0);// stop all
analogWrite(speedch2,0);// stop all
analogWrite(speedch3,0);// stop all
analogWrite(speedch4,0);// stop all
count = 0;
(SPEED = 200);
}
// the loop routine runs over and over again forever:
void loop() {
  
  if (Serial2.available() > 0) {
    // read the incoming byte:
   incomingByte = Serial2.read();               
  }
  
  if(incomingByte == 10 && check1 == 0) forward();
  else if(incomingByte == 11 && check2 == 0) rotate_right();
  else if(incomingByte == 12 && check3 == 0) backward();
  else if(incomingByte == 13 && check4 == 0) rotate_left();
  else if(incomingByte == 14 && check5 == 0) pause();
// if(incomingByte == 16){
// if (Lcount != Lcountsaved && Rcount != Rcountsaved)
 Serial2.print(Lcount,DEC);//send encoder data
 Serial2.print(",");
 Serial2.print(Rcount,DEC);
 Serial2.print(",");
 Serial2.println();
 
 incomingByte = 1;
// Lcountsaved = Lcount;
 //Rcountsaved = Rcount;
// }
 }
 
  
void LhandleEncoder()
{
if(digitalRead(encoderA) == digitalRead(encoderB))
{ Lcount++;
}
else
{ Lcount--;
}
}
void RhandleEncoder()
{
if(digitalRead(encoderC) == digitalRead(encoderD))
{ Rcount++;
}
else
{ Rcount--;
}
}
void forward()
{             
   check2 = 0;
   check3 = 0;
   check4 = 0;
   check5 = 0;
   
   analogWrite(speedch1,0);
   analogWrite(speedch2,0);
   analogWrite(speedch3,0);
   analogWrite(speedch4,0);
 
   delay(100);
 
   digitalWrite(dirch1,LOW);
   digitalWrite(dirch2,HIGH); 
   digitalWrite(dirch3,LOW);
   digitalWrite(dirch4,HIGH);
   analogWrite(speedch1,SPEED);
   analogWrite(speedch2,SPEED);
   analogWrite(speedch3,SPEED);
   analogWrite(speedch4,SPEED);
   
   check1 = 1;
}
void backward()
{  
   check1 = 0; 
   check2 = 0; 
   check4 = 0;
   check5 = 0;
   
   analogWrite(speedch1,0);
   analogWrite(speedch2,0);
   analogWrite(speedch3,0);
   analogWrite(speedch4,0);
   
   delay(100);
 
   digitalWrite(dirch1,HIGH);
   digitalWrite(dirch2,LOW); 
   digitalWrite(dirch3,HIGH);
   digitalWrite(dirch4,LOW);
   analogWrite(speedch1,SPEED);
   analogWrite(speedch2,SPEED);
   analogWrite(speedch3,SPEED);
   analogWrite(speedch4,SPEED);
   check3 = 1;
  
   
}
void rotate_right()
{  
   check1 = 0;
   check3 = 0;
   check4 = 0;
   check5 = 0;
   
   analogWrite(speedch1,0);
   analogWrite(speedch2,0);
   analogWrite(speedch3,0);
   analogWrite(speedch4,0);
   
   delay(100); //wait to stop
   
   digitalWrite(dirch1,LOW);
   digitalWrite(dirch2,HIGH); 
   digitalWrite(dirch3,HIGH);
   digitalWrite(dirch4,LOW);
   analogWrite(speedch1,SPEED);
   analogWrite(speedch2,SPEED);
   analogWrite(speedch3,SPEED);
   analogWrite(speedch4,SPEED);
   
   check2 = 1;
}
void rotate_left()
{  
   check1 = 0;
   check2 = 0;
   check3 = 0;
   check5 = 0;  
   
   analogWrite(speedch1,0);
   analogWrite(speedch2,0);
   analogWrite(speedch3,0);
   analogWrite(speedch4,0);
   
   delay(100);
   
   digitalWrite(dirch1,HIGH);
   digitalWrite(dirch2,LOW); 
   digitalWrite(dirch3,LOW);
   digitalWrite(dirch4,HIGH);
   analogWrite(speedch1,SPEED);
   analogWrite(speedch2,SPEED);
   analogWrite(speedch3,SPEED);
   analogWrite(speedch4,SPEED);
  
  check4 = 1;
}
void pause()
{ 
   check1 = 0;
   check2 = 0;
   check3 = 0;
   check4 = 0;  
  
   analogWrite(speedch1,0);
   analogWrite(speedch2,0);
   analogWrite(speedch3,0);
   analogWrite(speedch4,0);
  
  check5 = 1; 
}

Step 10: Final Processing Code

Here is the Processing code used to run the xbee. I have striped it back to the basics. arrow key for direction and ctrl for stop. I have included the data in channel to receive the encoders. it some times crashes when it only receives 1 encoder, i don't know why. Code written in 2.1.1

import processing.serial.*;
 Serial myPort;  // Create object from Serial class
 int lf = 10;    // Linefeed in ASCII
 int source1; 
 int source2;
 String myString = null;
void setup(){
  size(640, 360);
  println(Serial.list());
  String portName = Serial.list()[5]; // pick the port connected
  myPort = new Serial(this, portName, 9600);
  myPort.clear();
  myString = myPort.readStringUntil(lf);
  myString = null;
  source1 = 0;
  source2 = 0;
}
 
 void draw(){
   background(255,255,255);
   textSize(32);
   text(source1,20,60);
   text(source2,20,120);
   fill(0,0,0);
   while (myPort.available() > 0) {
    myString = myPort.readStringUntil(lf);
    if (myString != null) {
      println(myString);
  
String[] q = splitTokens(myString, ",");//split at ","
println(q.length + " values found");  // Prints 2 values found"
source1 = int(q[0]);
source2 = int(q[1]);
 }
 }
 }
 void keyPressed() {
  if (key == CODED) {
    if (keyCode == UP) {
     myPort.write(10);//Forward
    } else if (keyCode == DOWN) {
      myPort.write(12);//Backward
   } else if(keyCode == LEFT){
      myPort.write(13);//LEFT
  } else if(keyCode == RIGHT){
      myPort.write(11);//Right
  }else if(keyCode == CONTROL){
    myPort.write(14); //Pause
}
}
}

Step 11: Proof It Works

Here is a short video of the rover rolling over some obstacles. Hope this has been helpful to you. I will try to answer any question about my robot. I plan to enter some Instructable competitions and would love the help of your vote.

Tech Contest

Participated in the
Tech Contest

Microcontroller Contest

Participated in the
Microcontroller Contest