# Calculate battery percentage on LiPo battery?

I have voltage measuring on my LiPo battery that is defined full at 4.2V and empty at 3.2V. This reading is very accurate but I want to convert this to percentage numbers. I know that the percentage of energy left in the LiPo is not linear to the voltage levels, but I would be fine with defining a linear approximation of the percentage left. Something like (4.2V-3.2V)/100 would give me 1% increments.

The issue I'm facing is how would I program this to show the percentage? It seems like ridiculously bad coding to have a switch statement with 100 cases, each for every percentage like the pseudocode under:

Switch(BattVoltage)
case: BattVoltage > 4.19                         "print 100%"
case: BattVoltage < 4.19 && BattVoltage > 4.18   "print 99%"
.
.
...


How would one do this in a smart manner?

• That's really more of a programming than an electrical engineering problem, and what's smart and/or elegant depends on your programming language of choice, and while I'd usually assume C here, your syntax is nowhere related to C's switch-case statement, soooo I'm afraid this might be either not formulated as the electrical engineering problem that you'd solve on this site, or missing the language tag that it'd need on stackoverflow.com Commented Apr 28, 2019 at 9:28
• I know it is a programming issue, but I considered the issue at hand which is a LiPo battery and that it is useful to understand the workings of a LiPo battery to solve this equation. There might even be an equation directly related to the LiPo battery. Regarding the language it isn't important really, only the method by which to solve it. Commented Apr 28, 2019 at 9:30
• In this case a simple expression like round((Vbat-3.2)*100) would give you a percentage you could print. But be aware that the percentage of charge remaining is not even remotely close to the voltage at the battery terminals. Commented Apr 28, 2019 at 9:33
• The SOC/voltage curve for LiIon cells is relatively well defined at a given discharge rate. Battery university provides information on how curves change with discharge rate and temperature. Commented Apr 30, 2019 at 1:47

If you already have your voltage readings represented as voltage numbers (i.e. as you have shown 4.2, 3.9 or 3.2) you will want to convert these to integer numbers. Integer math is easily supported on almost all computing scenarios where you are taking the voltage readings. You would start by multiplying the voltage readings by 100 so you have numbers from 420 down to 320. Next you subtract 320 from the measurement value so you have numbers in the range of 100 down to 0. This leaves you with results which will be in direct units of percentage.

On the other hand you may very well be using the A/D converter on some microcontroller to take the voltage readings. A common example for consideration would be a 10-bit converter with a full scale reading of 5V. Such converter gives readings in a range from 1023 down to 0. The A/D value that would correspond to 4.2V would be 862 and for 3.2V would be 656. To convert numbers in this 862 to 656 range you subtract 656 from your A/D reading value to get numbers in the range of 206 down to 0. A simple divide by 2 comes very close to the integer percentage range of 100 to 0 so you may choose to just accept that a result over 100 is same as 100% and call things good. (Note that I would expect that on a real hardware setup that the A/D readings may not be exactly as shown above and you may have to tweak your calculations some. It may be required for example to multiply your A/D reading by 10 so then when you scale to the percentage reading that you can have more flexibility to divide by numbers around 20 rather than dividing by 2 as I suggested above to get closer to a full 100 down to 0 percentage range).

All of this of course is based upon a linear relationship of voltage to battery capacity. That may be good enough for what you are trying to do but will probably not represent the actual remaining capacity of your battery. There are chips available that are able to measure charge going into to the battery when it is being replenished and then measure charge leaving the battery when it is being depleted. Using one of these chips will give you a much better tracking of remaining battery capacity once you characterize the readings from such chip with whatever battery you are using. To learn more search for "battery metering chip" or "battery gas gauge chip".

• LiPo batteries do not have a linear relationship between voltage and battery capacity. If they did then the formula for converting the voltage to % would be BattPercentage = (Vmax - Vmin)/100 * (BattVoltage - Vmin) and if you want to protect against a battery going out of the specified range, you would then do BattPercentage = max( min( BattPercentage, 100 ), 0 ) Commented Jun 13, 2023 at 19:49
• @Stefan Yes. He did cover that in his last paragraph, and the OP said that a linear approximation may be acceptable (although a good linear approximation wiuld be better :-) ). Roho's answer gives a good lead even if probably not a perfect fit to his case. Commented Jun 14, 2023 at 2:13

