Introduction: Free Form XBee Remote

About: High school physics and engineering teacher in southern California. Love innovation and working with my hands to build cool stuff that teaches me something.
As a teacher of Robotics I have been searching for a universal remote solution for my high school course.  Although I don't mind the PS2 controller layout it has some issues and the connection is not as robust as I would like.  Once you have a connection it is stellar but when you lose your connection you often have to stand on your head and rub a rabbit's foot to re-connect.  So, in this instructable I am proposing a concept that has probably existed for some time although I have never seen it discussed as a united topic.  This free form remote control opens up a myriad of design options and possibilities.  As a starting point for coming up with a quick prototype to test my electronics I chose PVC because it is solid, connectable  and most importantly it is cheap.  The market uses plastic almost exclusively which makes sense for molded shapes but being a wood enthusiast my next one will be grained and stained.

The communication system used in this instructable is a pair of Series 1 XBee's.  The remote does not consist of any microcontroller to reduce the cost.  The other XBee is connected to an Arduino and a motor controller shield to drive a simple two motor robot.  Although XBee can be a pain at times (when the many settings are not quite right) it provides a robust communication link that sets up in seconds when powered and seems to have plenty of range.  It  has the capability for a lot of cool extensions beyond this  single direction communication setup which gives me room to grow.

Here's the list of stuff I used.  Some things are optional or easily swapped for a similar item.

