Home

Setting up XBees as a wireless extension of the Serial output is quite straightforward. However, for more complicated communication patterns you might need to use the XBee in API mode. For Arduino projects, there is a nice library for communicating with XBees in API mode. The following steps show how the XBee API Arduino library can be used to transmit analog signals between two Arduinos.

Setup: The setup are two Arduinos, each attached to an XBee Series 1. The Arduino on the left side reads two analog values (one from a flex sensor, one from a light sensor) and tranfers both values via the XBee to the Arduino on the right. The receiver Arduino has a piezzo speaker connected which duration of sound and frequency are controlled by the Sender-Arduino’s flex and light sensor respectively.

 

1) Configure and upload the latest firmware to the XBees. Ladyada provides a very illustrative tutorial how to do this. If you have a PC, you probably want to use X-CTU for the setup, its much less painful than working with the command line. Mac users will have to go with the command line or use a virtual machine. There is a hack to get X-CTU running on a Mac, but I haven’t tried this yet. In any case, make sure you set “API Enable” (Serial Interfacing -> AP) to 1. This will make the XBee run in API mode. Channel (CH), PAN ID (ID) need to be the same for both Sender and Receiver XBee. Select an individual 16-Bit Source Address (MY) for each XBee, e.g. 5000 and 5001. These values are later used in the Arduino-code to address where individual value packets need to be sent to.

Upload latest firmware and configure your XBee with X-CTU

Upload latest firmware and configure your XBee with X-CTU

 

2) Connect your XBee Sender and Receiver each to an Arduino. I used the XBee Explorer Regulated Board from Sparkfun, but you might as well use Adafruit’s Adapter kit. There are 4 wires you need to connect between the XBee and Arduino: GND to GND (ground), 5V to 5V (power), DOUT to RX, DIN to TX

XBee Series 1 on Sparkfun's XBee Explorer Regulated

XBee Series 1 on Sparkfun's XBee Explorer Regulated

3) Connect two analog sensors to A0 and A1 of the  “Sender-Arduino”. For this demo I used a flex sensor and a light sensor. You can use any analog sensor or device that spits out values between 0 and 1023. Use analogRead() to read the data coming from these sensors. Find detailed circuit descriptions for reading analog values at Ladyada and here.

4) Connect a piezzo buzzer to pin 10 of the “Receiver Arduino”, and its other leg to GND (make sure you use a PWM pin, i.e. 3,5,6,9,10 or 11).

5) Upload following code to the “Sender-Arduino”:

#include <XBee.h>
//--- XBEE-SETUP ---------------------------
 XBee xbee = XBee();
 unsigned long start = millis();
// allocate two bytes for to hold a 10-bit analog reading
uint8_t payload[7];
// payload array lenght needs to be at least one higher than the number of bytes to be transmitted
// 16-bit addressing: Enter address of remote XBee, typically the coordinator
  Tx16Request tx_5001 = Tx16Request(0x5001, payload, sizeof(payload));
  TxStatusResponse txStatus = TxStatusResponse();

//values to be transmitted 10 Bit, i.e. (0-1023)
int value1 = 0;
int value2 = 0;
int statusLed = 11;
int errorLed = 12;

void setup(void)
{
// initialise Xbee feedback LEDs
 pinMode(statusLed, OUTPUT);
 pinMode(errorLed, OUTPUT);

 xbee.begin(9600);

 Serial.begin(9600);
}

void loop(void)
{ 

 // start transmitting after a startup delay. Note: this will rollover to 0 eventually so not best way to handle
 if (millis() - start > 5000) {

 value1 = analogRead(0); //read from pin0
 Serial.print("Value 1: ");
 Serial.println(value1);

 value2 = analogRead(1);
 Serial.print("Value 2: ");
 Serial.println(value2);

 //value1 INTO PAYLOAD
 //break down 10-bit reading into two bytes and place in payload
 payload[0] = value1 >> 8 & 0xff; // payload[0] = MSB.
 payload[1] = value1 & 0xff; // 0xff = 1111 1111, i.e. cuts of the MSB from pin5 and all is left is the LSB

 //value2 INTO PAYLOAD
 payload[2] = value2 >> 8 & 0xff;
 payload[3] = value2 & 0xff; //LSB

 xbee.send(tx_5001);
// flash TX indicator
 flashLed(statusLed, 1, 100);
 }

 // after sending a tx request, we expect a status response
 // wait up to 5 seconds for the status response
 if (xbee.readPacket(5000)) {

 // got a response!
 // should be a znet tx status

 if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {
 xbee.getResponse().getZBTxStatusResponse(txStatus);

 // get the delivery status, the fifth byte
 if (txStatus.getStatus() == SUCCESS) {

 // success. time to celebrate
 flashLed(statusLed, 5, 50);
 } else {

 // the remote XBee did not receive our packet. is it powered on?
 flashLed(errorLed, 3, 500);
 }
 }
 } else {
 // local XBee did not provide a timely TX Status Response -- should not happen
 flashLed(errorLed, 2, 50);
 }

 delay(2000);

}

