Power Optimization — From 3 to 7 Months on a Single Charge
In the process of creating an IoT device, one of the most common challenges hardware and embedded software engineers face is power consumption optimization. There is usually a major trade-off between power consumption and device features. During my time in Sensibo, I developed the embedded software for the first generation of their devices. In this post I’ll go over the development and optimizations that went into that device.
Our system: The system I was working on had an end device, which communicated with the server through a gateway. The gateway was connected to AC power so its power budget was unlimited, and the end device was battery powered. It also had to be fairly responsive to user input from an app, and send periodic measurements to the server.
After the initial BSP was stabilized our CTO came up with a requirement — optimize the power requirement of the device so that the battery will last for about a year. The device was fairly optimized in terms of hardware design — we were able to shut off all non essential parts of the board using low leakage transistors, so barring unexpected issues, most of the optimizations would come from the embedded software side of the project.
How to measure current consumption
There are several methods to estimate the power consumption of your device. Basic requirements are bandwidth, accuracy and the ability to log your data to a computer to crunch the numbers that you came up with. The price range for solutions can be quite extreme:
- The simplest solution is to use a small (and accurate) resistor from the GND of the device to the power supply ground, and measure the voltage on it using an oscilloscope. You can also connect an opamp after the resistor get a better range. You can also use an off the shelf device that does exactly that, such as uCurrent.
- Use a DVM to measure the current to the device, we had a keithley-2110 DVM which could store 50k measurements per second. The only issue with a DVM is that it can create a large voltage drop when measuring which can interfere with the device.
- Use a current probe for an oscilloscope.
- Using a battery simulator.
As you can see the price range can go from dozens to hundreds and even more than a thousand dollars. I recommend to start experimenting and find the best solution for you. You can always go high end from the start, but where’s the fun in that?
In this case I was alternating between the first and second method, depending on what I wanted to measure.
Estimating Power Consumption
If the circuit is properly designed, your MCU will be the either be the dominant current consumer over time, or will directly control the current consumption. Its consumption is divided into two major components — the idle and dynamic consumption. What are we talking about?
- The idle consumption is the amount of current the device takes when it’s just sitting around waiting for the next command/event or interrupt. Depending on your use case you should strive to reduce this as much as possible. I’ll use the MCU I was working with as an example (the cc2538 — datasheet) — there are several sleep modes, each with different characteristics. For example if you need to sleep for less than several hundred s, going into power-mode 3 might not be worthwhile since waking up from it takes too long. However every peripheral that is being kept awake comes at a price as well.
- Dynamic power consumption — your device has to do something, it can light up LEDs, sound an alarm or do several measurements and transmit them, either way, these actions have a power consumption profile that can be measured using one of the above techniques.
Once you empirically measured both the static and dynamic power consumption, you put it in a spreadsheet and estimate the battery life of your device. If that’s not enough — it’s time to optimize!
Complicated? A little bit. Let’s use an example:
You have a 3000mAh battery, you want to calculate the average current per day to see how long your battery will last. Our imaginary scenario has:
- An event occurs once a minute and takes on average current of 10mA for 500ms.
- Static current consumption of 0.5mA.
In total, the events will consume a current 10mA * 0.5s = 5mA, combining with the static current we have an average current of 1mA. With our battery we’ll have 3000/1 = 3000 hours = 3000/24 = 125 days of operations.
Also, 3000mAh is quite a rough estimate, you can’t really use all the stored energy in a battery since its voltage drops as it discharges, also temperature and large current consumption (event instantaneous) can affect battery life!
Optimizing Power consumption
Now it’s time to take a close look at our simple example, where can we optimize?
If your current is higher than the datasheet suggests, you need to start checking your components one by one, both hardware and software. In my own experience, when going into the lowest power mode, only half of the memory was retained! I solved that by moving all the buffers used for building network packets to the un-retained area.
Another obstacle are the OS ticks that require the systick peripheral to keep working and consume power. The solution is to either go bare metal with no real time OS, or use a tickless configuration for your OS. For example freeRTOS has a tickless mode.
Now it’s time to take a long hard look at the requirements from your product. How responsive should it be? How many measurements do you really need? In our system a high current was consumed by waking up and asking the gateway if it had any pending data. We did some usability research with actual end users of our device and concluded that a delay of less than a second between pushing a button in the app and getting the device response is acceptable. We increased time between wake ups to about 500 milliseconds, but the results weren’t good enough. In the end I optimized the communication protocol further by reducing the time that the device is listening for data, and increasing the time that the gateway spends trying to reach the end device.
We got the device’s theoretical battery life to about 9 months. Real world battery life was between 6–9 months depending on the usage and RSSI. If I ask myself what could I have done differently my answer is a logging system to gather power related events from the device and analyze them. Collecting these events might have helped me pinpoint power related issues and close the gap between the theoretical and actual measurements.