Playing Xbee. Part 1 – First impression.

Xbee coordinator

Xbee coordinator

Couple of days ago, I picked a pair or Xbees at Sparkfun. The plan is to build low power sensor platform using PICs, Zigbee radios, and Linux. In this article, I’m sharing my experience in building with Xbees.

The BOM includes two Xbee 2.5 RPSMA radios, Xbee USB explorer, Xbee breakout, PIC18F4520 microcontroller, and a breadboard. The code is written in C18 and built in MPLAB. Project files are available in download section.

Even though it is (presumably) possible to get two Xbees talk without any configuration, I decided not to do it. First, the firmware was old; second, I’m planning on having more than two radios. In addition to that, new stack supports firmware upgrades over the air. I downloaded X-CTU and upgraded my radios to Xbee ZB; one became a coordinator( pictured on the right ), the other one a router.

I also followed a procedure outlined in “Quick start” guide for 2.5 and performed range test to make sure radios can see each other.

For the purpose of this demonstration, I made PIC part of the setup as simple as possible. The schematic diagram of Xbee to PIC connections contains MCU itself and 10K pull-up resistor. The MCU is clocked by 8MHz internal oscillator. The USART speed is set to 9600bps. The second radio is left installed in USB explorer board and connected to Linux machine. On my Ubuntu 8.04 server I can see it as /dev/ttyUSB0. To communicate to this device I use minicom terminal emulator. Similar setup can be made on Windows; my favorite terminal emulator for this platform is Putty.

Xbee terminates a line with single CR (carriage return, or return cursor to position number one). By default, terminal emulator program won’t add LF ( linefeed, or move cursor to the next line); as a result, new output gets printed over an old one. Most terminal emulator programs has a setting for this very case called “Add linefeed” in minicom or “implicit CR in every LF” in Putty. Output of my code is also formatted this way – no linefeeds.

Flow control is essential. Xbee’s serial engine is slower than PIC; it is very easy to fill Xbee’s receive buffer and start losing data. Usual approach is to pace the transmission rate using delays; however, this also increases time when MCU is awake and, consequently, power consumption. On the other hand, using flow control signals it is possible to put MCU to sleep during CTS high (as you can see on this logic analyzer trace, given constant trasmission, CTS goes high for quite some time and we can make waiting time even longer relative to sending time by increasing the port speed).

Let’s talk about pins. I always define PIC pins that I use in a header file called project_config.h. Later I use functional names given to pins instead of pin names. For example, CTS is defined in project_config.h as:

#define CTS            PORTDbits.RD0
#define CTS_TRIS    TRISDbits.TRISD0

This way, if you decide to use some other pin as CTS, you only need to change these two lines and recompile.

The code consists of initialization, 1ms timer interrupt, serial functions and interrupts, and CLI task, which runs in endless loop. Initialization is one-time hardware setup – configuring port direction, timer3, CCP2, USART, and interrupts. Serial routines are borrowed from Fred Eady’s numerous publications in “Circuit Cellar” and his 2 microcontroller communications books. I just ported them from Hi-Tech C to C18 and added CTS flow control. They are described in great detail in Networking and Internetworking with Microcontrollersbook. Here, I just want to point to one detail. There are two places where we can check on CTS. The first place is a sendchar() function on line 8:

/* send character                                                           */
/* blocks program execution while txbuf is full or CTS is high              */
/* use with caution                                                         */
BYTE sendchar(BYTE data)
  BYTE tmphead;
  tmphead = ( USART_Tx_head + 1 ) & USART_TX_BUF_MASK;  // calculate buffer index
  while ( CTS );                                        // wait for CTS to go low
  while ( tmphead == USART_Tx_tail );                   // wait for free space in buffer
  USART_Tx_buf[tmphead] = data;                         // store data in buffer
  USART_Tx_head = tmphead;                              // store new index
  PIE1bits.TXIE = 1;                                    // enable TX interrupt
  return data;

This works well if program is not transmitting a lot of data all the time.

The second place where CTS can be checked is serial transmit interrupt routine in line 16 (commented out). Since transmit interrupt flag won’t be cleared, the program will constantly go in and out of interrupt routine until CTS de-asserts.

#pragma interruptlow lowPriorityISR
void lowPriorityISR(void)
 BYTE data,tmphead,tmptail;           //USART vars
