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.
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
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.
This post is really helpful. I have tried a few other online examples but this worked on the first try. Thanks
LikeLike
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!
LikeLike
Thanks Marilou, glad you like it!
LikeLike
Re: The person who created the statement that this was a good web site really needs to possess their head inspected.
LikeLike
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.
LikeLike
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!
LikeLike
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
LikeLike
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
LikeLike
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
LikeLike
When you say use 5000 and 5001, do you mean xbee sender MY is 5000 and xbee MY receiver is 5001?
Thank You
LikeLike
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
LikeLike
These are truly wonderful ideas in concerning blogging.
You have touched some fastidious points here. Any way
keep up wrinting.
LikeLike
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.
LikeLike
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
LikeLike
Serial.begin(9600);
xbee.setSerial(Serial);
LikeLike
Full of Errors
LikeLike
i want to:
Serial.println(value1);
at receive code, but i think is not correct.
LikeLike
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
LikeLike
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.
LikeLike