Battery Bank State-of-Charge Monitor
Count every amp-hour in and out of a small LiFePO4 battery and show a real percentage instead of guessing from voltage.
LiFePO4 voltage stays almost flat between about 20% and 90% charge, so a voltmeter can't tell you much. Coulomb counting adds up current over time — the same method used by commercial battery monitors.
Fuse the battery's positive lead close to the terminal, use wire rated for the current, and never short a LiFePO4 battery — it can deliver very high current.
Mission steps
Place the sensor
Put the INA219 in series with the battery's negative or positive lead so every load and charge current passes through it.
Mind the limits
The common INA219 board with a 0.1 Ω shunt reads up to about 3.2 A and 26 V, which suits small 12 V banks; bigger systems need a higher-current shunt monitor.
Count amp-hours
Every second, add charge current and subtract load current from the stored amp-hours.
Re-sync at full
When voltage reaches the charger's full level and current tapers off, reset to 100% to cancel accumulated error.
Show it
Print to a terminal, an OLED or a small Flask page with percentage, watts and estimated hours left.
Code
import time, board, adafruit_ina219
ina = adafruit_ina219.INA219(board.I2C())
CAPACITY_AH = 6.0
ah = CAPACITY_AH # assume full at start
FULL_V, TAPER_A = 14.2, 0.1 # adjust to your charger
last = time.monotonic()
while True:
time.sleep(1)
now = time.monotonic(); dt = now - last; last = now
v, a = ina.bus_voltage, ina.current / 1000 # amps; + = charging (depends on wiring)
ah = max(0, min(CAPACITY_AH, ah + a * dt / 3600))
if v >= FULL_V and 0 <= a < TAPER_A:
ah = CAPACITY_AH
soc = 100 * ah / CAPACITY_AH
hours = ah / -a if a < -0.01 else float('inf')
print('%.2f V %+.2f A %5.1f %% %.1f h left' % (v, a, soc, hours))Tip: test every script on the bench before installing it in a moving machine.
Questions
Why does my percentage drift over days?
Small measurement errors add up. Regular full charges re-sync it; that is why commercial monitors need a full charge from time to time.