ZigBee wireless networking protocol has become accepted for data
control and acquisition in medium range applications such as Home
Automation, Smart Energy control etc in small buildings and others. It has
comprehensive networking layer protocol that allows essentially
automatic formation of networks of a mesh topology, with efficient and
redundant routing algorithms built in. This is built on top of a
standardised physical and datalink protocol IEEE 802.15.4. It also
incorporates application layer protocols to ensure reliable interworking
between device manufacturers.
The XBee is a device implementation by Digi International (originally by MaxStream) which
supports IEEE 802.15.4 alone, or in conjunction with ZigBee. The XBee
versions that support ZigBee use a so-called API mode in which serial
messages are used for command and data transfer operations from a
processor to an attached XBee, which then communicates with other nodes on the network.
This page describes some of the issues encountered during a project
establish a ZigBee network. The network consisted of a Raspberry Pi
board running Linux (later replaced by a larger machine with a disk
drive) connected to an XBee coordinator, and a set of remote
battery operated nodes. The product family is the low power XBee ZB
(S2), given as XB24-ZB with latest firmware version (21A7 for the
coordinator and 23A7 for routers).
Remote Nodes Requirements
remote nodes are battery operated they must draw
the smallest current possible. This can be assisted by using sleep
modes for the XBee. An attached microcontroller is valuable for expanding the capabilities of the XBee including more comprehensive power management options. It must be used where measurements are not possible with the XBee (in
particular, counting measurements). Modern microcontrollers can be put
into sleep modes, drawing as little as a few microamps of current. The
Atmel AVR series of microcontrollers were selected for this
although many other types are possible. The microcontroller has 3.3V
power shared with the XBee, a serial connection to the XBee and a
pullup resistor on the reset pin. Connections via the
XBee digital and analogue ports are application specific, and these need to
be considered in terms of reducing power drain during sleep
One additional feature to be used in this circuit is for one
of the digital outputs of the XBee to be used as a reset for the
microcontroller. A second digital output will be used to cause the
microcontroller on reset to enter a bootloader for firmware updates.
The XBee can be put into pin-sleep mode with an output of the
microcontroller used to wake it up. The microcontroller can also be
woken up with a third output of the XBee. This arrangement will provide a variety of
recovery options in the event of hardware or software failure.
For communication with the microcontroller the XBee has
an AT mode which is easy to setup and use, and is suitable for small
networks of a star topology where point-point communications are
dominant. This mode communicates by means of ASCII strings similar to the AT modem
mode referred to as API mode uses binary packets and is more
flexible, being suited to mesh networks. It has the full ZigBee
networking and application layer protocols and includes fault
reconfiguration management capabilities. There is a second API mode
in which the byte stream includes escape characters that will allow serial Xon
and Xoff flow controls (for use where hardware flow controls are missing), and which can also assist in synchronization of
packets in channels with high error rates.
Digi provides a configuration and test utility called X-CTU which can be used to program the devices.
I found great difficulty using the original version of X-CTU as it often failed with new devices,
apparently causing them to cease to respond. Instructions to recover a "bricked" XBee are messy and require resetting the
device partway through the operations. As neither of my support boards
boasted a reset switch this became tricky. Eventually I discovered that
by setting default values in X-CTU, recycling power and programming the device several
times, it seemed eventually to recover
and even improve over time. The most recent version of X-CTU may improve on this but it hasn't been tested yet.
Two new XBees of the same type and
recent manufacture, when set to end device mode, the
associate LED would blink twice per second for a few seconds, then
start to blink about four times per second. They seemed to respond to
external transmissions, at which the LED would revert to the 2Hz
blink rate, however they would not respond to serial communications. A
check of the manual showed that for end devices the cyclic sleep mode
is enabled by default and this appears to be what was happening.
Apparently sleep mode cannot be disabled. Setting them to router mode
resolved the issue. A suggestion
has been made to change to pin sleep and ground the appropriate pin.
Another possibility is to set the sleep time to the minimum value
(320ms) and the sleep hold-off time to maximum (65s).
If pin sleep mode is used, then the SLEEP_RQ pin needs to be
forced low to keep the devices awake. This requires an external
pull-down resistor if the pin is left open.
The first thing to do is to seek out a well established and well developed library to handle the XBee interface.
- libxbee is a most comprehensive and flexible C/C++ library. It is
strongly Unix/Windows flavoured. This worked well on a small Linux
based card computer (the Raspberry Pi). It may possibly be portable to
work under an
RTOS, but would be unsuitable for smaller embedded microcontrollers
without an OS. It uses the XBee API mode 1 (unescaped binary stream)
but has mode 2 (escaped binary stream) as a compile option.
is also appears to be a good C/C++ library that is well suited to an embedded
microcontroller without OS. This uses only the XBee API mode 2 (escaped
binary stream). It will require porting to other microcontroller
xbee-api-on-arduino is a small C/C++ library written
for the Maxstream XBee devices. This library was built about 2008 and
has practically no documentation. The Maxstream devices differ from the
Digi devices in at least some of the API message content.
a Java library. This may not be suitable for the smaller embedded
microcontrollers. Although minimal Java interpreters exist for some of these
they quite have low performance and flexibility. There is also a python
library and even a
.NET library which would be unsuitable for the same reasons.
- An XBee C library for the dsPIC32 was built about 2009 as part of a separate project.
It is not a
great idea to have two different libraries in a project, but given the
different realms of applicability of the first two C/C++ libraries
above it may be acceptable to make use of these.
In the XBee manual a number of different types of frames or packets (note
the terms packet and frame seem to be used interchangeably in the
manual) refer to a packetised communication between the external
controller and the XBee over the serial interface. Between XBees the
communication protocol is likely to be quite different.
The XBee ZB supports a large number of AT commands for querying and
changing parameters on a locally attached node or in a remote node. In
API mode these commands are packaged up into an API frame. The addressed node always returns an AT response frame.
Some of the
AT commands that are useful for data acquisition are as follows:
ND requests all
attached nodes to respond with basic information. This can be used to
build a database of attached devices for later communication purposes.
NI asks a node, (addressed by its 64 bit network address if it is remote), to give its Node Identifier string.
DN ask a remote node, addressed by its Node Identifier string, to give its 64 bit network address.
The Analogue inputs are limited in range between 0 and 1.2V which is
the internal voltage reference of the XBee chip (Silicon Labs EM250).
They can range to a maximum of 1.4V. The EM250 specifies a maximum high
voltage level as the power supply voltage plus 0.3V for all GPIO input
pins. The analogue conversions are 10 bits calibrated with a factor
Internal pullup resistors should be enabled if the device is to be set
into sleep mode and no external pullup or pulldown resistors are
provided. This will reduce noise currents generated by EM induction.
The EM250 appears to set a pull down resistor for enabled ADC inputs,
and to disable the pullup resistors.
In the following, once a port has been enabled or periodic
sampling has been set, it is not possible to revert to a disabled state
(despite the manual giving the appropriate parameter to do this). The
XBee needs to be software reset.
Dx where x is a
numerical digit as follows: ADCx (x = 0..3) or DIOx (x = 0..7)
configuration as "ADC in" (2), "digital in" (3), "digital out" high (4)
or low (5).
set the pullup
resistors (30K) on selected lines. This is a bit mask for 14 lines. All
but bit 13 (DIO7 which is also CTS, an output) are enabled by default. Themask bit definitions are
not in order of the I/O number. They are defined in the XBee ZB Manual.
If pin sleep is to be used then the pullup for SLEEP_RQ needs to be disabled as it will have an external pull down resistor.
V% read the power supply voltage, scale by 1200/1024. The XBee should be working in the range 2100 to 3600 mV.
IR Enable periodic
sampling of enabled input pins. I/O samples are sent to the coordinator
on each time tick. A setting of 0 disables this, otherwise use a
setting between 0x32 and 0xFFFF ms.
IS Force sampling of all enabled inputs. An I/O sample is sent immediately.
IC Set a mask of digital inputs to be monitored for changes. An I/O sample is sent when any of these change.
The bit mask of 12 bits sets the DIO pins to monitor, but each bit will
only take effect if the DIO pin is set to digital input.
The I/O sample message returned is formatted as follows:
Number of sample sets - this is always 1 (presumably for compatibility with other families?)
- Digital channel mask (13 bits) indicating which channels have been enabled as digital I/O.
Analogue channel mask indicating which channels have been enabled as analogue input.
- 2 bytes of digital I/O according to the digital channel mask. If no digital I/O is enabled, these bytes are absent.
2 bytes for each enabled analogue channel, up to 4 channels and the supply voltage channel.
Sleep Mode Commands
SM Set sleep mode: Pin sleep (wake when an input changes), cyclic sleep (wake on timer), or both cyclic and pin sleep.
SP Set sleep period in
10ms increments from 0x20 to 0xAF0 (28 seconds max). Coordinators and
routers buffer data for a maximum of 30 seconds and can receive
commands at the end of the sleep period.
Set an additional number of sleep periods to extend sleep beyond the 28
second maximum. On waking the node should contact the coordinator to
notify availability to receive commands.
ST Set a time after the last serial or RF reception before the device enters sleep mode.
SO Set sleep options.
When waking, remain awake for the entire ST time (2). This allows
external devices time to contact the node. Sleep for the entire SN*SP
time (4). This must be set if extended sleep is required.
FR Software reset the XBee. This clears enabled ports to their disabled values but retains the network settings saved in RO memory.
After 8 weeks of operation with the PAN ID set to a fixed value, the
network stopped working. The nodes (routers) all registered reception
of network notification messages from each other, but no node
transmitted to the coordinator (as evidenced by the silence of the RSSI
LED) . Replacement of the coordinator did not change the situation.
Only after each node was reprogrammed with a different PAN ID did the
In a second event of this type the routers were programmed with a PAN
ID of 0 to encourage them to pick up the coordinator. However the
operating PAN ID remained at the old value and nothing would shift it,
except a network reset command which had to be issued over the serial interface (as the network was non-operational)..
The XBee routers can be configured to monitor the network and reset
themselves. This is done by setting the channel verification (JV
command) which looks for the coordinator on the current channel and
will leave the network if it is not found. This happens only on power
up or when joining the network. In addition the Network Watchdog Timer
(NW command) can be set to cause the routers to check for a coordinator
every few minutes and again to leave the network if the coordinator is
not found. These settings are important to ensure that the network
remains operational without the need for manual intervention. They are not applicable however to end devices.
JV Set a router to verify on power-up that a coordinator is present on the current channel, and leave the network if not found.
NW Set a timer value in minutes for a router to check for a coordinator and leave the network if not found..
is a C/C++ library useable with Linux, Windows and OS/X
for interfacing with a Digi XBee device series 1 or 2. It is well
written and reasonably well documented but nevertheless it is difficult
to work out how to use it. Some examples are provided but these are not
as well documented as the library. The interface mode is API mode 1,
using unescaped binary packets (mode 2 uses escaped characters to allow
control signals such as serial flow control to be inserted).
library uses hardware flow control by default, but that
may be disabled in the config.mk file. Some USB-serial adapter boards
do not have the flow control connections wired in.
However if that is done, care must be taken when the XBee is issued
certain commands. In particular when starting up it requires a few
seconds to get to the point where it accepts serial commands. It is
best to ensure that any adapter board has flow controls present and in
In libxbee, communication with an XBee is done by setting up an XBee
class instance and a set of connection class instances. Each connection
is used to communicate either locally to the Xbee itself, or remotely
through the Xbee remote access controls. Typically a connection would
be used to send a command and wait for received responses. Connections
are also used where the XBee receives unsolicited transmissions, typically
carrying sensor data for processing and storage. Each of these connections is associated with a particular remote XBee address.
Three examples are quite easy
to get going as a first step. "Simple AT" sends out local AT commands
and prints the responses received from the attached XBee. "Remote AT"
remote AT commands to another XBee node and again prints the responses
received. The address of that node must be specified in the program (it
can be found from XCTU). These show how to
setup a connection, send a command (with addressing for the remote
commands) and receive the response via callback functions. The "Node
Detect" example also uses a local AT command which queries all nodes in
the network and causes them to return information about themselves.
Simple Data Example
This example is
difficult to understand for a number of
reasons. It sets up a connection referred to as a "listening"
connection, and waits for transmission from a remote XBee. It is not
immediately obvious what sort of transmission is expected or how it is
This "Data" connection waits for a "ZigBee
Receive Packet". At the other end a "ZigBee Transmit Request"
frame must be sent containing the data to be communicated.
Each XBee needs to setup two separate "Data" connections, one for transmission and
the other for reception. The receiving XBee also needs to specify the
address of the remote XBee from which it expects data to arrive. This
means that the receiver will need a separate connection for each
remote XBee that sends it data, and the data retrieved will then be associated unambiguously with the sender via the connection.
One way to run a useful test is to setup the remote XBee on a second PC with the "Broadcast" example which will
send out broadcast data frames with ASCII "Hello\n\r". This
is picked up by the Simple Data example and printed.
This example sends a message on a data connection as a broadcast. Once
the data connection has been opened, all data packets sent from the
nodes will be intercepted by the callback function.
is similar to the data example except that an I/O sample Rx indication
frame is expected. This is interpreted by libxbee to provide data
fields related to enabled ports on the remote XBee. The XBee manual
doesn't mention any corresponding frame format for the remote end. This
is because the remote XBee, when
appropriately configured, will transmit data regularly or in response
triggering event. This is an autonomous operation and requires no
interaction between any external controller and the XBee.
remote XBee was setup with a potentiometer wiper connected to analogue
input A1; the voltage across the potentiometer being reduced to about
1V by a series resistor (the analogue inputs are restricted to 1.25V at
maximum range). A0 was connected to that voltage but was not used.
XBee was then configured to enable the two analogue inputs
with AT commands "D0"2 and "D1"2 (the two-digit AT command is in ASCII
while the parameter is a raw integer 2 which sets a pin as analogue
input). It was also configured for cyclic transmission of all enabled
I/O port values every second with the command"IR"1000. This
configuration could be done with XCTU but I used a custom utility for
this. The sample code was then modified to print port A1 and the
address was set to the remote XBee. In the example as at this date, the
type of the variable "value" should
be set to unsigned int to display the entire 10 bit range of the XBee
A/D converter. The printf format can be set to %u for completeness.
in the tests, once a parameter was set to a non-zero value (enabled) it
could not be reset back to zero again, although it could be changed to
another non-zero value. On reset it reverted to the default disabled
state. UPDATE: this is a result of using xbee_conTx which treats the
parameters as a null terminated string. To send parameters that may
contain zeros use xbee_connTx which specifies a general buffer and its
sets up a listening
connection and waits for a remote node to join the network. It looks
for identification indication messages. If a node has already
joined, then it will retain that status even through power
cycling.Therefore to cause an identification indication message to be
ensure that port D0 is set to "Commissioning Button" mode (default),
and briefly connect the port to ground with a pushbutton or wire.
Configure the remote XBee for analogue input as described above in the I/O example, but not for cyclic transmission.
This example sends out a remote AT command to retrieve the data. The
example uses libxbee calls to interpret the data format in the returned
message and extract the desired I/O values. Note that callbacks are not
used here, rather the received data polling call is used. In the
example as at this date, the type of the variable "value" should be set
to unsigned int to display the entire 10 bit range of the XBee A/D
converter. The printf format can be set to %u for completeness.
instance of the xbee class provides the basis for a single locally
connected XBee. More than one of these can be active at the same time
on different interfaces.
This is a Java library, unfortunately as it makes
interworking with C/C++ code more difficult. It is possible for Java to
be compiled for use with small embedded devices with slower speed and
lower memory. However it is expected that this library would be used on
a larger machine.