Analog to Digital Converter (ADC) Calibration Driver

[中文]

Introduction

In ESP32-H4, the analog-to-digital converter (ADC) compares the input analog voltage to the reference, and determines each bit of the output digital result. By design, the ADC reference voltage for ESP32-H4 is 1100 mV. However, the true reference voltage can range from 1000 mV to 1200 mV among different chips. This guide introduces the ADC calibration driver to minimize the effect of different reference voltages, and get more accurate output results.

Functional Overview

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

Calibration Scheme Creation

The ADC calibration driver provides ADC calibration scheme(s). From the calibration driver's point of view, an ADC calibration scheme is created for 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. If you already know the supported schemes, this step can be skipped. Just call the corresponding function to create the scheme handle.

If you use your 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.

Note

If you want to use your 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, convert the ADC raw result into a calibrated result in mV.

Call adc_cali_raw_to_voltage(). If a scheme needs the ADC channel to apply channel-dependent corrections, use adc_cali_chan_raw_to_voltage().

These functions may fail due to an invalid argument. Especially, if they return ESP_ERR_INVALID_STATE, this means the calibration scheme is not 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 functions adc_cali_create_scheme_line_fitting() and adc_cali_create_scheme_curve_fitting() are 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.

Minimize Noise

The ESP32-H4 ADC is 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.

API Reference

Header File

  • components/esp_adc/include/esp_adc/adc_cali.h

  • This header file can be included with:

    #include "esp_adc/adc_cali.h"
    
  • This header file is a part of the API provided by the esp_adc component. To declare that your component depends on esp_adc, add the following to your CMakeLists.txt:

    REQUIRES esp_adc
    

    or

    PRIV_REQUIRES esp_adc
    

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.

Note

Schemes that apply channel-dependent corrections cannot do so here. Use adc_cali_chan_raw_to_voltage() when the conversion depends on the ADC channel.

Note

On ESP32-S31 this function is not supported and returns ESP_ERR_NOT_SUPPORTED. Use adc_cali_chan_raw_to_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

  • ESP_ERR_NOT_SUPPORTED: Scheme requires the channel-aware conversion API

esp_err_t adc_cali_chan_raw_to_voltage(adc_cali_handle_t handle, adc_channel_t channel, int raw, int *voltage)

Convert ADC raw data to calibrated voltage (channel-aware)

Compared with adc_cali_raw_to_voltage(), this takes the ADC channel the raw data was sampled from, so schemes that need it can apply channel-dependent corrections.

Note

On ESP32-S31, raw is a 17-bit comparator vector. Even-numbered channels are N-side and odd-numbered channels are P-side.

Parameters:
  • handle -- [in] ADC calibration handle

  • channel -- [in] ADC channel the raw data was sampled from

  • 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

  • components/esp_adc/include/esp_adc/adc_cali_scheme.h

  • This header file can be included with:

    #include "esp_adc/adc_cali_scheme.h"
    
  • This header file is a part of the API provided by the esp_adc component. To declare that your component depends on esp_adc, add the following to your CMakeLists.txt:

    REQUIRES esp_adc
    

    or

    PRIV_REQUIRES esp_adc
    

Was this page helpful?