Skip to main content

Metrics for Battery Life

Understanding Battery Life at Scale

Understanding battery life expectations, trends, and regressions with thousands to millions of devices in the field is hard.

In this guide, we will walk through common pitfalls and best practices for accurately tracking the battery life in your fleet.

Pitfall #1 - Sending Current Battery Life Sporadically

A firmware could be configured to send up battery life information at a non-standard interval. It may be whenever it connects to Wi-Fi, when it's within Bluetooth range of a cell phone, or when it's asked by a remote server for information.

In this information report, a device would usually send the current battery life percentage according to a pre-determined curve or a millivolt reading.

This type of information is perfect when looking at a single device's history of battery life, but that is about it. From these individual reports, and sporadic reports at that, a battery life drop might be missed entirely, such as in the chart below:

Battery life drop during period of time

When only taking into account the four captured data points, the battery life looks like it drops at a normal rate. However, there was a large drop in the middle.

Pitfall #2 - Ignoring Charging Status

Another common issue with reporting battery life information from devices is that the power state is ignored. Battery life statistics that are used in aggregations should not be taken into account if a device is currently plugged in or charging.

For example, the chart below shows the battery life of a device over a span of time:

Battery life drop during period of time

The battery is discharging around 10% per data point. However, there is one chunk of time where there is a large battery life drop, but the device is plugged into a charger quickly and by the time the next battery life report takes place, it's been charged and is reporting a normal-looking number again. It might look as if the battery regression never took place!

The same goes for a device that is reporting data for long periods while connected to a charger. It might report 100% for 3 days, and these calculations should not be taken into account when determining battery life calculations for a fleet of devices.

A Better Way

Memfault recommends capturing two data points per heartbeat interval: the current battery percentage and, more importantly, the battery drain over a fixed interval.

For example, if the battery dropped from 97% to 94% over an hour, then the device would report 3% as the battery life drain for that hour. It might also be more useful to scale out the battery percentage to be more granular, such as 0-1000 to represent 0-100%.

There are a few benefits of this approach that might not be immediately obvious:

  1. If an interval has a charging event, it can be thrown out or marked to be excluded from aggregations.
  2. The calculation of average battery life drain per hour can be easily computed. This enables quick battery life estimations and projects, even with fleet sizes well into the millions.
  3. Devices that are only online sporadically can still send battery life information to help compute statistics since the battery life drain is recorded every heartbeat interval and these heartbeats can be persisted and sent upon request.

Below are some example implementations on how to capture these two metrics Memfault recommends.

Current Battery Life Implementation

Track the current battery percentage or current mV reading from the battery.

static void prv_device_metrics_end_heartbeat(bool is_flushing) {
// Set to our BatteryLifeDrain metric
device_metrics_set(kDeviceMetricId_BatteryLifePct, battery_get_current_pct());

where battery_get_current_pct() is assumed to be the function in the customer's firmware that would fetch the current battery percentage.

Battery Life Drain Implementation

Calculate the battery drain over a consistent, fixed interval of time, such as an hour or a day, ignoring hours in which a power event took place.

// Stores the battery percentage from the start of the heartbeat interval
static int32_t s_previously_recorded_battery_pct;
static bool s_charger_connected_during_hour;

static void prv_device_metrics_start_heartbeat(bool is_flushing) {
// Sets the battery percentage at the start of the interval
s_previously_recorded_battery_pct = battery_get_current_pct();
// Determine whether a charger is connected at this exact moment.
// If the charger is connected during the hour, this should be
// updated by the battery/charging module too.
s_charger_connected_during_hour = battery_get_charger_connected();

static void prv_device_metrics_end_heartbeat(bool is_flushing) {
if (s_charger_connected_during_hour) {
// Don't report a metric during hours with a charging event

// Calculates the drop in percentage over the heartbeat interval
const int32_t current_battery_pct = battery_get_current_pct();
const int32_t battery_delta = current_battery_pct - s_previously_recorded_battery_pct;

// Set to our BatteryLifeDrain metric
device_metrics_set(kDeviceMetricId_BatteryLifeDrain, battery_delta);

Predicting Expected Battery Life

Need some more information here.

Projected # Days of Battery Life=100÷total battery percent drained over all heartbeatstotal # of heartbeatsProjected\ \#\ Days\ of\ Battery\ Life = 100 \div \frac{total\ battery\ percent\ drained\ over\ all \ heartbeats}{total\ \#\ of\ heartbeats}

Preventing Battery Life Regressions

The only real way to do this is to have a set of devices running production-like firmware in a production-like environment because it is impossible to run devices and firmware through the entire matrix of environmental conditions to understand real-world power usage.

This means that if a company makes a wearable device and it's shipped all over the world, it should be tested internally with a variety of Android and iOS phones, versions, connectivity interference, and usage patterns, but it should be understood that this will only be a small subset of the environments the device will experience.