xbee_arduino_code

Here follows an attempt at explaining my setup for the wind-up birds, which consisted of a coordinator and 6 nodes.

Each node consisted of a xbee series 2 RF transceiver (also known as the Znet 2.5) and a minimal arduino microcontroller. Most of the time both the xbee and arduino were in sleepmode, but every five minutes the coordinator woke up every node and sent out commands to trigger sounds in rapid sequence between the nodes. After a few seconds the nodes would go back to sleep again.
The software part on the nodes was quite simple: when the xbee was woken up, one of its ouput pins would go low, which again would wake up the arduino, starting a function to create a rapid on/off signals to the attached solenoid.
The coordinator end was much more complicated.
I was fortunate to get the help from Tom Igoe to get started with deciphering the xbee series 2 commands, partly based on the xbee API-library for processing, written by Rob Faludi and Daniel Schiffmann.

Another invaluable resource was the manual from digi.com.

After getting a working system in processing, I needed to port this to the arduino platform. This meant simplifying and just keeping what I needed for my particular project. Quite a lot of the code used are only slight modifications to the original processing code.
The coordinator module was quite similar to the nodes hardwarewise, but I also used two sets of serial ports, partly to send commands between the xbee and arduino, but also to monitor the system from the outside.

There are some important differences between xbee series 1 and 2. In series 1 you can switch back and forth between AT command mode and API mode. On the xbee series 2 there is a different firmware for AT and API.
So the right firmware needs to be uploaded to each module, using the X-CTU program (windows only).
You can also configure the individual parameters for the xbee module in this program.

The series 1 modules used fixed 16-bit addresses, the series 2 uses dynamic 16-bit addresses plus a static 64-bit address. When you want to send a message from one xbee to another you need to use both the 64bit and 16bit adress of the receiver. You can use 0xFFFE if you don´t know the dynamic address, then the receiving end will send back it´s 16bit address. However this causes a significant delay in the sending of the message, and for my setup it was crucial to have as little delay as possible.

So to resolve this I made an array with the 64bit addresses and one with the 16bit addresses, and at startup the coordinator sent a nodediscovery(ND) command, thus receiving the addresses from all the nodes, and then this was put in the 16bit array, sorted in relation to the 64bit addresses. Then I could use the right 16 bit addresses when sending a message to one of the xbee nodes.

long adL[] = {0xFFFF, 0x40481E94, 0x4054458F, 0x40481E87,0x40481F56, 0x40535030,0x40481E9B,0x4053502F,0x40481F59};
int ad16[] ={
0xFFFE,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008};

there is a function for looking at the incoming packets. If it is a reply to the ND command, it breaks up the dataframe into the separate packets, for instance the 64 and 16 bit addresses:

temp16=Serial.read();
for (int i=1;i<2;i++) {        //16 bit
int thisByte=Serial.read();
temp16=(temp16<<8)+thisByte;
}
mySerial.print(temp16,HEX);
mySerial.print(” “);

for (int i=0;i<4;i++) {        //64 bit high
int thisByte=Serial.read();

}
temp64=Serial.read();
for (int i=1;i<4;i++) {        //64 bit low
int thisByte=Serial.read();
temp64=(temp64<<8)+thisByte;
}
mySerial.println(temp64,HEX);

addressUpdate(temp64,temp16);

the addressUpdate function uses the arrays declared in the beginning:

void addressUpdate(long address64,int address16) {
for (int i=1; i< nodes+1;i++) {
if (adL[i]==address64) {
ad16[i]=address16;
mySerial.println(“adress update”);
i=6;
}
}
}

The xbees are primarily made for data gathering, not for triggering, so it took some time to figure out the right way to acheive this. Unlike series 1, the series 2 can send a remote ATcommand, inside a dataframe packet. So the arduino needed to construct a wrapper for the trigger commands using the API frame packets.
This is what a API frame would look like:
xbee_dataframe

This is what the arduino function looks like. I uses an array as a template, as much of the dataframe contains the same information, exept for the addresses and command.
At the end it calculates the checksum.

