Battery Monitoring with Zephyr’s Fuel Gauge Subsystem

This week I went on a fascinating odyssey into Zephyr’s fuel gauge subsystem. This doesn’t refer to gasoline (or petrol as my more refined colleagues would say). It instead deals with the ubiquitous Lithium rechargeable cell. There’s a lot that goes into monitoring and charging these batteries, so it’s not surprising that the silicon industry has a class of chips known as fuel gauge ICs. They automatically handle tasks like calculating percentage of battery capacity, run-time until empty, charge-time until full, current/voltage measurement, and battery cut-off. If you haven’t looked at these chips, you should!

Batteries are the future and Zephyr is ready for it with a number of drivers already in-tree. The drivers are pretty user-friendly, but what’s built into Zephyr does fall into two different driver categories. Let’s get plugged in and see what the fuel gauge is all about.

Is it a Fuel Gauge or a Sensor?

I’m not embarrassed to admit I lost a bunch of time trying to figure out why my Maxim max17262 fuel gauge IC has Zephyr support but doesn’t work with the fuel gauge subsystem. It turns out that some fuel gauge ICs have sensor drivers, while others have fuel gauge drivers. Don’t worry, you can get nearly the same data from either, but you need to use the one supported by your device.

How can you tell what kind of support exists for your chip? Head over to the Zephyr bindings index and look it up. On the face of it you can see several of the max17xxx chips have zephyr support.

Maxim max17xxx chips listed in the Zephyr bindings indexBut when we click on the links and drill down to the details for each of these drivers, we find that the max17048 has fuel gauge subsystem support while the max17262 has sensor subsystem support.

Maxim max17048 fuel gauge supportMaxim max17262 sensor subsystem supportDifferent drivers have Kconfig and API names that are… different. But the approach to working with these chips will be largely the same. You get an instance of the chip out of devicetree, run a fetch command to populate a struct with values read from the chip, then utilize those values.

Using the Fuel Gauge Subsystem

I don’t have a chip supported by the fuel gauge subsystem but I did take a thorough look into the drivers, including the sample app for the max17048. This driver has very few devicetree options available:

max17048:max17048@36 {
    compatible = "maxim,max17048";
    status = "ok";
    reg = <0x36 >;
};

Enable the library using Kconfig:

CONFIG_FUEL_GAUGE=y

Access the device readings in c using a typical Zephyr pattern:

const struct device *const dev = DEVICE_DT_GET_ANY(maxim_max17048);

union fuel_gauge_prop_val batt_val;
int ret = fuel_gauge_get_prop(dev, FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, &batt_val);

Your battery percentage will now be stored in batt_val.relative_state_of_charge. The sample code shows four different properties being read from the max17048 (which is all this particular driver support). The subsystem defines numerous properties, accessible depending on the driver for your specific chip.

Using the Sensor Subsystem

The Golioth Elixir has a max17262 fuel gauge IC on the board which has Zephyr support via the sensory subsystem. Zephyr does include a sample app for reading from this chip. Despite not being directly included in the fuel gauge subsystem, this chip has for reading 14 properties (significantly more than the first driver we looked at).

The devicetree binding for this chip includes a number of useful properties so that device readings are properly associated with the physical parameters of battery you are using.

max17262@36 {
    compatible = "maxim,max17262";
    reg = <0x36>;
    design-voltage = <4200>;
    desired-voltage = <3700>;
    desired-charging-current = <800>;
    design-cap = <850>;
    empty-voltage = <3300>;
    recovery-voltage = <3880>;
    charge-voltage = <4200>;
    status = "okay";
};

Enable the library using Kconfig:

CONFIG_SENSOR=y

Access the device readings in c using a typical Zephyr pattern:

static const struct device *const dev = DEVICE_DT_GET_ONE(maxim_max17262);

struct sensor_value batt_pct;
sensor_sample_fetch(dev); /* gather all sensor values */
sensor_channel_get(dev, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE, &batt_pct);

Your battery percentage will now be stored in batt_pct.  I’ll leave it up to you to explore all the other properties you can read form this device.

Useful Chips with Useful Driver

Adding a fuel gauge IC to your battery-powered designs offloads almost all effort when it comes to taking reliable battery readings and estimating charge and drain times. Zephyr’s support for these values makes using them a snap when the driver is already in-tree. But even if there is no existing driver, the infrastructure greatly lessens the burden of adding your own.

Mike Szczys
Mike Szczys
Mike is a Firmware Engineer at Golioth. His deep love of microcontrollers began in the early 2000s, growing from the desire to make more of the BEAM robotics he was building. During his 12 years at Hackaday (eight of them as Editor in Chief), he had a front-row seat for the growth of the industry, and was active in developing a number of custom electronic conference badges. When he's not reading data sheets he's busy as an orchestra musician in Madison, Wisconsin.

Post Comments

No comments yet! Start the discussion at forum.golioth.io

More from this author

Related posts

spot_img

Latest posts

Open sourcing the Tikk demo board

The Tikk is a demo board that showcases Golioth's Bluetooth-to-Cloud capabilities. It solders to a ProMicro form factor development board and has LEDs, motor drivers, sensors, NFC tag emulation, and a battery interface.

Adding Espressif ESP32 to the Golioth Bluetooth-to-Cloud Service

The ESP32 and the product line variants often run Bluetooth alongside Wi-Fi. This post shows how you can use the Bluetooth capabilities of an Espressif chip to talk back to the internet when a Wi-Fi signal isn't the right fit for your application.

Creating an off-grid, solar powered Bluetooth-to-Cloud gateway

What happens when you're ready to utilize Bluetooth-to-Cloud, but are far from a power point and network connection and want to ensure your Bluetooth nodes' data still shows up on the cloud? Utilize the power of the sun!

Want to stay up to date with the latest news?

Subscribe to our newsletter and get updates every 2 weeks. Follow the latest blogs and industry trends.