Read LiPo volt - more accurate reading ESP32

Hi

Im trying to do a more accurte voltage reading on my ESP32-WROOM

Hardware; LiPo batt max charging to 4.2
voltage divider is 1k + 1k ohm

I have used this code for reading battery voltage:

spenningLiPo = (float)(analogRead(LiPoPin)) / 4095 * 2 * 3.30 * 1.10;

Raw volt is 2257
This gives me a reading of 4.00 volt (in this moment) when using code above.
It works, but not too accurate.

I red from github user G6EJD
G6EJD/ESP32-ADC-Accuracy-Improvement-function

This code gives also raw 2257
but G6EJD gives calculated reading of 1.814 V

Can you please kick me in the right direction to solve my need for a more accurate voltage reading?

Just a hunch, but don't you need to add f to the calculation constants as in
4095f * 2f * 3.30f & 1.10f

Hi

Not sure if you understood my post.

My code works for this:
spenningLiPo = (float)(analogRead(LiPoPin)) / 4095 * 2 * 3.30 * 1.10;

I will try to ad the f's but my question is that I want to improve accuracy and my formula above is not good enough.

So question is to get some help/input to make a more accurate reading/calculation, I tried the code from G6EJD, but it gives not correct reading, and I cant find my "mistake".

M

I did understand your post. Try what I suggested and tell us the result.

@Modesty
Use analogReadMillivolts()

This function is used to get ADC raw value for a given pin/ADC channel and convert it to calibrated result in millivolts.

uint32_t analogReadMilliVolts(uint8_t pin);

1 Like


It's 4AM, so my earlier syntax might be off, but all those constants need to be written in a way that the compiler treats them as floating point. If not, the data will be off since 1.10 is quite different from 1.

@sonofcy thanks for clearing up.

I will do a test with f's!
image

Also did some research to make my own polynome formula.

I must do some volt test and get it into excel:

Example:

Why not use analogReadMillivolts, already calibrated.

Hi

Sorry, because I did not understand it...
Seems to be a much better approach than my initial idea!

like this?

uint32_t batLiPo = uint32_t analogReadMilliVolts(uint8_t LiPoPin);

M

Yes.
Since your voltage divider cuts the voltage in half, then just multiply batLipo by 2.0.
You may want to take several readings and then take the average value

You should spend some time reading the documentation for the ESP32
https://docs.espressif.com/projects/arduino-esp32/en/latest/libraries.html

2 Likes

Thanks Jim, you are a good advisor, for the last few years!

What about analogSetAttenuation()?

Should I use analogSetAttenuation() as a rule?

I have a voltage divider, can I remove that and use
ADC_ATTEN_DB_6 (6 db is half as I understand) to measure up to 4,2 V (battery fully charged).

M

The pin of a 3.3volt processor can't take more than 3.3volt, so you do need a voltage divider. 1k:1k is a drain on the battery though. I would use something like 220k:100k, with a 100n cap from pin to ground.
Leo..

1 Like

analogReadMillis() set the attenuation to 11dB and you do not want to change that.
You still need the voltage divider but use higher values.

batLiPo = uint32_t analogReadMilliVolts(LiPoPin);
BatteryVoltage = batLiPo / 0.75;

FYI:
The ESP32 ADC is not very accurate. With analogReadMillivolts the error can be +/-60mV

1 Like

@jim-p
110k:330k gets you more A/D values, but I picked a 100k:220k ratio to keep battery voltage more in the linear region of the A/D. Not that it makes much difference.
Leo..

1 Like

It doesn't. I picked them so it came out to 3/4

1 Like

Thanks for info

Battery charges to ca. 4.2 V so 110:330 gives 3.15 V as fully charged.

as @jim-p stated: 3,15/0.75 = 4.2

M

Actually @Wawa is right about keeping it in the linear region. When the battery voltage is at 3.7V, you want the input to the ADC to be less than 2450mV
So now I suggest making R1 = 162K and R2 = 301K. The ratio is now 0.65
This will give the best accuracy when you are trying to determine if the battery is near the end of it's capacity

1 Like

Hi

thanks for your info.

My system is to run 365 days a year (bee hive monitoring), and I use superCap (5V5 / 10F) due to cold winter, and LiPo as backup. Also uses solar to charge.
(i have never used a superC so Im a bit on deep water).

To control charging I read all voltages and tempereatur to determine charging priority.

One cycle of system is around 2 sec, and then go to sleep for a time X (1/2 h/ 2h, 18/h), max power in one cycle is 200mA (lora).

So a combo of voltages and temp I will decide witch bat to a) use b) charge.

This logic is not fished, and I find it challenging. I expect I will send some question's on this forum when I have my new HW ( version with super cap is only schematic by now) and struggle to find best optimization.

@jim-p schematic updated
image

Cheers
M

Just to be clear it's 162K and 301K

1 Like