When you run a project on battery, you are always thinking on how to conserve power so that you run longer. In the case of wireless remote nodes you do that by sleeping a lot and only waking up briefly to do some useful work (I know people that do the same). That requires a set of techniques – both hardware and software.
The hardware must be designed in such ways that low sleep power consumption is possible. Those of you following my blog may recall my woes with the MCP1703 LDO on the early Funky v2 prototypes, those would leak current when the Funky is powered from a battery i.e. the VOUT side is powered and the VIN not. I then found out that a MCP1700 performs better, but not ideal. I managed to get sleep currents at about 0.06mA/3V but had to keep battery power at less than 3.1V or the side effect happened again. For that reason I used the 3V version of the LTC3525 boost regulator on Funky v2. That still bothered me and I was looking for a LDO replacement ever since. Couple days ago I found the Torex XC6206 LDO series, those have in-built diode to prevent the parasitic currents I was experiencing:
I purchased few to try out and they work really well in eliminating that minimal but pesky parasitic leak – saving me extra 0.02mA and resolving the boost regulator issues. I can now again use the 3.3V versions of the LTC3525, although the 3.0V is more efficient. The quiescent draw is also better than the MCP1700 – only 1uA. I will use these in Funky v2 from now on.
Another hardware consideration that the Funky v2 has is the option to power up/down the on-board RFM12B transciever using a MOSFET. This allows for better power management and powering the RFM12B module from the software. The RFM12B has pretty high start-up power consumption, so you may power and put it to sleep only when you have sufficient power.
The clock source and frequency that you run at also has great impact on power usage. You get lower power consumption when running on the internal oscillator and lower frequency. Luckily, the ATMega32U4 that I use in Funky v2 has software control over both meaning you can switch between the internal RC oscillator and external crystal plus you can control the prescaler to run at different frequency. This gives you the option to decide which cock source and frequency to use depending on the particular application. I have an example on how to switch between clock sources and set the prescaler here. Changing the frequency at which the MCU runs is also necessary when running on low voltages, the Funky v2 has a 8Mhz crystal on-board because a 16Mhz crystal will require at least 4.5V. Running on 8Mhz requires at least 2.7V, but I have tested it to work reliably at a little less too.
Running on lower voltages will require that you lower the frequency. The RFM12B transceiver can communicate with the MCU down to 4Mhz, so running slower than that will prevent you from using it. Of course you can speed up/slow down as necessary.
Fuses are yet another possibility to save power. The fuses determine how the chip will act, whether it has a bootloader, what speed and voltage it likes to run at, etc. Note that despite being called ‘fuses’ they are re-settable and don’t have anything to do with protection from overpowering (like the fuses in a home). The Brown-out-detection (BOD) can be turned to save another 0.02mA, here are the fuse settings to do this for the Funky v2:
avrdude -v -v -patmega32u4 -cusbtiny -e -Ulock:w:0x3F:m -Uefuse:w:0xcf:m -Uhfuse:w:0xd8:m -Ulfuse:w:0xff:m avrdude -v -v -patmega32u4 -cusbtiny -Uflash:w:Caterina-lilypadusb.hex:i -Ulock:w:0x2F:m
Choosing the right power source for the project is important. Probably the hardest to deal with are the coin cell batteries – CR2032: these offer really small capacity of only 210mAh. I have also noticed that these are really sensitive to temperature and will drop their voltage notably when brought to low temperature. Picking the right battery depends on what you use your node for. A good tool for battery budgeting is this one, as you can see it all boils down to these parameters:
- What is the sleep current of the node
- How often does it wake
- What is the current consumption during wake state
- How long is it awake
Knowing these, one can estimate the expected battery life and plan accordingly. To get an idea of what is happening when running the DS18B20 sketch, I hooked a Funky to my oscilloscope. I also have Digital 13 go HIGH when the node is woken from sleep and LOW just before it goes down, so I can have a visual of the time when it is doing its job. This is the blue trace of the screenshot below, the yellow trace shows the current consumption times 10 in mA.
The sketch measures battery level, blinks the LED briefly, initiates DS18B20 conversion and waits in sleep mode (375ms for 11bit resolution) for it to finish. Once it is finished, it would transmit that value. So the whole thing happens for 466ms and average power consumption is 0.566mA (peaking to 26mA during transmission). The sleep current of the node is about 0.02mA (see screenshot at the end of this post). Lets assume 12 transmissions per hour i.e. one every 5 minutes. Punching in the numbers for a CR2032 coin cell battery gives me this:
1.09 years.. sounds good, I have doubts that this is realistic though 🙂
Most of the power consumption comes from the RFM12B transciever. It can eat up 24mA during active transmission. As I have experimented earlier, the modules’s transmission power can be lowered at the cost of range, so nodes that are closely located to the gateway may save power. It is a subject to experiment to find the lowest power settings that is sufficient to get the payload transported reliably to the gateway.
Speaking of payload, it too has to be designed smartly. Sending float values will use up 4 bytes, the larger the payload size the longer it takes to transmit it. I typically use integers to send floats by multiplying the value by 100, so a temperature reading of 36.74 will become integer value 3674 and fit two bytes. The receiving side has the task to reverse this, I do that by setting a processing rule in emoncms.
Another consideration would be how frequently to take/send telemetry readings. I see many users using unnecessarily frequent readouts, in my experience taking temperature readings for a room node more frequently than once every 5 minutes is an overkill. Use the largest interval you can without compromising data quality.
The software must power down all unused peripherals to save power, that provides great savings. I include that in every sketch that requires low-power mode, see an example here, function powersave();
I use the digital pins to power up/down small sensors attached to Funky’s pins since some of them still consume notable amounts of power even in idle mode.
The code should be checked for effectiveness, for example I have optimized the DS18B20 digital temperature sensor code by a factor.
So putting these trick to work I get sleep currents of 22.8μA when running off 2 AAA batteries (3V).
EDIT: Even 22uA seems high, so I tried to remove the LDO whatsoever.. I then got 2.6uA in power down mode.. amazing improvement. I guess I need to find a way to bypass the LDO when running on battery: