Designing a Sleeping XBee Sensor
From Digi Developer
How To Design a Good Sleeping XBee Sensor Product
This Wiki page outlines best practice at a higher-level functional level. It does NOT explain hardware design, and exists because some Digi XBee customers create wonderful designs - and a few have created stupid, unusable designs.
The basic assumption of the design outlined is that you integrate a PIC or other small controller to actually manage your sensor, then use standard serial communications to the XBee module.
Pin-Sleep vs Cycle-Sleep
Pin-Sleep - Your PIC Controls XBee
Primarily used for Xbee with 802.15.4, ZNet, Zigbee or Point-Multipoint technology.
- Offers the lowest power and longest battery life
- Allows PIC to take samples without powering up radio - could send less data when process is idle
- Your customers will require one powered fully-awake 'router' device for each eight to twelve sleeping devices
- Your PIC cycle time won't be accurate enough to use DigiMesh and sleeping routers
Cycle-Sleep - The XBee Controls Sleep
Can be used with any XBee technology - critical for DigiMesh with sleeping routers.
- Xbee suitable for DigiMesh have adjustable sleep-clocks accurate enough to keep all nodes waking at the same time
- Powered/Fully-awake routers are NOT required
- The accurate clock control increases power consumed while sleeping
So there is a trade-off between these two designs. You must consider what features are important - here are two ideas:
- If your devices will tend towards long sleeps and require no interaction, then the pin-sleep and hassle of powered routers is likely the best design. A tank farm or collection of chemical drums is an example of this system.
- If your devices will tend to be active every 10 or 15 minutes, and if the devices cooperate in a system, then the slightly worse battery life of a DigiMesh system with sleeping routers is likely the best design. An irrigation system is an example of this design.
An Ideal Example
The ideal XBee-based sleeping sensor/device does the following:
- the XBee has Zigbee End-Device API firmware.
- the PIC takes a sample using its own logic and power
- the PIC wakes the XBee and sends a serial packet in the API code 0x10 form to either MAC 00:00:00:00:00:00:00:00 or optionally a user loaded MAC. For Zigbee this goes to the "coordinator" - the Digi gateway.
- the PIC keeps the XBee awake for a user-defined time - probably in the 10 to 30 second range. This allows the host to react to the data sent, issuing other requests to the PIC or XBee.
This design can be greatly improved by having the PIC send multiple readings within one packet. Minimizing the number of transmissions by sending as much data in each packet maximizes battery life. For example, a sensor taking hourly readings could send the last 8 hourly readings every 4 hours - or 9 hourly readings every 3 hours. In the unlikely event of packet loss, this 'history' within each send allows the host to transparently recover from the problem without any "retry" scheme requiring more RF transmissions.
The use of API mode is not required. You could use AT-mode, however starting with the API-mode allows more future flexibility. For example, API-mode would enable optionally 'routing' two samples to two diverse nodes for added redundancy. AT-mode would not permit this.
Example Data Production
The world has moved away from the old master/slave poll/response paradigms. While there are many sets of jargon, perhaps the easiest to adopt is the producer/consumer model. Your sleeping sensor is a producer of data. The gateway and ultimately your customer's host application is a consumer of data. When your sensor wakes, it sends a data production out and in truth does not care if anything consumed it. In truth, it is the consumer (and YOU) who needs to solve network problems - not your small, battery powered sensor.
Here is an example data production of roughly 52 bytes which assumes the last 8 readings are repeated.
|2 to 4 bytes||Header and device status, which indicates that this is a data production. It may include a rev or data format code to allow different formats.|
|2 to 3 bytes||Running counter - your sys-ticks. This acts as a sequence count, plus helps the gateway application relate the data samples to real time of day|
|2 bytes||Sample Rate, perhaps the number of seconds (or sys-ticks) between samples|
|2 bytes||Sensor voltage. There is no reason to take this 'per sample' - once per production is fine. If you only want to send this once every 10 productions to save the ADC sampling power, define a "null" value like 0x0000 or 0xFFFF.|
|8 x 5 bytes||Eight Samples, each sample perhaps 5 bytes. Perhaps the sample consists of two 16-bit values and 1 byte of status and reading quality info.|
|1 byte||Simple XOR or addition checksum. It probably isn't required since the mesh includes many levels of checksum and retry already. But it won't hurt and will make some users feel more comfortable.|
- You might chose to save the readings in FLASH, but it might not be worth the power. Assuming some memory remains valid during sleep, your sensor could maintain a prepared message, where the 7 old samples are shifted over before the newest sample is inserted.
- There is no reason to support sending less than 8 during 'start-up'. In theory that occurs once in 3 to 5 years. Instead, define unused samples as 0x00 00 00 00 00 or 0xFF FF FF FF FF.
- There is no reason to number or time-stamp the samples. The first sample is assumed 'now', with the other seven being one sample-time in the past. If the sample rate changes, then design your PIC firmware to zero/null out the old samples. Since many host applications blindly reload configuration settings in sensors each time the application restarts, your PIC firmware must be smart enough to detect the host rewriting an unchanged sample rate, and not clear out the old data needlessly.
What NOT to do
Do NOT have the PIC wake the Xbee, then wait silently for a serial poll
This is a bad/unusable design! In contrast, your PIC and XBee MUST SAY SOMETHING anytime it wakes up. It could send an "I am Awake" message and expect the host to send a serial request/poll, however that wastes battery life. Since your PIC must say something, why not just send the most recent data?
Do NOT use broadcast
In mesh, Broadcast = Very_Bad. Yes, Zigbee has a broadcast and 1 or 2 Zigbee nodes can survive with broadcasts, but you will produce a non-scalable solution. Digi has had many customers IGNORE this, thinking broadcast is the easy way out ... they all had to redesign their protocols and systems. Either learn from their mistakes - or repeat them.
Do NOT design things to require tight timing
Avoid protocols with complex procedures where the host must do a series of steps in a tightly timed sequence. For example, a two-step reboot where the host sends the reboot command, the device sends an "Are you sure?" response and the host must send a special second confirmation within a few seconds. This design is NOT scalable. If the mesh has dozens or hundreds of devices, it is not possible for the host to reliably send a tightly timed sequence of messages because other devices are talking and also asking for service. Worse-case your device may end up in an unstable state due to lack of host follow-through; best-case the host can never accomplish the task because it can never meet the timing requirements.
Do NOT design unstable test modes
Do not require the host to reconfigure the device into a "broken mode" to initiate a test. If the host goes offline, the device may become unreachable. For example one product required the host to turn off sampling, risking the device sleeping silently (see the first DO NOT above) - and in this situation if the host got busy, the device was lost to the mesh. Instead, any request for a test should be a one-shot, where the device temporarily changes settings as required, plus starts a timer. If the host fails to complete the full test or transaction, then the device should reboot with the older operational steady-state parameters, returning to normal operations.
Do NOT treat the sample and mesh-report timers as independent
The mesh-report "timer" should be some multiple of the sample timer, so in reality you send a report after "X-th" sample is taken.
- An example of a bad design: device takes a sample every hour, and sends the last 6 samples every 3 hours. While this sounds good, the problem occurs if the time of the last sample is not related to the time of report. It is easy for the host to assume the newest of the 6 samples occurred "now" and the older 5 occurred 1 sample period ago, yet if the sample timer is independent of the report timer, then the samples might have been taken 10 seconds ago - or 59 minutes ago. It is impossible to recreate an accurate history this way.
- So a good design would have the report "timer" be checked after any sample. In this example, after the third new sample the report should be triggered. Thus the host can reasonable assume the samples occurred as-of "now". So the best configuration setting for reports is NOT how often, but after how many samples. So one sample per hour, report after 3 samples would be the better design.
Questions / FAQ
Do I need to check for collisions or busy radio traffic when I wake the radio?
No. The Xbee does this for you. You send your serial message into the XBee, and it 'fits' the message into the mesh.
Can I have the host 'Acknowledge' the data, and the PIC retry if no 'Acknowledge' is seen?
You can, but you will NOT find it useful. The XBee already does intelligent RF sense to avoid collisions and 1 retry to the parent/peer node. If the host fails to see the first send of the data, then a retry within a minute probably will ALSO fail. This is the nature of a smart mesh. Plus what if someone powers the host off for a few days? Do you really want all of your sensors retrying and cutting their battery life in half?
Won't the sleeping node's parent hold a few message for it?
Yes, but only for 28 seconds. Thus if your sensor sleeps for 1 hour and wakes up, there is little probability that any queued messages are waiting for it.
Can I use cyclic sleep on the XBee, then have the Xbee wake up my PIC?
Yes, you can. This has the big advantage of enabling support for DigiMesh and sleeping routers. It has the small disadvantage of requiring the XBee to be awake even when the PIC discovers it has nothing to say.
I don't want to use addresses; I just want to treat it like RS-485
Sorry, you can't do this. The mesh can be organized in a "virtual star/hub design", where end-devices reply to the central node without addressing (in Zigbee, the Digi Gateway). However, the gateway will need to send unicast messages to the MAC address of a single end-device.