Sunday, July 3, 2011

XBee Enabled Joystick, part II

This is a continuation of XBee Enabled Joystick, part I, that involved the physical hacking of the joystick. Part II consists of setting up the XBee to spit out sensor data from the joystick to another XBee.

Alright, it has been awhile, but I decided to finally finish off this project. Sort of. For today, I will just be doing something simple with the final result, eventually, I may even hook the XBee enabled joystick up to something that moves.

What is an XBee anyway?

Before I begin, I'm going to explain a little about what an XBee really is. Most people think of XBees as wireless modems, and not much more. XBees do much more, however, than just act as a modem, transporting bits from here to there.

First, XBees contain a processor, which takes care of the communication processing, taking care of packet routing, buffering data, power management, and more. Now, if you are putting a micro processor into something that has ADCs, PWMs, GPIOs and more, why not use them? For this reason, the XBee can do much more than just act as a method to communicate. Some of the later versions of XBees even allow you to load and execute your own code in the spare memory.

With all the extra functionality, Maxstream hoped that the XBee could function on its own without an additional processor to carry out simple tasks, such as reading sensor data.

First steps first, configuring the XBees to talk to each other. For this, I will simply be setting them up with short 16 bit addresses that point to each other. Perhaps in the future, I might do a post more in depth about configuring XBees with coordinators and such.

For this tutorial, I assume you have either an XBee Explorer, XBee dev kit, or some other way to connect directly to the XBee to change settings and whatnot.

Wiring up your Joystick to an XBee

If you've completed the basic steps in the first part of the XBee Enabled Joystick, connecting an XBee to your joystick should be straight forward. Just connect the analog outs to the ADCs on the XBee, and the digital buttons to the remaining available digital inputs on the XBee. Supply 3.3V to the XBee and to VREF, and you should have every connection you need. You can add some .01uF to .1uF capacitors between the the analog input pins and ground to reduce noise.

Setting up the Joystick XBee

  1. First things first, open up handy X-CTU. I don't have a working install of windows right now, so I will be running X-CTU through wine. It seems to work fine! The only thing you have to do is create a user defined COM port pointing to the USB COM created in wine.

  2. Make sure that you can communicate with your XBee. Select the COM port in X-CTU and click the 'Test / Query' button. You should get a box that looks like this

  3. Next, click on the 'Modem Configuration' tab. Click the 'Read' button to load the settings on the XBee. I will assume that you are starting with the default settings. You can click 'Restore' to return all the settings back to default.

  4. The first setting we want to change is to select a PAN ID (ID). The specific PAN ID isn't important, I have chosen 4343. You will need the PAN ID to set up the receiving XBee once you are done. The PAN ID is something like the network ID.
    Don't write the settings, yet. We will do that once we change everything we need.
  5. Now, we need change the destination (DL) and source addresses (MY). For simplicity, I will just use 16bit address, so make sure the DH is set to 0. I set my DL to 513 (we will use this later, so remember it) and MY to 512. The destination settings determines where data is sent, while the source address determines which data this XBee will listen for.
  6. I always add a node identifier (NI) for all my XBees. A node identifier is just a short string that is a meaningful name associated with a specific XBee. Set this to 'JOYSTICK' for now.
  7. Now we get to the complicated part. To set up the XBee as a wireless sensor, we need to set each pin to either digital input or analog input. How you set up the XBee depends on how your joystick is wired. I am using pins 0 to 3 as ADC, and the rest as DI.
  8. Last IO setting to change, we need to set the sample rate (IR). The number you put here will be how often a sample is taken and sent to the receiving XBee that we specified earlier. Set it to 3E8 for now, which is 1000 in hex. Later, once everything works, you can change this to a smaller number for a faster update rate. Just remember, though, that your sample rate will be limited by the interface baud rate on the receiving end.
  9. Alright, we are almost done. At this point, you can click the 'write' button. Now, all of the settings will be saved to the XBee. If you please, you can save this profile if you want to use it again later.

Voila! Your XBee is now configured to read info from the joystick and send the data to the receiver. You can now hook up this XBee to your joystick.

Configuring the receiving XBee

  1. With the other XBee hooked up to communicate to your PC, go to the 'Modem Configuration' tab in X-CTU.
  2. Click the 'Read' button. Again, start with the default settings.
  3. We want the PAN IDs of the two XBees to match, so change the ID setting to 4343, or whatever you selected for the Joystick XBee.
  4. Now, we need change the destination (DL) and source addresses (MY). Make sure the DH is set to 0 to ensure 16 bit addressing. Set the DL to 512 (This should be the MY setting for the Joystick XBee) and MY to 513 (the DL from the Joystick).
  5. Set the NI for this XBee to 'RECEIVER' for clarity.
  6. Hit the 'write' button and save the profile if you want to use it again later.

