# Analog to Digital Converter (ADC) Calibration Driver

[中文]

## Introduction

In ESP32, 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 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 - covers how to create a calibration scheme handle and delete the calibration scheme handle.

- Result Conversion - covers 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 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.

#### 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`, bit width of ADC raw result.

There is also a configuration `adc_cali_line_fitting_config_t::default_vref`. Normally this can be simply set to 0. Line Fitting scheme does not rely on this value. However, if the Line Fitting scheme required eFuse bits are not burned on your board, the 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 is `ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP` or `ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF`. This means the Line Fitting scheme uses calibration parameters burned 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 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

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, 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 an invalid argument. Especially, if this function returns `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 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 the calibration eFuse value is not set to `ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP`.

- CONFIG_ADC_CAL_EFUSE_VREF_ENABLE - disable this to decrease the code size, if the calibration eFuse value is not set to `ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF`.

- CONFIG_ADC_CAL_LUT_ENABLE - disable this to decrease the code size, if you do not calibrate the ADC raw results under `ADC_ATTEN_DB_12`.

### Minimize Noise

The ESP32 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.

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

## 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.

  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

- 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?

- Thank you! We received your feedback.
- If you have any comments, fill in Espressif Documentation Feedback Form.

- We value your feedback.
- Let us know how we can improve this page by filling in Espressif Documentation Feedback Form.