Skip to content

Commit b9b4cc9

Browse files
committed
Merge branch 'fix/update_button_for_idf6' into 'master'
fix(button): improve ADC button target support See merge request ae_group/esp-iot-solution!1587
2 parents e5a4866 + fa98591 commit b9b4cc9

7 files changed

Lines changed: 63 additions & 20 deletions

File tree

.gitlab/ci/build.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@
8686
matrix:
8787
- IMAGE: espressif/idf:release-v5.5
8888

89+
.build_idf_ge_than_v5_4_to_v6_2:
90+
parallel:
91+
matrix:
92+
- IMAGE: espressif/idf:release-v5.4
93+
- IMAGE: espressif/idf:release-v5.5
94+
- IMAGE: espressif/idf:release-v6.0
95+
- IMAGE: espressif/idf:latest
96+
8997
# ESP-IDF 6.0 is currently in pre-release stage.
9098

9199
.build_idf_ge_than_v5_5_with_pre_release:
@@ -1067,7 +1075,7 @@ build_components_button_test_apps:
10671075
extends:
10681076
- .build_examples_template
10691077
- .rules:build:components_button_test_apps
1070-
- .build_idf_active_release_version
1078+
- .build_idf_ge_than_v5_4_to_v6_2
10711079
variables:
10721080
EXAMPLE_DIR: components/button/test_apps
10731081

.gitlab/ci/target_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ components_test_button:
237237
parallel:
238238
matrix:
239239
- IDF_TARGET: esp32s3
240-
IDF_VERSION: ["5.2", "5.3", "5.4", "5.5"]
240+
IDF_VERSION: ["5.4", "5.5"] # NOTE: v6.0 and v6.2 are not supported yet
241241
ENV_TAG: "button"
242242
tags:
243243
- ${IDF_TARGET}

components/button/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# ChangeLog
22

3+
## v4.1.7 - 2026-06-03
4+
5+
### Fix:
6+
7+
* Improved ADC button compatibility across targets with different attenuation, bitwidth, and channel capabilities.
8+
* Fixed ADC button voltage handling when software calibration is unavailable.
9+
310
## v4.1.6 - 2026-02-09
411

512
### Fix:

components/button/button_adc.c

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
1+
/* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
22
*
33
* SPDX-License-Identifier: Apache-2.0
44
*/
@@ -22,10 +22,19 @@ static const char *TAG = "adc_button";
2222
#define NO_OF_SAMPLES CONFIG_ADC_BUTTON_SAMPLE_TIMES //Multisampling
2323

2424
/*!< Using atten bigger than 6db by default, it will be 11db or 12db in different target */
25+
#if SOC_ADC_ATTEN_NUM >= 4
2526
#define DEFAULT_ADC_ATTEN (ADC_ATTEN_DB_6 + 1)
27+
#else
28+
#define DEFAULT_ADC_ATTEN ADC_ATTEN_DB_0
29+
#endif
2630

31+
#ifdef SOC_ADC_RTC_MAX_BITWIDTH
2732
#define ADC_BUTTON_WIDTH SOC_ADC_RTC_MAX_BITWIDTH
28-
#define ADC_BUTTON_CHANNEL_MAX SOC_ADC_MAX_CHANNEL_NUM
33+
#else
34+
#define ADC_BUTTON_WIDTH SOC_ADC_DIGI_MAX_BITWIDTH
35+
#endif
36+
37+
#define ADC_BUTTON_CHANNEL_MAX(adc_unit) SOC_ADC_CHANNEL_NUM(adc_unit)
2938
#define ADC_BUTTON_ATTEN DEFAULT_ADC_ATTEN
3039