That is it! Now, it's time to test things out and make sure we are getting data from the joystick.

With the receiver XBee still connected to the PC, choose the 'Terminal' tab in X-CTU. With everything powered on and hooked up correctly, you should see data coming in once per second.

Dissecting the packet

With the XBees set up as I outlined, the data should come in an API mode packet, specific for I/O data. Lets look at one that pulled out.
Packet Data:  7E 00 12 83 05 12 28 00 01 1F F0 01 50 02 46 02 29 03 FF 01 AA BC
Byte:          1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22

Compare this data to the outline of an API frame

All API frames begin with 7E.

The next 2 bytes tell us the length of the packet data. Here, it is 00 12, or 0x0012, which equals 18 bytes.

The next byte contains the API identifier, in this case 83, or 0x83. According to the XBee manual, 0x83 identifies the packet as a 16 bit addressed RX packet containing I/O data. So far so good.

Lets look at the format of this packet

Bytes 5-6 tell us the source address. For our packet, 05 12 or 512, which is correct.

Byte 7 tells us RSSI, 28, which means 0x28 -dBm. Lower means a stronger signal. Because my two XBees are close together, -40 dBm seems good.

Byte 8 tells us the options used for this packet. Our packet reads 00, all still good.

Now things get interesting. Take a look at the format for an I/O data header.

Byte 9 tells us how many samples are included in this packet. 01 for us means, well, 1 sample.

The next two bytes, bytes 10 & 11, tells us which channels are active in this sample. We got 1F F0, or in binary 00011111 11110000. According to the manual, this packet contains ADC samples for channels 0-3 and DIO data for D4-D8.

Now, it is time to chew through the actual data.

So, the next two bytes, bytes 12 & 13 (0x0150) contain the digital input data. For the joystick, this means every I/O line is pulled high, and no buttons have been pressed.

Finally, we are to the ADC readings. For every channel marked active in the IO data header, there will be a 16 bit reading for that ADC channel. In our case, 4 channels are active, so there should be 8 bytes, starting at byte 14, containing ADC readings. Converting those values from hex to decimal,

A0: 02 46 = 0x0246 = 582
A1: 02 29 = 0x0229 = 553
A2: 03 FF = 0x03FF = 1023
A3: 01 AA = 0x01AA = 426

Guess what? That looks great! XBees use a 10 bit ADC, meaning the values should range from 0 to 1023. A2 isn't connected to anything so it reads the maximum value. All the other axis were roughly centered, which means the other ADC channels appear to be correct!

The final byte is a checksum, which you can ignore for now.

What is next?

For the XBee enabled joystick to be useful, you'll have to up the interface data rate on the XBees and increase the sample rate. Once you get that working, you'll be ready to go.

Now that you have an XBee enabled joystick, you need something to control with it.  Hopefully soon I will have a video and a follow up post with some application.


  1. Could you explain me why didn't you use a regular I2C to coomunicate eachoder the xbees? is it beause you didn't use the tx and rx comunication pins?

    Because I didnt understud well about the API.

    1. The XBees can act as a standalone client. In client mode they autonomously read (without the need of another computer to talk to the XBee) I/O pins, reporting the I/O pin status wirelessly to another XBee (the server). Those messages come out the at the server on the Rx/Tx pins.

      The API mode just wraps messages that the XBees send to each other that go through the Rx/Tx lines in a nice frame. The message framing allows you simpler access to some of the functionality without having to use the modems 'AT' commands. The API also provides additional feedback to see if your messages made it to their destination, RSSI values, the source of incoming messages, and more.

      If you just use the XBees as point to point wireless serial links, the API mode may not make a lot of sense. In more complex topologies, the API mode is essential.

      Does that help clarify why to use the API?

    2. Sure! and I'm reading some manuals to understand well the API, I'm doing an hexacopter which to be driven by RC, and with this blog you have just saved me of buying an arduino.

      I'll be doing my work and perhaps I'll be here again to ask you some other questions.

      Thank you very much for your time!

  2. This comment has been removed by the author.

  3. Is there any way I can get a copy of your xbee files? I cannot get mine to communicate with each other.

    1. It might take a bit before I can dig them up, but I'll see if I can find them and append them to the post.

  4. Hi!
    Can you share your code for this project?

  5. Check out the overview of the project,

    Part III has the code

  6. if i want to read 4 adc readings..what edition should i do in the code,as i am new in this please help me out.
    Actually i am using your code in my quadcopter