Percentage Based on LiIon Voltage

As part of my LocalPaper project, I wanted to have a battery indicator. However, Trmnl device I use reports only voltage, leaving conversion to percent reading to the software. So, how to convert it?

After charging the Trmnl device, I saw that fully charged its voltage goes to 4.1V. If I check docs, I can see that voltage cutoff for their battery is at 2.75V. So, one could be tempeted to set those as limits. But, there are two issues with that approach.

First, you should not wait until cutoff point as this means you are close to (potentially) damaging the battery. You should probably report 0% before you allow battery’s safety to kick in. Also, I have only 1 device and thus 4.1V measured here might not be what other devices would show.

Fortunately, for more data, we can turn to flashlight crowd. While not conclusive, we can see that 4.1V maximum is probably spot-on. For minium, we could just go with 2.75V safety cut-off, but I would actually recommend 3.1V. Why? Well, it’s higher than safety cut-off and it actually makes math really easy. So, my suggested formula for turning voltage in percentages would be:

Percent = (Vmeasured - 3.1) * 100;

And yes, this could go under 0% or over 100% so we might want to adjust it a bit:

Percent = (int)Math.Min(Math.Max(Math.Ceiling( (Vmeasured - 3.1) * 100 ), 0), 100);

Is this precise? Not really. But thanks to LiIon rather linear voltage curve, it’s actually precise enough. We lie at the top range because we don’t want users to overcharge the battery and/or end with fully charged battery showing 99%. We lie at the bottom range because we don’t want to drain battery fully before user goes to recharge. But overall, we do use most of energy stored in the battery. And, we’re not stopping user from going down to the cut-off point. We’re just not going to encourage it.

But what if you have somee other priorities and you want to select other points? Well, formula above would probably not work since it depends on 1V range. We need something slighlty more general.

Vmin = 3.1;
Vmax = 4.1;
Percentage = (int)Math.Min(Math.Max(Math.Ceiling( 100.0 * (Vmeasured - Vmin) / (Vmax - Vmin) ), 0), 100);

Not precise, but probably good enough for any purpose you might need it for.