Battery Fuel Gauges: MAX17043 Explained

Stop guessing battery level from voltage: the MAX17043 fuel gauge reports real state of charge over I2C. Learn why voltage-based estimation fails, how the chip works, wiring, the essential registers with Arduino code, and how to make your node adapt its behavior to remaining charge.

Written by Projectech7 min readPublished
For B.E./B.Tech Electronics, E&TC and IoT students building battery-powered projects who need accurate state-of-charge readings instead of crude voltage guesses Topics: MAX17043, I2C, Li-ion, ESP32, Arduino
Illustration of a MAX17043 fuel gauge chip connected over I2C to a microcontroller, displaying a battery state-of-charge percentage gauge beside a lithium cell.
Illustration generated for this guide.
In this guide

Your battery node reports "3.7V" — is that 80% charged or 20%? On a lithium cell, voltage alone cannot tell you: the discharge curve is flat through the middle and dives at the ends, and it shifts with temperature and load. Students usually cope by guessing from voltage thresholds, which is why battery indicators jump from "half" to "dead" in an hour.

A fuel gauge IC measures what is actually happening inside the cell and reports state of charge as a percentage. The MAX17043 is the classic student-friendly choice: a tiny I2C chip that does the hard electrochemistry math for you. This guide explains what fuel gauges do, how the MAX17043 works, how to wire and read it, and how to turn its output into battery behavior your project can act on.

Why voltage alone lies

A lithium-ion cell's voltage vs charge curve is deceptively flat: roughly 4.2V full, 3.7V nominal through most of the discharge, then a steep fall below ~3.4V to the 3.0V cutoff. The problems with voltage-based estimation:

  • Flat middle: between 3.9V and 3.6V the cell might be anywhere from 80% to 30% — voltage cannot resolve it.
  • Load sag: voltage dips under current draw (WiFi transmit!) and recovers at rest — a reading taken during transmission underestimates charge.
  • Temperature shift: the curve moves with temperature; a cold battery reads lower at the same charge.
  • Aging: capacity fades with cycles; voltage thresholds calibrated on a new cell drift.

A fuel gauge solves this by combining voltage measurement with a cell model (and in fancier gauges, coulomb counting — integrating current over time). The result is a state-of-charge percentage that actually tracks reality.

What the MAX17043 does

The MAX17043 is a 1-cell lithium fuel gauge using Maxim's ModelGauge algorithm: it measures cell voltage (and temperature, with an external thermistor optionally) and runs it through a model of lithium-cobalt-oxide cell behavior to estimate state of charge. Key facts:

  • Interface: I2C, fixed address — two wires plus power, readable from any microcontroller.
  • Outputs: state of charge as a percentage (with 1/256% resolution in the raw register), plus raw cell voltage.
  • Alerts: a configurable low-battery alert pin — the chip can wake your sleeping microcontroller when charge drops below a threshold, no polling needed.
  • Power: microamps of its own consumption — it does not meaningfully affect the battery it measures.
  • No current sense resistor needed: unlike coulomb-counting gauges, there is no shunt to wire — simpler hardware, at the cost of some accuracy vs true current integration.

Note: the ModelGauge algorithm is tuned for standard lithium-cobalt cells. It works reasonably for most single-cell Li-ion/LiPo pouches and 18650s; exotic chemistries (LiFePO4 has a very different curve) need different gauge approaches.

Wiring it up

The minimal circuit: battery positive to the CELL pin (through the recommended RC filter), battery negative to ground, SDA/SCL to your microcontroller's I2C bus with pull-ups, and the ALERT pin to a GPIO if you want low-battery interrupts.

Practical points:

  • The chip measures the cell it is powered from — it is inherently a single-cell device. Multi-cell packs need per-cell or pack-level gauges, a different design.
  • Keep the sense traces short and away from noisy switching regulators; the ADC is measuring millivolts of difference.
  • The breakout boards commonly sold include the filter components — if you are using a module, wiring is just battery + I2C.

For the I2C side, the standard shared bus works: the gauge coexists with your other sensors. If you are rusty on pull-ups and addressing, review the protocol basics first.

Reading it: the essential registers

