Skip to content

Commit b2cd32d

Browse files
committed
Merge branch 'feat/add_s2_adc_range_extension' into 'master'
feat(adc): add s2 adc extension patch and make patch configurable Closes AEG-1825 See merge request ae_group/esp-iot-solution!1175
2 parents c9c3d5b + f140f40 commit b2cd32d

File tree

9 files changed

+552
-68
lines changed

9 files changed

+552
-68
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
From 9964b799053269c4f2106629d583e4e44d3cdb5e Mon Sep 17 00:00:00 2001
2+
From: yanke <[email protected]>
3+
Date: Thu, 12 Dec 2024 15:32:09 +0800
4+
Subject: [PATCH] feat(adc): support esp32s2 adc range above 2500mv
5+
6+
---
7+
components/driver/Kconfig | 23 ++++++++++++
8+
components/driver/adc_common.c | 26 ++++++++++++++
9+
components/esp_adc_cal/esp32s2/esp_adc_cal.c | 5 +++
10+
components/esp_adc_cal/esp_adc_cal_common.c | 37 ++++++++++++++++++++
11+
4 files changed, 91 insertions(+)
12+
13+
diff --git a/components/driver/Kconfig b/components/driver/Kconfig
14+
index 7b838784cb..cb24eccf8f 100644
15+
--- a/components/driver/Kconfig
16+
+++ b/components/driver/Kconfig
17+
@@ -41,6 +41,29 @@ menu "Driver configurations"
18+
If you stick to this, you can enable this option to force use ADC2 under above conditions.
19+
For more details, you can search for errata on espressif website.
20+
21+
+ menu "ADC User Code Offset"
22+
+ depends on IDF_TARGET_ESP32S2
23+
+ config ENABLE_ADC_USER_CODE_OFFSET
24+
+ bool "Enable ADC user code offset"
25+
+ default y
26+
+ help
27+
+ On ESP32S2, you can enable the USER_CODE_OFFSET setting to adjust the ADC range to 1000mV - 3300mV.
28+
+
29+
+ choice
30+
+ prompt "ADC calibration type"
31+
+ depends on ENABLE_ADC_USER_CODE_OFFSET
32+
+ default ADC_CAL_TYPE_FLOAT
33+
+ config ADC_CAL_TYPE_FLOAT
34+
+ bool "Float"
35+
+ help
36+
+ Use float type for ADC calibration calculations.
37+
+ config ADC_CAL_TYPE_DOUBLE
38+
+ bool "Double"
39+
+ help
40+
+ Use double type for ADC calibration calculations.
41+
+ endchoice
42+
+
43+
+ endmenu
44+
endmenu # ADC Configuration
45+
46+
menu "MCPWM configuration"
47+
diff --git a/components/driver/adc_common.c b/components/driver/adc_common.c
48+
index 93dbb2f4f6..dd162b0297 100644
49+
--- a/components/driver/adc_common.c
50+
+++ b/components/driver/adc_common.c
51+
@@ -390,6 +390,25 @@ esp_err_t adc1_lock_release(void)
52+
return ESP_OK;
53+
}
54+
55+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
56+
+static int16_t g_adc_cal_delta = 0;
57+
+static int16_t g_adc_cal_delta_actual = 0;
58+
+/**
59+
+ * @brief Set adc1 calibration delta value
60+
+ *
61+
+ * @param delta_mv delta value in mv, This value will be added to the calibration value.
62+
+ *
63+
+ */
64+
+void adc1_set_cal_delta(int16_t delta_mv)
65+
+{
66+
+ g_adc_cal_delta = delta_mv * 1.54f;
67+
+}
68+
+int16_t adc1_get_cal_delta()
69+
+{
70+
+ return g_adc_cal_delta_actual;
71+
+}
72+
+#endif
73+
+
74+
int adc1_get_raw(adc1_channel_t channel)
75+
{
76+
int adc_value;
77+
@@ -399,7 +418,14 @@ int adc1_get_raw(adc1_channel_t channel)
78+
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
79+
// Get calibration value before going into critical section
80+
uint32_t cal_val = get_calibration_offset(ADC_NUM_1, channel);
81+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
82+
+ uint32_t cal_val_new = cal_val + g_adc_cal_delta;
83+
+ cal_val_new = cal_val_new > 4095 ? 4095 : cal_val_new;
84+
+ g_adc_cal_delta_actual = cal_val_new - cal_val;
85+
+ adc_hal_set_calibration_param(ADC_NUM_1, cal_val_new);
86+
+#else
87+
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
88+
+#endif
89+
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
90+
91+
SARADC1_ENTER();
92+
diff --git a/components/esp_adc_cal/esp32s2/esp_adc_cal.c b/components/esp_adc_cal/esp32s2/esp_adc_cal.c
93+
index 3da83880d3..bc2b6bec0c 100644
94+
--- a/components/esp_adc_cal/esp32s2/esp_adc_cal.c
95+
+++ b/components/esp_adc_cal/esp32s2/esp_adc_cal.c
96+
@@ -196,5 +196,10 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
97+
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
98+
{
99+
assert(chars != NULL);
100+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
101+
+ extern int16_t adc1_get_cal_delta();
102+
+ return (adc_reading + adc1_get_cal_delta() * 2) * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling;
103+
+#else
104+
return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling;
105+
+#endif
106+
}
107+
diff --git a/components/esp_adc_cal/esp_adc_cal_common.c b/components/esp_adc_cal/esp_adc_cal_common.c
108+
index 09878cc015..3e60ce0e6b 100644
109+
--- a/components/esp_adc_cal/esp_adc_cal_common.c
110+
+++ b/components/esp_adc_cal/esp_adc_cal_common.c
111+
@@ -17,6 +17,10 @@
112+
113+
const static char *TAG = "ADC_CALI";
114+
115+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
116+
+extern void adc1_set_cal_delta(int16_t delta_mv);
117+
+#endif
118+
+
119+
esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
120+
const esp_adc_cal_characteristics_t *chars,
121+
uint32_t *voltage)
122+
@@ -33,11 +37,44 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
123+
} else {
124+
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, TAG, "Invalid channel");
125+
ret = adc2_get_raw(channel, chars->bit_width, &adc_reading);
126+
+ if (ret != ESP_OK) {
127+
+ ESP_LOGD(TAG, "adc2_get_raw error, please retry");
128+
+ return ret;
129+
+ }
130+
}
131+
132+
if (ret == ESP_OK) {
133+
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
134+
}
135+
+
136+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
137+
+
138+
+#if CONFIG_ADC_CAL_TYPE_FLOAT
139+
+ typedef const float ADC_CAL_TYPE;
140+
+#else
141+
+ typedef const double ADC_CAL_TYPE;
142+
+#endif
143+
+ if (chars->atten == ADC_ATTEN_DB_12) {
144+
+ if (*voltage > 2600) {
145+
+ ESP_LOGV(TAG, "first is %u", *voltage);
146+
+ adc1_set_cal_delta(1000);
147+
+ adc_reading = adc1_get_raw(channel);
148+
+ adc1_set_cal_delta(0);
149+
+ uint32_t voltage_b = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
150+
+
151+
+ ADC_CAL_TYPE a = -0.0000050800531;
152+
+ ADC_CAL_TYPE b = 0.02334678273232382;
153+
+ ADC_CAL_TYPE c = -26.699083271336267;
154+
+ ADC_CAL_TYPE e = a * voltage_b * voltage_b + b * voltage_b + c;
155+
+
156+
+ voltage_b = voltage_b * (1 + e / 100);
157+
+
158+
+ ESP_LOGD(TAG, "after is %u", voltage_b);
159+
+ *voltage = voltage_b;
160+
+ }
161+
+ }
162+
+#endif
163+
+
164+
return ret;
165+
}
166+
167+
--
168+
2.34.1
169+
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
From 43afc527438ea55086c35bb0db9f3938c660e8fc Mon Sep 17 00:00:00 2001
2+
From: yanke <[email protected]>
3+
Date: Thu, 12 Dec 2024 15:25:49 +0800
4+
Subject: [PATCH] feat(adc): support esp32s2 adc range above 2500mv
5+
6+
---
7+
components/esp_adc/Kconfig | 23 +++++++
8+
components/esp_adc/adc_oneshot.c | 61 +++++++++++++++++++
9+
.../esp_adc/esp32s2/adc_cali_line_fitting.c | 7 ++-
10+
components/esp_hw_support/adc_share_hw_ctrl.c | 7 +++
11+
4 files changed, 97 insertions(+), 1 deletion(-)
12+
13+
diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig
14+
index 0bdf4dd73e..f9fcb88822 100644
15+
--- a/components/esp_adc/Kconfig
16+
+++ b/components/esp_adc/Kconfig
17+
@@ -66,6 +66,29 @@ menu "ADC and ADC Calibration"
18+
If you stick to this, you can enable this option to force use ADC2 under above conditions.
19+
For more details, you can search for errata on espressif website.
20+
21+
+ menu "ADC User Code Offset"
22+
+ depends on IDF_TARGET_ESP32S2
23+
+ config ENABLE_ADC_USER_CODE_OFFSET
24+
+ bool "Enable ADC user code offset"
25+
+ default y
26+
+ help
27+
+ On ESP32S2, you can enable the USER_CODE_OFFSET setting to adjust the ADC range to 1000mV - 3300mV.
28+
+
29+
+ choice
30+
+ prompt "ADC calibration type"
31+
+ depends on ENABLE_ADC_USER_CODE_OFFSET
32+
+ default ADC_CAL_TYPE_FLOAT
33+
+ config ADC_CAL_TYPE_FLOAT
34+
+ bool "Float"
35+
+ help
36+
+ Use float type for ADC calibration calculations.
37+
+ config ADC_CAL_TYPE_DOUBLE
38+
+ bool "Double"
39+
+ help
40+
+ Use double type for ADC calibration calculations.
41+
+ endchoice
42+
+ endmenu
43+
+
44+
config ADC_ONESHOT_FORCE_USE_ADC2_ON_C3
45+
depends on IDF_TARGET_ESP32C3
46+
bool "Force use ADC2 oneshot mode on ESP32C3"
47+
diff --git a/components/esp_adc/adc_oneshot.c b/components/esp_adc/adc_oneshot.c
48+
index 0691e22f1a..dceeea4735 100644
49+
--- a/components/esp_adc/adc_oneshot.c
50+
+++ b/components/esp_adc/adc_oneshot.c
51+
@@ -166,6 +166,29 @@ esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle, adc_chann
52+
return ESP_OK;
53+
}
54+
55+
+
56+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
57+
+static int16_t g_adc_cal_delta = 0;
58+
+static int16_t g_adc_cal_delta_actual = 0;
59+
+/**
60+
+ * @brief Set adc1 calibration delta value
61+
+ *
62+
+ * @param delta_mv delta value in mv, This value will be added to the calibration value.
63+
+ *
64+
+ */
65+
+void adc1_set_cal_delta(int16_t delta_mv)
66+
+{
67+
+ g_adc_cal_delta = delta_mv * 1.54f;
68+
+}
69+
+int16_t adc1_get_cal_delta()
70+
+{
71+
+ return g_adc_cal_delta_actual;
72+
+}
73+
+
74+
+extern uint32_t get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten);
75+
+#endif
76+
+
77+
+
78+
esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw)
79+
{
80+
ESP_RETURN_ON_FALSE(handle && out_raw, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
81+
@@ -180,7 +203,16 @@ esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan,
82+
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
83+
adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan);
84+
adc_hal_calibration_init(handle->unit_id);
85+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
86+
+ adc_calc_hw_calibration_code(handle->unit_id, atten);
87+
+ uint32_t cal_val = get_calibration_offset(handle->unit_id, atten);
88+
+ uint32_t cal_val_new = cal_val + g_adc_cal_delta;
89+
+ cal_val_new = cal_val_new > 4095 ? 4095 : cal_val_new;
90+
+ g_adc_cal_delta_actual = cal_val_new - cal_val;
91+
+ adc_hal_set_calibration_param(handle->unit_id, cal_val_new);
92+
+#else
93+
adc_set_hw_calibration_code(handle->unit_id, atten);
94+
+#endif
95+
#endif // SOC_ADC_CALIBRATION_V1_SUPPORTED
96+
bool valid = false;
97+
valid = adc_oneshot_hal_convert(&(handle->hal), out_raw);
98+
@@ -255,6 +287,35 @@ esp_err_t adc_oneshot_get_calibrated_result(adc_oneshot_unit_handle_t handle, ad
99+
ESP_LOGD(TAG, "raw: 0d%d", raw);
100+
ESP_RETURN_ON_ERROR(adc_cali_raw_to_voltage(cali_handle, raw, cali_result), TAG, "adc calibration fail");
101+
102+
+#if (CONFIG_IDF_TARGET_ESP32S2 & CONFIG_ENABLE_ADC_USER_CODE_OFFSET)
103+
+ int voltage_b = 0;
104+
+#if CONFIG_ADC_CAL_TYPE_DOUBLE
105+
+ typedef const double ADC_CAL_TYPE;
106+
+#else
107+
+ typedef const float ADC_CAL_TYPE;
108+
+#endif
109+
+
110+
+ adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan);
111+
+ if(atten == ADC_ATTEN_DB_12) {
112+
+ if(*cali_result > 2600) {
113+
+ ESP_LOGD(TAG, "first is %u", *cali_result);
114+
+ adc1_set_cal_delta(1000);
115+
+ ESP_RETURN_ON_ERROR(adc_oneshot_read(handle, chan, &raw), TAG, "adc oneshot read fail");
116+
+ adc1_set_cal_delta(0);
117+
+ ESP_RETURN_ON_ERROR(adc_cali_raw_to_voltage(cali_handle, raw, &voltage_b), TAG, "adc calibration fail");
118+
+
119+
+ ESP_LOGD(TAG, "before is %u", voltage_b);
120+
+ ADC_CAL_TYPE a = -0.0000050800531;
121+
+ ADC_CAL_TYPE b = 0.02334678273232382;
122+
+ ADC_CAL_TYPE c = -26.699083271336267;
123+
+ ADC_CAL_TYPE e = a * voltage_b * voltage_b + b * voltage_b + c;
124+
+ voltage_b = voltage_b * (1 + e / 100);
125+
+ ESP_LOGD(TAG, "after is %u", voltage_b);
126+
+ *cali_result = voltage_b;
127+
+ }
128+
+ }
129+
+#endif
130+
+
131+
return ESP_OK;
132+
}
133+
134+
diff --git a/components/esp_adc/esp32s2/adc_cali_line_fitting.c b/components/esp_adc/esp32s2/adc_cali_line_fitting.c
135+
index 2e826e1f08..a43cdc5173 100644
136+
--- a/components/esp_adc/esp32s2/adc_cali_line_fitting.c
137+
+++ b/components/esp_adc/esp32s2/adc_cali_line_fitting.c
138+
@@ -143,8 +143,13 @@ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage)
139+
//pointers are checked in the upper layer
140+
141+
cali_chars_line_fitting_t *ctx = arg;
142+
- *voltage = raw * ctx->coeff_a / coeff_a_scaling + ctx->coeff_b / coeff_b_scaling;
143+
144+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
145+
+ extern int16_t adc1_get_cal_delta();
146+
+ *voltage = (raw + adc1_get_cal_delta() * 2) * ctx->coeff_a / coeff_a_scaling + ctx->coeff_b / coeff_b_scaling;
147+
+#else
148+
+ *voltage = raw * ctx->coeff_a / coeff_a_scaling + ctx->coeff_b / coeff_b_scaling;
149+
+#endif
150+
return ESP_OK;
151+
}
152+
153+
diff --git a/components/esp_hw_support/adc_share_hw_ctrl.c b/components/esp_hw_support/adc_share_hw_ctrl.c
154+
index 32f3c67b79..74019195bc 100644
155+
--- a/components/esp_hw_support/adc_share_hw_ctrl.c
156+
+++ b/components/esp_hw_support/adc_share_hw_ctrl.c
157+
@@ -96,6 +96,13 @@ void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
158+
ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04" PRIX32, version, adc_n + 1, atten, init_code);
159+
}
160+
161+
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2)
162+
+uint32_t get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten)
163+
+{
164+
+ return s_adc_cali_param[adc_n][atten];
165+
+}
166+
+#endif
167+
+
168+
void IRAM_ATTR adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
169+
{
170+
adc_hal_set_calibration_param(adc_n, s_adc_cali_param[adc_n][atten]);
171+
--
172+
2.34.1
173+

0 commit comments

Comments
 (0)