SOC is an estimate, not a measurement

Here is the thing nobody tells you when you first open a BMS app: that big percentage in the middle of the screen is not measured anywhere. There is no fuel-level sensor inside a lithium cell. The state of charge is a running estimate the BMS maintains, and like any estimate it drifts. Once you understand how it is calculated, every weird SOC behaviour you have seen suddenly makes sense.

How the BMS counts

The BMS does what accountants call bookkeeping: it measures current flowing in and out through a shunt, multiplies by time, and adds or subtracts from a running total. Charge 10 Ah into the pack, the counter goes up by 10 Ah. This is called coulomb counting, and it works well — except that every measurement carries a tiny error, and the errors accumulate. Week after week, the running total slides away from reality.

To stop the slide, the BMS re-anchors the counter whenever the pack reaches a state it can recognise with certainty — usually completely full, when the voltage hits the top and the current tapers to nothing. That moment resets the estimate to 100%, and the bookkeeping starts fresh. If your pack never reaches full, the counter never re-anchors, and the drift compounds.

Classic symptoms of drift

You can diagnose SOC drift from the couch, because it always looks the same. The percentage jumps suddenly — from 76% to 89% without explanation — when the BMS finally re-anchored. The pack sits at 100% for ages and then falls off a cliff. Or the vehicle dies while the app still swears there is 20% left. None of these mean the battery lost capacity overnight; they mean the estimate and the reality drifted apart, and reality won.

The calibration cycle

The fix is to give the BMS the reference point it has been missing. Once a month, or whenever the numbers feel dishonest, run one deliberate full cycle:

  1. Charge the pack completely, and keep the charger connected until the current tapers near zero — not just until the app first says 100%.
  2. Let it rest for half an hour.
  3. Use the pack normally down to around 20–30%.
  4. Charge fully again, letting the taper finish.

Watch the app during the second full charge — you will often see the percentage snap to 100% along with a small jump in reported capacity. That snap is the recalibration happening. Packs that get a full charge regularly hardly ever drift far in the first place, which is the real lesson: the calibration cycle is only dramatic if you have never done one.

Why LiFePO4 is worst

If your pack is LiFePO4 — and most e-rickshaw and solar packs are — drift hits harder. LiFePO4's voltage curve is nearly flat between roughly 20% and 90%, so voltage tells the BMS almost nothing in the middle of the range. It cannot sanity-check the coulomb counter against voltage the way other chemistries can; the counter is all it has. The full-charge anchor is therefore not optional maintenance for LiFePO4. It is the only calibration mechanism the pack gets.

When it is not drift

Calibration fixes bookkeeping errors; it does not create capacity. If the pack recalibrates cleanly and the usable range is still short, look at the reported cycle count and full-charge capacity in the app — a pack showing far less capacity than its label after a proper full charge has genuinely aged. And if one cell's voltage sags away from its siblings under load in the cell voltage view, your problem was never SOC at all: a weak cell drags the whole pack down and cuts the ride short regardless of what the percentage claims.