Xbee module supports two modes of operation – transparent mode and API mode. To create simple point-to-point links, Xbee works nicely in transparent mode without much coding. However, if your goal is to build a network consisting of more than two devices, AT mode becomes too difficult to bear. You will spend almost all the time switching in and out of command mode, wasting time and draining batteries in the process. On the other hand, in API mode commands and data travel in specially formatted frames and no switching is necessary. Another advantage of API mode is that serial speed on transmitters doesn’t have to match – one can be configured for 115200bps, another for 2400bps, third left with default 9600bps. There is another nice feature called remote command; you can remotely request the state of Xbee module pins, for example, or change an output pin level. It means that for simple measuring and control applications no MCU is even necessary at the sensor.
API mode requires re-flashing module firmware and some extra coding on both sides of the link. I started with upgrading the firmware. Picture on the right shows X-CTU screen with serial speed drop-down expanded – along with loading API firmware I’m changing the speed of coordinator Xbee to 115200.
At the end of re-flashing you need to reset a module. Keep a piece of wire or a pair of tweezers handy to short reset pin to ground when asked by X-CTU. You then need to go to “PC Settings” tab and check “Enable API” to restore communications to the module.
After flashing API coordinator firmware to one Xbee module and API End device to another, it’s time to run a quick test to make sure we still can communicate. The following project contains API mode test routines, you will need to compile it, program the PIC and run. In this code I started using reset line, which runs from Xbee reset pin ( 5 ) to PIC pin RC2 ( 13 ), make sure you have it on your board.
First two functions are contained in xbee_api.c module. The first one performs Xbee initialization. Function releases Xbee module from reset on line 10 and waits for “Modem status reset” frame from the module. First ‘while’ loop on line 11 checks incoming character for frame delimiter 0×7e. After that, it grabs next 5 bytes from the USART receive buffer and compares it to “modem_reset” pattern. If everything is good, it terminates returning TRUE. After this function finishes, we can start sending data to Xbee.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /* Xbee initialization */ /* De-asserts reset and waits for modem status "reset" from Xbee */ BOOL Xbee_init( void ) { BYTE modem_reset[ 5 ] = { 0x00, 0x02, 0x8a, 0x00, 0x75 }; //modem status "Reset" frame including checksum BYTE buf[ 5 ] = { 0 }; BYTE i = 0; BYTE tmp; DWORD delay = uptime + 2000; //2 seconds from current uptime XBEE_RST = 1; //release reset while( uptime < delay ) { if( CharInQueue()) { tmp = recvchar(); if( tmp == 0x7e ) { //waiting for frame delimiter break; } } } if( tmp != 0x7e ) { //fail if no frame delimiter was received in 2 sec. Typical reset time is 300ms return( FALSE ); } while(( i < 5 ) && ( uptime < delay )) { if( CharInQueue()) { buf[ i ] = recvchar(); i++; } } if( memcmp( (const far char *)modem_reset, (const far char *)buf, 5 ) == 0 ) { //if received packet is modem status "Reset" return( TRUE ); } else { return( FALSE ); } } |
Next function is written to generate a transmit packet. It is straightforward sending of necessary bytes and calculating checksum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /* sends transmit request to addr, network */ /* 256 bytes max.payload; Xbee max.payload is 100 bytes */ void Xbee_xmit_request( BYTE *addr64, WORD network, BYTE nbytes, BYTE *data, BYTE frameid, BYTE bradius, BYTE options ) { WORD tmpword = 0; BYTE checksum = XMIT_REQ; //frame type is added since it BYTE tmpbyte; char i; char *byteptr = NULL; sendchar( FRM_DLM ); //send frame delimiter tmpword = nbytes + 14; //payload plus frame type, frame ID, addr, network, broadcast radius, options byteptr = ( char *)&tmpword; //little-endian assumed for( i = 1; i > -1; i-- ) { sendchar( *( byteptr + i )); } sendchar( XMIT_REQ ); //send frame type /* starting calculating checksum from here */ checksum += sendchar( frameid ); //send frame ID for( i = 7; i > -1; i-- ) { //send address tmpbyte = *( addr64 + i); checksum += sendchar( *( addr64 + i )); } byteptr = ( char *)&network; for( i = 1; i > -1; i-- ) { //send network checksum += sendchar( *( byteptr + i )); } checksum += sendchar( bradius ); //send broadcast radius checksum += sendchar( options ); //send options for( i = 0; i < nbytes; i++) { //send payload tmpbyte = *data; checksum += sendchar( *data ); data++; } checksum = 0xff - checksum; sendchar( checksum ); } |
Next function is a simple test sending “Hello!” string to the coordinator. It is part of the main module. The coordinator 64-bit address is all zeroes, the 16-bit address is 0xfffe. This function simply calls “Xbee_xmit_request” with necessary parameters.
1 2 3 4 5 6 | void APItest( void ) { char tmpstr[] = "Hello\r"; BYTE coord[ 8 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Xbee_xmit_request( coord, 0xfffe, 6, tmpstr, 1, 0, 0 ); } |
Finally, let’s take a look at the main routine:
1 2 3 4 5 6 7 8 9 10 11 | void main ( void ) { Board_init(); USART_init(); if( Xbee_init() == FALSE ) { while( 1 ); } while(1) { //main loop APItest(); } } |
The routine calls “Xbee_init()” and goes to infinite loop if initialization fails. This way, if something is wrong with the setup, we can catch it in the debugger. If initialization is successful, the main routine enters next infinite loop sending a packet to the coordinator.
Assuming our PIC test program is loaded and running, let’s now move to the coordinator side. The first test can be done right from X-CTU. Connect the USB coordinator with USB explorer to a PC running X-CTU, start the program, check connectivity from the PC Settings tab and switch to the Terminal tab. The following screenshot shows what you will see if your communication works. If everything is good here, we can move the coordinator to its final destination – Linux machine.
The Linux part is written in Python using pySerial module. This module is available for almost all platforms; however, it’s not part of a standard Python distribution and may need to be installed first. Connect USB explorer with coordinator Xbee to the Linux machine, open your editor and type the following text:
#!/usr/bin/env python import serial TTY = '/dev/ttyUSB0' ser_port = serial.Serial( TTY, 115200, rtscts = 1 ) print ser_port.portstr while True: if( ser_port.inWaiting() ): print( ser_port.read() )
Save the file with name ‘try.py’ and run it like that:’./try.py’. The following screenshot shows what you should see if everything works correctly. If you can see it, congratulations!
Oleg.
Related posts:


Hey, am designing P18 and zigbee based sensor network
Am using only one xbee with pic and rest 3 xbees with 3 sensors,
how to receive and distinguish the data received at PIC? please help
You can distinguish by sensor address or give them names and distinguish by name.
You can use API mode. When Xbee sends data using frame ID 0×10, receiving Xbee gets data in 0×90 frame ID. The sender’s address is part of 0×90 frame format. See doc for more info.
oleg, you say “You can distinguish by sensor address…” you mean that or you meant “You can distinguish by ZIGBEE address…”
Zigbee addresses are dynamic – that what coordinator assigns to endpoints when they register. Each radio has unique factory-programmed address, I suggested using this one because it is constant. You can configure textual name to the radio and use this name to distinguish between radios (this is going to be two step process – first your software discovers name to address relation, then use this address to get to particular radio, much like in DNS ).
I’m working on the project about Zigbee. My supervisor forces me to use the AT mode in Zigbee to set up the network among many devices, He said I didn’t need to use API mode. There is another way to do that without using API mode. He didn’t tell me about that ,he advised me to find out. Do you have any idea abou this problem.
You can switch destinations using AT commands. There is a sample code on my site demonstration going in and out of command mode. The commands to set destination are documented in the user manual. This is going to be very slow, around 3-4 seconds to switch destinations. If you have 20 end devices it would take a minute to talk to all of them. API mode is much faster when more than 2 devices are involved.
My system is very simple, I have three Zigbee modules , all of them will transmit data to one Zigbee center, it looks like multi-point to point. So if I use AT mode ,it could take nearly 10 seconds . I’m wondering that if three Zigbee modules transmit data to one Zigbee center AT THE SAME TIME.
How could the Zigbee center deal with this case in API mode?
Which one Zigbee center could choose to receive the data?
Thanks for your help
You don’t need to worry about simultaneous transmissions, it gets sorted out automagically.
Hi. I have experience with module in transparent mode, now I want use API to send data.
It’s strictly necesary have one module as coordinator and others as end devices, or only set same PAN and Channel in all’s modules?
thanks
You don’t have to set anything manually. What you need is to load coordinator firmware in one xbee, and end device firmware in other. PAN and channel would be set in coordinator automatically and end devices would join this PAN automatically also.
I’m not really familiar with the PIC18F you’re using – can you please tell me which interrupt you’re hooking for the lowPriorityISR? Is it just the 1ms timer (using CCP2)? Or is that just the highPriorityISR? Thanks!
Low priority ISR is used for USART transmissions, high priority – for 1ms timer.
Hi Oleg,
I’m working with API mode and PIC18, I have various Zigbee modules (router or End-devices) that are continuously transmitting measures to the Coordinator (this works fine), but sometimes Coordinator must send some data to a ZIgbee module and read the response to this data.
My problem is when Coordinator is sending data while he should be receiving measures, the PIC can not do both things at once. HOw do you think I could fix this? Maybe using USART interrupts??
Thanks and best regards
How many modules do you have? I never had problems with simultaneous transmission and receiving. And yes – I am using interrupt-driven serial routines in my PIC code, they work better in general so I use them everywhere.
Hi Oleg, I’ve used #INT_RDA interrupt and PICs work much better. From here I’ll always use USART interrupts for transmit and receive
Thanks
hii am using xbee connected to pic18f4520 and 3xbees with 3 sensors
how to distinguish them?? am unable to find proper
programming technique for my PIC to do so?
how to identify the received bytes at PIC am using
C programmig and mikroC compiler
please help
I think you should work with API mode.
When a frame is received by the coordinator, this frame have a field with the address of the device that transmitted it.
I want to communicate using 4 xbee.ie one coordinator and 3 end devices.The end devices must send and receive data from other end devices.How can i configure xbee.I want to use AT mode or API mode ? i am using xbee pro series2
For this scenario, I would use API mode. As far as configuration, nothing special needs to be done, just load API firmware to your modules and you’re ready to go.
I have already loaded the API firmware.But i have one doubt.If i wants to send data from end device1 to end device3 what should be Destination address.Next time if I want to send data from end device1 to end device2 how can i change the destination address.I am interfacing the zigbee device to microcontroller.Can u help me giving the document
The destination address should be address of a module where data is sent. It’s a field in any API packet, you would set it for every transmission. You need to read this -> http://ftp1.digi.com/support/documentation/90000976_D.pdf
I tried to send the API command from the microcontroller to the UART of zigbee for changing the vales of the source zibee as well as the remote zigbee, but it is not working.But when I send these commands directly from the computers serial(COM) port to the UART of zigbee it is working.I think the time taken to send API commands from microcontroller is somewhat high. What must be the time interval to send the API commands. Give me one solution to overcome this problem
I have three Xbee series 1(802.15.4) devices,and my goal is building a wireless sensor network beetween them,but i don’t know how to configure for Xbee to transmit and revieve data beetween Nodes.I only know X-CTU software for test and configure simply.So you can tell me how to do that problem,and which software should i use to do that?thanks a lot.
My system is very simple, I have three Zigbee modules , all of them will transmit data to one Zigbee center, it looks like multi-point to point.How can i configure xbee.I want to use API mode in X-CTU?
Please show me the way to load API firmware to my modules.
Thanks for your help!
Hi!I dont know how to use AS in AT command. Can you explain to me in detail. Thankyou very much!
I just finished my first project connecting avr32 with XBee
hope it can help someone.
http://snatgassensor.blogspot.com/
Oleg tried to post you first in private but didn’t found how
I’m using a PIC24HJ64GP502, I’ve configured two XBees using X-CTU to be in API mode. I’ve used libraries that have written by another person plus some of my own code for PIC24 in order to get it to write to UART_TX. I’ve connected one XBee to the PIC and the other to the comp running X-CTU terminal. The code I have creates a packet (as far as I know) and it is sending something to the XBee, but it’s not transmitting anything at all and the second XBee isn’t receiving anything, for obvious reasons. I’ve tried everything I know of, which really isn’t much, I’ve no idea what else to try.
Were you able to make your two Xbees talk in serial emulation mode? Also, are you using proper firmware, i.e., coordinator on one of Xbees, router/end device on the other?
The website below explains how to load API firmware onto your xbee. It’s not mention in the XBee product manual.
http://ftp1.digi.com/support/firmware/Instructions%20for%20firmware%20upgrades.pdf
To understand better of API modes, refer to Chapter 9 of API operation from the Xbee product manual