Voltage monitor of battery
Posted: Wed Jan 13, 2021 5:41 pm
So, I've read a ton of forum posts here and elsewhere - I get the non-linearity of the ADC, at below 0.5v and above 2.5v.
I know about the attenuation, etc.
But the voltages I'm reading from the ADCs are just wrong - and don't fit any of the details I've read about. I assume I *must* be doing something wrong, but for the life of me, I'm not sure what.
I'm using a cheap ESP32 D1 Mini board. It works for the other stuff I've tinkered with. I don't think it's a board problem.
Here's a sample of how I'm reading voltage. (The end intent is to monitor an 18650 - I know I'll need a voltage divider - and I've got that handled. However, I'm currently using a 10K POT to check the voltages I get from the ADC against a Fluke 189 DMM to ensure accuracy, etc. The pot is fed from the 18650, and I'm generally measuring voltages from 1v - 2.5v - which should be the sweet-spot for the ESP - since the ADC should be highly linear here.)
I've also tinkered with several different pins. (ADC 2-6, and ADC's ADC1-5,6,7) All produce pretty similar readings.
Here are some readings I've gotten.
As you can see, the ADC doesn't match the DMM at all. At 1v, it's 0.0559v below the DMM, and at 2.5v, it's 0.0837 above. (This will be compounded when I use a voltage divider, since a 10K/10K divider will halve the voltage, so a 0.0837 error becomes an actual voltage error of 0.1674. And the total swing between 2.5v and 1v is 0.139v across that range - that's HUGE.
Some limitations.
I don't have a scope.
I don't know my DMM is accurate, but I have no reason to question it. It's also not a cheap POS, which makes me trust it.
I don't really know a lot about what I'm doing, so it's possible I'm making some stupid mistake.
Here's the "guts" of the code I'm using to read the ADC and calculate voltage.
Any suggestions on what I'm doing wrong?
I know about the attenuation, etc.
But the voltages I'm reading from the ADCs are just wrong - and don't fit any of the details I've read about. I assume I *must* be doing something wrong, but for the life of me, I'm not sure what.
I'm using a cheap ESP32 D1 Mini board. It works for the other stuff I've tinkered with. I don't think it's a board problem.
Here's a sample of how I'm reading voltage. (The end intent is to monitor an 18650 - I know I'll need a voltage divider - and I've got that handled. However, I'm currently using a 10K POT to check the voltages I get from the ADC against a Fluke 189 DMM to ensure accuracy, etc. The pot is fed from the 18650, and I'm generally measuring voltages from 1v - 2.5v - which should be the sweet-spot for the ESP - since the ADC should be highly linear here.)
I've also tinkered with several different pins. (ADC 2-6, and ADC's ADC1-5,6,7) All produce pretty similar readings.
Here are some readings I've gotten.
Code: Select all
DMM - ADC - ADC/DMM (in percent)
2.5063 2.59 103.34%
2.4042 2.46 102.32%
2.299 2.35 102.22%
2.201 2.24 101.77%
2.1055 2.13 101.16%
2.0029 2.02 100.85%
1.9025 1.92 100.92%
1.8017 1.81 100.46%
1.7052 1.7 99.70%
1.6009 1.59 99.32%
1.5031 1.49 99.13%
1.403 1.37 97.65%
1.3009 1.27 97.62%
1.2076 1.17 96.89%
1.1061 1.06 95.83%
1.0059 0.95 94.44%
Some limitations.
I don't have a scope.
I don't know my DMM is accurate, but I have no reason to question it. It's also not a cheap POS, which makes me trust it.
I don't really know a lot about what I'm doing, so it's possible I'm making some stupid mistake.
Here's the "guts" of the code I'm using to read the ADC and calculate voltage.
Code: Select all
#define VOLTAGE_MON_PIN 14
analogSetAttenuation(ADC_11db);
//ADC_0db ADC_2_5db ADC_6db ADC_11db
adcAttachPin(VOLTAGE_MON_PIN);
analogReadResolution(12);
analogSetCycles(253);
avg_dig_voltage=0;
x=0;
//sample the ADC 20 times to get an average.
while (x<20)
{
cur_dig_voltage = analogRead(VOLTAGE_MON_PIN);
avg_dig_voltage += cur_dig_voltage;
x++;
}
avg_dig_voltage= (avg_dig_voltage/20);
cur_voltage = ((3.3/4095)*cur_dig_voltage);
avg_voltage = ((3.3/4095)*avg_dig_voltage);
Serial.print("Current digital voltage level: ");
Serial.println(cur_dig_voltage);
Serial.print("Avg digital voltage level: ");
Serial.println(avg_dig_voltage);
Serial.print("Current Voltage: ");
Serial.println(cur_voltage);
Serial.print("Avg Voltage: ");
Serial.println(avg_voltage);