void flashLed(int pin, int times, int wait) {

 for (int i = 0; i < times; i++) {
 digitalWrite(pin, HIGH);
 delay(wait);
 digitalWrite(pin, LOW);

 if (i + 1 < times) {
 delay(wait);
 }
 }
}

The sensor data are stored into the value 1 and value 2 variables. As these sensor data are analog, they can have a value from 0 – 1023, i.e. max 10 bit. Note that the data to be transmitted is stored in a byte array, i.e. each index value in the array holds 8-bit. Therefore each sensor value needs to be saved across two index values least significant bit (LSB) and most significant bit (MSB) in the array, e.g.

 payload[0] = value1 >> 8 & 0xff; //MSB
 payload[1] = value1 & 0xff; //LSB
 payload[2] = value2 >> 8 & 0xff; //MSB
 payload[3] = value2 & 0xff; //LSB

These will be put together on the receiver side again.

6) Upload following code to the “Receiver-Arduino”:

#include <XBee.h>
// XBEE setup -------------------------------
XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();
int pinSpeaker = 10;
// LED indicating XBee status
int statusLed = 4;
int errorLed = 3;
int dataLed = 5;
// XBEE setup -------------------------------
void setup(void)
{
 pinMode(statusLed, OUTPUT);
 pinMode(errorLed, OUTPUT);
 pinMode(dataLed, OUTPUT);

 pinMode(pinSpeaker, OUTPUT);

 xbee.begin(9600);
 flashLed(statusLed, 3, 50);

}

void loop(void)
{
 xbee.readPacket();

 if (xbee.getResponse().isAvailable()) {
 // got something

 if (xbee.getResponse().getApiId() == RX_16_RESPONSE || xbee.getResponse().getApiId() == RX_64_RESPONSE) {
 // got a rx packet

 if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
 xbee.getResponse().getRx16Response(rx16);

 //READ VALUE1
 uint8_t analogHigh = rx16.getData(0);
 uint8_t analogLow = rx16.getData(1);
 int value1 = analogLow + (analogHigh * 256);

 //READ VALUE2
 uint8_t analogHigh2 = rx16.getData(2);
 uint8_t analogLow2 = rx16.getData(3);
 int value2 = analogLow2 + (analogHigh2 * 256); 

 playTone(value1, value2);
 delay(value1);

 flashLed(dataLed, 3, 50);

 } else {
 xbee.getResponse().getRx64Response(rx64);
}

 flashLed(statusLed, 1, 10);

 } else {
 // not something we were expecting
 flashLed(errorLed, 1, 25);
 }
 }

}
// duration in mSecs, frequency in hertz
void playTone(long duration, int freq) {
 duration *= 1000;
 int period = (1.0 / freq) * 1000000;
 long elapsed_time = 0;
 while (elapsed_time < duration) {
 digitalWrite(pinSpeaker,HIGH);
 delayMicroseconds(period / 2);
 digitalWrite(pinSpeaker, LOW);
 delayMicroseconds(period / 2);
 elapsed_time += (period);
 }
}
// flash control LEDs to indicate status of the XBee
void flashLed(int pin, int times, int wait) {

 for (int i = 0; i < times; i++) {
 digitalWrite(pin, HIGH);
 delay(wait);
 digitalWrite(pin, LOW);

 if (i + 1 < times) {
 delay(wait);
 }
 }
}

Note how the least significant bit (LSB) and most significant bit (MSB) are put together again.

 uint8_t analogHigh = rx16.getData(0);
 uint8_t analogLow = rx16.getData(1);
 int value1 = analogLow + (analogHigh * 256);

The playTone(long duration, int freq) method plays a tone on the piezzo speaker with a set duration and frequency. The first value received from the Sender-Arduino sets the duration, the second value the frequency. When we bend the flex sensor or cover the light sensor, the piezzo speaker changes the length and frequency of its tone respectively.

