Electronic – esp32-wrover ADC, incorrect values

adcesp32

I'm trying to understand the ADC pins on an ESP32-WROVER, I can't seem to figure out the values I am reading. I've been trying to read the voltage of a battery but haven't been able to get any good results, I've tried using ADC1 channels, ADC2 channels, via Arduino analogRead and esp-idf toolchain adc1_get_raw, adc2_get_raw but all give me readings I can't seem to interpret.

I ended up taking the esp32 out of the circuit I am trying to build just to test with so I put in the bare minimum, e.g. GND(1), VCC(2), EN(3), GND(15), IO0(25) and the ADC2_7(12). I then applied voltage to the ADC pin in increments of 100mV.

The mappings I got were:

ADC_ATTEN_DB_0: 0-1.09V = 0-4095

ADC_ATTEN_DB_11: 0-3.09V = 0-4095

From my understanding (and it is very limited), I would have expected that +3.3V would equal around 4095 with ADC_ATTEN_DB_0 (a 1:1 mapping). What am I missing? How come the readings aren't what I'm expecting?

The code I use to read the ADC2 channel is:

// .. called once during init
adc2_config_channel_atten(ADC2_CHANNEL_7, ADC_ATTEN_DB_0);

// .. called in a while loop with a 2ms delay
// ADC_SAMPLE_COUNT = 64
uint32_t result = 0;

for (int i = 0; i < ADC_SAMPLE_COUNT; ++i)
{
    int v = 0;
    adc2_get_raw(ch.first, ADC_WIDTH_BIT_12, &v);
    result += v;
}

result /= ADC_SAMPLE_COUNT;

Also, just to note, during my poking around, when I apply voltage to one of the ADC pins it would affect the reading of another pin that was not connected to anything (I don't remember which ones now) but is this normal?

Update 00

In the esp32 datasheet I found the following:

Atten=0, effective measurement range of 100–950 mV –23 23 mV
Atten=1, effective measurement range of 100–1250 mV –30 30 mV
Atten=2, effective measurement range of 150–1750 mV –40 40 mV
Atten=3, effective measurement range of 150–2450 mV –60 60 mV

Atten=0 = Db0 and Atten=3 = Db11 these are pretty close to the readings I was getting.

Also, after more searching I found someone that did some tests and came to the conclusion that using 11 bits for the capture width and Db6 for attenuation along with a capacitor give a much nicer linear set of readings.

By simply probing at the low range and high range I was able to map the adc reading to the voltage reading. Once I got the mapping correct, I then changed the attenuation back to Db11 and re-probed, updated the mapping and it was quite obvious that the readings were no longer linear.

I couldn't create an ADC characteristics to produce an accurate voltage, so I went back to Db6 and the manual mapping, it works, which is fine; I suppose.

Update 01

After much reading and poking around, the esp32 ADC is a all over the place, not sure if this is normal as this is all still new to me and first time using ADC.

  • The range of ADC input will depend on what the attenuation is configured as; the datasheet lists the values.
  • Instead of configuring a characteristics to convert from a raw value to voltage, I ended up probing to find the low end and high end of reading and then mapped the raw adc value, which worked fine. e.g. \$\frac{(adc-adc_{min})(v_{max}-v_{min})}{(adc_{max}
    -adc_{min})} + v_{min}\$
  • The higher the attenuation and higher the bits the less linear the values are, e.g. at 12-bits, 11Db the values are non-linear and thus the linear mapping would not work, I suppose this is what the characteristics is for, instead, using < 12 bits and < 11db made the readings mostly linear, (e.g. 11-bit, 6Db)

Best Answer

Are you trying to measure voltages between 1v and 3.3v directly? the ADC only works with voltages between 0 and 1v