Does esp_adc_cal_characterize() work on ESP32S3?

techtoys
Posts: 28
Joined: Sat Jun 01, 2019 11:11 am

Does esp_adc_cal_characterize() work on ESP32S3?

Postby techtoys » Tue Jul 18, 2023 3:42 pm

Hi

Chip: ESP32S3
IDE: MS Visual Studio with VMicro plugin
Arduino ESP32 core : 2.0.10

I am calling

Code: Select all

esp_adc_cal_characterize()
to learn how vref deviates from 1100mV on my ESP32S3 Dev Module.
Code snippet as follows:

Code: Select all

#include "esp_adc_cal.h"
//...
void setup()
{
  esp_adc_cal_characteristics_t adc_chars;
  esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars);
  float vref = adc_chars.vref; // Obtain the device ADC reference voltage
  Serial.print(F("vref is : ")); Serial.println(vref);
}
Result of vref is 0.0 on ESP32S3. However, the same code runs on an old ESP32 PICO D4 returns 1100.

Does esp_adc_cal_characterize() work on esp32s3?

John

lbernstone
Posts: 797
Joined: Mon Jul 22, 2019 3:20 pm

Re: Does esp_adc_cal_characterize() work on ESP32S3?

Postby lbernstone » Tue Jul 18, 2023 5:12 pm

You should use 0 for the 4th parameter in characterize in order to use the factory measured calibration setting stored in efuse, unless you have a very old esp32 which doesn't have this.
https://docs.espressif.com/projects/esp ... eristics_t

techtoys
Posts: 28
Joined: Sat Jun 01, 2019 11:11 am

Re: Does esp_adc_cal_characterize() work on ESP32S3?

Postby techtoys » Wed Jul 19, 2023 11:35 am

lbernstone wrote:
Tue Jul 18, 2023 5:12 pm
You should use 0 for the 4th parameter in characterize in order to use the factory measured calibration setting stored in efuse
Re-run the program with efuse check-up first:

Code: Select all

esp_err_t err = esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP); //run this line twice with arg=ESP_ADC_CAL_VAL_EFUSE_VREF
switch (err) {
  case ESP_OK:
      Serial.println(F("The calibration mode is supported in eFuse."));
      break;
  case ESP_ERR_NOT_SUPPORTED:
      Serial.println(F("Error, eFuse values are not burned."));
      break;
  default:
      Serial.println(F("Error, invalid argument (ESP_ADC_CAL_VAL_DEFAULT_VREF)."));
  };
err = esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF);
The result is :
Error, eFuse values are not burned.
Error, eFuse values are not burned.


Now I run

Code: Select all

esp_adc_cal_value_t efuse = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 0, &adc_chars);
with the 4th param set 0. Value of efuse returns 3, but adc_chars.vref remains 0.

Not sure if it is a problem of my chip so I turned to the native example esp-idf\examples\peripherals\adc\oneshot_read\main\oneshot_read_main.c but it confirms that my chip supports a calibration scheme of Curve Fitting (see attachment for results).

What did I miss with esp_adc_cal_characterize()?
Attachments
2023-07-19_19h06_00.png
2023-07-19_19h06_00.png (66.5 KiB) Viewed 2798 times

lbernstone
Posts: 797
Joined: Mon Jul 22, 2019 3:20 pm

Re: Does esp_adc_cal_characterize() work on ESP32S3?

Postby lbernstone » Thu Jul 20, 2023 5:05 am

ESP32-S3 uses ESP_ADC_CAL_VAL_EFUSE_TP_FIT curves. https://github.com/espressif/esp-idf/bl ... read.c#L46
The vref is going to be 0. I don't know the exact math of those curve fits, but it is coeff_a that actually varies per chip.

techtoys
Posts: 28
Joined: Sat Jun 01, 2019 11:11 am

Re: Does esp_adc_cal_characterize() work on ESP32S3?

Postby techtoys » Thu Jul 20, 2023 8:40 am

Now it is working with the right argument for ESP32S3 (ESP_ADC_CAL_VAL_EFUSE_TP_FIT). Thanks a lot.
There is a function esp_adc_cal_raw_to_voltage() to return the calibrated ADC reading but for me, the other function esp_adc_cal_get_voltage() is enough.

Max. ADC voltage returns 3073mV on my board. Complete sketch is shown below.

Code: Select all

///A simple sketch to use calibrated characteristics built-in an ESP32S3 to read an ADC pin

#include "esp_adc_cal.h"

#define ADC_CHANNEL ADC_CHANNEL_4   ///Using ADC1 with GPIO5 wired to a trimmer

esp_adc_cal_characteristics_t adc_chars;

void setup() {
  Serial.begin(115200);
  delay(500);
  esp_err_t err = esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP_FIT); //S3 only supports ESP_ADC_CAL_VAL_EFUSE_TP_FIT
  switch (err) {
  case ESP_OK:
      Serial.println(F("The calibration mode is supported in eFuse."));
      break;
  case ESP_ERR_NOT_SUPPORTED:
      Serial.println(F("Error, eFuse values are not burned."));
      break;
  default:
      Serial.println(F("Error, invalid argument (ESP_ADC_CAL_VAL_DEFAULT_VREF)."));
  };

  esp_adc_cal_value_t efuse_config = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 0, &adc_chars);

  if (efuse_config != ESP_ADC_CAL_VAL_EFUSE_TP_FIT) {
      Serial.println(F("ALERT, ADC calibration failed"));
  }
}

void loop() {
    uint32_t voltage;
    esp_err_t err = esp_adc_cal_get_voltage(ADC_CHANNEL, &adc_chars, &voltage);
    if (err == ESP_OK) {
        Serial.print(F("Cali voltage is ")); Serial.print(voltage); Serial.println(F("mV"));
    }
    else {
        if (err == ESP_ERR_INVALID_ARG)
            Serial.println(F("ESP_ERR_INVALID_ARG"));
        else
            Serial.println(F("ESP_ERR_INVALID_STATE"));
    }
    
    delay(1000);
}

lbernstone
Posts: 797
Joined: Mon Jul 22, 2019 3:20 pm

Re: Does esp_adc_cal_characterize() work on ESP32S3?

Postby lbernstone » Thu Jul 20, 2023 5:35 pm

What does analogRead() return at 3v3? You don't have to reinvent the wheel.

techtoys
Posts: 28
Joined: Sat Jun 01, 2019 11:11 am

Re: Does esp_adc_cal_characterize() work on ESP32S3?

Postby techtoys » Fri Jul 21, 2023 3:32 pm

lbernstone wrote:
Thu Jul 20, 2023 5:35 pm
What does analogRead() return at 3v3? You don't have to reinvent the wheel.
When 3.3V is applied, both analogRead() and esp_adc_cal_get_voltage() returns 3073mV.
To make a comparison, two analog channels at GPIO5 (read with esp_adc_cal_get_voltage) and GPIO9(read with analogRead) are adjusted to a raw mV value of 1000. My multimeter probe reads 1021 and 1023 with nice consistency.

Please forgive my stupidity. When I first looked at the ADC example, the first thing I noticed from IDF's oneshot_read_main.c example is the adc_cali_create_scheme_curve_fitting() which led me to think adc calibration is mandatory to get an accurate result. Didn't realize analodRead() took care of everything already.

Thanks a lot for the posts.

Who is online

Users browsing this forum: Google [Bot] and 36 guests