For more information on XBees and the XBee API check out O’Reilly’s Wireless Sensor Networks book. It provides probably the best introduction and documentation of how Zigbees and XBees work.

19 thoughts on “How to wirelessly transmit analog signals using the Arduino XBee API?

  1. Hi! I’ve been reading your site for a while now and finally got the courage to go ahead and give you a shout out from New Caney Texas! Just wanted to tell you keep up the great job!

    Like

  2. I’m impressed, I have to admit. Rarely do I encounter a blog that’s both
    educative and entertaining, and let me tell you,
    you have hit the nail on the head. The issue is something which too few people are speaking intelligently about.
    I am very happy that I found this during my hunt for something
    relating to this.

    Like

  3. Excellent blog you have here but I was curious if you knew of any
    discussion boards that cover the same topics talked
    about here? I’d really like to be a part of community where I can get opinions from other experienced individuals that share the same interest. If you have any suggestions, please let me know. Thanks a lot!

    Like

  4. thank you for sharing your work!
    I’m studying these modules xbee and are interested in the transmission of multiple variable values​​.
    your work is very helpful me.

    to reciprocate, I have posted on my facebook diary a small code that decodes 2 RC channel , and driving 2 + 2 differential PWM outputs.
    useful for controlling hydraulic valves or with a small change to the code, power H bridges.

    thanks
    greetings
    Salvatore

    Like

    • Hey my friend we should share, where could I take a peek at you sketch? I have mine completed filtering the analog to pwm also , just wanted to see if I could make it better.

      lets share if you are interested, I am currently trying out this instruction to pass analog input to receiver and then filtering to pwm pins on arduino

      http://www.youtube.com/user/fabiolus2007

      Like

  5. This is great instruction, 1 question what would be the setting for the xbee receiving and do you plug the GND to GND (ground), 5V to 5V (power), DOUT to RX, DIN to TX on the receiver as well?

    I have a similar setup and I want to capture the analog signal X&Y from joystick similar to what you demonstrated then transport the analog values captured to the xbee receiving and run them in the arduino receiving so it can calibrate the joystick through my sketch then output both signals to PWM pins from Arduino receiving.

    Cheers
    Fab

    Like

  6. Can someone please help me with the sender code? These are the errors I’m getting…
    sketch_sep25a:3: error: ‘XBee’ does not name a type
    sketch_sep25a:9: error: ‘Tx16Request’ does not name a type
    sketch_sep25a:10: error: ‘TxStatusResponse’ does not name a type
    sketch_sep25a.ino: In function ‘void setup()’:
    sketch_sep25a:24: error: ‘xbee’ was not declared in this scope
    sketch_sep25a.ino: In function ‘void loop()’:
    sketch_sep25a:52: error: ‘xbee’ was not declared in this scope
    sketch_sep25a:52: error: ‘tx_5001’ was not declared in this scope
    sketch_sep25a:59: error: ‘xbee’ was not declared in this scope
    sketch_sep25a:64: error: ‘TX_STATUS_RESPONSE’ was not declared in this scope
    sketch_sep25a:65: error: ‘txStatus’ was not declared in this scope
    sketch_sep25a:68: error: ‘SUCCESS’ was not declared in this scope

    Like

  7. this is very nice tutorial, but sir i am confused about zigbee my address. how can use zigbee my address in other microcontrollers programming because i am using PIC controller, sir i wan to send two analog and many digitla values using zigbee, is it possible, sir please help me i am working like this college project.please help me.

    Like

  8. Hi, this is exactly what I am trying to achieve but I get this conversion error. Can someone point me in resolving this?

    kavas.ino:25:17: error: no matching function for call to ‘XBee::begin(int)’
    kavas.ino:25:17: note: candidate is:
    In file included from kavas.ino:1:0:
    C:\Program Files\Arduino\libraries\XBee/XBee.h:706:7: note: void XBee::begin(Stream&)
    void begin(Stream &serial);
    ^
    C:\Program Files\Arduino\libraries\XBee/XBee.h:706:7: note: no known conversion for argument 1 from ‘int’ to ‘Stream&’
    Error compiling

    Like

  9. Hi I am trying the same with ACS712 Current sensor of 5A…Please can u show the circuit diagram here….I am kinda unclear here of how the buzzers and the LEDs Have to be connected

    Like

  10. It would be wonderful if just once a program would compile without a multitude of errors, which this program certainly has in spades. I appreciate you taking the time to post this sketch, I only wish it worked.

    Like

Leave a comment