Skip to content

Commit fae0bd2

Browse files
committed
Merge branch 'feat/add_adc_tp_calibration' into 'master'
feat(adc): support adc two point calibration See merge request ae_group/esp-iot-solution!1274
2 parents 60ae86e + 7a0b4eb commit fae0bd2

31 files changed

+1469
-1
lines changed

.github/workflows/upload_component.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ jobs:
9595
components/usb/usb_device_uac;
9696
components/usb/usb_device_uvc;
9797
components/usb/usb_stream;
98+
components/utilities/adc_tp_calibration;
9899
components/utilities/xz;
99100
components/zero_detection;
100101
tools/cmake_utilities;

.gitlab/ci/build.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,18 @@ build_example_utilities_xz_decompress_file:
976976
variables:
977977
EXAMPLE_DIR: examples/utilities/xz_decompress_file
978978

979+
build_example_utilities_adc_tp_calibration:
980+
extends:
981+
- .build_examples_template
982+
- .rules:build:example_utilities_adc_tp_calibration
983+
parallel:
984+
matrix:
985+
- IMAGE: espressif/idf:release-v5.0
986+
- IMAGE: espressif/idf:release-v5.1
987+
- IMAGE: espressif/idf:release-v5.2
988+
variables:
989+
EXAMPLE_DIR: examples/utilities/adc_tp_calibration
990+
979991
build_example_vision_opencv_color_tracker:
980992
extends:
981993
- .build_examples_template
@@ -1684,6 +1696,14 @@ build_example_elf_loader_build_elf_file_example:
16841696
variables:
16851697
EXAMPLE_DIR: examples/elf_loader/build_elf_file_example
16861698

1699+
build_components_utilities_adc_tp_calibration_test_apps:
1700+
extends:
1701+
- .build_examples_template
1702+
- .rules:build:components_utilities_adc_tp_calibration_test_apps
1703+
- .build_idf_active_release_version
1704+
variables:
1705+
EXAMPLE_DIR: components/utilities/adc_tp_calibration/test_apps
1706+
16871707
build_components_zero_detection_test_apps:
16881708
extends:
16891709
- .build_examples_template

.gitlab/ci/rules.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@
343343
- "components/sensors/power_monitor/ina236/**/*"
344344
- "tools/cmake_utilities/package_manager.cmake"
345345

346+
.patterns-components_utilities_adc_tp_calibration: &patterns-components_utilities_adc_tp_calibration
347+
- "components/utilities/adc_tp_calibration/**/*"
348+
- "tools/cmake_utilities/package_manager.cmake"
349+
346350
# examples folder, in the alphabetic order
347351
.patterns-docs: &patterns-docs
348352
- "docs/**/*"
@@ -397,6 +401,7 @@
397401
- "components/usb/usb_device_uac/include/usb_device_uac.h"
398402
- "components/usb/usb_device_uvc/include/usb_device_uvc.h"
399403
- "components/usb/usb_stream/include/usb_stream.h"
404+
- "components/utilities/adc_tp_calibration/include/adc_tp_calibration.h"
400405
- "components/zero_detection/include/zero_detection.h"
401406
# examples folder, in the alphabetic order
402407
.patterns-example_ai_esp_dl_human_activity_recognition: &patterns-example_ai_esp_dl_human_activity_recognition
@@ -621,6 +626,9 @@
621626
.patterns-example_usb_otg_usb_host_device_mode_manual_switch: &patterns-example_usb_otg_usb_host_device_mode_manual_switch
622627
- "examples/usb/otg/usb_host_device_mode_manual_switch/**/*"
623628

629+
.patterns-example_utilities_adc_tp_calibration: &patterns-example_utilities_adc_tp_calibration
630+
- "examples/utilities/adc_tp_calibration/**/*"
631+
624632
.patterns-example_utilities_xz_decompress_file: &patterns-example_utilities_xz_decompress_file
625633
- "examples/utilities/xz_decompress_file/**/*"
626634

@@ -1590,6 +1598,18 @@
15901598
- <<: *if-dev-push
15911599
changes: *patterns-example_usb_otg_usb_host_device_mode_manual_switch
15921600

1601+
.rules:build:example_utilities_adc_tp_calibration:
1602+
rules:
1603+
- <<: *if-protected
1604+
- <<: *if-label-build
1605+
- <<: *if-trigger-job
1606+
- <<: *if-dev-push
1607+
changes: *patterns-build_system
1608+
- <<: *if-dev-push
1609+
changes: *patterns-components_utilities_adc_tp_calibration
1610+
- <<: *if-dev-push
1611+
changes: *patterns-example_utilities_adc_tp_calibration
1612+
15931613
.rules:build:example_utilities_xz_decompress_file:
15941614
rules:
15951615
- <<: *if-protected
@@ -2470,6 +2490,17 @@
24702490
- <<: *if-dev-push
24712491
changes: *patterns-components_usb_usb_device_uvc
24722492