20 inches of 1/2" PVC pipe   ($2)
6 PVC elbows  ($2)
2 PVC T connectors  ($1)
1 Arduino  ($30)
2 Series 1 XBee units ($46)
2 XBee adapters ($20 Adafruit Adapter kit)
2 Potentiometer joysticks (single or dual axis) ($20)
1 Full size breadboard ($8)
1 Mini breadboard ($4)
3.3 V power supply (we'll make one and use a 9 V battery) ($5)
Arduino power supply (Robotshop 7.4V) ($20)
2 DC motors  (lots of options, had 2 VEX motors around)
1 Motorshield ($20 Adafruit)


Step 1: The PVC Remote

Using PVC as a prototyping material was generally pretty quick.  The picture represents a slight variation to the first remote I drew on paper and the center XBee square on the bottom worked better than the top.  I didn't want to make it too heavy but I wanted it to be solid.  Cut out the necessary pieces below and stick it all together according to these dimensions.

1 Long Piece (top)  7 3/4"
2 Sides 4"
2 Bottom 2"
4 Square 1 3/4"

The breadboard that will be assembled in the next step will need a place on the PVC remote.  After much thought on the many different ways to accomplish this I used 0.093" thick acrylic sheet from Home Depot.  Although I have inserted the acrylic inside the PVC I am not sure if it was necessary.  Simply gluing it to the PVC may suffice and safe you the hassle (I used a chop saw and a drummel but you have to be comfortable with power tools).  I used Loctite Stik N Seal which dries transparent and has no odor.  From the picture I also mounted a piece of acrylic on the bottom of the square so that the battery and wires would not float through the bottom.

Step 2: Setting Up the Joyticks

The joysticks used in this project were purchased from Adafruit for $5.95 (http://www.adafruit.com/products/512).  Although they have 2 axes, I am only making use of one axis for forward and backward control for each side of the robot.  Place the joysticks on either side of the full-sized breadboard.  I have rotated the joysticks so that I am actually using the x-axis instead of the y-axis in order to plug the header on the joystick into the breadboard horizontally.

Optional:  3.3 V power supply.

Both the joysticks and the XBees need to be powered.  Since the XBees need 3.3 V we will use that for both.  If you have a small breadboard power supply you could just plug it in and you're set.  If you don't want to commit your power supply to this remote than consider wiring this one shown in the schematic.  I used the following parts to make a simple 3.3 V supply that uses a 9V battery as its source.

Parts: 

LM317
9V battery input
Ci (input) = 0.1 µF
Co (output) =1 µF
R1 = 270
R2 = 440 (I used two 220 in series) 

Double check that your ouput is close to 3.3 V using a multimeter.  From my picture you can see that I quickly wired it to test it out and then later cleaned it up so that it looked a little more respectable (pretty hard to follow the original wiring job).  When you have 3.3 V you can plug in the power (Vcc) and ground (GND) on your joystick connection.  On the Xout for each joystick place a long wire that can get to your XBee.

My full-sized breadboard had an adhesive backing so I removed that and simply mounted it on the acrylic sheet on the remote.  In the next step we will set-up the remote XBee to send our joystick data to the robot.

Step 3: Setting Up and Programming the Transmitting XBee

XBee's need to be programmed to operate properly and I've spent hours trying to get those settings right on many different projects.  When you do get the settings right XBees are alot of fun.  In this instructable I am using Series 1 XBee's so if you have Series 2 you will probably have to use different settings.  I would refer to the formidable Arduino Cookbook Section 14.4 to see how Series 2 may be used here if that is what you have available.  

If you haven't programmed XBee's before you should take a look at the Adafruit tutorials at:
http://www.ladyada.net/make/xbee/arduino.html    I would also highly recommend using X-CTU free software for completing the XBee set-up steps.  Ensure that the XBee modem types are the same and that they carry the same firmware versions.  This can be done by plugging your XBee into the FTDI cable (need to use an XBee adapter) and from the X-CTU front screen click on Test\Query to bring up the XBee basic information screen.  This also ensures that you have a proper serial connection between the XBee and the computer.  From there click on Terminal closer to the top of the screen and type in the following commands.  

The settings for the remote transmitting XBee are as follows:

+++     (initiates AT command mode)
ATRE          (reset modem settings)
ATMY1234   (set 10bit transmitting xbee address)
ATDL5678  (indicates 10bit receiver xbee address)
ATDH0  (set to zero)
ATID0  (ID's must be the same for both XBees - here it is zero)
ATD02    (set I/O pin 0 to analog (2) input)
ATD12    (set I/O pin 1 to analog (2) input)
ATIR64  (set data transfer rate to 100 msec (64 hex = 100 decimal))
ATWR    (write data to XBee)

The Transmitting XBee diagram indicates which wires need to be connected on the transmitting XBee.  You may also notice from the picture that I have a switch installed.  The flow of electricity goes from the 9V battery to the 3.3 V regulator and in addition to powering the breadboard for joystick power it must return to the XBee to power it as well.  I strongly encourage you to wire the unit outside of the PVC first to ensure it is functional and then clean it up as needed.  The PVC does provide an excellent conduit for hiding wires.  Wire as shown and then move to the next step where we will get the robot ready to be controlled.





Step 4: Setting Up and Programming the Arduino and Receiving XBee

On the receiving end the XBee needs to communicate with the computer to be able to receive programs.  It's also handy to be able to view information gathered between XBee and computer to debug as necessary.  So, in order to leave the normal computer serial connection intact I moved my XBee communication to a software serial line.  Since I also had to ensure I wouldn't conflict with things happening on my motor shield I moved the Arduino communication lines with the receiving XBee all the way over to the first two analog pins.  In the diagram you can see the orange and green lines connecting A0 (Rx) and A1 (Tx) on the Arduino to the Tx (pin 2) and Rx (pin 3) respectively on the Xbee.  The other XBee connections are simply power and ground which can be taken from the Arduino.

Program the receiving XBee using X-CTU as you did the transmitting XBee but with the following settings:

+++
ATRE
ATMY5678
ATDL1234
ATDH0
ATID0
ATWR

The program that I modified from the very helpful Arduino Cookbook is given below.  Since I am still working it all out I will leave it as an exercise for interested users to breakdown the way the program pulls out the important data sent in the API frame.  It goes without saying that without Michael Margolis laying down the framework for getting at the received data I wouldn't have figured that out given an infinite amount of time.  I am pretty sure that there are details to the code that could be eliminated but I haven't tried to thin it down yet and since it works I am leaving it as is for now.  Transfer this program to your Arduino and then move on to the final step and consider what you can add to the project.

/*********
*
*      ER_RemoteA  (Engineering & Robotics Remote Option)
*
*      XBee standalone transmitter sends analog joystick readings to an Arduino
*      connected receiver XBee.  Analog values are read from a pair of
*      Joysticks to drive a left and right motor in "tank mode".
*   
*      An Adafruit motorshield is connected to the Arduino UNO to handle motor direction control.
*      The motors used are VEX motors.
*
*      XBee communication occurs through Digital pins 14 & 15 (A0 & A1) through software serial
*      in order to leave TX & RX free for serial communication and debugging purposes.  There is alot
*      of debugging read outs that can be eliminated from the code.  Sub-routines could also be used to
*      clean up the code.
*
*      Adapted from the Arduino Cookbook:  Section 14.4
*      Date:  Aug. 15, 2013
*      Author:  Mylo Hildebrand
*
***********/

#include <AFMotor.h>
#include <SoftwareSerial.h>

SoftwareSerial xbee(14,15); // RX, TX

AF_DCMotor leftmotor(1);
AF_DCMotor rightmotor(2);

void setup() {
  Serial.begin(9600);
 
  //Set the data rate for the SoftwareSerial port
  xbee.begin(9600);

  configureRadio(); // check the return value if you need error handling
}

boolean configureRadio() {
// put the radio in command mode:
  while(xbee.read() >=0 );
 
  xbee.print("+++");
  delay(100);
  String ok_response = "OK\r"; // the response we expect.
// Read the text of the response into the response variable
  String response = String("");
 
  while (response.length() < ok_response.length()) {
    if (xbee.available() > 0) {
      response += (char) xbee.read();
    }
  }

// If we got the right response, configure the radio and return true.
  if (response.equals(ok_response)) {
    xbee.print("ATAP1\r"); // Enter API mode
    delay(100);
    xbee.print("ATCN\r");
    return true;
  }
  else {
    return false; // This indicates the response was incorrect.
  }
}

void loop() {
  if (xbee.available() >= 14) { // Wait until we have a mouthful of data
  if (xbee.read() == 0x7E) { // Start delimiter of a frame

// Skip over the bytes in the API frame we don't care about
  for (int i = 0; i < 10; i++) {
    xbee.read();
  }

// The next two bytes are the high and low bytes of the sensor reading
  int leftHigh = xbee.read();
  Serial.print("HL:  ");
  Serial.println(leftHigh);
  int leftLow = xbee.read();
  Serial.print("LL:  ");
  Serial.println(leftLow);
  int leftValue = leftLow + (leftHigh * 256);
  Serial.print("AL:  ");
  Serial.println(leftValue);

  int rightHigh = xbee.read();
  Serial.print("HR:  ");
  Serial.println(rightHigh);
  int rightLow = xbee.read();
  Serial.print("LR:  ");
  Serial.println(rightLow);
  int rightValue = rightLow + (rightHigh * 256);
  Serial.print("AR:  ");
  Serial.println(rightValue);

//Drive Functions Using Analog Joysticks.  Left for left side and right for right side.
    int leftjoystick = map(leftValue, 0, 1023, -250, 250);
   
    if(leftjoystick > 50) // print stick values if either is TRUE
    {
        leftmotor.setSpeed(leftjoystick);
        leftmotor.run(BACKWARD);
    }
    else if(leftjoystick < -50) // print stick values if either is TRUE
    {
        leftmotor.setSpeed(abs(leftjoystick));
        leftmotor.run(FORWARD);
    }
    else
    {
        leftmotor.setSpeed(0);
    }
   
    int rightjoystick = map(rightValue, 0, 1023, -250, 250);
   
    if (rightjoystick > 50) // print stick values if either is TRUE
    {
        rightmotor.setSpeed(rightjoystick);
        rightmotor.run(FORWARD);
    }
    else if(rightjoystick < -50) // print stick values if either is TRUE
    {
        rightmotor.setSpeed(abs(rightjoystick));
        rightmotor.run(BACKWARD);
    }
    else
    {
        rightmotor.setSpeed(0);
    }
    delay(50);
    }
  }
}


Step 5: Test Run and Extension Considerations

So, inevitably there are details that I should have included but failed to so feel free to make a comment and I will fill in some blanks.  My hope is to take this system and make it work with multiple users like in FTC and FRC competitions.  I think the XBee is versatile and capable enough to handle 2 or even 3 students controlling one single robot as a team.  Adding extra analog or digital lines should also not be a problem to increase the functionality of any single remote.  A servo or extra motor would be a good place to start.

I hope someone reads this and comes up with something really great.  Let me know if you do.  Have a great time building.  
Remote Control Contest

Participated in the
Remote Control Contest

Arduino Contest

Participated in the
Arduino Contest