You only need a few registers for a working integration:

Register Contents Use
VCELL Raw cell voltage (12-bit) Sanity checks, logging
SOC State of charge, % with fractional bits The headline number for your dashboard
CONFIG Alert threshold, alert enable Set the low-battery alert level
MODE Quick-start command Force a fresh estimate after battery swap

A minimal Arduino read pattern:

#include <Wire.h>
#define MAX17043_ADDR 0x36

float readSOC() {
  Wire.beginTransmission(MAX17043_ADDR);
  Wire.write(0x04);  // SOC register
  Wire.endTransmission(false);
  Wire.requestFrom(MAX17043_ADDR, 2);
  uint16_t raw = (Wire.read() << 8) | Wire.read();
  return (raw >> 8) + (float)(raw & 0xFF) / 256.0;  // percent
}

Send the alert threshold once at startup (say 20%), then either poll SOC with your telemetry or let the ALERT pin interrupt the microcontroller — the interrupt approach suits deep-sleep designs, where the gauge watches the battery while everything else sleeps.

Turning SOC into project behavior

A percentage is only useful if the system acts on it:

  • Telemetry: include SOC in every uplink; graph it alongside voltage to see the discharge curve of your actual deployment.
  • Adaptive behavior: below 30%, lengthen the sleep interval; below 15%, switch to heartbeat-only mode (one "I am alive" per hour). This graceful degradation can add weeks of useful life.
  • Alerts: the hardware alert pin wakes the MCU for a final "battery critical, shutting down sensors" transmission — far more useful than the node just dying silently.
  • Charging logic: for solar-augmented nodes, SOC tells the system when to resume normal operation after a low-battery brownout period.

The combination of fuel gauge + adaptive sleep intervals is what separates "runs until it dies" from "manages its own lifetime" — and it is very demoable: show the dashboard SOC graph with the node automatically shifting to low-power mode.

Accuracy: honest expectations

The MAX17043's estimate is good — typically within a few percent for standard cells after it has observed a charge cycle — but it is an estimate, not a measurement. Factors that degrade it: wrong chemistry assumptions, extreme temperatures, very old cells whose capacity has faded (the gauge reports percentage of design capacity unless compensated). For student projects it is dramatically better than voltage thresholds; for medical or safety-critical metering it would not be enough. State it as what it is: a modeled estimate, validated against your cell by observing a full discharge once.

Coulomb counting vs ModelGauge: choosing a gauge

The MAX17043 estimates charge from voltage plus a cell model. The alternative family — coulomb counters — measures current through a sense resistor and integrates it over time: charge in minus charge out equals charge remaining. How to choose:

ModelGauge (voltage + model) Coulomb counting
Hardware No sense resistor, simpler Precision shunt plus careful layout
Accuracy Good for standard cells (a few percent) Better — tracks actual charge flow
Calibration Minimal — quick-start and go Needs known-full and known-empty learning cycles
Cost and complexity Low Higher
Fits Student projects, single cells Products, multi-cell packs, precise runtime prediction

For student work, the ModelGauge approach wins on simplicity: no shunt sizing, no precision layout, no learning cycles. Move to coulomb counting when the project demands it — runtime predictions in minutes for a mobile robot, or multi-cell packs where per-cell tracking matters.

Whatever gauge you choose, validate it once against reality: fully charge the cell, run the node until cutoff, and compare the gauge's reported curve against the actual runtime. That single discharge test calibrates your expectations and gives your report a real measurement instead of a datasheet claim.

Common mistakes checklist

  • Voltage-threshold thinking. If you wanted thresholds you did not need the chip — use the SOC output.
  • Reading during transmit peaks. Sample when the system is at rest, or average several readings.
  • Forgetting quick-start after battery swap. The gauge's model tracks the old cell; reset it when the battery changes.
  • Ignoring the alert pin. Polling SOC every second wastes the power you are trying to manage — interrupt instead.
  • Multi-cell pack on a single-cell gauge. One MAX17043 per cell chemistry assumption; packs need different designs.
  • No chemistry check. LiFePO4 and other chemistries need different gauge approaches.

Where to go from here

More project guides

More in IoT & Embedded