-
Notifications
You must be signed in to change notification settings - Fork 801
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
9 changed files
with
552 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
From 9964b799053269c4f2106629d583e4e44d3cdb5e Mon Sep 17 00:00:00 2001 | ||
From: yanke <[email protected]> | ||
Date: Thu, 12 Dec 2024 15:32:09 +0800 | ||
Subject: [PATCH] feat(adc): support esp32s2 adc range above 2500mv | ||
|
||
--- | ||
components/driver/Kconfig | 23 ++++++++++++ | ||
components/driver/adc_common.c | 26 ++++++++++++++ | ||
components/esp_adc_cal/esp32s2/esp_adc_cal.c | 5 +++ | ||
components/esp_adc_cal/esp_adc_cal_common.c | 37 ++++++++++++++++++++ | ||
4 files changed, 91 insertions(+) | ||
|
||
diff --git a/components/driver/Kconfig b/components/driver/Kconfig | ||
index 7b838784cb..cb24eccf8f 100644 | ||
--- a/components/driver/Kconfig | ||
+++ b/components/driver/Kconfig | ||
@@ -41,6 +41,29 @@ menu "Driver configurations" | ||
If you stick to this, you can enable this option to force use ADC2 under above conditions. | ||
For more details, you can search for errata on espressif website. | ||
|
||
+ menu "ADC User Code Offset" | ||
+ depends on IDF_TARGET_ESP32S2 | ||
+ config ENABLE_ADC_USER_CODE_OFFSET | ||
+ bool "Enable ADC user code offset" | ||
+ default y | ||
+ help | ||
+ On ESP32S2, you can enable the USER_CODE_OFFSET setting to adjust the ADC range to 1000mV - 3300mV. | ||
+ | ||
+ choice | ||
+ prompt "ADC calibration type" | ||
+ depends on ENABLE_ADC_USER_CODE_OFFSET | ||
+ default ADC_CAL_TYPE_FLOAT | ||
+ config ADC_CAL_TYPE_FLOAT | ||
+ bool "Float" | ||
+ help | ||
+ Use float type for ADC calibration calculations. | ||
+ config ADC_CAL_TYPE_DOUBLE | ||
+ bool "Double" | ||
+ help | ||
+ Use double type for ADC calibration calculations. | ||
+ endchoice | ||
+ | ||
+ endmenu | ||
endmenu # ADC Configuration | ||
|
||
menu "MCPWM configuration" | ||
diff --git a/components/driver/adc_common.c b/components/driver/adc_common.c | ||
index 93dbb2f4f6..dd162b0297 100644 | ||
--- a/components/driver/adc_common.c | ||
+++ b/components/driver/adc_common.c | ||
@@ -390,6 +390,25 @@ esp_err_t adc1_lock_release(void) | ||
return ESP_OK; | ||
} | ||
|
||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+static int16_t g_adc_cal_delta = 0; | ||
+static int16_t g_adc_cal_delta_actual = 0; | ||
+/** | ||
+ * @brief Set adc1 calibration delta value | ||
+ * | ||
+ * @param delta_mv delta value in mv, This value will be added to the calibration value. | ||
+ * | ||
+ */ | ||
+void adc1_set_cal_delta(int16_t delta_mv) | ||
+{ | ||
+ g_adc_cal_delta = delta_mv * 1.54f; | ||
+} | ||
+int16_t adc1_get_cal_delta() | ||
+{ | ||
+ return g_adc_cal_delta_actual; | ||
+} | ||
+#endif | ||
+ | ||
int adc1_get_raw(adc1_channel_t channel) | ||
{ | ||
int adc_value; | ||
@@ -399,7 +418,14 @@ int adc1_get_raw(adc1_channel_t channel) | ||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED | ||
// Get calibration value before going into critical section | ||
uint32_t cal_val = get_calibration_offset(ADC_NUM_1, channel); | ||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+ uint32_t cal_val_new = cal_val + g_adc_cal_delta; | ||
+ cal_val_new = cal_val_new > 4095 ? 4095 : cal_val_new; | ||
+ g_adc_cal_delta_actual = cal_val_new - cal_val; | ||
+ adc_hal_set_calibration_param(ADC_NUM_1, cal_val_new); | ||
+#else | ||
adc_hal_set_calibration_param(ADC_NUM_1, cal_val); | ||
+#endif | ||
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED | ||
|
||
SARADC1_ENTER(); | ||
diff --git a/components/esp_adc_cal/esp32s2/esp_adc_cal.c b/components/esp_adc_cal/esp32s2/esp_adc_cal.c | ||
index 3da83880d3..bc2b6bec0c 100644 | ||
--- a/components/esp_adc_cal/esp32s2/esp_adc_cal.c | ||
+++ b/components/esp_adc_cal/esp32s2/esp_adc_cal.c | ||
@@ -196,5 +196,10 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, | ||
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars) | ||
{ | ||
assert(chars != NULL); | ||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+ extern int16_t adc1_get_cal_delta(); | ||
+ return (adc_reading + adc1_get_cal_delta() * 2) * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling; | ||
+#else | ||
return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling; | ||
+#endif | ||
} | ||
diff --git a/components/esp_adc_cal/esp_adc_cal_common.c b/components/esp_adc_cal/esp_adc_cal_common.c | ||
index 09878cc015..3e60ce0e6b 100644 | ||
--- a/components/esp_adc_cal/esp_adc_cal_common.c | ||
+++ b/components/esp_adc_cal/esp_adc_cal_common.c | ||
@@ -17,6 +17,10 @@ | ||
|
||
const static char *TAG = "ADC_CALI"; | ||
|
||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+extern void adc1_set_cal_delta(int16_t delta_mv); | ||
+#endif | ||
+ | ||
esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, | ||
const esp_adc_cal_characteristics_t *chars, | ||
uint32_t *voltage) | ||
@@ -33,11 +37,44 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, | ||
} else { | ||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, TAG, "Invalid channel"); | ||
ret = adc2_get_raw(channel, chars->bit_width, &adc_reading); | ||
+ if (ret != ESP_OK) { | ||
+ ESP_LOGD(TAG, "adc2_get_raw error, please retry"); | ||
+ return ret; | ||
+ } | ||
} | ||
|
||
if (ret == ESP_OK) { | ||
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars); | ||
} | ||
+ | ||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+ | ||
+#if CONFIG_ADC_CAL_TYPE_FLOAT | ||
+ typedef const float ADC_CAL_TYPE; | ||
+#else | ||
+ typedef const double ADC_CAL_TYPE; | ||
+#endif | ||
+ if (chars->atten == ADC_ATTEN_DB_12) { | ||
+ if (*voltage > 2600) { | ||
+ ESP_LOGV(TAG, "first is %u", *voltage); | ||
+ adc1_set_cal_delta(1000); | ||
+ adc_reading = adc1_get_raw(channel); | ||
+ adc1_set_cal_delta(0); | ||
+ uint32_t voltage_b = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars); | ||
+ | ||
+ ADC_CAL_TYPE a = -0.0000050800531; | ||
+ ADC_CAL_TYPE b = 0.02334678273232382; | ||
+ ADC_CAL_TYPE c = -26.699083271336267; | ||
+ ADC_CAL_TYPE e = a * voltage_b * voltage_b + b * voltage_b + c; | ||
+ | ||
+ voltage_b = voltage_b * (1 + e / 100); | ||
+ | ||
+ ESP_LOGD(TAG, "after is %u", voltage_b); | ||
+ *voltage = voltage_b; | ||
+ } | ||
+ } | ||
+#endif | ||
+ | ||
return ret; | ||
} | ||
|
||
-- | ||
2.34.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
From 43afc527438ea55086c35bb0db9f3938c660e8fc Mon Sep 17 00:00:00 2001 | ||
From: yanke <[email protected]> | ||
Date: Thu, 12 Dec 2024 15:25:49 +0800 | ||
Subject: [PATCH] feat(adc): support esp32s2 adc range above 2500mv | ||
|
||
--- | ||
components/esp_adc/Kconfig | 23 +++++++ | ||
components/esp_adc/adc_oneshot.c | 61 +++++++++++++++++++ | ||
.../esp_adc/esp32s2/adc_cali_line_fitting.c | 7 ++- | ||
components/esp_hw_support/adc_share_hw_ctrl.c | 7 +++ | ||
4 files changed, 97 insertions(+), 1 deletion(-) | ||
|
||
diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig | ||
index 0bdf4dd73e..f9fcb88822 100644 | ||
--- a/components/esp_adc/Kconfig | ||
+++ b/components/esp_adc/Kconfig | ||
@@ -66,6 +66,29 @@ menu "ADC and ADC Calibration" | ||
If you stick to this, you can enable this option to force use ADC2 under above conditions. | ||
For more details, you can search for errata on espressif website. | ||
|
||
+ menu "ADC User Code Offset" | ||
+ depends on IDF_TARGET_ESP32S2 | ||
+ config ENABLE_ADC_USER_CODE_OFFSET | ||
+ bool "Enable ADC user code offset" | ||
+ default y | ||
+ help | ||
+ On ESP32S2, you can enable the USER_CODE_OFFSET setting to adjust the ADC range to 1000mV - 3300mV. | ||
+ | ||
+ choice | ||
+ prompt "ADC calibration type" | ||
+ depends on ENABLE_ADC_USER_CODE_OFFSET | ||
+ default ADC_CAL_TYPE_FLOAT | ||
+ config ADC_CAL_TYPE_FLOAT | ||
+ bool "Float" | ||
+ help | ||
+ Use float type for ADC calibration calculations. | ||
+ config ADC_CAL_TYPE_DOUBLE | ||
+ bool "Double" | ||
+ help | ||
+ Use double type for ADC calibration calculations. | ||
+ endchoice | ||
+ endmenu | ||
+ | ||
config ADC_ONESHOT_FORCE_USE_ADC2_ON_C3 | ||
depends on IDF_TARGET_ESP32C3 | ||
bool "Force use ADC2 oneshot mode on ESP32C3" | ||
diff --git a/components/esp_adc/adc_oneshot.c b/components/esp_adc/adc_oneshot.c | ||
index 0691e22f1a..dceeea4735 100644 | ||
--- a/components/esp_adc/adc_oneshot.c | ||
+++ b/components/esp_adc/adc_oneshot.c | ||
@@ -166,6 +166,29 @@ esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle, adc_chann | ||
return ESP_OK; | ||
} | ||
|
||
+ | ||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+static int16_t g_adc_cal_delta = 0; | ||
+static int16_t g_adc_cal_delta_actual = 0; | ||
+/** | ||
+ * @brief Set adc1 calibration delta value | ||
+ * | ||
+ * @param delta_mv delta value in mv, This value will be added to the calibration value. | ||
+ * | ||
+ */ | ||
+void adc1_set_cal_delta(int16_t delta_mv) | ||
+{ | ||
+ g_adc_cal_delta = delta_mv * 1.54f; | ||
+} | ||
+int16_t adc1_get_cal_delta() | ||
+{ | ||
+ return g_adc_cal_delta_actual; | ||
+} | ||
+ | ||
+extern uint32_t get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten); | ||
+#endif | ||
+ | ||
+ | ||
esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw) | ||
{ | ||
ESP_RETURN_ON_FALSE(handle && out_raw, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); | ||
@@ -180,7 +203,16 @@ esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, | ||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED | ||
adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan); | ||
adc_hal_calibration_init(handle->unit_id); | ||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+ adc_calc_hw_calibration_code(handle->unit_id, atten); | ||
+ uint32_t cal_val = get_calibration_offset(handle->unit_id, atten); | ||
+ uint32_t cal_val_new = cal_val + g_adc_cal_delta; | ||
+ cal_val_new = cal_val_new > 4095 ? 4095 : cal_val_new; | ||
+ g_adc_cal_delta_actual = cal_val_new - cal_val; | ||
+ adc_hal_set_calibration_param(handle->unit_id, cal_val_new); | ||
+#else | ||
adc_set_hw_calibration_code(handle->unit_id, atten); | ||
+#endif | ||
#endif // SOC_ADC_CALIBRATION_V1_SUPPORTED | ||
bool valid = false; | ||
valid = adc_oneshot_hal_convert(&(handle->hal), out_raw); | ||
@@ -255,6 +287,35 @@ esp_err_t adc_oneshot_get_calibrated_result(adc_oneshot_unit_handle_t handle, ad | ||
ESP_LOGD(TAG, "raw: 0d%d", raw); | ||
ESP_RETURN_ON_ERROR(adc_cali_raw_to_voltage(cali_handle, raw, cali_result), TAG, "adc calibration fail"); | ||
|
||
+#if (CONFIG_IDF_TARGET_ESP32S2 & CONFIG_ENABLE_ADC_USER_CODE_OFFSET) | ||
+ int voltage_b = 0; | ||
+#if CONFIG_ADC_CAL_TYPE_DOUBLE | ||
+ typedef const double ADC_CAL_TYPE; | ||
+#else | ||
+ typedef const float ADC_CAL_TYPE; | ||
+#endif | ||
+ | ||
+ adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan); | ||
+ if(atten == ADC_ATTEN_DB_12) { | ||
+ if(*cali_result > 2600) { | ||
+ ESP_LOGD(TAG, "first is %u", *cali_result); | ||
+ adc1_set_cal_delta(1000); | ||
+ ESP_RETURN_ON_ERROR(adc_oneshot_read(handle, chan, &raw), TAG, "adc oneshot read fail"); | ||
+ adc1_set_cal_delta(0); | ||
+ ESP_RETURN_ON_ERROR(adc_cali_raw_to_voltage(cali_handle, raw, &voltage_b), TAG, "adc calibration fail"); | ||
+ | ||
+ ESP_LOGD(TAG, "before is %u", voltage_b); | ||
+ ADC_CAL_TYPE a = -0.0000050800531; | ||
+ ADC_CAL_TYPE b = 0.02334678273232382; | ||
+ ADC_CAL_TYPE c = -26.699083271336267; | ||
+ ADC_CAL_TYPE e = a * voltage_b * voltage_b + b * voltage_b + c; | ||
+ voltage_b = voltage_b * (1 + e / 100); | ||
+ ESP_LOGD(TAG, "after is %u", voltage_b); | ||
+ *cali_result = voltage_b; | ||
+ } | ||
+ } | ||
+#endif | ||
+ | ||
return ESP_OK; | ||
} | ||
|
||
diff --git a/components/esp_adc/esp32s2/adc_cali_line_fitting.c b/components/esp_adc/esp32s2/adc_cali_line_fitting.c | ||
index 2e826e1f08..a43cdc5173 100644 | ||
--- a/components/esp_adc/esp32s2/adc_cali_line_fitting.c | ||
+++ b/components/esp_adc/esp32s2/adc_cali_line_fitting.c | ||
@@ -143,8 +143,13 @@ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage) | ||
//pointers are checked in the upper layer | ||
|
||
cali_chars_line_fitting_t *ctx = arg; | ||
- *voltage = raw * ctx->coeff_a / coeff_a_scaling + ctx->coeff_b / coeff_b_scaling; | ||
|
||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+ extern int16_t adc1_get_cal_delta(); | ||
+ *voltage = (raw + adc1_get_cal_delta() * 2) * ctx->coeff_a / coeff_a_scaling + ctx->coeff_b / coeff_b_scaling; | ||
+#else | ||
+ *voltage = raw * ctx->coeff_a / coeff_a_scaling + ctx->coeff_b / coeff_b_scaling; | ||
+#endif | ||
return ESP_OK; | ||
} | ||
|
||
diff --git a/components/esp_hw_support/adc_share_hw_ctrl.c b/components/esp_hw_support/adc_share_hw_ctrl.c | ||
index 32f3c67b79..74019195bc 100644 | ||
--- a/components/esp_hw_support/adc_share_hw_ctrl.c | ||
+++ b/components/esp_hw_support/adc_share_hw_ctrl.c | ||
@@ -96,6 +96,13 @@ void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten) | ||
ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04" PRIX32, version, adc_n + 1, atten, init_code); | ||
} | ||
|
||
+#if (CONFIG_ENABLE_ADC_USER_CODE_OFFSET & CONFIG_IDF_TARGET_ESP32S2) | ||
+uint32_t get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten) | ||
+{ | ||
+ return s_adc_cali_param[adc_n][atten]; | ||
+} | ||
+#endif | ||
+ | ||
void IRAM_ATTR adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten) | ||
{ | ||
adc_hal_set_calibration_param(adc_n, s_adc_cali_param[adc_n][atten]); | ||
-- | ||
2.34.1 | ||
|
Oops, something went wrong.