analogRead too imprecise. ESP32

Hi people, how are you? I need some help.

void setup() {
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  
  //set the resolution to 12 bits (0-4096)
  analogReadResolution(10);
}

void loop() {
  // read the analog / millivolts value for pin 2:
  int analogValue = analogRead(2);
  int analogVolts = analogReadMilliVolts(2);
  
  // print out the values you read:
  Serial.printf("ADC analog value = %d\n",analogValue);
  Serial.printf("ADC millivolts value = %d\n",analogVolts);
  
  delay(1000);  // delay in between reads for clear read from serial
}

I had that simple code, i wat to sense the Volts of a solar panel. In and Out.
I let you a log to see my problem

ADC millivolts value = 2269
ADC analog value = 1023
ADC millivolts value = 2295
ADC analog value = 647
ADC millivolts value = 2233
ADC analog value = 635
ADC millivolts value = 2009
ADC analog value = 645
ADC millivolts value = 2226
ADC analog value = 635
ADC millivolts value = 2262
ADC analog value = 650
ADC millivolts value = 2305
ADC analog value = 652
ADC millivolts value = 2249
ADC analog value = 652

I nedd to sense form 24V to 19V aprox.
I make a this circuit (voltage divider)

Voltage Divider

And the problem is the precision of analog Input of ESP32. It var from 600 to 652, it's imposible make a measure with this numbers.
I check the input and it's constant, I use a regulated power supply, and a battery, then a put a filter. It's look like the problem is the input of ESP32. All of them are equals? May be this is a bad quality ESP32?

This is mine ESP32

The result also depend on stability of esp32 power

#include <driver/adc.h>


void setup()
{
  eg = xEventGroupCreate(); // get an event group handle
  x_message.topic.reserve(100);
  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11);// using GPIO 34 wind direction
  adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_11);// using GPIO 39 current
  adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);// using GPIO 36 battery volts

}

void fReadBattery( void * parameter )
{
  const float r1 = 50500.0f; // R1 in ohm, 50K
  const float r2 = 10000.0f; // R2 in ohm, 10k potentiometer
  const TickType_t xFrequency = 1000; //delay for mS
  float    adcValue = 0.0f;
  float    Vbatt = 0.0f;
  int      printCount = 0;
  float    vRefScale = (3.3f / 4096.0f) * ((r1 + r2) / r2);
  uint64_t TimePastKalman  = esp_timer_get_time(); // used by the Kalman filter UpdateProcessNoise, time since last kalman calculation
  SimpleKalmanFilter KF_ADC_b( 1.0f, 1.0f, .01f );
  TickType_t xLastWakeTime = xTaskGetTickCount();
  for (;;)
  {
    adc1_get_raw(ADC1_CHANNEL_0); //read and discard
    adcValue = float( adc1_get_raw(ADC1_CHANNEL_0) ); //take a raw ADC reading
    KF_ADC_b.setProcessNoise( (esp_timer_get_time() - TimePastKalman) / 1000000.0f ); //get time, in microsecods, since last readings
    adcValue = KF_ADC_b.updateEstimate( adcValue ); // apply simple Kalman filter
    Vbatt = adcValue * vRefScale;
    xSemaphoreTake( sema_CalculatedVoltage, portMAX_DELAY );
    CalculatedVoltage = Vbatt;
    xSemaphoreGive( sema_CalculatedVoltage );
    
      printCount++;
      if ( printCount == 3 )
      {
      //log_i( "Vbatt %f", Vbatt );
      printCount = 0;
      }
    
    TimePastKalman = esp_timer_get_time(); // time of update complete
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
    //log_i( "fReadBattery %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete( NULL );
}

is how I do it.

I use a 10K for R2 and this site for proper resistor value calculation, Voltage Divider Calculator.

As a note pin 2 on a ESP32 is not an analog pin for ADC1.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.