About a year ago, I started building wireless sensors that needed to run on a battery. I quickly found out however that this wasn’t going to be easy: A battery would only last for a few days, before it would be gone. Browsing around the internet, I learned about the fantastic work of Jean Claude Wippler of Jeelabs fame. JC has been working on wireless sensors for years and tackled the battery issue way before I did. So let me explain in my own way why you kill a battery in days and what you can/should do to fix this.

Why will a standard Arduino eat a battery in days?

Arduino separates itself from a bare ATMEGA from the hardware side of things are it’s form factor (allowing for the use of standard shields), standard USB interface, power regulation and some LEDs. Now some of these things that make Arduino hardware great are also killing battery consumption: When you run a standard Arduino (Uno for instance), it already consumes more than 15mA, just sitting there doing nothing. Given that a typical Alkaline 9V block has a capacity of approx 450mAh, this means it drains the battery in just 30 hours or less two days (450mAh/15mA).

How to go from this?

So how do we go from this? Well, first of all we need to get rid off al those current sucking peripherals if we want to improve battery life. To do this you either buy a really barebones Arduino (clone) that doesn’t have the USB interface on board, lacks always-on LEDs and preferably has a low quiescent current converter chip (LDO) like MCP1702, like Arduino Mini, Arduino Lilypad, Jeenode or RBBB. Or you build a barebones Arduino yourself on a piece of bread board, like I described in a previous post (seems like many liked it: 17k views and 110 upvotes on HN, thanks guys!).

On the software side

On the software side we also have to do something: The Barebones Arduino is now taking 6mA instead of >15 mA, but still way too much. There is an easy fix for this: Put the Arduino to sleep as much of the time as possible and only wake it when we want to take an action or read a sensor value. This reduces the current to somewhere close to 10uA, almost a 1000-fold improvement.

Example Calculation

So for instance you have an analog temperature sensor (mcp9700, 6uA) that you want to read and based on the value either buzz a buzzer or not. What you can now do is put the Arduino to sleep for 10s, the wake up, read the value and shortly 0.5s buzz or not, and put the Arduino to sleep again. Based on this, you might improve the battery time from less than two days to almost three weeks (example 1):

Average current = (10mA*0.5s+16uA*10s)/10.5s = 0.49mA

Battery time = 450mAh/0.49mA = 918 hrs = at least 38 days (worst case: Buzz with every measurement)

Example Code

Putting the Arduino to sleep is really easy with the loseSomeTime function found in the JeeLib libary. See the modified classic blink (example 2) below:

#include <JeeLib.h> // Include library containing low power functions int led = 13; ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup for low power waiting void setup() { pinMode(led, OUTPUT); } void loop() { digitalWrite(led, HIGH); Sleepy::loseSomeTime(1000); // Instead of delay(1000); digitalWrite(led, LOW); Sleepy::loseSomeTime(1000); // Instead of delay(1000); }

As you can see is the modification minor: Add the library, initiate low power waiting with standard expression (always the same), use loseSomeTime() instead of delay().

Working this way, I was able to build wireless moisture, light and temperature sensors that are running on a single battery for months on end, while measuring and communicating once per few minutes.

What else can you do?

As you start to read up on this stuff, you will find that there are numerous ways to further improve. One is easier than the other, one has a larger impact on the user experience than the other. But to name a few for further reference: Reduce internal clock rate by changing fuse settings (Arduino current can go from 6mA to <1mA), IRQ pin or pin-change IRQ for waking instead of timed wakeup, play with LED, buzzer on/off times and duty-cycle and finally don’t forget to watch currents of sensors and communication modules/ICs (select the low power ones and put them also to sleep when not in use).

Debugging

A last remark about debugging: When doing this kind of changes it is really handy to use a multimeter to check standard current consumption in static modes. For more detailed and dynamic visibility, you can use a (digital storage) oscilloscope measuring over a 10R resistor in one of the battery lines.

Summary

It is quite possible to run an ATMEGA with Arduino code for weeks if not months on a normal 9V battery, but it requires a different/special Arduino (clone). By using the JeeLib library, the needed software changes can be minimal in a lot of cases. Low power Arduino is absolutely possible, but it takes some effort.

Need a product developed or Want more Arduino and Hardware tips in your inbox?

Next to our own projects, we also develop for other companies (often with wifi, Ethernet, bluetooth, GSM/GPRS). Do you want us to develop or built a prototype for you? Feel free to contact us: hans@cloudsensor.us

Do you want to hear more about Arduino, embedded hardware and hardware startups? Click on the “Follow” button on the right, I appreciate it.