Logic For AmpHour Meter

I have built a Battery Management System (BMS) for a 200 Ah, LiFePO4 battery bank using a commercial BMS for most safety/battery protection functions with an Arduino for controlling the charge sources based on individual cell voltages and current.

I measure cell voltages and current to determine the end-of-charge condition and then integrate the current drawn over time to give me AmpHours.

When charging is complete the Arduino turns off the charging relays and sets a integer variable representing state of charge (SOC) to 200 ... a "full" battery with 200 Ah.

The sketch then monitors current out in each iteration, multiplies it by the elapsed time [using millis() function] and converts the product from Amp-milliseconds to Amp-Hours.

The sketch deducts the AmpHours in each iteration from the SOC and basically counts down as the bank is depleted. It gives an audible alarm at 100 AmpHours (50% remaining) and at 40 AmpHours (20% remaining). The BMS shuts down all relays, isolating the battery from everything before the voltage of any individual cell gets low enough (or high enough) to cause damage.

For various safety reasons, recharging is only initiated by manually activating a momentary switch. This turns on the charge sources. When charging is complete, the AmpHour counter is reset to 200 and then begins counting down again.

I want to add a feature that writes the SOC to EPROM for recovery in any case where the Arduino loses power, is shut down by manual reset, or shuts down for any other reason.

I know that the EPROM has limited writes, so cannot write the SOC to EPROM inside the loop - at least not every iteration.

I also know that a write to EPROM can (somehow?) be programmed to happen only when the value of SOC has changed but, this value is continuously changing.

I am wondering whether there is some technique that would allow me to read the SOC variable from the EPROM once during setup, let it count down in the loop, and then only update the EPROM in the instant before a reset is executed or in the instant between power loss (Vcc declining but not yet zero) and actual shut down? In that case, the SOC will be available to be read during setup when the Arduino resets or repowers.

Any thoughts or different ideas would be appreciated.

All good, so far but here is my question:

Is there a simple way


One option is to write to the EEPROM only when the SOC has decreased by a certain amount. Storing a time stamp might be useful, as well, if you have a real time clock module.

However, if the battery continues to discharge when the Arduino is not running, the stored value won't be correct anyway.

It may be sufficient to update the EEPROM when the SOC has changed by a specific amount - for example if you only update the EEPROM when it changes by 1 unit there would be a max of 200 writes for every re-charge. And with 100,000 write cycles that would allow for 500 charge cycles. Updating with wider intervals would extend the life of the EEPROM.

With a little more coding effort you could implement wear-levelling. For example each day you could write to a different EEPROM location and then you could continue to operate for many more charge cycles. One EEPROM location could be used to identify which location is being used today.


PS ... The last paragraph of Reply #2 is important

Sorry to have troubled you Mrs. Drew.

spycathcher2k, jremington, and Robin2: thank you very much for your helpful and quick responses.

I will update eprom at every 2 AmpHours and then with some wear levelling the eprom should outlast the battery life.

If BMS loses contact with Arduino it opens all relays (load bus, charge bus, and master) so bank should not discharge while Arduino is off.

Thanks again.