3140
#define ADC_BUTTON_MAX_CHANNEL CONFIG_ADC_BUTTON_MAX_CHANNEL
@@ -95,7 +104,6 @@ static int find_channel(adc_unit_t unit_id, uint8_t channel)
95104
}
96105
return -1;
97106
}
98-
99107
static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle)
100108
{
101109
adc_cali_handle_t handle = NULL;
@@ -135,19 +143,21 @@ static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_ha
135143
*out_handle = handle;
136144
if (ret == ESP_OK) {
137145
ESP_LOGI(TAG, "Calibration Success");
138-
} else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
139-
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
140146
} else if (ret == ESP_ERR_NOT_SUPPORTED) {
141-
ESP_LOGW(TAG, "Calibration not supported");
147+
ESP_LOGW(TAG, "ADC calibration is not supported, skip software calibration");
142148
} else {
143-
ESP_LOGE(TAG, "Invalid arg or no memory");
149+
ESP_LOGE(TAG, "ADC calibration init failed: %s", esp_err_to_name(ret));
144150
}
145151

146152
return calibrated;
147153
}
148154

149155
static bool adc_calibration_deinit(adc_cali_handle_t handle)
150156
{
157+
if (handle == NULL) {
158+
return true;
159+
}
160+
151161
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
152162
if (adc_cali_delete_scheme_curve_fitting(handle) == ESP_OK) {
153163
return true;
@@ -166,7 +176,7 @@ static bool adc_calibration_deinit(adc_cali_handle_t handle)
166176
esp_err_t button_adc_del(button_driver_t *button_driver)
167177
{
168178
button_adc_obj *adc_btn = __containerof(button_driver, button_adc_obj, base);
169-
ESP_RETURN_ON_FALSE(adc_btn->ch < ADC_BUTTON_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "channel out of range");
179+
ESP_RETURN_ON_FALSE(adc_btn->ch < ADC_BUTTON_CHANNEL_MAX(adc_btn->unit_id), ESP_ERR_INVALID_ARG, TAG, "channel out of range");
170180
ESP_RETURN_ON_FALSE(adc_btn->index < ADC_BUTTON_MAX_BUTTON, ESP_ERR_INVALID_ARG, TAG, "button_index out of range");
171181

172182
int ch_index = find_channel(adc_btn->unit_id, adc_btn->ch);
@@ -184,7 +194,7 @@ esp_err_t button_adc_del(button_driver_t *button_driver)
184194
}
185195
if (unused_button == ADC_BUTTON_MAX_BUTTON && g_button.unit[adc_btn->unit_id].ch[ch_index].is_init) { /**< if all button is unused, deinit the channel */
186196
g_button.unit[adc_btn->unit_id].ch[ch_index].is_init = 0;
187-
g_button.unit[adc_btn->unit_id].ch[ch_index].channel = ADC_BUTTON_CHANNEL_MAX;
197+
g_button.unit[adc_btn->unit_id].ch[ch_index].channel = ADC_BUTTON_CHANNEL_MAX(adc_btn->unit_id);
188198
ESP_LOGD(TAG, "all button is unused on channel%d, deinit the channel", g_button.unit[adc_btn->unit_id].ch[ch_index].channel);
189199
}
190200

@@ -222,9 +232,27 @@ static uint32_t get_adc_voltage(adc_unit_t unit_id, uint8_t channel)
222232
adc_reading /= NO_OF_SAMPLES;
223233
//Convert adc_reading to voltage in mV
224234
int voltage = 0;
225-
adc_cali_raw_to_voltage(g_button.unit[unit_id].adc_cali_handle, adc_reading, &voltage);
226-
ESP_LOGV(TAG, "Raw: %"PRIu32"\tVoltage: %dmV", adc_reading, voltage);
227-
return voltage;
235+
if (g_button.unit[unit_id].adc_cali_handle != NULL) {
236+
esp_err_t ret = adc_cali_raw_to_voltage(g_button.unit[unit_id].adc_cali_handle, adc_reading, &voltage);
237+
if (ret != ESP_OK) {
238+
ESP_LOGE(TAG, "ADC calibration conversion failed: %s", esp_err_to_name(ret));
239+
return 0;
240+
}
241+
} else {
242+
#if CONFIG_IDF_TARGET_ESP32S31
243+
// Keep the offset correction in signed arithmetic to avoid unsigned underflow near zero.
244+
voltage = (int32_t)adc_reading * 4 * 1000 / 4393 - 2;
245+
if (voltage < 0) {
246+
voltage = 0;
247+
}
248+
#else
249+
// No calibration handle means the chip does not support software calibration; return 0 to indicate that the voltage value is not available.
250+
voltage = 0;
251+
#endif
252+
}
253+
254+
ESP_LOGD(TAG, "Raw: %"PRIu32"\tVoltage: %dmV", adc_reading, voltage);
255+
return (uint32_t)voltage;
228256
}
229257

230258
uint8_t button_adc_get_key_level(button_driver_t *button_driver)
@@ -233,7 +261,7 @@ uint8_t button_adc_get_key_level(button_driver_t *button_driver)
233261
static uint16_t vol = 0;
234262
uint32_t ch = adc_btn->ch;
235263
uint32_t index = adc_btn->index;
236-
ESP_RETURN_ON_FALSE(ch < ADC_BUTTON_CHANNEL_MAX, 0, TAG, "channel out of range");
264+
ESP_RETURN_ON_FALSE(ch < ADC_BUTTON_CHANNEL_MAX(adc_btn->unit_id), 0, TAG, "channel out of range");
237265
ESP_RETURN_ON_FALSE(index < ADC_BUTTON_MAX_BUTTON, 0, TAG, "button_index out of range");
238266

239267
int ch_index = find_channel(adc_btn->unit_id, ch);
@@ -257,7 +285,7 @@ esp_err_t iot_button_new_adc_device(const button_config_t *button_config, const
257285
esp_err_t ret = ESP_OK;
258286
ESP_RETURN_ON_FALSE(button_config && adc_config && ret_button, ESP_ERR_INVALID_ARG, TAG, "Invalid argument");
259287
ESP_RETURN_ON_FALSE(adc_config->unit_id < ADC_UNIT_NUM, ESP_ERR_INVALID_ARG, TAG, "adc_handle out of range");
260-
ESP_RETURN_ON_FALSE(adc_config->adc_channel < ADC_BUTTON_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "channel out of range");
288+
ESP_RETURN_ON_FALSE(adc_config->adc_channel < ADC_BUTTON_CHANNEL_MAX(adc_config->unit_id), ESP_ERR_INVALID_ARG, TAG, "channel out of range");
261289
ESP_RETURN_ON_FALSE(adc_config->button_index < ADC_BUTTON_MAX_BUTTON, ESP_ERR_INVALID_ARG, TAG, "button_index out of range");
262290
ESP_RETURN_ON_FALSE(adc_config->max > 0, ESP_ERR_INVALID_ARG, TAG, "key max voltage invalid");
263291
button_adc_obj *adc_btn = calloc(1, sizeof(button_adc_obj));

components/button/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "4.1.6"
1+
version: "4.1.7"
22
description: GPIO and ADC and Matrix button driver
33
url: https://github.com/espressif/esp-iot-solution/tree/master/components/button
44
repository: https://github.com/espressif/esp-iot-solution.git

components/button/test_apps/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# in this exact order for cmake to work correctly
44
cmake_minimum_required(VERSION 3.5)
55

6-
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components"
7-
"../../button")
6+
set(EXTRA_COMPONENT_DIRS "../../button")
7+
88
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
99
project(button_test)

components/button/test_apps/main/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ endif()
44

55
idf_component_register(SRC_DIRS "."
66
PRIV_INCLUDE_DIRS "."
7-
PRIV_REQUIRES esp_event unity test_utils button ${PRIVREQ}
7+
PRIV_REQUIRES esp_event unity button ${PRIVREQ}
88
WHOLE_ARCHIVE)

0 commit comments

Comments
 (0)