Go Down

Topic: ESP32 shows wrong voltage (Read 314 times) previous topic - next topic

x0RRY

Jan 08, 2021, 11:39 am Last Edit: Jan 08, 2021, 06:21 pm by x0RRY
Hi everyone,

I'm currently trying to use a CO2 sensor. It runs with a 5V heating voltage (passed directly from USB) and outputs a test voltage, which is fed into an impedance converter:


I then take its output into my microcontroller, which shows a voltage of around 75mV for an ESP32. However, if I measure it with a voltmeter, I get 200mV - which is an expected value considering the datasheet.

Example code for the ESP32:
Code: [Select]
void setup() {
  Serial.begin(115200);
  pinMode(35, INPUT);
}

float voltage = 0;
void loop() {
  voltage = (analogRead(35)*3300.0)/4096.0;
  Serial.println(voltage);
}


What am I missing here? I'm still a beginner, so please be patient with me ;-)
Thanks a lot already!

septillion

If i'm correct, by default the ESP32 uses attenuation on the analog in.

Don't see code for Nano or a schematic so can't comment on that.
Use fricking code tags!!!!
I want x => I would like x, I need help => I would like help, Need fast => Go and pay someone to do the job...

NEW Library to make fading leds a piece of cake
https://github.com/septillion-git/FadeLed

Idahowalker

I found that, especially for the A:D converter, that using the ESP32 AD API is a lot more accurate then using the ESP32 Arduino core.

ESP#@ AD API
1/18/2018, got my first Arduino Uno.

Idahowalker

Code: [Select]
#include <driver/adc.h>

void setup()
{
  // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
  // set up A:D channels
  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11);
}
//
void TaskAnalogVoltRead_LIDAR( void *pvParameters )
{
  // String localBuffer;
  // localBuffer.reserve ( StringBufferSize300 );
  int iBit = 1;
  float ADbits = 4095.0f;
  float offSET = 1.0f;
  float r1 = 100800.0f; // R1 in ohm, 100k = 100,800.0 //
  float r2 = 38780.0f; // R2 in ohm, 38k = 38000.0 //actual 38780K
  float uPvolts = 3.3f;
  // ADC1 channel 0 is GPIO36
  // ADC1 channel 1 is GPIO37
  // ADC1 channel 6 is GPIO34
  // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
  // to get resistor R2 go to:
  // http://www.ohmslawcalculator.com/voltage-divider-calculator
  //   used 12 volts for the input voltage to calculate R2, used 100K for R1
  for (;;)
  {
    // group handle, WaitForBits, ClearOnExitBit, WaitForAllBits, TicksToWait
    xEventGroupWaitBits( eg, evtAnalogVoltReadTask_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY );
    //    // read the input
    iBit = iBit << 1;
    if ( iBit == 1073741824 )
    {
      if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
      {
        ptrVbatt_LIDAR[0] += ( ((( uPvolts * adc1_get_raw(ADC1_CHANNEL_6)) / ADbits) / r2 * ( r1 + r2)) + offSET );
       
      } // if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
      iBit = 1;
    } // if ( iBit == 1073741824 )
  }
  vTaskDelete( NULL );
}


Some code removed but the basics of using the ESP32 AD API
1/18/2018, got my first Arduino Uno.

x0RRY

#4
Jan 08, 2021, 07:09 pm Last Edit: Jan 08, 2021, 07:10 pm by x0RRY
Thanks for the replies!
I corrected the title, it is working correctly on an Arduino Nano - I just tested it. Therefore, the issue is only the ESP32.

Using the following code:
Code: [Select]
#include <driver/adc.h>

void setup() {
  Serial.begin(115200);
  adc1_config_width(ADC_WIDTH_BIT_12);
  adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_0);
}

float voltage = 0;

void loop() {

for (int i=0;i<1000;i++)
  voltage += (adc1_get_raw(ADC1_CHANNEL_7)*1100.0)/4096.0;
voltage /= 1000;

Serial.print(voltage);
Serial.println("mV");
}


I still get measurements around 120mV, while the Multimeter comes close to 200mV... Could this be an issue with the impedance converter?

Idahowalker

#5
Jan 08, 2021, 07:46 pm Last Edit: Jan 08, 2021, 07:48 pm by Idahowalker
Off the top of my head, when I look at the code in loop(), you might consider using a delay of sort before making another reading allowing the A:D a larger sampling time. Consider you are not asking the CPU core1 to do very much and the A:D may need more time between readings. I'd try a delay of 100uS using, delayMicroseconds or something like that. If the readings improve then you know you are on the right track.

You might try using the A:D calibration procedure as per the ESP32 AD API.
1/18/2018, got my first Arduino Uno.

runaway_pancake

"Who is like unto the beast? who is able to make war with him?"
When all else fails, check your wiring!

x0RRY

#7
Jan 08, 2021, 09:47 pm Last Edit: Jan 08, 2021, 09:48 pm by x0RRY
Adding a delay doesn't change anything.
I'm afraid the calibration goes a bit over my head, but

"Per design the ADC reference voltage is 1100 mV, however the true reference voltage can range from 1000 mV to 1200 mV amongst different ESP32s."

tells me that this issue should be in the range of +-10% at a maximum.

However, I managed to find a potentiometer and did some measurements:

ESP: 125mV        Voltmeter: 190mV
ESP: 500mV        Voltmeter: 509mV
ESP: 1000mV      Voltmeter: 950mV

This matches the results from using the CO2 sensor. In the middle range of ~500mV, the measurements seem to be quite accurate. Could the ADC really be THAT non-linear?

I guess I could just use an amplifier then?


the2ndtierney

Could the ADC really be THAT non-linear?
Yes, they really are not great. 
particularly at the ends (closer to 0V and closer to 3.3V) and above 1V. 

This problem is well known and has already been mentioned here. 
https://randomnerdtutorials.com/esp32-adc-analog-read-arduino-ide/

Go Up