TL;DR: By using Xbee pin sleep, I was able to bring my board power consumption from 100mA-ish to 35mA-ish average by ensuring that the Xbee radio is off most of the time (unfortunately, it doesn't have a mode where you can just have it be send only and wake up the RF radio only when you give it serial data).
Longer version:
I've been using my Mobsendat Board to log my [sleep positions|], and both for fun, and because I'm lazy, I've been using Xbee to send data from the mobsendat to my PC.
I used some Xbee Pro modules because I wanted to get as long a range as possible, and because the data may have to go through my body, which is some kind of RF shield.
First, I tried the Xbee 1 modules, because they were easier to get and a bit easier to program since more people were using them. My mobsendat board was using 33mA and with the Xbee 1 module, would go between 80 and 110mA. This is of course a fair amount of power.
I then upgraded the modules to Xbee 2.5 ZB Pro modules, and that shaved off 10mA or so. It was however clear that I would have to put the modules to sleep to save further.
To do this, I used some of the free pins on the AT mega 328, and wired up:
AT Mega Pin 14 (Digital 8) -> Xbee DTR
AT Mega Pin 16 (Analog 2) <- Xbee RSSI
AT Mega Pin 17 (Analog 3) <- Xbee Assoc
The Xbee was flashed with the latest ZB end device AT firmware with pin sleep (be careful, the default setting of cyclic sleep puts the module to sleep as soon as it's flashed, so even X-Ctu can't re-read its settings without having the module be reset). See my page Xbee Adapter page with reset pin hack.
I left the pullup resistor enabled in the Xbee, so I was able to use simple wires to connect the pins.
Xbee sleep works like this: bringing DTR up puts the module to sleep if it's not in the process of sending/resending data (that's nice, you don't have to worry about waiting for an ACK which you can't read in AT mode before putting the device to sleep, you can just fill its buffer, give it the sleep signal and it'll go to sleep when it's done sending).
This works great: by putting the module to sleep for 95% of the time or so (I transmit every 5 sec), the power use goes back to 33mA for most of the time (with quick peaks to 100mA during send).
Now, for how to deal with sleep more intelligently:
If you have AI/RSSI LEDs and your module is not associated, you can easily see that sleep will not put the module to sleep after sending data until all the retries have failed.
In my case, I wired the RSSI and Assoc outputs to my arduino inputs so that I could read the analog values. If you're sending data from an end device, you can read RSSI as a poor's man ack value by keeping track of last time it was high (defined as between 32 and 1024 on my system since it a signal strength value and anything below 32 has been noise in my experience). What this means is that by reading RSSI multiple loop cycles in a row, I can detect when I'm not receiving any data (and therefore missing acks) and not put the module to sleep at all with the hope that it will "reconnect" on its own.
One might thing that you can read the Assoc value to guess whether AI=0 (associated) or not. Note that the LED actually shows solid when not associated and will blink when associated, so it's not as easy as just getting an on/off value. To deal with this one, I actually read the LED output value multiple times, average it, and if it's flashing, I'll get less than 800 avg (out of 1024).
Now, this is where it gets more counter intuitive: AI (association) unfortunately does not go back to unassociated when I remove the router or coordinator in my network. What this means is that I can't detect if my module can't talk to the network by using AI (only getting ACK return values can really tell me that, and I'd have to switch to API mode for that). But, there is a trick: if the module is waiting for ACKs, it will not go to sleep, and AI will normally flash. When that happens, I will read Assoc analog values that are less than 800 and by averaging a few, I can tell that the LED is flashing and therefore that the module isn't going to sleep.
Neat, eh?
This is what my data looks like when I have RF issues:
"2011/05/24 05:53:29",,X:0.13,Y:-1.00,Z:0.11,V:4.96,left,rssi:904(DC:0),assoc:847(avg:844)
"2011/05/24 05:53:34",,X:0.15,Y:-1.00,Z:0.14,V:4.92,left,rssi:904(DC:0),assoc:844(avg:844)
"(DC:4),assoc:0(avg:337|ANS)
"2011/05/24 05:53:59",,X:0.14,Y:-1.00,Z:0.13,V:4.97,left,rssi:0(DC:5),assoc:842(avg:337|ANS)
"2011/05/24 05:54:04",,X:0.14,Y:-1.00,Z:0.12,V:4.97,left,rssi:0(DC:6|RNS),assoc:842(avg:336|ANS)
It shows rssi dropping to 0 with DC:5 (down count due to RSSI being 0), and assoc average having dropped from 844 to 337 (we don't see instant low assoc values since they were not transmitted outside of the truncated line).
Next step is lowering down the Mobsendat power base consumption from 33mA to 12mA by simply disabling two of its status LEDs. |