ESP32 ADC measurment with variable input voltage?

I want to measure the voltage of a LiFePo4 battery with an ESP32 and have two options connecting the battery to the MCU:

  1. The LiFePo4 can be connected directly to the 3.3V input pin since the ESP can handle the whole range of the battery and it is commonly done
  2. I can use an LDO that regulates the voltage down to 3.3 if the battery is above 3.5V and then the input voltage drops with the discharge of the battery
  3. I can use a buck/boost circuit that always puts 3.3V into the ESP.

So I either want to be energy efficient (option 1) or have a very steady supply voltage (option 3). Option 2 doesnt do anything really good and would be only used with LiPo batterys in my opinion.

My question is: Do I even get an accurate voltage measurment with option 1 where the batterys voltags, and thus also the voltage input of the ESP, varies between 3.2 and 3.6V? Or is the reference voltage also varying so that it makes it impossible to measure accurately and I have to use option 3?

The Uno has an internal fixed reference you can select as an option. Look to see if the ESP32 has one. If so, drop your battery voltage to a compatible range with a large-value divider, measure that, and back-calculate the actual battery voltage.

At full charge, the battery voltage can be as high as 3.65V, which could damage the input. Connecting the battery directly to the input may be "commonly done", but that is not a positive recommendation.

In any case, the ESP32 ADC is defective and nonlinear, so it is not very useful for making accurate measurements.

The ESP32 uses an internal voltage refrence of 1.1V. So if you stay within the recommended operating voltage range, the ADC measurments will be within specs.

LiFePO4 can go as high as 3.65V but if you don't fully charge the battery it should be OK

Charging it using a CN3058E ::: ALLDATASHEET ::: should be fine, right?
It charges up to 3.6V +-1.5%

3.6 x 1.015 = 3.654V . So no good
You need to charge it, then discharge it untll it's just below 3.6V

How reliable to do you think it is to generate the 1.1V inside the ESP32 when the input voltage is varying between, 3.0 and 3.6V?
I have found this thread here which states that some users get very different ADC voltages depending on the input voltage:
How to measure voltage of battery using ESP32 internal reference voltage? - Using Arduino / General Electronics - Arduino Forum
Could the cause be that the reference voltage is not generated reliable?

The easiest way is to put a voltage divider with high value resistors; 1M Omh each. And a ceramic capacitor of 100nF from the middle point to GND, to have enough current for the short readings.

This way you will convert the voltage range of the battery from about 2.5V - 3.7V to half: 1.25V - 1.85V
This is also better for accuracy, because the ADC is not very precise in the extremes of the range, but in the middle is good enough.

This way it works fine.

the voltage divider is already done and exactly like you described.
still, even the perfect output of the divider has no use if the reference voltage is not steady

What level of accuracy is ok for your needs, what is ADC used for?
One tip, ESP32 internal ADC attenuator is very nonlinear, so if you want accuracy use 0dB attenuation in code settings (in this configuration, max input voltage is about 950mV, so you need to reconfigure external attenuator).

Very

I have found this thread here which states that some users get very different ADC voltages depending on the input voltage:

It seems that the OP was somewhat confused about the ADC and could not prove his claims.

The charge courve of the battery type is very flat.
LiFePO4 Voltage Chart (3.2V, 12V, 24V & 48V) - BatteryFinds
Almost all the charge is between 3.3 and 3.2 volts.
So I would need an accuracy of about 0.05 volts I think. Especially if the battery drops from 3.30 to 3.25, the reference voltage needs to be steady enough that although the input voltage of the ESP varies in that range, the reference voltage needs to be steady enough that the ADC measures that difference.
I have no problem with manually adjustig/calibrating the voltage values. It is just important for me that I can still measure wether the state of charge is, lets say, 60% or 40%. I dont need an accuracy of 1% of state of charge, but at least 10% would be good

According to the data sheet, provided you are measuring DC, have a 100nF capacitor connected to the ADC input and have WiFi and Bluetooth turned off, then the best total ADC error after calibration is +/-2.4%
The ESP32 ADC is not known for it’s accuracy.

As jim-p said, the voltage reference is completely stable and independent of VCC level. It works well.

For the previous version of the ESP32 the accuracy was good between 0.5V and 2.5V And for the new ESP32-S3 it has improved and is not a problem anymore. Anyway better stay away from the rails.

So, in the worst case you will have good accuracy from 0.5V to 2.5V. Adjust the voltage divider to that range and test if it is enough for you. For testing the battery level should be ok. I have done and it works very well.
Put the capacitor close to the MCU pin, and take several samples in your code and average them.

And the ADC comes already calibrated, if I'm not wrong. What will be not calibrated are your resistors, so you have to adjust in software anyway.

ok, but if the voltage is divided by 2 by the voltage divider, that value needs to de doubled right? So it would be about 5% inaccurate

But how is that technically possible? I can not understand that.
How can it just set something to such a stable voltage without comparing it to anything? Would there not have to be some stable voltage to achieve a steady reference voltage?

good that I chose the S3 then! I did not know that

No it's still +/-2.4%
However everything I have said applies the the ESP32 NOT the ESP32-S3

A voltage reference is an electronic device that ideally produces a fixed (constant) voltage irrespective of the loading on the device, power supply variations, temperature changes, and the passage of time. Voltage references are used in power supplies, analog-to-digital converters, digital-to-analog converters and other measurement and control systems.
Voltage reference - Wikipedia

You could check how it is done technically, but you don't have to worry about that. It is something internal to the chip and it's used by its circuitry, not by you.
You have to focus in the specs of the ADC, how to use it, in the datasheet.

Which module do you have? ESP32, ESP32-S3, S2, C3...?

1 Like

In my schematic I have currently put in an ESP32 S3 Wroom and reading your last comment give me confidence to keep that

For the S3, according to the data sheet, provided you are measuring DC, have a 100nF capacitor connected to the ADC input and have WiFi turned off, then the best total ADC error after calibration is +/-0.55%

1 Like

Yes, ESP-S3 is a very good MCU and the ADC is better than in previous versions. But anyway it would work fine.

You can create the divider with 470KΩ and 1MΩ resistor, put the 100nF capacitor, switch off the wifi and calibrate.

You could even take several samples every time and average them, but I think that you don't need a lot of precision anyway.