void trigger(int i,int status) {

int packet[]={
0x7E,0x00,0x10,0x17,0x00,0x00,0x13,0xA2,0x00,0x40,0x3E,0x17,0xE5,0x00,0x01,0x02,0x44,0x31,0x5,0x3C    };
int current=5; //the initial bytes are identical in all packets
int frameLength=0x10;
int packetLength=frameLength+4;

status=status+4;                  //low=4, high=5

for (int b = 3 ; b > -1; b–) {        //64 bit
if(i==0) {
packet[current]=0x00;
}
current++;
//Serial.print(thisByte,HEX);
}
for (int b = 3 ; b > -1; b–) {
thisByte = byte(adL[i] >> (8*b));
packet[current]=thisByte;
current++;
// Serial.print(thisByte,HEX);
}

for (int b = 1 ; b > -1; b–) {         //16 bit
thisByte = byte(ad16[i] >> (8*b));
packet[current]=thisByte;
current++;
// Serial.print(thisByte,HEX);
}
current=current+3;                      // the next three commands are the same: 0x02,0x44,0x31
packet[current]=status;
current++;
packet[packetLength - 1]  = checkSum(packet,frameLength);

for (i=0; i<packetLength;i++) {
Serial.print(packet[i],BYTE);
}
}

This is the checksum function:

int checkSum(int thisArray[],int length) {
byte ck = 0;
// add all the bytes:
for (int i = 0; i < length; i++) {
ck += byte(thisArray[i+3]);          //+3 because we start after startframe and length bytes

}
// subtract the result from 0xFF.
// note that it should be only one byte, that’s why we
// convert it to a byte. then back to an int to return it

ck = byte(0xFF – ck);
return int(ck);
}

The basic structure of my arduino code was:
at startup, issue a node discovery command, wait for the results, update the address arrays accordingly.
check if it is day or night. If night, do nothing.
If day start the cycle:
About every 5 minutes (using previousMillis instead of delay)
wake up the nodes,
create a random trigger sequence, and execute this sequence (this is done twice).

I have included the whole code for download, maybe some parts can be useful for others. I am sure that some of the code is far from optimized, but it has worked running for over a month without any problems in my project.

I will not be able to give support on specific questions to the code.

6 Responses to “xbee_arduino_code”

  1. Controlling a xbee network using an arduino « Conversations with spaces Says:

    [...] xbee network using an arduino December 12, 2008 — hcgilje As promised some days ago, here is the followup to the minimal arduino post. I share the arduino code used in controlling a znet [...]

  2. wc Says:

    Hi..sorry I know this is an very old post..but do you still have the whole code for this project? The link you given is already dead. I am currently going to working up with a project which is much similar as this which need a coordinator and a few end device to send data. So I might get some help from the reference of the code. Would you mind to share it to me again? Millions of thanks.

    by

    Chung

  3. hcgilje Says:

    Hi, thanks for letting me know about the dead link. I recently had to clean my server completely due to malware and some files got lost. The link should be working again now.
    Mind you, this is based on the xbee series 2.
    Hope you find it useful and it would be great if you shared your result!

    best,
    hc

  4. fmc Says:

    Hi, I have a similar project that consists of end nodes based on minimal arduinos and xbees but I have found a few designs and I am not convinced yet. Can you tell me if this design is power efficient. I mean, can this node be powered with batteries and last for months?, of course considering sleep modes in both Arduino and xbee. Thanks!

  5. hcgilje Says:

    Hi, here are my energy calculations. I have had no issues with running them on battery for about a month, which is the longest I have tried.

    end device ontime
    ca 60 mA (xbee+avr) 10 sec every 5.minute (12 times per hour)
    10 sec x 12 x 24 = 2880 sec, 48 minutes per 24h, or ca 1 hour.
    30 days x 60mAh= 1.8 Ah

    constant energy consumption end device
    voltage regulator lf33: 0.6mA
    arduino sleep :0.2 mA
    xbee sleep : 0.2mA
    total 1mA x 24 x 30=0.72Ah for a month


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 174 other followers

%d bloggers like this: