I want to measure the voltage of a LiFePo4 battery with an ESP32 and have two options connecting the battery to the MCU:
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
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
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
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.
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).
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
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...?
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%