2493+
.rules:build:components_utilities_adc_tp_calibration_test_apps:
2494+
rules:
2495+
- <<: *if-protected
2496+
- <<: *if-label-build
2497+
- <<: *if-label-target_test
2498+
- <<: *if-trigger-job
2499+
- <<: *if-dev-push
2500+
changes: *patterns-build_system
2501+
- <<: *if-dev-push
2502+
changes: *patterns-components_utilities_adc_tp_calibration
2503+
24732504
.rules:build:components_sensors_humiture_aht20_test_apps:
24742505
rules:
24752506
- <<: *if-protected

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ The registered components in ESP-IoT-Solution are listed below:
5757
| Component | Version |
5858
| --- | --- |
5959
| [adc_mic](https://components.espressif.com/components/espressif/adc_mic) | [![Component Registry](https://components.espressif.com/components/espressif/adc_mic/badge.svg)](https://components.espressif.com/components/espressif/adc_mic) |
60+
| [adc_tp_calibration](https://components.espressif.com/components/espressif/adc_tp_calibration) | [![Component Registry](https://components.espressif.com/components/espressif/adc_tp_calibration/badge.svg)](https://components.espressif.com/components/espressif/adc_tp_calibration) |
6061
| [aht20](https://components.espressif.com/components/espressif/aht20) | [![Component Registry](https://components.espressif.com/components/espressif/aht20/badge.svg)](https://components.espressif.com/components/espressif/aht20) |
6162
| [apds9960](https://components.espressif.com/components/espressif/apds9960) | [![Component Registry](https://components.espressif.com/components/espressif/apds9960/badge.svg)](https://components.espressif.com/components/espressif/apds9960) |
6263
| [at24c02](https://components.espressif.com/components/espressif/at24c02) | [![Component Registry](https://components.espressif.com/components/espressif/at24c02/badge.svg)](https://components.espressif.com/components/espressif/at24c02) |

README_CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ ESP-IoT-Solution 中注册的组件如下:
5757
| 组件 | 版本 |
5858
| --- | --- |
5959
| [adc_mic](https://components.espressif.com/components/espressif/adc_mic) | [![Component Registry](https://components.espressif.com/components/espressif/adc_mic/badge.svg)](https://components.espressif.com/components/espressif/adc_mic) |
60+
| [adc_tp_calibration](https://components.espressif.com/components/espressif/adc_tp_calibration) | [![Component Registry](https://components.espressif.com/components/espressif/adc_tp_calibration/badge.svg)](https://components.espressif.com/components/espressif/adc_tp_calibration) |
6061
| [aht20](https://components.espressif.com/components/espressif/aht20) | [![Component Registry](https://components.espressif.com/components/espressif/aht20/badge.svg)](https://components.espressif.com/components/espressif/aht20) |
6162
| [apds9960](https://components.espressif.com/components/espressif/apds9960) | [![Component Registry](https://components.espressif.com/components/espressif/apds9960/badge.svg)](https://components.espressif.com/components/espressif/apds9960) |
6263
| [at24c02](https://components.espressif.com/components/espressif/at24c02) | [![Component Registry](https://components.espressif.com/components/espressif/at24c02/badge.svg)](https://components.espressif.com/components/espressif/at24c02) |

components/.build-rules.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ components/usb/usb_device_uvc/test_apps:
194194
enable:
195195
- if: SOC_USB_OTG_SUPPORTED == 1 and IDF_VERSION_MAJOR >= 5
196196

197+
components/utilities/adc_tp_calibration/test_apps:
198+
enable:
199+
- if: IDF_TARGET in ["esp32", "esp32s2"]
200+
197201
components/sensors/power_monitor/ina236/test_apps:
198202
enable:
199203
- if: INCLUDE_DEFAULT == 1
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# ChangeLog
2+
3+
## v0.1.0 - 2025-4-18
4+
5+
First release version.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
idf_component_register(SRC_DIRS "."
2+
INCLUDE_DIRS "include")
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# ADC Tow-Point Calibration Component
2+
3+
``adc_tp_calibration`` is a component that performs two-point ADC calibration for ESP32 and ESP32-S2 chips at the application level. By loading calibration parameters in the application layer, it enables easy implementation of two-point ADC calibration. This component offers the following features:
4+
5+
1. Supports inputting calibration parameters at the application level, allowing users to store the calibration data in storage media such as NVS or SD cards.
6+
2. Supports the two-point calibration scheme for ESP32 and the Method 2 two-point calibration scheme for ESP32-S2, without interfering with the existing calibration scheme provided by ESP-IDF.
7+
8+
## How to Configure Calibration Parameters
9+
10+
You can refer to the calibration principles described in the [documentation](https://docs.espressif.com/projects/esp-iot-solution/en/latest/others/adc_tp_calibration.html) to obtain the calibration parameters required by the adc_tp_calibration component.
11+
12+
Note that when collecting the raw ADC data needed for calibration, it is recommended to use an external 100 nF filtering capacitor and apply software filtering to ensure stable ADC readings.
13+
14+
## Add component to your project
15+
16+
Please use the component manager command `add-dependency` to add the `adc_tp_calibration` to your project's dependency, during the `CMake` step the component will be downloaded automatically
17+
18+
```
19+
idf.py add-dependency "espressif/adc_tp_calibration=*"
20+
```
21+
22+
Alternatively, you can create `idf_component.yml`. More is in [Espressif's documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html).
23+
24+
## How to use
25+
26+
Since the calibration scheme is closely related to the ADC attenuation setting, please ensure that the attenuation used by the ``adc_tp_calibration`` component matches the one configured in the ADC driver.
27+
28+
```c
29+
30+
// Step1: Initializing Calibration Parameters
31+
32+
#if CONFIG_IDF_TARGET_ESP32
33+
adc_tp_cali_config_t tp_cali_config = {
34+
.adc_unit = ADC_UNIT_1,
35+
.adc_raw_value_150mv_atten0 = 323,
36+
.adc_raw_value_850mv_atten0 = 3300,
37+
};
38+
#elif CONFIG_IDF_TARGET_ESP32S2
39+
adc_tp_cali_config_t tp_cali_config = {
40+
.adc_unit = ADC_UNIT_1,
41+
.adc_raw_value_600mv_atten0 = 5895,
42+
.adc_raw_value_800mv_atten2_5 = 5786,
43+
.adc_raw_value_1000mv_atten6 = 5820,
44+
.adc_raw_value_2000mv_atten12 = 6287,
45+
};
46+
#endif
47+
48+
// Step2: Initializing Two-Point ADC Calibration
49+
50+
adc_tp_cali_handle_t adc_tp_cali = adc_tp_cali_create(&tp_cali_config, ADC_ATTEN_DB_0);
51+
52+
// Step3: Initialize the ADC driver and acquire raw ADC data.
53+
...
54+
55+
// Step4: Calibrate ADC Data
56+
adc_tp_cali_raw_to_voltage(adc_tp_cali, raw_value, &voltage)
57+
```
58+
59+
Please note that the calibration data used in the above process must be determined by the user based on the [documentation](https://docs.espressif.com/projects/esp-iot-solution/en/latest/others/adc_tp_calibration.html). This data is not universal and must be obtained through manual calibration.
60+
61+
## Reference
62+
63+
[Documentation](https://docs.espressif.com/projects/esp-iot-solution/en/latest/others/adc_tp_calibration.html)
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include <stdio.h>
7+
#include <string.h>
8+
#include "esp_log.h"
9+
#include "esp_check.h"
10+
#include "adc_tp_calibration.h"
11+
12+
static const char* TAG = "adc_tp_cal";
13+
14+
#if CONFIG_IDF_TARGET_ESP32
15+
#define TP_LOW_VOLTAGE 150
16+
#define TP_HIGH_VOLTAGE 850
17+
#define LIN_COEFF_A_SCALE 65536
18+
#define LIN_COEFF_A_ROUND (LIN_COEFF_A_SCALE/2)
19+
static const uint32_t adc1_tp_atten_scale[4] = {65504, 86975, 120389, 224310};
20+
static const uint32_t adc2_tp_atten_scale[4] = {65467, 86861, 120416, 224708};
21+
static const uint32_t adc1_tp_atten_offset[4] = {0, 1, 27, 54};
22+
static const uint32_t adc2_tp_atten_offset[4] = {0, 9, 26, 66};
23+
#elif CONFIG_IDF_TARGET_ESP32S2
24+
static const int coeff_a_scaling = 65536;
25+
static const int coeff_b_scaling = 1024;
26+
static const uint32_t v_high[] = {600, 800, 1000, 2000};
27+
#endif
28+
29+
typedef struct {
30+
adc_atten_t atten;
31+
adc_tp_cali_config_t config;
32+
uint32_t coeff_a;
33+
uint32_t coeff_b;
34+
#if CONFIG_IDF_TARGET_ESP32
35+
const uint32_t *atten_scales;
36+
const uint32_t *atten_offsets;
37+
#elif CONFIG_IDF_TARGET_ESP32S2
38+
uint32_t high[4];
39+
#endif
40+
} adc_tp_cali_t;
41+
42+
adc_tp_cali_handle_t adc_tp_cali_create(adc_tp_cali_config_t *config, adc_atten_t atten)
43+
{
44+
ESP_RETURN_ON_FALSE(config, NULL, TAG, "config is NULL");
45+
ESP_RETURN_ON_FALSE(config->adc_unit == ADC_UNIT_1 || config->adc_unit == ADC_UNIT_2, NULL, TAG, "invalid ADC unit");
46+
47+
adc_tp_cali_t *adc_tp_cal = (adc_tp_cali_t *)calloc(1, sizeof(adc_tp_cali_t));
48+
ESP_RETURN_ON_FALSE(adc_tp_cal, NULL, TAG, "memory allocation for device handler failed");
49+
50+
adc_tp_cal->atten = atten;
51+
adc_tp_cal->config = *config;
52+
53+
#if CONFIG_IDF_TARGET_ESP32
54+
if (adc_tp_cal->config.adc_unit == ADC_UNIT_1) {
55+
adc_tp_cal->atten_scales = adc1_tp_atten_scale;
56+
adc_tp_cal->atten_offsets = adc1_tp_atten_offset;
57+
} else {
58+
adc_tp_cal->atten_scales = adc2_tp_atten_scale;
59+
adc_tp_cal->atten_offsets = adc2_tp_atten_offset;
60+
}
61+
62+
uint32_t delta_x = config->adc_raw_value_850mv_atten0 - config->adc_raw_value_150mv_atten0;
63+
uint32_t delta_v = TP_HIGH_VOLTAGE - TP_LOW_VOLTAGE;
64+
adc_tp_cal->coeff_a = (delta_v * adc_tp_cal->atten_scales[atten] + (delta_x / 2)) / delta_x;
65+
adc_tp_cal->coeff_b = TP_HIGH_VOLTAGE - ((delta_v * config->adc_raw_value_850mv_atten0 + (delta_x / 2)) / delta_x) + adc_tp_cal->atten_offsets[atten];
66+
#elif CONFIG_IDF_TARGET_ESP32S2
67+
const uint32_t high_values[] = {
68+
config->adc_raw_value_600mv_atten0,
69+
config->adc_raw_value_800mv_atten2_5,
70+
config->adc_raw_value_1000mv_atten6,
71+
config->adc_raw_value_2000mv_atten12
72+
};
73+
memcpy(adc_tp_cal->high, high_values, sizeof(high_values));
74+
75+
adc_tp_cal->coeff_a = coeff_a_scaling * v_high[atten] / adc_tp_cal->high[atten];
76+
adc_tp_cal->coeff_b = 0;
77+
#endif
78+
return (adc_tp_cali_handle_t)adc_tp_cal;
79+
}
80+
81+
esp_err_t adc_tp_cali_delete(adc_tp_cali_handle_t *adc_tp_cali_handle)
82+
{
83+
if (*adc_tp_cali_handle == NULL) {
84+
return ESP_OK;
85+
}
86+
87+
adc_tp_cali_t *adc_tp_cal = (adc_tp_cali_t *)(*adc_tp_cali_handle);
88+
free(adc_tp_cal);
89+
*adc_tp_cali_handle = NULL;
90+
return ESP_OK;
91+
}
92+
93+
esp_err_t adc_tp_cali_raw_to_voltage(adc_tp_cali_handle_t adc_tp_cali_handle, int raw_value, int *voltage)
94+
{
95+
ESP_RETURN_ON_FALSE(adc_tp_cali_handle && voltage, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
96+
97+
adc_tp_cali_t *adc_tp_cal = (adc_tp_cali_t *)adc_tp_cali_handle;
98+
#if CONFIG_IDF_TARGET_ESP32
99+
*voltage = (((adc_tp_cal->coeff_a * raw_value) + LIN_COEFF_A_ROUND) / LIN_COEFF_A_SCALE) + adc_tp_cal->coeff_b;
100+
#elif CONFIG_IDF_TARGET_ESP32S2
101+
*voltage = (raw_value * adc_tp_cal->coeff_a / (coeff_a_scaling / coeff_b_scaling) + adc_tp_cal->coeff_b) / coeff_b_scaling;
102+
#endif
103+
return ESP_OK;
104+
}

0 commit comments

Comments
 (0)