Estimating the battery life of a device can be a daunting task. With that in mind, Doug set out to design and build a tool that easily provides an estimate of battery life for his projects. He steps through each element of his design process, including current profiling, battery emulation, Python software development and more.
As anyone who has ever designed battery-powered devices can attest, many factors determine battery life. They include battery chemistry, number of cells, hardware component selection, processor sleep current, firmware active events (such as wake up, read sensor, process information, transmit/receive data) and time between active events—not to mention other environmental factors, such as temperature, aging and charging lifecycle.
In my experience building battery-powered devices over the past few years, I have learned that the process of measuring and estimating battery life can be labor intensive. The process is tedious, with multiple test equipment arrangements to capture current profiles for different firmware states, manual data logging, and spreadsheets for data input and calculations, to get to an estimate of battery life for my device under test (DUT).
I needed a better way, which drove me to build the BattLab-One (Battery Laboratory). My goal was to deliver a design tool that quickly and effortlessly provides an estimate of battery life for my projects, enabling me to spend more time on design and less time on measuring and calculating battery life.
Capturing and profiling current on battery-powered devices can be challenging due to many factors. Typically, the DUT has a large dynamic current consumption range—from hundreds of nanoamps in deep sleep mode to hundreds of milliamps during active events. In addition, many rapid current transitions and long periods between active events can add to the complexity of determining battery life. Understanding how different aspects of the DUT firmware affect battery life requires capturing each firmware state separately (processor wake-up, wireless transmit/receive, sensor read, data processing and so on).
Traditional test methods, such as a multimeter or an oscilloscope with sense resistor, can get the job done, but can be time consuming and cumbersome. Because I’m working with battery-powered voltage levels, multimeter burden voltage often becomes an issue. It’s also cumbersome and may have limited data-logging capabilities (depending on your multimeter). An oscilloscope with a current shunt resistor helps, but again, it’s cumbersome and lacks the “what-if” analysis capabilities I need. It becomes tiresome to have to plug the captured current profiles from these separate acquisition methods into a spreadsheet and then calculate an estimated battery life.
Of course, products designed specifically for this type of measurement are available, but they can be quite pricey. Solutions like the Keysight CX3322A Device Current Waveform Analyzer  cost well over $20,000 at the time of writing this article. It has incredible specifications and features, but it is way outside my budget! While these more expensive solutions provide amazing results, my personal projects (and budget) drove me to a simpler, less expensive, faster solution to get a reasonable estimate of battery life. The BattLab-One allows me to get to an estimate quickly, tweak my design parameters, and come up with a new approach to meet my product design goals.
Estimating battery life requires the ability to capture current profiles during active events, sleep mode current, a method for capturing the long intervals between active events and a model for calculating battery life. In addition, providing the ability to identify high impact (in terms of battery consumption) firmware states and comparisons of previous current profiles is extremely helpful. Finally, an ideal solution would provide the ability to optimize a design by tweaking the variables and do “what-if” analysis scenarios on the project’s battery life. Essentially, it’s a software laboratory for battery-life estimation.
My idea was to develop a battery emulator that I could use to power my device under test, and capture current profiles directly from the power supply unit (PSU), emulating the battery voltage. My overall approach was to design a data acquisition device connected via USB to a PC for data logging, and with an ability to do “what-if” analysis on my captured current profiles.
In the process of designing my solution, I learned there’s a reason why accurately measuring and auto-ranging across a 140dB dynamic current range is so difficult. My goal was to develop a tool that would get me to a “reasonable” estimate of how long my DUT (device under test) would live in the wild without breaking the bank. So instead of a 140dB dynamic range, I decided on a smaller, 74dB dynamic range. Capturing current profiles from the 500mA down to the 100µA range would meet the characteristics that most of my battery-powered devices typically consume.
The 500mA upper bound represents about a 0.2C discharge rate for a typical lithium-ion (Li-ion) 18650 battery, about 0.3C for typical AA batteries and 0.7C to 0.9C for AAA alkaline batteries. The 100µA on the lower end ensures there’s enough room within an ADC’s dynamic range. That gave me a more reasonable 5000:1 dynamic range (74dB) to work with. The upper bound was perfect for me, since many of my projects use the Espressif Systems ESP8266 Wi-Fi chip for communication, so I could capture the +300mA spikes for transmitting and receiving on Wi-Fi. The distribution of the rest of my DUT power budget is usually in the hundreds of microamps to tens of milliamps range for reading sensors, driving logic and doing some calculations on the processor.
While sleep current can be the most important determinant of battery life, it’s typically just a single value that occurs over long stretches of time. The nature of sleep current meant that instead of designing a complex auto-ranging feature, I could use a manual approach. I decided to deploy a software-selectable sense resistor to capture sleep currents (tens of nanoamps to tens of microamps), and I provided a field for entering the sleep interval time manually.
With the dynamic-range approach resolved (or at least rationalized), I focused on other areas of process improvement. I thought a feature to enter a pre-determined capture duration, from 1 second up to many hours (dependent on PC disk space), and the ability to trigger the BattLab from the DUT firmware or other external source would give the user greater flexibility for data logging. The trigger feature allows the user to see the effects of different firmware states on overall battery life. I also decided on a feature to save and compare profiles and do “what-if” analysis. A screenshot of the BattLab-One user interface is shown in Figure 1.
I decided to architect my current sensing solution around the Texas Instruments (TI) INA233 chip. It’s a high-side / low-side current, voltage and power monitoring device with a 16-bit delta-sigma ADC and I2C for control. It provides data capture of shunt voltage and bus voltage, plus calculated power output. It has a 96dB dynamic range, user-selectable ADC conversion rate (from 140µs to 8.244ms) and a sampling averaging feature. It requires an external shunt resistor, and I am using a 0.10Ω sense resistor to meet my dynamic range specification (more on that shortly).
To capture the sleep state of my DUT, I added a MOSFET to switch in a 100Ω sense resistor (via software) and then prompt the user to manually enter the sleep interval in the user interface. The MOSFET RDSON actually adds to the overall sense resistance, for a total of about 0.15Ω (the 0.10Ω sense resistor plus the 0.05Ω RDSON of the MOSFET). This gives me a worst case (at 500mA) burden voltage of 0.075V, which represents about 6.25% at 1.2V output (0.075/1.2 × 100), and a 1.7% burden voltage at 4.5V output (0.075/4.5 × 100). The good news is, since I’m controlling the output voltage, I can tweak the 1.2V output to about 1.25V to alleviate some of the burden voltage impact at the low-voltage ranges.
I used a TI MSP430G2553 MCU as the main processor and an FT232RL from FTDI Chip for UART-to-USB translation for communication with the PC. The MSP430 supports I2C and is plenty fast enough at 16MHz. I used the 3.3V LDO of the FT232RL for powering the MSP430 and other logic on the primary side (USB side) of the PCB. Digital isolation (power and data) is important and something to be mindful of when using USB to power your projects. Dave Jones provides a great video blog on “How not to blow up your oscilloscope,” which is related to this issue . The video is posted on Circuit Cellar’s article materials webpage.
For the power supply that emulates the battery for the DUT, I used an AP2318, which is an adjustable LDO linear supply from Diodes Incorporated. The AP2318 supplies 600mA, but in practice BattLab can provide only about 450mA of continuous current at the various output voltages—1.2V, 1.25V, 1.5V, 2.4V, 3V, 3.6V, 3.7V and 4.5V. The selectable voltages emulate combinations of up to three AA or AAA (alkaline, NiMh, NiCd) batteries or a single cell Li-ion battery (CR2032 or 18650).
To power the components on the secondary isolated side of the board, I used a TI SN6505 DC-DC converter and a Würth Elektronik 750315371 transformer to provide a +5V, approximately 500mA power supply. Since I kept the MSP430 on the primary isolation side of the board, I needed to add a TI ISO1540 for I2C signal isolation. I used a TI ISO7742 4-channel digital isolator for other isolated logic. I used one channel of the ISO7742 for the MSP430, to control the gate on the MOSFET for switching the 100Ω sense resistor, one for controlling the AP2318 (turning on and off the power supply output to the DUT), one from the DUT to the MSP430 for triggering, and one extra channel just in case I need it in the future.
The AP2318 has a dropout voltage of 0.35V at the maximum rated output current, so the maximum 4.5V output just fits just within my USB +5V power budget (5 – 0.35 = 4.65V). I used an Analog Devices AD5248 dual digital potentiometer as the adjustment resistors to set the LDO output, again using I2C for control.
As mentioned earlier, I am often powering an ESP8266 device for my projects, so I placed a beefy 1000µF output capacitor to handle the power-surge demand of that device. It does cause some RC time constant issues when re-setting from a large PSU output voltage (4.5V) to a lower PSU voltage setting (1.2V), since it takes a while for that capacitor to discharge. Figure 2 shows a schematic of the BattLab-One and Figure 3 shows the completed hardware.
The PC application software for BattLab is written in Python 3.6 using the Tkinter GUI toolkit. All the graphing is based on Matplotlib, which has a great navigation bar at the bottom to let you zoom in/out, pan, return home, navigate and even save the current profile graph as an image file. The MSP430 firmware is written in C and can be updated, since I’ve brought the MSP430 ground, Test and Reset pins out to a header. You can use a TI Launchpad to program it.
The software is intended to be intuitive, and basically walks the user through a four-step process:
Step 1. Step 1 prompts the user to set the battery type, quantity, DUT cut-off voltage, and capacity of the battery cells you will be supplying as power output to your DUT. Effectively, you’re setting the output voltage of the BattLab’s PSU to power the DUT. The user then clicks the On button to turn on the PSU.
Step 2. This step has the user select the amount of time for the profile capture (1 second through many hours, depending on your PC’s disk space) or have it triggered by the DUT. If triggering is selected, BattLab waits for a low-to-high event on the trigger port to start the capture, and then a high-to-low event to stop it. You’ll need a spare pin on your DUT processor to start and stop the trigger. You’ll also need to program your firmware to trigger the pin. The input trigger can accept +3.3V to +5V, and has input protection. The user then clicks the Capture button to start capturing the current profile of the DUT.
Step 3. After you’ve captured the current profile of the active states of your DUT in Step 2, Step 3 prompts the user to capture the sleep current. Basically, the BattLab switches in the 100Ω sense resistor to measure current at the nanoamp scale. BattLab assumes you’ve put your DUT into sleep mode to capture this data. The application then prompts the user to enter the sleep interval between active events.
Step 4. This is the fun part. Once the battery profile data has been captured in Step 1, and the active and sleep event current profiles have been captured in Steps 2 and 3, an estimate of your battery life is presented. You can select and alter all variables in “what-if” scenarios to see how the battery life would compare to the captured profile. You can save profiles and compare multiple graph outputs in the chart. A plot with a completed sample current profile and an estimated battery life is shown in Figure 1.
The INA233 ADC is multiplexed to take two voltage measurements for each ADC conversion, VSHUNT and VBUS. I am only using VSHUNT readings in Release 1 of the BattLab. Unfortunately, there is no way to turn off the VBUS read time. This means I must add the additional VBUS conversion rate to the VSHUNT conversion rate. I set the ADC conversion rate for both VSHUNT and VBUS to 140µs for a total single capture rate of 280µs.
I’ve fixed the number of averages to 4 per sample, so the overall the capture rate is about 960µs (280µs × 4). Add another 80µs to 100µs to transfer the 2-byte sample via I2C to the MSP430, and the BattLab is operating at about a 1kHz sample rate. Is it possible that BattLab will drop some short duration current spikes? Yes, for sure. But it’s proven fast enough to get a reasonable estimate of battery life. To calibrate the BattLab, I use several precision current sources (100nA, 100µA and 100mA) and set a calibration factor within the MSP430 firmware.
I recently designed a device that tweets out (to my own private Twitter account) the status on my garage door (open or closed plus temperature and humidity of the garage). Since my DUT uses a Li-ion battery (18650), I chose 4.2V (fully charged 18650) for Step 1. My cutoff voltage is 3.4V, and I then enter the battery capacity of my Li-ion (2,300mA-hours) and turn on the PSU.
In Step 2, instead of setting a duration for capture time, I used a spare pin on the ESP8266 module to trigger the BattLab to capture the current profile, from when the unit boots up until sleep mode. I connect my DUT to the BattLab and then click Capture, turn on my DUT—which triggers the BattLab—and the resulting current profile is plotted. A code snippet used for triggering the BattLab-One in my Lua code for the ESP8266 is shown in Listing 1—in this case, the firmware event for reading the sensors.
gpio.write(4, gpio.HIGH) -- Trigger BattLab-One to start capturing data
doorstatus = gpio.read(6);
temp = 0
for i=1,3,1 do
temp = temp + adc.read(0)
tempC = ((temp/3)-500)/10
tempF = ((tempC*9)/5) +32
voltage = adc.read(0)/1024
return doorstat, volt, tempF;
gpio.write(4, gpio.LOW) -- Trigger BattLab-One to stop capturing data
LISTING 1 – A code snippet used for triggering the BattLab-One in my Lua code for the ESP8266
Next, the software prompts the user to capture the sleep current of the DUT. I make sure the unit is powered and my device is in sleep mode. (It should be, given that I’ve completed Steps 1 and 2.) I select the Capture Sleep button and BattLab captures data over a 5 second duration and averages it over that time. For my sleep event interval, I entered 71 minutes (4,250 seconds), since I use the maximum sleep time of the ESP8266.
Finally, the fun part. In Step 4 I click Analyze and my estimated battery life is displayed in days and hours. I can now adjust parameters such as sleep duration, type and capacity of battery, temperature, sleep time and so forth. I can save and compare profiles to use for my design goals. Using the BattLab on my garage door sensor enabled me to quickly understand the firmware and other design changes on my product’s battery life.
IDEAS FOR FUTURE ENHANCEMENT
Ideas for new features would be to leverage more of what the INA233 provides. Today I am only capturing the shunt voltage from the INA233 device through my sense resistor. I would like to integrate with the SMBus more tightly, to get the VBUS and power measurements from this device. I’d also like to allow the user to set the averaging mode used and the ADC conversion time.
Currently, the BattLab uses a default discharge rate (based on the average current profile) and a percentage of the entered value for battery capacity (based on the DUT cutoff voltage). In the future, I would like to include a battery specification library, based on real-world testing of multiple battery types over time. The idea would be to capture the discharge profile by changing multiple variables—such as average current consumption, temperature and humidity—and capturing statistics over multiple battery types. This would provide BattLab with a look-up table of values to draw from to improve the accuracy of the battery-life estimation.
In addition, I would like to add more advanced triggering capabilities. One thought is to use a positive edge trigger to start the capture of the Wake event of the DUT (as it does now). Then, on the negative slope trigger event (the last active state before deep sleep mode), it could auto-enable my 100Ω sense resistor for capturing sleep current. The auto-range speed is not as important in this scenario, since the sleep mode typically lasts for minutes to hours.
One of the unplanned benefits of the BattLab-One is that it makes a decent USB-isolated power supply with a 0.8V to 4.5V output at approximately 450mA. In the future, I may provide more selectable voltages, rather than just those associated with specific battery types. This would make the BattLab more usable as a general-purpose, mobile power supply.
The finished product of the BattLab-One device is shown in Figure 4. For me, this was an extremely successful project. I learned a lot on the journey, and was able to develop a tool that I can use to quickly estimate battery life for my battery-powered designs.
I am currently in the process of getting my design approved for the Open Source Hardware Association (www.oshwa.org), because I think the BattLab-One could be a great platform for other projects. In the meantime, my source code, schematics and board layout are all available on my GitHub site . If you have interest in this project, please feel free to reach out to me by email at [email protected]
 Keysight CX3322A Device Current Waveform Analyzer:
 Dave Jones, “How not to blow up your oscilloscope.” (See video below)
 Source code, schematics and layout for the BattLab-One device:
Analog Devices | www.analog.com
Diodes Incorporated | www.diodes.com
Espressif Systems | www.espressif.com
FTDI Chip | www.ftdichip.com
Keysight Technologies | www.keysight.com
Texas Instruments | www.ti.com
Würth Elektronik | www.we-online.com
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • JULY 2020 #360 – Get a PDF of the issueSponsor this Article