Analog to Digital Converter (ADC) Calibration Driver

Introduction

Based on series of comparisons with the reference voltage, ESP32 ADC determines each bit of the output digital result. Per design the ESP32 ADC reference voltage is 1100 mV, however the true reference voltage can range from 1000 mV to 1200 mV among different chips. This guide will introduce an ADC calibration driver to minimize this difference.

Functional Overview

The following sections of this document cover the typical steps to install and use the ADC calibration driver:

  • Calibration Scheme Creation - covers how to create a calibration scheme handle and delete the calibration scheme handle.

  • Calibration Configuration - covers how to configure the calibration driver to calculate necessary characteristics used for calibration.

  • Result Conversion - convers how to convert ADC raw result to calibrated result.

  • Thread Safety - lists which APIs are guaranteed to be thread safe by the driver.

  • Minimize Noise - describes a general way to minimize the noise.

  • Kconfig Options - lists the supported Kconfig options that can be used to make a different effect on driver behavior.

Calibration Scheme Creation

The ADC calibration driver provides ADC calibration scheme(s). From calibration driver’s point of view, an ADC calibration scheme is created to an ADC calibration handle adc_cali_handle_t.

adc_cali_check_scheme() can be used to know which calibration scheme is supported on the chip. For those users who are already aware of the supported scheme, this step can be skipped. Just call the corresponding function to create the scheme handle.

For those users who use their custom ADC calibration schemes, you could either modify this function adc_cali_check_scheme(), or just skip this step and call your custom creation function.

ADC Calibration Line Fitting Scheme

ESP32 supports ADC_CALI_SCHEME_VER_LINE_FITTING scheme. To create this scheme, set up adc_cali_line_fitting_config_t first.

  • adc_cali_line_fitting_config_t::unit_id, the ADC that your ADC raw results are from.

  • adc_cali_line_fitting_config_t::atten, ADC attenuation that your ADC raw results use.

  • adc_cali_line_fitting_config_t::bitwidth, the ADC raw result bitwidth.

There is also a configuration adc_cali_line_fitting_config_t::default_vref. Normally this can be simply set to 0. Line Fitting scheme doesn’t rely on this value. However, if the Line Fitting scheme required eFuse bits are not burnt on your board, driver will rely on this value to do the calibration.

You can use adc_cali_scheme_line_fitting_check_efuse() to check the eFuse bits. Normally the Line Fitting scheme eFuse value will be ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP or ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF. This means Line Fitting scheme will use calibration parameters burnt in the eFuse to do the calibration.

When the Line Fitting scheme eFuse value is ADC_CALI_LINE_FITTING_EFUSE_VAL_DEFAULT_VREF, you need to set the esp_adc_cali_line_fitting_init::default_vref. Default vref is an estimate of the ADC reference voltage provided by the users as a parameter during calibration.

After setting up the configuration structure, call adc_cali_create_scheme_line_fitting() to create a Line Fitting calibration scheme handle.

ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
adc_cali_line_fitting_config_t cali_config = {
    .unit_id = unit,
    .atten = atten,
    .bitwidth = ADC_BITWIDTH_DEFAULT,
};
ESP_ERROR_CHECK(adc_cali_create_scheme_line_fitting(&cali_config, &handle));

When the ADC calibration is no longer used, please delete the calibration scheme handle by calling adc_cali_delete_scheme_line_fitting().

Delete Line Fitting Scheme
ESP_LOGI(TAG, "delete %s calibration scheme", "Line Fitting");
ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle));

Note

For users who want to use their custom calibration schemes, you could provide a creation function to create your calibration scheme handle. Check the function table adc_cali_scheme_t in components/esp_adc/interface/adc_cali_interface.h to know the ESP ADC calibration interface.

Result Conversion

After setting up the calibration characteristics, you can call adc_cali_raw_to_voltage() to convert the ADC raw result into calibrated result. The calibrated result is in the unit of mV. This function may fail due to invalid argument. Especailly, if this function returns ESP_ERR_INVALID_STATE, this means the calibration scheme isn’t created. You need to create a calibration scheme handle, use adc_cali_check_scheme() to know the supported calibration scheme. On the other hand, you could also provide a custom calibration scheme and create the handle.

Get Voltage

ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc_cali_handle, adc_raw[0][0], &voltage[0][0]));
ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN0, voltage[0][0]);

Thread Safety

The factory function esp_adc_cali_new_scheme() is guaranteed to be thread safe by the driver. Therefore, you can call them from different RTOS tasks without protection by extra locks.

Other functions that take the adc_cali_handle_t as the first positional parameter are not thread safe, you should avoid calling them from multiple tasks.

Kconfig Options

  • CONFIG_ADC_CAL_EFUSE_TP_ENABLE, disable this to decrease the code size, if you are aware of the calibration eFuse value ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP isn’t this one.

  • CONFIG_ADC_CAL_EFUSE_VREF_ENABLE, disable this to decrease the code size, if you are aware of the calibration eFuse value ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF isn’t this one.

  • CONFIG_ADC_CAL_LUT_ENABLE, disable this to decrease the code size, if you don’t calibrate the ADC raw results under ADC_ATTEN_DB_12.

Minimize Noise

The ESP32 ADC can be sensitive to noise leading to large discrepancies in ADC readings. Depending on the usage scenario, you may need to connect a bypass capacitor (e.g. a 100 nF ceramic capacitor) to the ADC input pad in use, to minimize noise. Besides, multisampling may also be used to further mitigate the effects of noise.

ADC noise mitigation

Graph illustrating noise mitigation using capacitor and multisampling of 64 samples.

API Reference

Header File

Functions

esp_err_t adc_cali_check_scheme(adc_cali_scheme_ver_t *scheme_mask)

Check the supported ADC calibration scheme.

Parameters

scheme_mask[out] Supported ADC calibration scheme(s)

Returns

  • ESP_OK: On success

  • ESP_ERR_INVALID_ARG: Invalid argument

  • ESP_ERR_NOT_SUPPORTED: No supported calibration scheme

esp_err_t adc_cali_raw_to_voltage(adc_cali_handle_t handle, int raw, int *voltage)

Convert ADC raw data to calibrated voltage.

Parameters
  • handle[in] ADC calibration handle

  • raw[in] ADC raw data

  • voltage[out] Calibrated ADC voltage (in mV)

Returns

  • ESP_OK: On success

  • ESP_ERR_INVALID_ARG: Invalid argument

  • ESP_ERR_INVALID_STATE: Invalid state, scheme didn’t registered

Type Definitions

typedef struct adc_cali_scheme_t *adc_cali_handle_t

ADC calibration handle.

Enumerations

enum adc_cali_scheme_ver_t

ADC calibration scheme.

Values:

enumerator ADC_CALI_SCHEME_VER_LINE_FITTING

Line fitting scheme.

enumerator ADC_CALI_SCHEME_VER_CURVE_FITTING

Curve fitting scheme.

Header File