Wednesday, September 28, 2011

Controlling XBee IO lines with ZigBee commands

Summary: this post explains to send remote AT commands to an XBee module using ZigBee commands. The end point, profile ID, cluster ID and command and response format is documented. This is useful if you need to control a XBee's IO lines from a non-XBee device.
The Digi XBee Series 2 module. 
The Digi XBee module is a popular RF module featuring a UART and several IO lines that can be configured as input/output or in some cases ADC or PWM. The "Series 2" version of these modules can be flashed with ZigBee compatible firmware. The modules then participate in a ZigBee mesh network.

The modules are configured and controlled by  AT commands (like the modems of old) which are issued through the module's UART by a computer or microcontroller. There are two varieties of the firmware: AT mode and API mode. The latter provides access to more advanced features of the module.

One feature of the API mode is the ability to send AT commands to remote XBee modules. This can be used to control relays, read the state of switches, read temperature etc. This in theory allows many small control applications to be accomplished with nothing more than a XBee module on it's own -- no need for an attached microcontroller.

There is a problem however. All the examples and documentation I've seen to date (I may very well have missed something, but not for the lack of trying) only cover controlling a XBee module through the XBee API. So if your interface to the ZigBee network is not a XBee (or equivalent Digi product) you're out of luck. In my case I have a Texas Instruments CC2530 based USB dongle and I require that software running on a computer control the state of a remote XBee's IO lines.

So, reverse engineering time! I wrote scripts to control the XBee digital IO lines from another XBee, and simultaneously ran a 802.15.4 packet sniffer. This is what I learned:

For remote AT commands the sending XBee issues a ZigBee command to the remote XBee on endpoint 230 (0xE6), with profile 0xC105 (Digi private profile), cluster 0x0021. The command is formatted as follows:

0x00, 0x32, 0x00, frame-id, sender-ieee-addr, 0x00, 0x00, atcmd0, atcmd1, [param]

frame-id: one byte API frame ID used in many XBee API calls
sender-ieee-addr: the 64 bit IEEE address (8 bytes, the most significant byte first)
atcmd0: the ASCII code of first character of the AT command (eg 0x4d or 'M' if command is ATMY)
atcmd1: the ASCII code of the second char of the AT command (eg ...)
params: zero, one or more optional parameter bytes

For example: to send ATMY (get 16 bit network address) the command will be:
0x00, 0x32, 0x00, 0x0f, 0x00, 0x13, 0xa2, 0x00, 0x40, 0x3c, 0x15, 0x5c, 0x00, 0x00, 0x4d, 0x59

The bytes with values 0x00 and 0x32 may have some significance, but I have no idea what it might be. I'm not sure if the sender IEEE address is important. It seems to work the same no mater what address I use.

Responses are sent on cluster 0x00a1. In response to the ATMY command I get:
0x0f, 0x4d, 0x59, 0x00, 0xd1, 0xed

So that seems to be:
frame-id, atcmd0, atcmd1, 0x00, atresponse...

The XBee digital IO lines are configured with the ATDn commands, where 'n' is the number of the IO line. The lines can be configured as input, output low, output high, analog and PWM (not all lines are capable of all the functions). The two functions that are of interest to me are output high (parameter value 5) and output low (parameter value 4).

Note: there is potential for some confusion encoding AT commands. Take for example the command ATD04. What this means is AT command D0 with parameter 4.  The digit 0 in the command part is encoded as the ASCII code ie 0x30, but the digit in the parameter part (4) is the byte value 0x04. So the command and parameters is encoded as 0x44, 0x30, 0x04.

Other clusters in endpoint 230 have other functions, which I'll document in another post.

Update (2 Oct 2011): Small edit. I omitted the frame-id in the format of the AT command response.

4 comments:

YM said...

Joe,

Thanks for sharing you knowledge. I have recently purchased a XBee sensor which run this Digi profile C105 on E6. As it does not run the zigbee public profile I have no idea how to read the measurement of this thing. Do you know of any documentation on this C105 profile?

Thanks,
YM

Joe Desbonnet said...

YM: I looked very hard for documentation on this and found nothing. Questions relating to this on Digi's forums were unanswered. The good news is that it seems to be easy to reverse engineer if you have a packet sniffer. If you can setup two XBee modules to do what ever it is your interested in through their proprietary API and see what's going on the air you can quickly figure the protocol. My blog post covers sending AT commands. I'll try to update with some of the other features (ADC readings etc soon).

YM said...

I've found a C105 related Cluster list in their python ESP suite. It seem like the XBee sensor only support 0092 and 0011 cluster and their still remain the question on what the attributes are...anyhow

I agree your suggested method is the most direct way to find out. Since the XBee sensor is the only Digi I have, what other Digi ZB product would you suggest for reading off the sensor?

Joe Desbonnet said...

YM: if, for example, you wanted to get regular ADC readings from a remote XBee, then setup one XBee as network coordinator, associate the remote XBee to the network. Then use Digi's API and documentation to implement regular ADC readings from the remote XBee to the coordinator. (O'Reilly's 'Building Wireless Sensor Networks' book is a good introduction to this). Run this for a few seconds while monitoring packets with a packet sniffer. Hopefully you will then see what needs to be sent over the air to the remote XBee and how the data is returned. You can then implement those commands using another manufacturer's ZigBee API.

That's the nature of the sensor? Is it using the XBee's ADC or is it a digital IO (on/off) type sensor?