/* USART handler start */
    if(PIR1bits.RCIF) {
        data = RCREG;                                                   // read the received data
        tmphead = ( USART_Rx_head + 1 ) & USART_RX_BUF_MASK;            // calculate buffer index
        USART_Rx_head = tmphead;                                        // store new index
        if ( tmphead == USART_Rx_tail ) {
        // ERROR! Receive buffer overflow
        USART_Rx_buf[ tmphead ] = data;                                 // store received data in buffer
    //? need to check for Tx IF
    if( TXSTAbits.TRMT /* && ( CTS == 0 ) */) {
                                                                        // check if all data is transmitted
        if ( USART_Tx_head != USART_Tx_tail ) {
            tmptail = ( USART_Tx_tail + 1 ) & USART_TX_BUF_MASK;        // calculate buffer index
            USART_Tx_tail = tmptail;                                    // store new index
            TXREG = USART_Tx_buf[ tmptail ];                            // start transmition
        else {
            PIE1bits.TXIE = 0;         // disable TX interrupt
/* USART handler end */

Xbee console

Xbee console

CLI, which runs from the main loop, checks for incoming character. If there is one, CLI branches according to the character. If no character was entered, CLI returns to the main loop and gets started again. CLI is a state machine; it remembers where it last returned from and starts from the same place next time. The menus are empty except for “Show” menu item 1; other menus are just placeholders.

Finally, I’d like to show you how the end result looks like. Build both ends of the link as described, then build and run the PIC software. If everything is correct, you will see the banner and prompt. Press “1” and prompt will change. Press “1” again and the software will print current uptime.

I will be building several different sensors based on this setup. They will be posted here as soon as they are operational. In my next article I talk about next steps in Xbee sensor development – taking measurements and switching between Xbee command and data modes.

Good luck with this project. Let me know if you have any questions or issues.


53 comments to Playing Xbee. Part 1 – First impression.

  • radu022003

    hi, please help me with xbee, i’m also interfacing xbee with 18F, 18f4550.
    I’m connected with xbee only with rx, tx and gnd. If i send data from :
    pic ->xbee ))))))xbee->pic i got huge lag. i tryed to send 0 to 9(with 1s delay between chars) in a for loop from one pic to another and i receive first 9 chars ok, but after that it stops and receiving 3-4 bytes bulk, and i lose data. i can give you the schematic, code, everything you need, please help me.

    • Have you tried to use my code? You shouldn’t get much lag – around 0.1sec, and if you insert 1sec delay between symbols, you won’t need any flow control.

  • Davidb

    I’m having a similar prob – The receiver sometimes saves up all the received bytes and then just releases them in one big lump. The first few are ok though?

    • There are several things to check. First, the packetization timeout – basically, Xbee accumulates some data before sending. It can be configured to zero, if desired. Second is the distance. I saw similar delays when Xbees were far away from each other. Also, I saw it more often when Xbees are working in AT mode; for some reason, API mode is more robust.

  • Davidb

    Hmmm, interesting.
    I have set packetisation to zero for both the co-ordinator and the end device, and the XBees are within 1m of each other! Typing one character per second works, but any faster and occasionally they get buffered and then spurted out, sometimes with one missing… Am just using two computers.

  • Boris

    Добрый день Олег!
    Пишу по русски, чтобы ты не забывал родной язык.
    Я живу в Санкт-Петербурге и работаю в Северо-Западном техническом университете. Сейчас стоит задача разработать аппаратуру для съема физиологических и биомеханических параметров (ЭКС, пневмограмма, электромиограмма, ускорения) со спортсменов во время их тренировок и непрерывной передачи их в реальном времени на ПК тренера. Дальность передачи от 100м до 1-го 2-3 км (разные вариаты), возможно с ретрансляторами.
    Исходя из твоего опыта для модулей Xbee на какую скорость передачи данных можно рассчитывать. И, очевидно, мы можем воспользоваться твоей программой программирования микроконтроллеров. Сейчас у нас наибольшая проблемма – это прогаммирование микроконтроллеров(PIC или TI).
    С уважением, Борис

  • I had same problem with using AT commands to communicate with Xbee’s After first 7~8 bytes (using PC-to-PC terminal software) I would loose any other bytes sent. Then all sudden out no where Id get the lost bytes, this time delay could be seconds to good solid minute! But it only seem happen one direction, forget if it delayed from Cord. to End point or other way around. In any case API mode is way go, really study the Datasheet/Manual, as what I am doing again today! 🙂 Once you “see” how there examples work, and perhaps try pluging them by hand into a terminal program, you will see the Xbee in API mode come alive.

    my two cents anyways…


    • Try to turn flow control on (CTS). Also, PC might simply wait for serial transmit buffer to be filled before sending/receiving the data. Many people report this kind of behavior, however, I’m yet to see one communicating between Xbee series 2 and Linux machine with flow control turned on on both sides.

  • fadh

    I use to have the same problem with my xbee. The connection is the same (with no cts) and I operate in AT mode. The problem is that I set XBEE in multicast mode (DH=0, DL=FFFF for both Xbee). It did sent data between the two but there is delay and as though the data being buffered.

    My solution is to set XBEE in unicast mode ( DH & DL of the first XBEE is the SH & SL of the other XBEE and vice versa). The data came out as expected and there was no delay. For more info on multicast and unicast plz goto

    Hope this will help.

  • andrew

    I get same problem with xbee series 2, coordinator in broadcast mode. Very unreliable transmission. Fine once destination addresses are set.

    • Eric S

      Hi Andrew,

      Did you ever solve your Zigbee (broadcast mode) losing inpuit and output data?

      I am trying to use API mode to send AT commands to set four DIO’s on multiple endpoints. The problem is that I need to broadcast one API (Type 17) packet for each DIO pin. I get a bunch of replies (Type 97 Packets), one for eaxch DIO for each endpoint. A lot of packets are getting overwritten in both the TX and RX buffers. Would using CTS and RTS pins between my arduino and the coordinator help me?

      I would really appreciate your feedback.


  • David Crespo

    Hi! I’m now at work with ZigBee modules. I’m trying to communicate a PIC16F84A and a PC with XBee pro but with no results. The problem is that the PIC doesn’t have serial input/outputs. I think that I should use your pic, PIC18F452 in order to achieve an easy connection between PIC and ZigBee. The Pic controlls two motors and I ony wanted to send the commands by Hyperterminal or X-CTU for example.
    I have read your information about PIC-Programming but I don’t understand why should I programm all that in order to implement a transparent connection (replacement of an Serial cable). Could you help me? Thanks Oleg!

    • You don’t need to do anything special for transparent connection. The only thing necessary is working serial interface on a PIC.

  • David Crespo

    Thanks, Oleg. Where could I find information to programm a PIC18F452. I want to test it with a short programm in order to implement PIC–>ZigBee–>PC communication but I have no idea about this PIC, only about PIC16F84A.

  • hugo

    i got the same buffering problem when using 2 xbee as end point (with dh/dl set to coordinator) and a coordinator( with dh and dl set to ffff). does anyone have a solution for this situation ?
    i already tried to set RO to 0 in all of my xbees, and nothing changed.

  • Have you tried to run your serial routines with RTS/CTS flow control?

  • hugo

    yes, it was my last try and i still have this issue. sometimes when sending about 40 bytes packet from coordinator, i have a 2/3 secs receiving delay in end point device. when sending the same 40 bytes packet from end point to coordinator i got no delay. i think it sould be a problem in addressing, because both of end points devices are using coordinator addr as DH and DL, and coordinator is using FF.

    do you think that i can solve this using api mode ?


    • API mode may help since in API mode Xbee is not waiting to fill the buffer – packet gets sent as soon as last byte is received from serial.

  • natanel

    Ok I think I solved some xbee problem attaching it to atmel avr32
    what do you think?
    number 3 is relevant but I wrote it all so other may use the implemantaion

    1) there is a problem in atmel mcu using usart and RTS. follow this

    Do not use the hardware handshaking mode of the USART.
    If it is necessary to drive the RTS output high
    when the Peripheral DMA receive buffer becomes full,
    use the normal mode of the USART.
    Configure the Peripheral DMA Controller
    to signal an interrupt when the receive buffer is full.
    In the interrupt handler code,
    write a one to the RTSDIS bit in the USART Control Register (CR).
    This will drive the RTS output high.
    After the next DMA transfer is started and a receive buffer is available,
    write a one to the RTSEN bit in the USART CR so that RTS will be driven low.

    remmber to pdca_disable_interrupt_transfer_complete/pdca_enable_interrupt_transfer_complete as needed.

    2) in XBEE, mcu RTS-> xbee RTS and mcu CTS-> xbee CTS

    3) there is also a problem in XBEE RTS (this was the hard one), after RTS is set there is an over head of 6 byte that will pass (if they where in XBEE RX buffer)
    so add “overhead” byte to each transmition
    in matlab code

    s = serial(port,’BaudRate’,baudrate,’DataBits’,dataBits,’Parity’,parity,’StopBits’,stopbits);
    data=[ ‘some data’];
    overhead=[ 0 1 2 3 4 5];

    % open serial
    fwrite(s,[ data overhead 1 2 3 4 overhead 5 6 overhead] ,’uint8′);

    this will do the trick

    4) as overhead is needed, the MCU RXCHR register will be full
    remmber to empty it before next pdca buffer reloading.
    if not the last overhead byte will be read

    if (usart_test_hit(TEMP_USART))

    5) this is my interupt function

    /*! \USART brief RTS setting
    #if __GNUC__
    #elif __ICCAVR32__
    #pragma shadow_registers = full // Naked.
    static void pdca_RTS_int_handler( void)
    /* This ISR can cause a context switch, so the first statement must be a
    call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any
    variable declarations. */

    // prevent re-entering
    pdca_disable_interrupt_transfer_complete( PDCA_CHANNEL_RX);

    // close !(RTS), stop transfer


    6) this is my reading code

    // clean last overhead
    if (usart_test_hit(TEMP_USART))
    // load channel
    pdca_reload_channel( PDCA_CHANNEL_RX, (void *) psParametersShadow, sizeof(xParameters));

    // Enable PDCA transfer interrupt when completed
    pdca_enable_interrupt_transfer_complete( PDCA_CHANNEL_RX);

    //set !(RTS), start transfer

    // wait read end
    while(!(pdca_get_transfer_status(PDCA_CHANNEL_RX) & PDCA_TRANSFER_COMPLETE));

    hope this will help someone

  • guy’s can u help me in preparing code for transmitting some binary sequence

  • Holger

    I’m trying to use the module zigbee UZ2400 of UBEC with pic18f26k20. The is a problem with the communication and no signal is going out. Can you help me with this?
    Thanks in advance

    • Your UZ2400 is connected to the PIC via SPI, correct? Have you been able to verify that SPI works correctly without errors – I’ve seen errors on 26k20 when SPI is clocked too fast.

  • Sachitha

    I’m planning to use xbee for a prototype sensor network with 5-6 nodes (with a pic 18F452). I want to be able to program a wireless routing protocol (simplified AODV or DSR) on the PIC to run on xbee. Is this possible?

  • suna

    Hi everyone. V r doin 8th sem proj usin zigbee series 2. V configured one as co ordinator n other as end device. Wit dh dl and sh sl interchanged. Nw how to find out transmission???

  • mat

    Hi, i’m new to xbee and i just want to know if i can connect analog voltages directly to the analog pins of the transmit xbee (without using the USART pins) and expect the voltages to show up in the receive xbee?

  • Hi Oleg,

    >>I downloaded X-CTU and upgraded my radios to Xbee ZB; one became a coordinator( pictured on the right ), the other one a router.

    Did you mean “the other one an endpoint”?


  • Spk

    I am interfacing xbee pro with pic18f452. Is the usual usart code enough for pic to communicate with zigbee? i have connected only vcc, gnd and rx,tx pins for xbee. any more pins to be used? the data sent has to be this way: pic to xbee xbee to pic.

  • Cass

    Can this code work with PIC16F877A?

  • Sansu

    Hi Oleg,
    I am using Xbee as a receiver and I use MSP430controller. From a Transmiting Radio I sent 38520 bytes data. In the first case I connected receiver end Xbee-pro directly to PC with hardware flow controlled thru software. I am receiving all 38520 bytes.

    In the second case I interfaced Receiver Xbee to the controller (MSP430) with RTS. logic is as follows

    #pragma vector=USART0RX_VECTOR
    __interrupt void usart0_rx (void)
    P2OUT &= ~0x80; // RTS low stop overflow
    pic[q] = RXBUF0; // RXBUF0 to pic array
    P2OUT |= 0x80; // RTS high;

    I didn’t connect CTS at all to controller. here i m not getting exact number of data bytes. Any help would be thankful.

  • Cass

    if i using 18F4580,this coding still work?

  • amin

    i have two zigbee pro … i want to use that at AT Command mode with pic microcontoller
    first i should send ‘+++’ to zigbee and zigbee response to me ‘ok’ … after that i dont know to do??
    please discribe for me??

  • sya

    i have a problem with xctu terminal. I have 2 xbee that to communicate between us. But now when i try to send data to other xbee at terminal rx that get data but have error together with the data.And at terminal only one CTS is green and other one is to get both CTS green.

    example at terminal xctu

    xbee1 xbee2
    send “a” receive “\…~a…w…….”
    that error i mean

    • ALI

      HI OLEG,

      I am trying to connect XBEE series 1 to connect with microchip PICDEM development board. ( The other Xbee is connected to the computer using USB.
      I connected the pins right, but I am having a hardtime interfacing the two together. basically I am just trying to test it out by sending a message from my computer to show on LCD on the development board. Can you help me regarding codes and connections

  • Roseman

    Hi man, do you happen to know the realistic range in metres of these xBee tranceivers?

  • Ilya


    I’m currently finishing my electrical engineering degree project, and what I have left to do is the wireless communication between my robot and the Altera DE2 board. All is implemented by VHDL.

    I’m using XBee 1mW Chip Antennas that are connected to Xbee Regulated. At first I had problems sending data from one to another, the received data was messed up and entirely different from what I had sent.
    Yesterday ,however, I got it somehow to work. Well,almost. In VHDL code I coded it to send start bit ‘0’ , then 8 bits (depending on some switchs on the DE2 board) and stop bit ‘1’, after that I tried using some delay, so I just sent 8 bits of ‘1’ , and then all over again (start bit,data,stop bit,delay…). Now ,the problem is:
    I connected both Xbees to oscilloscope and and what I found out is that the while the reciving Xbee receives that data(including start and stop bits) correctly, it then just repeats this data over and over until I change the data itself (switchs on the DE2 board). Although.. I did notice that the stop bit is 2 bits long, which is strange..
    There’s also a delay , or more correctly – they’re not synchronous, But it’s pretty obvious..

    Is this how that Xbee works? it ‘saves’ the data received and repeats and over and over until the sent data is changed? Why isn’t the receiving Xbee receving the ‘delay’ I created – the 8 ‘1’ bits ?

    Thank you.

    • what you see is called an echo. You can turn it off in Xbee.

      • Ilya

        Thank you.

        What are the ways to turn it off? I don’t have that USB connection on my Xbee Regulated, so I can’t connect it to a PC and use X-CTU

        In the worst case scenario, can it work that way as well? I mean I only need the first data packet, right?

        It goes like this:
        First of all, I need to send a START word, which is ‘FF'(something random I chose) to the robot (well, to the xbee on the robot) , then it sends me ACK, then I send him where to go , for example ‘A3’ , then I receive ACK , then it tells me what he found at that location , so it sends me back another packet , then I send ACK , and now I send him where to go once again and then it’s all over again and again.

        Thank you once again! (;

  • Imad

    I bought a Xbee, s1, module. it is 1mW Chip Antenna – Series 1 (802.15.4). it has built-in antenna. I tried to make a communication between PIC microcontroller and MATLAB software. It works very well at small distance e.g. 4 m but if distance becomes larger the communication signal is lost wether was inside or outside. although in the datasheet of Xbee was mentioned that the distance can be 100 m.

    also, if the xbee module is moved the signal will be lost at distance larger than 3-4 m and the uart command must be resent again to return the signal .
    I read the power level, it was at the highest level. I only changed the data rate to 115200 bit/sec.moreover, I tried xbees at 9600 bps but with same results which the signal of communication was lost at around 4m.

    I chenged (MY) of first xbee to 1 and its (DL) to 2 and (MY) of second xbee to 2 and its (DL) to 1 that means short 16- bit unicast addressing. moreover, I increased (RR) retries but it did not work too where the problem still exists

    is usually the signal between two xbee modules lost when any one of them is moved? is this normal??

    is there any configuration parameter that I should change???
    how can I communicate at 100m or even 30m outdoor ??
    I don’t know what I should do to keep the signal of communication because I’ll use xbee module for a robot ???
    would you help me??
    Thanks a lot

    • The signal does become weaker when you move away from the transmitter but it doesn’t happen that quickly. Check if you possibly block the signal with something or reset the Xbee when you touch it.

      • Imad

        I did what you tolled me to do, xbee does not reset . it is not covered by anything but what do you mean siganl blocked by something.
        moreover, I prepared a code to communicate between matlab and PIC microcontroller. Indoor, the range was 2-3 m as I said before. but when I tested outdooor, it seems like there is no signal at all 🙁
        even I put them face to face but I did not work athough it worked indoor. aftr that, I tried the test range in xctu software and it worked as at indoor place but at small range 2-3m.

        do you know what the reason for tis problem? do you that there is a malfunction in my xbee modules??

        • This can not be – xbees should work better outdoor unless you have a radio broadcast station next to your place. You’re probably missing a connection, most likely ground.

          • Imad

            I repeated the test today at outdoor and indoor place, the results were same as metioned before, below 4 m the communication is good but if the distance was larger than 4m the communication was bad, a lot of interruptions were happened espacially during moving. do you think that there is mistake in the configuration settings or in the xbee itself

  • omar

    hello ,
    i just want to know would a xbee s1 communicate with a pic16f and is there any datasheet or website that can help me with that ?

  • EZXNA1


    I am trying to transfer analog voltage values collected from a sensor to matlab using arduino. I did this experiment using USB cable and it works fine. Now i wan to establish a wireless communication and in this part i am completely clueless. Can anyone help me to have an idea about code to perform this operation using matlab and xbee. How can i configure xbee in matlab? t will be highly appreciated if i get any help from any one.