According to some empirical values I found on the *net, this seems to be a quite accurate estimation of remaining energy (in percent) of a typical lipo (rated 3.7V, fully charged at 4.2V):

$$123 - {123\over(1 + (v/3.7)^{80})^{0.165}}$$

This was based on measured values found on the Ampow: Lipo Voltage Chart that I curve fitted using MyCurveFit.

The least you should do is square the measured voltage, because power is proportional to the square of voltage. This would be accurate if the battery was a linear capacitor, which it unfortunately is not.

• Thanks @SamGibson for editing my text. The Ampow website is for RC batteries, which are the high discharge ones (low Rs). I guess the lower power ones found in, say, mp3 players, phones and laptops might have (slightly) other characteristics.
– Roho
Commented Oct 19, 2021 at 22:24
• +1 2 years on.. The curvefit page was good to know of. || The voltage-capacity curves for RC LiPo are interesting. They do note that Vcell MUST never go under 3.0V - which I agree with. Their 3.71V at 15% capacityis substantially different to what you'd get from batteries load at "sensible" levels - which RC isn't :-). 3.6V or 3.7V is usually given as the mean voltage of a LiIon cell across its discharge range. So, interesting. || I'm also somewhat surprised at the shape of his curve, but it may well be OK. Commented Jun 14, 2023 at 2:45
• @RussellMcMahon If you fill in your 3.0 V in the formula, you will find that at this voltage about 1 ppm of the battery capacity remains. This will round to 0 in any battery energy gauge. Of course, a battery protection circuit of some sort should be used to protect from cell damage due to over-discharge and over-charge. This is beyond the scope of this topic. The shape of the curve was chosen from the available 'prototypes' in MyCurveFit that best matched the values found on the Ampow site.
– Roho
Commented Aug 28, 2023 at 9:06
• "My" 3V was the V_min_absolute from the link. Not what I'd suggest as a discharge limit (no surprise :-) ). If by 1 ppm you mean "1 part per million" that would be rather low for small prismatics, and maybe a modest exaggeration for larger RC batteries or cylindrical "power cells". Figures 1 & 2 here (battery university) are for 18650s but seem likely to reasonably represent small and large prismatics. The fig 2 curves dive rather steeply with 1C energy under 3V maybe 0.1% or so. Maybe ~=2% for NCR18650B Commented Aug 28, 2023 at 12:44

Either you can try to find a mathematical model or (which is mostlikely much more ressources efficient) you implement a lookup table which in the end boils down to something similar to your case thingy but is more elegant code wise. Depending on the used env/language you should find enough ressources explaining the implementation of lookup tables.

First off, thanks to @Roho for the tip on using an online curve fitter. Unfortunately, with MyCurveFit you can only enter a limited of number data points without registering, and even then, if you want to fit more than a trivial number of data points they make you pay, who are they kidding? I used https://curve.fit instead (much better and no BS)! I have a GPS tracker that sends voltage but not % remaining. It makes sense because normally the tracker would be attached to a vehicle battery which is constantly being charged, so not all that important to monitor, although I do calculate that as well since it's normally powered by my ebike battery which I also monitor. However, when unplugged, it uses the GPS internal backup battery, and I wanted to be able to monitor % remaining when unplugged. I use flespi.com to intercept, analyze, and modify data before sending it to the tracking platform. I fully charged the tracker, then looked at voltage data points sent to flespi until the internal battery cut off. The tracker sent 800 data points (one every 30 seconds) until the battery cut off. Column X is the voltage for data point n. Column Y is estimated % remaining = 100% - 100%/800 * (n-1). I pasted the X and Y values into curve.fit and found a quadratic gave a reasonable fit. Much better than linear! Quartic would be even better. The tracker has a 3.7V lipo battery but is reporting a much higher voltage than would be expected. This ultimately doesn't matter, I just need to convert voltage sent to the server (overstated or not) to estimated % battery remaining. I guess the takeaway here is every battery is different, voltages may be overstated or understated, and one size does not fit all. If you have the data it's fairly easy to roll your own!