static const uint8_t lifepo4[NUM_BATT_READINGS][2] = {
{144, 100}, {136, 100}, {134, 99}, {133, 90},
{132, 70}, {131, 40}, {130, 30}, {129, 20},
{128, 17}, {125, 14}, {120, 9}, {100, 0}
};
int16_t measurements_get_batt_perc(int16_t mv)
{
int16_t pct = 0;
int32_t x1, x2, vD, pD;
int32_t theta;
if (mv >= lifepo4[0][0]*100)
pct = lifepo4[0][1]; // cap value at 100%
else
{
for (int i=0; i<NUM_BATT_READINGS-1; i++)
{
// put voltages into mV instead of 100s of mV
x1 = (int32_t)(lifepo4[i][0])*100L; // Higher value
x2 = (int32_t)(lifepo4[i+1][0])*100L; // Lower value
if (mv <= x1 && mv > x2)
{
vD = x1-x2;
pD = (int32_t)(lifepo4[i][1] - lifepo4[i+1][1]);
if (pD != 0)
theta = pD*10000/vD;
else
theta = 0;
pct = lifepo4[i][1] - (x1-mv)*theta/10000;
break;
}
}
}
return pct;
}
The code is calculating battery percentage based in a LUT from this table:
https://www.mobile-solarpower.com/diy-lifepo4-solar-battery1.html
Does anyone have an idea or a better approach to help calculate battery percentage? The voltage is changing with respect to load. Is there a known formula for calculating battery percentage with a varying load etc? Or what is the best way to fuse the integral of current with voltage?
The battery percentage follows the chart provided however it does not take into account the current load and therefore is not displaying an accurate estimate.
OP is on the right track.
Some ideas:
if (mv <= x1 && mv > x2)only one test needed with a monotonic_function.Lack of in-code documentation left unclear the meaning of the
lifepo4.Scaling by
100Lmay incur 64-bit math. Only 32-bit needed.Consider rounding.
Use better names.
Let
lifepo4[]driveBATT_READING_Nrather than the other way around.