Button
The button component supports GPIO and ADC mode, and it allows the creation of two different kinds of the button at the same time. The following figure shows the hardware design of the button:
GPIO button: The advantage of the GPIO button is that each button occupies an independent IO and therefore does not affect each other, and has high stability however when the number of buttons increases, it may take too many IO resources.
ADC button: The advantage of using the ADC button is that one ADC channel can share multiple buttons and occupy fewer IO resources. The disadvantages include that you cannot press multiple buttons at the same time, and instability increases due to increase in the closing resistance of the button due to oxidation and other factors.
Note
The GPIO button needs to pay attention to the problem of pull-up and pull-down resistor inside the chip, which will be enabled by default. But there is no such resistor inside the IO that only supports input, external connection requires.
The voltage of the ADC button should not exceed the ADC range.
Button event
Triggering conditions for each button event are enlisted in the table below:
Event |
Trigger Condition |
---|---|
BUTTON_PRESS_DOWN |
Pressed |
BUTTON_PRESS_UP |
Released |
BUTTON_PRESS_REPEAT |
Pressed and released >= 2 times |
BUTTON_PRESS_REPEAT_DONE |
Repeated press completed |
BUTTON_SINGLE_CLICK |
Pressed and released once |
BUTTON_DOUBLE_CLICK |
Pressed and released twice |
BUTTON_MULTIPLE_CLICK |
Pressed and released N times specified, triggers when achieved |
BUTTON_LONG_PRESS_START |
Instant when held for a threshold duration of time |
BUTTON_LONG_PRESS_HOLD |
Triggered continuously during long press |
BUTTON_LONG_PRESS_UP |
Released after a long press |
BUTTON_PRESS_REPEAT_DONE |
Repeated press and release ended |
BUTTON_PRESS_END |
Indicate that the button has completed its current detection. |
Each button supports call-back and pooling mode.
Call-back: Each event of a button can register a call-back function for it, and the call-back function will be called when an event is generated. This method has high efficiency and real-time performance, and no events will be lost.
Polling: Periodically call
iot_button_get_event()
in the program to query the current event of the button. This method is easy to use and is suitable for occasions with simple tasks
Note
you can also combine the above two methods.
Attention
No blocking operations such as TaskDelay are allowed in the call-back function
Configuration
BUTTON_PERIOD_TIME_MS : scan cycle
BUTTON_DEBOUNCE_TICKS : debounce time
BUTTON_SHORT_PRESS_TIME_MS : short press down effective time
BUTTON_LONG_PRESS_TIME_MS : long press down effective time
ADC_BUTTON_MAX_CHANNEL : maximum number of channel for ADC
ADC_BUTTON_MAX_BUTTON_PER_CHANNEL : maximum number of ADC buttons per channel
ADC_BUTTON_SAMPLE_TIMES : ADC sample time
BUTTON_SERIAL_TIME_MS : call-back interval triggered by long press time
BUTTON_LONG_PRESS_TOLERANCE_MS: Used to set the tolerance time for long presses.
Demonstration
Create a button
// create gpio button
button_config_t gpio_btn_cfg = {
.type = BUTTON_TYPE_GPIO,
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
.gpio_button_config = {
.gpio_num = 0,
.active_level = 0,
},
};
button_handle_t gpio_btn = iot_button_create(&gpio_btn_cfg);
if(NULL == gpio_btn) {
ESP_LOGE(TAG, "Button create failed");
}
// create adc button
button_config_t adc_btn_cfg = {
.type = BUTTON_TYPE_ADC,
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
.adc_button_config = {
.adc_channel = 0,
.button_index = 0,
.min = 100,
.max = 400,
},
};
button_handle_t adc_btn = iot_button_create(&adc_btn_cfg);
if(NULL == adc_btn) {
ESP_LOGE(TAG, "Button create failed");
}
// create matrix keypad button
button_config_t matrix_button_cfg = {
.type = BUTTON_TYPE_MATRIX,
.long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
.short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
.matrix_button_config = {
.row_gpio_num = 0,
.col_gpio_num = 1,
}
};
button_handle_t matrix_button = iot_button_create(&matrix_button_cfg);
if(NULL == matrix_button) {
ESP_LOGE(TAG, "Button create failed");
}
Note
When the IDF version is greater than or equal to release/5.0, the ADC button uses ADC1. If ADC1 is used elsewhere in the project, please provide the adc_handle and adc_channel to configure the ADC button.
Register callback function
The Button component supports registering callback functions for multiple events, with each event capable of having its own callback function. When an event occurs, the callback function will be invoked.
In this context:
The
BUTTON_LONG_PRESS_START
andBUTTON_LONG_PRESS_UP
enumerations support setting specific long press times.The
BUTTON_MULTIPLE_CLICK
enumeration supports setting the number of consecutive button presses.Here’s a simple example:
static void button_single_click_cb(void *arg,void *usr_data) { ESP_LOGI(TAG, "BUTTON_SINGLE_CLICK"); } iot_button_register_cb(gpio_btn, BUTTON_SINGLE_CLICK, button_single_click_cb,NULL);
And here’s an example involving multiple callback functions:
static void button_long_press_1_cb(void *arg,void *usr_data) { ESP_LOGI(TAG, "BUTTON_LONG_PRESS_START_1"); } static void button_long_press_2_cb(void *arg,void *usr_data) { ESP_LOGI(TAG, "BUTTON_LONG_PRESS_START_2"); } button_event_config_t cfg = { .event = BUTTON_LONG_PRESS_START, .event_data.long_press.press_time = 2000, }; iot_button_register_event_cb(gpio_btn, cfg, button_long_press_1_cb, NULL); cfg.event_data.long_press.press_time = 5000; iot_button_register_event_cb(gpio_btn, cfg, button_long_press_2_cb, NULL);
Dynamically Modifying Default Button Values
iot_button_set_param(btn, BUTTON_LONG_PRESS_TIME_MS, 5000);
Find an event
button_event_t event;
event = iot_button_get_event(button_handle);
Low power
In light_sleep mode, the esp_timer triggers periodically, resulting in sustained high overall CPU power consumption. To address this issue, the button component offers a low-power mode.
Configuration Required:
Enable the CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE option to include low-power-related code in the component.
Ensure all created buttons type are GPIO type and have enable_power_save activated. The presence of other buttons may render the low-power mode ineffective.
Note
This feature ensures that the Button component only wakes up the CPU when in use, but does not guarantee the CPU will always enter low-power mode.
Power Consumption Comparison:
Without enabling low-power mode, pressing the button once:
With low-power mode enabled, pressing the button once:
Because GPIO wakes up the CPU, supporting only level triggering, the CPU is awakened only when the button is at its operating level. Therefore, in low-power mode, the average current during a single press is higher than when low-power mode is not enabled, depending on the duration of the button press. However, over larger operational periods, it saves more power than when low-power mode is not enabled.
Without enabling low-power mode, pressing the button three times within 4 seconds:
With low-power mode enabled, pressing the button three times within 4 seconds:
As shown, low-power mode results in more power savings.
button_config_t btn_cfg = {
.type = BUTTON_TYPE_GPIO,
.gpio_button_config = {
.gpio_num = button_num,
.active_level = BUTTON_ACTIVE_LEVEL,
.enable_power_save = true,
},
};
button_handle_t btn = iot_button_create(&btn_cfg);
When to Enter Light Sleep
Using Auto Light Sleep: The device will enter Light Sleep automatically after the button closes the esp_timer.
User-Controlled Light Sleep: The device can enter Light Sleep when
enter_power_save_cb
is called.
void btn_enter_power_save(void *usr_data)
{
ESP_LOGI(TAG, "Can enter power save now");
}
button_power_save_config_t config = {
.enter_power_save_cb = btn_enter_power_save,
};
iot_button_register_power_save_cb(&config);
How to Use Buttons Normally After Enabling the CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP Option?
When this macro is enabled, the GPIO module will be powered down. To use the button functionality, you must use RTC/LP GPIO and change the wake-up source to EXT 1.
GPIO Type |
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP Enabled? |
Wake-Up Source |
---|---|---|
Digital Pin |
N |
GPIO Level Trigger |
Digital Pin |
Y |
None |
RTC/LP Pin |
N |
GPIO Level Trigger / EXT 1 |
RTC/LP Pin |
Y |
EXT 1 |
Note
The LP GPIOs of ESP32-C5 and ESP32-C6 support both GPIO level wake-up and EXT 1 wake-up, and you also need to enable gpio_hold_en
.
Stop and resume
The component supports being turned on and off at any given moment.
// stop button
iot_button_stop();
// resume button
iot_button_resume();
API Reference
Header File
Functions
-
button_handle_t iot_button_create(const button_config_t *config)
Create a button.
- Parameters
config – pointer of button configuration, must corresponding the button type
- Returns
A handle to the created button, or NULL in case of error.
-
esp_err_t iot_button_delete(button_handle_t btn_handle)
Delete a button.
- Parameters
btn_handle – A button handle to delete
- Returns
ESP_OK Success
ESP_FAIL Failure
-
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb, void *usr_data)
Register the button event callback function.
- Parameters
btn_handle – A button handle to register
event – Button event
cb – Callback function.
usr_data – user data
- Returns
ESP_OK on success
ESP_ERR_INVALID_ARG Arguments is invalid.
ESP_ERR_INVALID_STATE The Callback is already registered. No free Space for another Callback.
ESP_ERR_NO_MEM No more memory allocation for the event
-
esp_err_t iot_button_register_event_cb(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb, void *usr_data)
Register the button event callback function.
- Parameters
btn_handle – A button handle to register
event_cfg – Button event configuration
cb – Callback function.
usr_data – user data
- Returns
ESP_OK on success
ESP_ERR_INVALID_ARG Arguments is invalid.
ESP_ERR_INVALID_STATE The Callback is already registered. No free Space for another Callback.
ESP_ERR_NO_MEM No more memory allocation for the event
-
esp_err_t iot_button_unregister_event(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb)
Unregister the button event callback function. In case event_data is also passed it will unregister function for that particular event_data only.
- Parameters
btn_handle – A button handle to unregister
event_cfg – Button event
cb – callback to unregister
- Returns
ESP_OK on success
ESP_ERR_INVALID_ARG Arguments is invalid.
ESP_ERR_INVALID_STATE The Callback was never registered with the event
-
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event)
Unregister all the callbacks associated with the event.
- Parameters
btn_handle – A button handle to unregister
event – Button event
- Returns
ESP_OK on success
ESP_ERR_INVALID_ARG Arguments is invalid.
ESP_ERR_INVALID_STATE No callbacks registered for the event
-
size_t iot_button_count_cb(button_handle_t btn_handle)
counts total callbacks registered
- Parameters
btn_handle – A button handle to the button
- Returns
0 if no callbacks registered, or 1 .. (BUTTON_EVENT_MAX-1) for the number of Registered Buttons.
ESP_ERR_INVALID_ARG if btn_handle is invalid
-
size_t iot_button_count_event(button_handle_t btn_handle, button_event_t event)
how many callbacks are registered for the event
- Parameters
btn_handle – A button handle to the button
event – Button event
- Returns
0 if no callbacks registered, or 1 .. (BUTTON_EVENT_MAX-1) for the number of Registered Buttons.
ESP_ERR_INVALID_ARG if btn_handle is invalid
-
button_event_t iot_button_get_event(button_handle_t btn_handle)
Get button event.
- Parameters
btn_handle – Button handle
- Returns
Current button event. See button_event_t
-
const char *iot_button_get_event_str(button_event_t event)
Get the string representation of a button event.
This function returns the corresponding string for a given button event. If the event value is outside the valid range, the function returns error string “event value is invalid”.
- Parameters
event – [in] The button event to be converted to a string.
- Returns
Pointer to the event string if the event is valid.
”invalid event” if the event value is invalid.
-
esp_err_t iot_button_print_event(button_handle_t btn_handle)
Log the current button event as a string.
This function prints the string representation of the current event associated with the button.
- Parameters
btn_handle – [in] Handle to the button object.
- Returns
ESP_OK: Successfully logged the event string.
ESP_FAIL: Invalid button handle.
-
uint8_t iot_button_get_repeat(button_handle_t btn_handle)
Get button repeat times.
- Parameters
btn_handle – Button handle
- Returns
button pressed times. For example, double-click return 2, triple-click return 3, etc.
-
uint32_t iot_button_get_ticks_time(button_handle_t btn_handle)
Get button ticks time.
- Parameters
btn_handle – Button handle
- Returns
Actual time from press down to up (ms).
-
uint16_t iot_button_get_long_press_hold_cnt(button_handle_t btn_handle)
Get button long press hold count.
- Parameters
btn_handle – Button handle
- Returns
Count of trigger cb(BUTTON_LONG_PRESS_HOLD)
-
esp_err_t iot_button_set_param(button_handle_t btn_handle, button_param_t param, void *value)
Dynamically change the parameters of the iot button.
- Parameters
btn_handle – Button handle
param – Button parameter
value – new value
- Returns
ESP_OK on success
ESP_ERR_INVALID_ARG Arguments is invalid.
-
uint8_t iot_button_get_key_level(button_handle_t btn_handle)
Get button key level.
- Parameters
btn_handle – Button handle
- Returns
1 if key is pressed
0 if key is released or invalid button handle
-
esp_err_t iot_button_resume(void)
resume button timer, if button timer is stopped. Make sure iot_button_create() is called before calling this API.
- Returns
ESP_OK on success
ESP_ERR_INVALID_STATE timer state is invalid.
-
esp_err_t iot_button_stop(void)
stop button timer, if button timer is running. Make sure iot_button_create() is called before calling this API.
- Returns
ESP_OK on success
ESP_ERR_INVALID_STATE timer state is invalid
Unions
-
union button_event_data_t
- #include <iot_button.h>
Button events data.
Public Members
-
struct button_event_data_t::long_press_t long_press
long press struct, for event BUTTON_LONG_PRESS_START and BUTTON_LONG_PRESS_UP
-
struct button_event_data_t::multiple_clicks_t multiple_clicks
multiple clicks struct, for event BUTTON_MULTIPLE_CLICK
-
struct button_event_data_t::long_press_t long_press
Structures
-
struct button_event_config_t
Button events configuration.
Public Members
-
button_event_t event
button event type
-
button_event_data_t event_data
event data corresponding to the event
-
button_event_t event
-
struct button_custom_config_t
custom button configuration
Public Members
-
uint8_t active_level
active level when press down
-
esp_err_t (*button_custom_init)(void *param)
user defined button init
-
uint8_t (*button_custom_get_key_value)(void *param)
user defined button get key value
-
esp_err_t (*button_custom_deinit)(void *param)
user defined button deinit
-
void *priv
private data used for custom button, MUST be allocated dynamically and will be auto freed in iot_button_delete
-
uint8_t active_level
-
struct button_config_t
Button configuration.
Public Members
-
button_type_t type
button type, The corresponding button configuration must be filled
-
uint16_t long_press_time
Trigger time(ms) for long press, if 0 default to BUTTON_LONG_PRESS_TIME_MS
-
uint16_t short_press_time
Trigger time(ms) for short press, if 0 default to BUTTON_SHORT_PRESS_TIME_MS
-
button_gpio_config_t gpio_button_config
gpio button configuration
-
button_matrix_config_t matrix_button_config
matrix key button configuration
-
button_custom_config_t custom_button_config
custom button configuration
-
union button_config_t::[anonymous] [anonymous]
button configuration
-
button_type_t type
Type Definitions
-
typedef void (*button_cb_t)(void *button_handle, void *usr_data)
-
typedef void *button_handle_t
Enumerations
-
enum button_event_t
Button events.
Values:
-
enumerator BUTTON_PRESS_DOWN
-
enumerator BUTTON_PRESS_UP
-
enumerator BUTTON_PRESS_REPEAT
-
enumerator BUTTON_PRESS_REPEAT_DONE
-
enumerator BUTTON_SINGLE_CLICK
-
enumerator BUTTON_DOUBLE_CLICK
-
enumerator BUTTON_MULTIPLE_CLICK
-
enumerator BUTTON_LONG_PRESS_START
-
enumerator BUTTON_LONG_PRESS_HOLD
-
enumerator BUTTON_LONG_PRESS_UP
-
enumerator BUTTON_PRESS_END
-
enumerator BUTTON_EVENT_MAX
-
enumerator BUTTON_NONE_PRESS
-
enumerator BUTTON_PRESS_DOWN