forked from espressif/esp-idf
refactor(touch): update touch related examples to use new API
This commit is contained in:
@@ -461,16 +461,9 @@ examples/peripherals/touch_sensor/touch_element:
|
||||
examples/peripherals/touch_sensor/touch_sens_basic:
|
||||
disable:
|
||||
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1
|
||||
- if: SOC_TOUCH_SENSOR_VERSION == 1
|
||||
temporary: true
|
||||
reason: not supported yet
|
||||
depends_components:
|
||||
- esp_driver_touch_sens
|
||||
|
||||
examples/peripherals/touch_sensor/touch_sensor_v1:
|
||||
disable:
|
||||
- if: SOC_TOUCH_SENSOR_VERSION != 1
|
||||
|
||||
examples/peripherals/twai/twai_alert_and_recovery:
|
||||
disable:
|
||||
- if: SOC_TWAI_SUPPORTED != 1
|
||||
|
@@ -1,7 +1,7 @@
|
||||
| Supported Targets | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- |
|
||||
|
||||
# Capacity Touch Sensor Example (for hardware version 3)
|
||||
# Capacity Touch Sensor Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
@@ -34,42 +34,44 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
||||
|
||||
## Example Output
|
||||
|
||||
You can see the following output in the monitor if the example runs successfully:
|
||||
You can see the following output in the monitor if the example runs successfully (take ESP32-P4 for example):
|
||||
|
||||
```
|
||||
W (461) touch: [sample_cfg_id 0] clock precision loss, expect 4000000 hz, got 4006725 hz
|
||||
W (461) touch: [sample_cfg_id 1] clock precision loss, expect 8000000 hz, got 8013450 hz
|
||||
W (461) touch: [sample_cfg_id 2] clock precision loss, expect 16000000 hz, got 16026900 hz
|
||||
Touch [CH 0] enabled on GPIO2
|
||||
Touch [CH 1] enabled on GPIO3
|
||||
Touch [CH 2] enabled on GPIO4
|
||||
Touch [CH 3] enabled on GPIO5
|
||||
=================================
|
||||
Initial benchmark and new threshold are:
|
||||
[CH 0] 0: 4114, 411 1: 2057, 205 2: 1028, 102
|
||||
[CH 1] 0: 4643, 464 1: 2322, 232 2: 1160, 116
|
||||
[CH 2] 0: 4848, 484 1: 2424, 242 2: 1211, 121
|
||||
[CH 3] 0: 4340, 434 1: 2170, 217 2: 1085, 108
|
||||
Touch [CH 0] 0: 5161, 77 1: 5121, 76 2: 2533, 37
|
||||
Touch [CH 1] 0: 5007, 75 1: 5036, 75 2: 2464, 36
|
||||
Touch [CH 2] 0: 5086, 76 1: 5056, 75 2: 2487, 37
|
||||
Touch [CH 3] 0: 4965, 74 1: 4989, 74 2: 2433, 36
|
||||
=================================
|
||||
benchmark [CH 0]: 4115 2056 1028
|
||||
chan_data [CH 0]: 4115 2056 1028
|
||||
benchmark [CH 0]: 5160 5121 2533
|
||||
smooth [CH 0]: 5160 5122 2533
|
||||
|
||||
benchmark [CH 1]: 4644 2322 1160
|
||||
chan_data [CH 1]: 4644 2322 1160
|
||||
benchmark [CH 1]: 5007 5036 2464
|
||||
smooth [CH 1]: 5007 5036 2464
|
||||
|
||||
benchmark [CH 2]: 4848 2423 1211
|
||||
chan_data [CH 2]: 4848 2423 1211
|
||||
benchmark [CH 2]: 5086 5056 2487
|
||||
smooth [CH 2]: 5086 5056 2487
|
||||
|
||||
benchmark [CH 3]: 4337 2168 1084
|
||||
chan_data [CH 3]: 4337 2168 1084
|
||||
benchmark [CH 3]: 4964 4989 2433
|
||||
smooth [CH 3]: 4964 4990 2433
|
||||
|
||||
=================================
|
||||
benchmark [CH 0]: 4109 2054 1027
|
||||
chan_data [CH 0]: 4109 2054 1027
|
||||
benchmark [CH 0]: 5159 5121 2533
|
||||
smooth [CH 0]: 5160 5121 2533
|
||||
|
||||
benchmark [CH 1]: 4638 2318 1158
|
||||
chan_data [CH 1]: 4638 2318 1158
|
||||
benchmark [CH 1]: 5005 5036 2464
|
||||
smooth [CH 1]: 5006 5035 2464
|
||||
|
||||
benchmark [CH 2]: 4843 2421 1210
|
||||
chan_data [CH 2]: 4845 2421 1210
|
||||
benchmark [CH 2]: 5085 5056 2487
|
||||
smooth [CH 2]: 5086 5056 2488
|
||||
|
||||
benchmark [CH 3]: 4334 2167 1084
|
||||
chan_data [CH 3]: 4334 2167 1083
|
||||
benchmark [CH 3]: 4964 4990 2433
|
||||
smooth [CH 3]: 4964 4990 2433
|
||||
...
|
||||
```
|
||||
|
||||
@@ -77,46 +79,33 @@ And if you touch and release a button, you will see the following output:
|
||||
|
||||
```
|
||||
...
|
||||
I (1321) touch_callback: [CH 1] active
|
||||
I (2861) touch_callback: [CH 0] active
|
||||
=================================
|
||||
benchmark [CH 0]: 4111 2055 1027
|
||||
chan_data [CH 0]: 4111 2055 1027
|
||||
benchmark [CH 0]: 5755 5425 2762
|
||||
smooth [CH 0]: 5997 5666 2841
|
||||
|
||||
benchmark [CH 1]: 4676 2339 1168
|
||||
chan_data [CH 1]: 17701 8798 4399
|
||||
benchmark [CH 1]: 5025 5049 2473
|
||||
smooth [CH 1]: 5025 5050 2473
|
||||
|
||||
benchmark [CH 2]: 4870 2434 1217
|
||||
chan_data [CH 2]: 4867 2433 1217
|
||||
benchmark [CH 2]: 5104 5066 2495
|
||||
smooth [CH 2]: 5105 5066 2495
|
||||
|
||||
benchmark [CH 3]: 4333 2165 1082
|
||||
chan_data [CH 3]: 4333 2165 1082
|
||||
benchmark [CH 3]: 4982 5002 2441
|
||||
smooth [CH 3]: 4982 5001 2441
|
||||
|
||||
I (3021) touch_callback: [CH 0] inactive
|
||||
=================================
|
||||
benchmark [CH 0]: 4109 2053 1027
|
||||
chan_data [CH 0]: 4108 2053 1027
|
||||
benchmark [CH 0]: 5756 5428 2763
|
||||
smooth [CH 0]: 5756 5428 2764
|
||||
|
||||
benchmark [CH 1]: 4676 2339 1168
|
||||
chan_data [CH 1]: 11256 8817 4363
|
||||
benchmark [CH 1]: 5025 5048 2473
|
||||
smooth [CH 1]: 5026 5048 2474
|
||||
|
||||
benchmark [CH 2]: 4868 2434 1217
|
||||
chan_data [CH 2]: 4862 2429 1214
|
||||
benchmark [CH 2]: 5104 5066 2495
|
||||
smooth [CH 2]: 5104 5066 2495
|
||||
|
||||
benchmark [CH 3]: 4332 2165 1082
|
||||
chan_data [CH 3]: 4330 2164 1081
|
||||
|
||||
I (1931) touch_callback: [CH 1] inactive
|
||||
=================================
|
||||
benchmark [CH 0]: 4106 2052 1026
|
||||
chan_data [CH 0]: 4106 2052 1026
|
||||
|
||||
benchmark [CH 1]: 4649 2323 1161
|
||||
chan_data [CH 1]: 4650 2323 1161
|
||||
|
||||
benchmark [CH 2]: 4847 2422 1211
|
||||
chan_data [CH 2]: 4846 2422 1211
|
||||
|
||||
benchmark [CH 3]: 4329 2163 1082
|
||||
chan_data [CH 3]: 4329 2164 1082
|
||||
benchmark [CH 3]: 4981 5002 2441
|
||||
smooth [CH 3]: 4981 5002 2441
|
||||
...
|
||||
```
|
||||
|
||||
|
@@ -1,3 +1,2 @@
|
||||
idf_component_register(SRCS "touch_sens_basic_example_main.c"
|
||||
REQUIRES esp_driver_touch_sens
|
||||
INCLUDE_DIRS ".")
|
||||
REQUIRES esp_driver_touch_sens)
|
||||
|
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
touch_sens_examples_common:
|
||||
path: ${IDF_PATH}/examples/peripherals/touch_sensor/touch_sens_examples_common
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
@@ -12,13 +12,21 @@
|
||||
#include "esp_check.h"
|
||||
#include "touch_sens_example_config.h"
|
||||
|
||||
static touch_sensor_handle_t s_sens_handle = NULL;
|
||||
static touch_channel_handle_t s_chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM] = {};
|
||||
// Touch version 3 supports multiple sample configurations (i.e. supports frequency hopping),
|
||||
// others only have one set of sample configurations.
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM TOUCH_SAMPLE_CFG_NUM // Up to 'TOUCH_SAMPLE_CFG_NUM'
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 4
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_SAMPLE_CFG_NUM <= TOUCH_SAMPLE_CFG_NUM, "sample configuration number exceed the supported number");
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_CHANNEL_NUM <= (TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID + 1), "touch channel number exceed the max supported number ");
|
||||
|
||||
// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio))
|
||||
static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
[0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.015f, // 1.5%
|
||||
};
|
||||
// The touch channel IDs that used in this example
|
||||
// For the corresponding GPIOs of these channel, please refer to 'touch_sensor_channel.h'
|
||||
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
TOUCH_MIN_CHAN_ID,
|
||||
TOUCH_MIN_CHAN_ID + 1,
|
||||
@@ -38,50 +46,62 @@ bool example_touch_on_inactive_callback(touch_sensor_handle_t sens_handle, const
|
||||
return false;
|
||||
}
|
||||
|
||||
static void example_touch_do_initial_scanning(void)
|
||||
static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle, touch_channel_handle_t chan_handle[])
|
||||
{
|
||||
/* Enable the touch sensor to do the initial scanning, so that to initialize the channel data */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(s_sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
|
||||
/* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(s_sens_handle, 2000));
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(sens_handle, 2000));
|
||||
}
|
||||
|
||||
/* Disable the touch channel to rollback the state */
|
||||
ESP_ERROR_CHECK(touch_sensor_disable(s_sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_disable(sens_handle));
|
||||
|
||||
/* (Optional) Read the initial channel benchmark and reconfig the channel active threshold accordingly */
|
||||
printf("Initial benchmark and new threshold are:\n");
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
/* Read the initial benchmark of the touch channel */
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#else
|
||||
/* Read smooth data instead if the touch V1 hardware does not support benchmark */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark));
|
||||
#endif // SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Calculate the proper active thresholds regarding the initial benchmark */
|
||||
printf("[CH %d]", i);
|
||||
printf("Touch [CH %d]", s_channel_id[i]);
|
||||
/* Generate the default channel configuration and then update the active threshold based on the real benchmark */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
// Touch V1 (ESP32) uses absolute threshold.
|
||||
chan_cfg.abs_active_thresh[j] = (uint32_t)(benchmark[j] * (1 - s_thresh2bm_ratio[i]));
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.abs_active_thresh[j]);
|
||||
#else
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[i]);
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]);
|
||||
#endif // SOC_TOUCH_SENSOR_VERSION == 1
|
||||
}
|
||||
printf("\n");
|
||||
/* Update the channel configuration */
|
||||
ESP_ERROR_CHECK(touch_sensor_reconfig_channel(s_chan_handle[i], &chan_cfg));
|
||||
ESP_ERROR_CHECK(touch_sensor_reconfig_channel(chan_handle[i], &chan_cfg));
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* Use the default sample configurations */
|
||||
touch_sensor_sample_config_t sample_cfg[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
/* Allocate new touch controller handle */
|
||||
/* Handles of touch sensor */
|
||||
touch_sensor_handle_t sens_handle = NULL;
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
|
||||
/* Step 1: Create a new touch sensor controller handle with default sample configuration */
|
||||
touch_sensor_sample_config_t sample_cfg[TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg);
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &s_sens_handle));
|
||||
|
||||
/* Configure the touch sensor filter */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(s_sens_handle, &filter_cfg));
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle));
|
||||
|
||||
/* Step 2: Create and enable the new touch channel handles with default configurations */
|
||||
/** Following is about setting the touch channel active threshold of each sample configuration.
|
||||
*
|
||||
* @How to Determine:
|
||||
@@ -89,7 +109,10 @@ void app_main(void)
|
||||
* we need to run the touch app first to get the `benchmark` and the `smooth_data` that being touched.
|
||||
*
|
||||
* @Formula:
|
||||
* threshold = benchmark * coeff, (coeff for example, 0.1%~20%)
|
||||
* Touch V1 uses absolute threshold, and it has no benchmark, so you can use untouched smooth data instead:
|
||||
* abs_active_thresh = benchmark * (1 - coeff), (coeff for example, 0.1%~20%)
|
||||
* Touch V2/V3 uses relative threshold:
|
||||
* active_thresh = benchmark * coeff, (coeff for example, 0.1%~20%)
|
||||
* Please adjust the coeff to guarantee the threshold < smooth_data - benchmark
|
||||
*
|
||||
* @Typical Practice:
|
||||
@@ -102,48 +125,55 @@ void app_main(void)
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
/* Allocate new touch channel on the touch controller */
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(s_sens_handle, s_channel_id[i], &chan_cfg, &s_chan_handle[i]));
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, s_channel_id[i], &chan_cfg, &chan_handle[i]));
|
||||
/* Display the touch channel corresponding GPIO number, you can also know from `touch_sensor_channel.h` */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[i], &chan_info));
|
||||
printf("Touch [CH %d] enabled on GPIO%d\n", s_channel_id[i], chan_info.chan_gpio);
|
||||
}
|
||||
printf("=================================\n");
|
||||
|
||||
/* Do the initial scanning to initialize the touch channel data
|
||||
/* Step 3: Confiture the default filter for the touch sensor (Note: Touch V1 uses software filter) */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg));
|
||||
|
||||
/* Step 4: Do the initial scanning to initialize the touch channel data
|
||||
* Without this step, the channel data in the first read will be invalid
|
||||
*/
|
||||
example_touch_do_initial_scanning();
|
||||
example_touch_do_initial_scanning(sens_handle, chan_handle);
|
||||
|
||||
/* Register the touch sensor callbacks, here only take `active` and `deactivate` event for example */
|
||||
/* Step 5: Register the touch sensor callbacks, here only take `active` and `inactive` event for example */
|
||||
touch_event_callbacks_t callbacks = {
|
||||
.on_active = example_touch_on_active_callback,
|
||||
.on_inactive = example_touch_on_inactive_callback,
|
||||
.on_measure_done = NULL,
|
||||
.on_scan_done = NULL,
|
||||
.on_timeout = NULL,
|
||||
.on_proximity_meas_done = NULL,
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(s_sens_handle, &callbacks, NULL));
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL));
|
||||
|
||||
/* Enable the touch sensor */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(s_sens_handle));
|
||||
/* Step 6: Enable the touch sensor */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
|
||||
/* Start continuous scanning, you can also trigger oneshot scanning manually */
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(s_sens_handle));
|
||||
/* Step 7: Start continuous scanning, you can also trigger oneshot scanning manually */
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle));
|
||||
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
uint32_t chan_data[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
/* Step8: Print the sampled data of each enabled touch channel */
|
||||
uint32_t data[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
while (1) {
|
||||
printf("=================================\n");
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Read and print the benchmark of each sample configuration */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, data));
|
||||
printf("benchmark [CH %d]:", s_channel_id[i]);
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
printf(" %"PRIu32, benchmark[j]);
|
||||
printf(" %"PRIu32, data[j]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
/* Read and print the channel data of each sample configuration */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, chan_data));
|
||||
printf("chan_data [CH %d]:", s_channel_id[i]);
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, data));
|
||||
printf("smooth [CH %d]:", s_channel_id[i]);
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
printf(" %"PRIu32, chan_data[j]);
|
||||
printf(" %"PRIu32, data[j]);
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/touch_sens.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Touch version 3 supports multiple sample configurations
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM TOUCH_SAMPLE_CFG_NUM // Up to 'TOUCH_SAMPLE_CFG_NUM'
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 4
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_SAMPLE_CFG_NUM <= TOUCH_SAMPLE_CFG_NUM, "sample configuration number exceed the supported number");
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_CHANNEL_NUM <= (TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID + 1), "touch channel number exceed the max supported number ");
|
||||
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 2
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(500, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_2V2)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {2000}, \
|
||||
.charge_speed = TOUCH_CHARGE_SPEED_7, \
|
||||
.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_LOW, \
|
||||
}
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 3
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG(res, cap, coarse_freq_tune, fine_freq_tune) { \
|
||||
.div_num = 8, \
|
||||
.charge_times = 500, \
|
||||
.rc_filter_res = res, \
|
||||
.rc_filter_cap = cap, \
|
||||
.low_drv = fine_freq_tune, \
|
||||
.high_drv = coarse_freq_tune, \
|
||||
.bias_volt = 5, \
|
||||
.bypass_shield_output = false, \
|
||||
}
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {EXAMPLE_TOUCH_SAMPLE_CFG(3, 29, 8, 3),\
|
||||
EXAMPLE_TOUCH_SAMPLE_CFG(2, 88, 31, 7), \
|
||||
EXAMPLE_TOUCH_SAMPLE_CFG(3, 10, 31, 7)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {1000, 2500, 5000}, \
|
||||
}
|
||||
#else
|
||||
#error "Target not supported"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -1,15 +1,16 @@
|
||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32p4
|
||||
@pytest.mark.generic
|
||||
def test_touch_sens_v3(dut: Dut) -> None:
|
||||
def test_touch_sens(dut: Dut) -> None:
|
||||
dut.expect(r'Touch \[CH [0-9]+\] enabled on GPIO[0-9]+')
|
||||
dut.expect_exact('Initial benchmark and new threshold are:')
|
||||
dut.expect(r'\[CH [0-9]+\] 0: [0-9]+, [0-9]+')
|
||||
dut.expect(r'benchmark \[CH [0-9]+\]: [0-9]+')
|
||||
dut.expect(r'chan_data \[CH [0-9]+\]: [0-9]+')
|
||||
dut.expect(r'Touch \[CH [0-9]+\] 0: [0-9]+, [0-9]+')
|
||||
dut.expect(r'smooth \[CH [0-9]+\]: [0-9]+')
|
||||
|
@@ -0,0 +1,2 @@
|
||||
# register I2S common dependencies as a component
|
||||
idf_component_register(INCLUDE_DIRS ".")
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/touch_sens.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(5.0, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_1V7)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.abs_active_thresh = {1000}, \
|
||||
.charge_speed = TOUCH_CHARGE_SPEED_7, \
|
||||
.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_LOW, \
|
||||
.group = TOUCH_CHAN_TRIG_GROUP_BOTH, \
|
||||
}
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32-S2 & ESP32-S3
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(500, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_2V2)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {2000}, \
|
||||
.charge_speed = TOUCH_CHARGE_SPEED_7, \
|
||||
.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_LOW, \
|
||||
}
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32-P4
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(3, 29, 8, 3),\
|
||||
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(2, 88, 31, 7), \
|
||||
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(3, 10, 31, 7)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {1000, 2500, 5000}, \
|
||||
}
|
||||
#else
|
||||
#error "Target not supported"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -1,8 +0,0 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
project(touch_pad_interrupt)
|
@@ -1,65 +0,0 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# Touch Pad Interrupt Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to set up ESP32's capacitive touch pad peripheral to trigger interrupt when a pad is touched. It also shows how to detect the touch event by software for sensor designs where greater touch detection sensitivity is required.
|
||||
|
||||
- The hardware interrupt mode occupies less CPU resources, but we can only apply fixed threshold and software algorithms are also impossibile.
|
||||
- The polling mode is flexible and supports various software algorithms. However, it comsumes more CPU.
|
||||
|
||||
ESP32 supports touch detection by configuring hardware registers. The hardware periodically detects the pulse counts. If the number of pulse counts exceeds the set threshold, a hardware interrupt will be generated to notify the application layer that a certain touch sensor channel may be triggered.
|
||||
|
||||
For the sensors covered with glass or plastic, the capacitance difference caused by a touch action could be very small. In such cases, software polling is used so software algorithms can be applied to reduce noise and catch small changes of the pulse counts. In certain cases, we may need to add additional routines to adjust the threshold level dynamically as it may change depending on environment conditions.
|
||||
|
||||
For a simpler example how to configure and read capacitive touch pads, please refer to [touch_pad_read](../touch_pad_read).
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP32 chip
|
||||
* Proper touch sensor system
|
||||
|
||||
For hardware and firmware design guidelines on ESP32 touch sensor system, please refer to [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.1/documents/touch_pad_solution/touch_sensor_design_en.md), where you may find comprehensive information on how to design and implement touch sensing applications, such as linear slider, wheel slider, matrix buttons and spring buttons.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
The application cycles between the interrupt mode and the pooling mode with a filter, to compare performance of the touch sensor system between both scenarios:
|
||||
|
||||
```
|
||||
I (6303) Touch pad: Waiting for any pad being touched...
|
||||
I (6733) Touch pad: T6 activated!
|
||||
I (7333) Touch pad: T5 activated!
|
||||
I (7723) Touch pad: T3 activated!
|
||||
I (8043) Touch pad: T2 activated!
|
||||
I (8883) Touch pad: T4 activated!
|
||||
I (9523) Touch pad: T7 activated!
|
||||
I (12503) Touch pad: Waiting for any pad being touched...
|
||||
I (15483) Touch pad: T6 activated!
|
||||
I (16253) Touch pad: T5 activated!
|
||||
I (17903) Touch pad: Waiting for any pad being touched...
|
||||
I (22903) Touch pad: Waiting for any pad being touched...
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Sensing threshold is set up automatically at start up by performing simple calibration. Application is reading current value for each pad and assuming two thirds of this value as the sensing threshold. Do not touch pads on application start up, otherwise sensing may not work correctly.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@@ -1,3 +0,0 @@
|
||||
idf_component_register(SRCS "tp_interrupt_main.c"
|
||||
PRIV_REQUIRES driver
|
||||
INCLUDE_DIRS ".")
|
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "driver/touch_pad.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
|
||||
static const char *TAG = "Touch pad";
|
||||
|
||||
#define TOUCH_THRESH_NO_USE (0)
|
||||
#define TOUCH_THRESH_PERCENT (80)
|
||||
#define TOUCHPAD_FILTER_TOUCH_PERIOD (10)
|
||||
|
||||
static bool s_pad_activated[TOUCH_PAD_MAX];
|
||||
static uint32_t s_pad_init_val[TOUCH_PAD_MAX];
|
||||
|
||||
/*
|
||||
Read values sensed at all available touch pads.
|
||||
Use 2 / 3 of read value as the threshold
|
||||
to trigger interrupt when the pad is touched.
|
||||
Note: this routine demonstrates a simple way
|
||||
to configure activation threshold for the touch pads.
|
||||
Do not touch any pads when this routine
|
||||
is running (on application start).
|
||||
*/
|
||||
static void tp_example_set_thresholds(void)
|
||||
{
|
||||
uint16_t touch_value;
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
//read filtered value
|
||||
touch_pad_read_filtered(i, &touch_value);
|
||||
s_pad_init_val[i] = touch_value;
|
||||
ESP_LOGI(TAG, "test init: touch pad [%d] val is %d", i, touch_value);
|
||||
//set interrupt threshold.
|
||||
ESP_ERROR_CHECK(touch_pad_set_thresh(i, touch_value * 2 / 3));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Check if any of touch pads has been activated
|
||||
by reading a table updated by rtc_intr()
|
||||
If so, then print it out on a serial monitor.
|
||||
Clear related entry in the table afterwards
|
||||
|
||||
In interrupt mode, the table is updated in touch ISR.
|
||||
|
||||
In filter mode, we will compare the current filtered value with the initial one.
|
||||
If the current filtered value is less than 80% of the initial value, we can
|
||||
regard it as a 'touched' event.
|
||||
When calling touch_pad_init, a timer will be started to run the filter.
|
||||
This mode is designed for the situation that the pad is covered
|
||||
by a 2-or-3-mm-thick medium, usually glass or plastic.
|
||||
The difference caused by a 'touch' action could be very small, but we can still use
|
||||
filter mode to detect a 'touch' event.
|
||||
*/
|
||||
static void tp_example_read_task(void *pvParameter)
|
||||
{
|
||||
static int show_message;
|
||||
int change_mode = 0;
|
||||
int filter_mode = 0;
|
||||
while (1) {
|
||||
if (filter_mode == 0) {
|
||||
//interrupt mode, enable touch interrupt
|
||||
touch_pad_intr_enable();
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
if (s_pad_activated[i] == true) {
|
||||
ESP_LOGI(TAG, "T%d activated!", i);
|
||||
// Wait a while for the pad being released
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
// Clear information on pad activation
|
||||
s_pad_activated[i] = false;
|
||||
// Reset the counter triggering a message
|
||||
// that application is running
|
||||
show_message = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//filter mode, disable touch interrupt
|
||||
touch_pad_intr_disable();
|
||||
touch_pad_clear_status();
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
uint16_t value = 0;
|
||||
touch_pad_read_filtered(i, &value);
|
||||
if (value < s_pad_init_val[i] * TOUCH_THRESH_PERCENT / 100) {
|
||||
ESP_LOGI(TAG, "T%d activated!", i);
|
||||
ESP_LOGI(TAG, "value: %"PRIu16"; init val: %"PRIu32, value, s_pad_init_val[i]);
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
// Reset the counter to stop changing mode.
|
||||
change_mode = 1;
|
||||
show_message = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
// If no pad is touched, every couple of seconds, show a message
|
||||
// that application is running
|
||||
if (show_message++ % 500 == 0) {
|
||||
ESP_LOGI(TAG, "Waiting for any pad being touched...");
|
||||
}
|
||||
// Change mode if no pad is touched for a long time.
|
||||
// We can compare the two different mode.
|
||||
if (change_mode++ % 2000 == 0) {
|
||||
filter_mode = !filter_mode;
|
||||
ESP_LOGW(TAG, "Change mode...%s", filter_mode == 0 ? "interrupt mode" : "filter mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Handle an interrupt triggered when a pad is touched.
|
||||
Recognize what pad has been touched and save it in a table.
|
||||
*/
|
||||
static void tp_example_rtc_intr(void *arg)
|
||||
{
|
||||
uint32_t pad_intr = touch_pad_get_status();
|
||||
//clear interrupt
|
||||
touch_pad_clear_status();
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
if ((pad_intr >> i) & 0x01) {
|
||||
s_pad_activated[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Before reading touch pad, we need to initialize the RTC IO.
|
||||
*/
|
||||
static void tp_example_touch_pad_init(void)
|
||||
{
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
//init RTC IO and mode for touch pad.
|
||||
touch_pad_config(i, TOUCH_THRESH_NO_USE);
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Initialize touch pad peripheral, it will start a timer to run a filter
|
||||
ESP_LOGI(TAG, "Initializing touch pad");
|
||||
ESP_ERROR_CHECK(touch_pad_init());
|
||||
// If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
|
||||
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
|
||||
// Set reference voltage for charging/discharging
|
||||
// For most usage scenarios, we recommend using the following combination:
|
||||
// the high reference valtage will be 2.7V - 1V = 1.7V, The low reference voltage will be 0.5V.
|
||||
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
|
||||
// Init touch pad IO
|
||||
tp_example_touch_pad_init();
|
||||
// Initialize and start a software filter to detect slight change of capacitance.
|
||||
touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD);
|
||||
// Set thresh hold
|
||||
tp_example_set_thresholds();
|
||||
// Register touch interrupt ISR
|
||||
touch_pad_isr_register(tp_example_rtc_intr, NULL);
|
||||
// Start a task to show what pads have been touched
|
||||
xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 4096, NULL, 5, NULL);
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.generic
|
||||
def test_touch_pad_interrupt_v1(dut: Dut) -> None:
|
||||
dut.expect_exact('Touch pad: Initializing touch pad')
|
||||
dut.expect(r'test init: touch pad \[\d+\] val is \d+')
|
||||
dut.expect_exact('Touch pad: Waiting for any pad being touched...')
|
||||
dut.expect_exact('Touch pad: Change mode...filter mode')
|
||||
dut.expect_exact('Touch pad: Waiting for any pad being touched...')
|
@@ -1,8 +0,0 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
project(touch_pad_read)
|
@@ -1,55 +0,0 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# Touch Pad Read Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
Read and print raw values or IIR filtered values from capacitive touch sensors.
|
||||
|
||||
Once configured, ESP32 will continuously measure capacitance of touch pad sensors. Measurement is reflected as numeric value inversely related to sensor's capacitance. With a finger touched on a pad, its capacitance will get larger meanwhile the measured value gets smaller, and vice versa.
|
||||
|
||||
To detect if a sensor is touched or not, each particular design should be calibrated by obtaining both measurements for each individual sensor. Then a threshold between both values can be established. With specific threshold, API is then able to distinguish whether specific sensor is touched or released.
|
||||
|
||||
|
||||
There is another similar example that demonstrates how to perform simple calibration and trigger an interrupt when a pad is touched - see [touch_pad_interrupt](../touch_pad_interrupt).
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP32 chip
|
||||
* Proper touch sensor system
|
||||
|
||||
For hardware and firmware design guidelines on ESP32 touch sensor system, please refer to [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.1/documents/touch_pad_solution/touch_sensor_design_en.md), where you may find comprehensive information on how to design and implement touch sensing applications, such as linear slider, wheel slider, matrix buttons and spring buttons.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
ESP32 supports up to ten capacitive touch pad sensors, T0 - T9, which are connected to specific GPIO pins. For the information about touch sensor capable pins, please refer to [Technical Reference Manual](https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf). This example will initialize all the 10 touch pads, and print the measured values to serial terminal:
|
||||
|
||||
```
|
||||
Touch Sensor filter mode read, the output format is:
|
||||
Touchpad num:[raw data, filtered data]
|
||||
|
||||
T0:[1072,1071] T1:[ 475, 475] T2:[1004,1003] T3:[1232,1231] T4:[1675,1676] T5:[1146,1146] T6:[1607,1607] T7:[1118,1118] T8:[1695,1695] T9:[1223,1222]
|
||||
T0:[1072,1071] T1:[ 475, 475] T2:[1003,1003] T3:[1231,1231] T4:[1676,1676] T5:[1146,1146] T6:[1607,1607] T7:[1118,1118] T8:[1694,1694] T9:[1222,1221]
|
||||
T0:[1071,1071] T1:[ 475, 475] T2:[1004,1004] T3:[1231,1231] T4:[1678,1677] T5:[1147,1146] T6:[1607,1607] T7:[1118,1118] T8:[1694,1694] T9:[1222,1221]
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@@ -1,3 +0,0 @@
|
||||
idf_component_register(SRCS "tp_read_main.c"
|
||||
PRIV_REQUIRES driver
|
||||
INCLUDE_DIRS ".")
|
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/touch_pad.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define TOUCH_PAD_NO_CHANGE (-1)
|
||||
#define TOUCH_THRESH_NO_USE (0)
|
||||
#define TOUCH_FILTER_MODE_EN (1)
|
||||
#define TOUCHPAD_FILTER_TOUCH_PERIOD (10)
|
||||
/*
|
||||
Read values sensed at all available touch pads.
|
||||
Print out values in a loop on a serial monitor.
|
||||
*/
|
||||
static void tp_example_read_task(void *pvParameter)
|
||||
{
|
||||
uint16_t touch_value;
|
||||
uint16_t touch_filter_value;
|
||||
#if TOUCH_FILTER_MODE_EN
|
||||
printf("Touch Sensor filter mode read, the output format is: \nTouchpad num:[raw data, filtered data]\n\n");
|
||||
#else
|
||||
printf("Touch Sensor normal mode read, the output format is: \nTouchpad num:[raw data]\n\n");
|
||||
#endif
|
||||
while (1) {
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
#if TOUCH_FILTER_MODE_EN
|
||||
// If open the filter mode, please use this API to get the touch pad count.
|
||||
touch_pad_read_raw_data(i, &touch_value);
|
||||
touch_pad_read_filtered(i, &touch_filter_value);
|
||||
printf("T%d:[%4"PRIu16",%4"PRIu16"] ", i, touch_value, touch_filter_value);
|
||||
#else
|
||||
touch_pad_read(i, &touch_value);
|
||||
printf("T%d:[%4"PRIu16"] ", i, touch_value);
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void tp_example_touch_pad_init(void)
|
||||
{
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
touch_pad_config(i, TOUCH_THRESH_NO_USE);
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Initialize touch pad peripheral.
|
||||
// The default fsm mode is software trigger mode.
|
||||
ESP_ERROR_CHECK(touch_pad_init());
|
||||
// Set reference voltage for charging/discharging
|
||||
// In this case, the high reference valtage will be 2.7V - 1V = 1.7V
|
||||
// The low reference voltage will be 0.5
|
||||
// The larger the range, the larger the pulse count value.
|
||||
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
|
||||
tp_example_touch_pad_init();
|
||||
#if TOUCH_FILTER_MODE_EN
|
||||
touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD);
|
||||
#endif
|
||||
// Start task to read values sensed by pads
|
||||
xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 4096, NULL, 5, NULL);
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.generic
|
||||
def test_touch_pad_read_v1(dut: Dut) -> None:
|
||||
dut.expect_exact('Touch Sensor filter mode read, the output format is:')
|
||||
dut.expect(r'T0:\[\s*\d+,\s*\d+\] T1:\[\s*\d+,\s*\d+\] T2:\[\s*\d+,\s*\d+\] T3:\[\s*\d+,\s*\d+\] T4:\[\s*\d+,\s*\d+\]'
|
||||
r' T5:\[\s*\d+,\s*\d+\] T6:\[\s*\d+,\s*\d+\] T7:\[\s*\d+,\s*\d+\] T8:\[\s*\d+,\s*\d+\] T9:\[\s*\d+,\s*\d+\]')
|
@@ -1,6 +1,12 @@
|
||||
idf_component_register(SRCS "deep_sleep_example_main.c"
|
||||
set(srcs "deep_sleep_example_main.c"
|
||||
"gpio_wakeup.c"
|
||||
"ext_wakeup.c"
|
||||
"touch_wakeup.c"
|
||||
PRIV_REQUIRES driver nvs_flash ulp
|
||||
INCLUDE_DIRS ".")
|
||||
"ext_wakeup.c")
|
||||
set(includes ".")
|
||||
|
||||
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED AND CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP)
|
||||
list(APPEND srcs "touch_sens_wakeup.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES nvs_flash ulp esp_driver_gpio esp_driver_touch_sens
|
||||
INCLUDE_DIRS ${includes})
|
||||
|
@@ -3,11 +3,12 @@ menu "Example Configuration"
|
||||
config EXAMPLE_TOUCH_WAKEUP
|
||||
bool "Enable touch wake up"
|
||||
default y
|
||||
depends on SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP && !IDF_TARGET_ESP32P4
|
||||
depends on SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP && SOC_TOUCH_SENSOR_SUPPORTED
|
||||
help
|
||||
This option enables wake up from deep sleep using touch pads.
|
||||
ESP32 - TOUCH8 and TOUCH9, which correspond to GPIO33 and GPIO32.
|
||||
ESP32S2/S3 - TOUCH9, which corresponds to GPIO9.
|
||||
ESP32P4 - TOUCH2, which corresponds to GPIO4.
|
||||
|
||||
Note: On ESP32, touch wakeup source can not be used together with ext0 wakeup source.
|
||||
|
||||
@@ -284,4 +285,18 @@ menu "Example Configuration"
|
||||
supported. If this option is enabled, it is a high level wake up, otherwise it is a low level wake up.
|
||||
endmenu
|
||||
|
||||
menu "Touch wakeup configuration"
|
||||
visible if EXAMPLE_TOUCH_WAKEUP
|
||||
|
||||
config EXAMPLE_TOUCH_ALLOW_DSLP_PD
|
||||
bool "Allow RTC_PERIPH power domain to be powered down during deep sleep"
|
||||
depends on !IDF_TARGET_ESP32
|
||||
default y
|
||||
help
|
||||
Enable this option if allow the RTC_PERIPH power domain (contain touch sensor) to be powered down
|
||||
during deep sleep. It can help to save more power, but only one specified touch channel can wakeup
|
||||
from the deep sleep. If this option is disabled, the RTC_PERIPH power domain will be powered up
|
||||
during deep sleep, and all enabled touch channels can wakeup from the deep sleep.
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
@@ -100,7 +100,7 @@ static void deep_sleep_task(void *args)
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP
|
||||
case ESP_SLEEP_WAKEUP_TOUCHPAD: {
|
||||
printf("Wake up from touch on pad %d\n", esp_sleep_get_touchpad_wakeup_status());
|
||||
printf("Wake up from touch\n");
|
||||
break;
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_TOUCH_WAKEUP
|
||||
|
3
examples/system/deep_sleep/main/idf_component.yml
Normal file
3
examples/system/deep_sleep/main/idf_component.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
touch_sens_examples_common:
|
||||
path: ${IDF_PATH}/examples/peripherals/touch_sensor/touch_sens_examples_common
|
148
examples/system/deep_sleep/main/touch_sens_wakeup.c
Normal file
148
examples/system/deep_sleep/main/touch_sens_wakeup.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/touch_sens.h"
|
||||
#include "touch_sens_example_config.h"
|
||||
|
||||
static const char *TAG = "touch_wakeup";
|
||||
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM 1
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 3
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
// The touch channel IDs that used in this example
|
||||
// If you want to change the wake-up channels, please make sure the channel GPIOs won't conflict to the EXT wakeup GPIOs
|
||||
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {7, 8, 9};
|
||||
|
||||
// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio))
|
||||
static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
[0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.02f, // 2%
|
||||
};
|
||||
|
||||
static bool example_touch_on_active_cb(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d active", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool example_touch_on_inactive_cb(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d inactive", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle, touch_channel_handle_t chan_handle[])
|
||||
{
|
||||
/* Enable the touch sensor to do the initial scanning, so that to initialize the channel data */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
|
||||
/* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(sens_handle, 2000));
|
||||
}
|
||||
|
||||
/* Disable the touch channel to rollback the state */
|
||||
ESP_ERROR_CHECK(touch_sensor_disable(sens_handle));
|
||||
|
||||
/* (Optional) Read the initial channel benchmark and reconfig the channel active threshold accordingly */
|
||||
printf("Initial benchmark and new threshold are:\n");
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
/* Read the initial benchmark of the touch channel */
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#else
|
||||
/* Read smooth data instead if the hardware does not support benchmark */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark));
|
||||
#endif // SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Calculate the proper active thresholds regarding the initial benchmark */
|
||||
printf("Touch [CH %d]", s_channel_id[i]);
|
||||
/* Generate the default channel configuration and then update the active threshold based on the real benchmark */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
// Touch V1 (ESP32) uses absolute threshold.
|
||||
chan_cfg.abs_active_thresh[j] = (uint32_t)(benchmark[j] * (1 - s_thresh2bm_ratio[i]));
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.abs_active_thresh[j]);
|
||||
#else
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[i]);
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]);
|
||||
#endif // SOC_TOUCH_SENSOR_VERSION == 1
|
||||
}
|
||||
printf("\n");
|
||||
/* Update the channel configuration */
|
||||
ESP_ERROR_CHECK(touch_sensor_reconfig_channel(chan_handle[i], &chan_cfg));
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t example_deep_sleep_register_touch_wakeup(void)
|
||||
{
|
||||
printf("Enabling touch wakeup\n");
|
||||
|
||||
/* Handles of touch sensor */
|
||||
touch_sensor_handle_t sens_handle = NULL;
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
|
||||
/* Step 1: Create a new touch sensor controller handle with default sample configuration */
|
||||
touch_sensor_sample_config_t sample_cfg[TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg);
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle));
|
||||
|
||||
/* Step 2: Create and enable the new touch channel handles with default configurations */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, s_channel_id[i], &chan_cfg, &chan_handle[i]));
|
||||
/* Display the touch channel corresponding GPIO number, you can also know from `touch_sensor_channel.h` */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[i], &chan_info));
|
||||
printf("Touch [CH %d] enabled on GPIO%d\n", s_channel_id[i], chan_info.chan_gpio);
|
||||
}
|
||||
|
||||
/* Step 3: Confiture the default filter for the touch sensor (Note: Touch V1 uses software filter) */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg));
|
||||
|
||||
/* (Optional) Do the initial scanning to initialize the touch channel data
|
||||
* Without this step, the channel data in the first read will be invalid
|
||||
*/
|
||||
example_touch_do_initial_scanning(sens_handle, chan_handle);
|
||||
|
||||
/* (Optional) Register the callbacks, optional for deep sleep wakeup */
|
||||
touch_event_callbacks_t callbacks = {
|
||||
.on_active = example_touch_on_active_cb,
|
||||
.on_inactive = example_touch_on_inactive_cb,
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL));
|
||||
|
||||
/* Step 4: Enable the deep sleep wake-up with the basic configuration */
|
||||
#if CONFIG_EXAMPLE_TOUCH_ALLOW_DSLP_PD
|
||||
/* Get the channel information to use same active threshold for the sleep channel */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[0], &chan_info));
|
||||
|
||||
touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_PD_CONFIG(chan_handle[0],
|
||||
chan_info.active_thresh[0],
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 3
|
||||
chan_info.active_thresh[1],
|
||||
chan_info.active_thresh[2],
|
||||
#endif
|
||||
);
|
||||
printf("Touch channel %d (GPIO%d) is selected as deep sleep wakeup channel\n", chan_info.chan_id, chan_info.chan_gpio);
|
||||
#else
|
||||
touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_CONFIG();
|
||||
#endif
|
||||
/* Enable deep sleep wake up for touch sensor */
|
||||
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &deep_slp_cfg));
|
||||
|
||||
/* Step 5: Enable touch sensor controller and start continuous scanning before entering deep sleep */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle));
|
||||
|
||||
ESP_LOGI(TAG, "touch wakeup source is ready");
|
||||
return ESP_OK;
|
||||
}
|
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP
|
||||
#include "driver/touch_pad.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define TOUCH_THRESH_NO_USE 0
|
||||
|
||||
static void calibrate_touch_pad(touch_pad_t pad)
|
||||
{
|
||||
int avg = 0;
|
||||
const size_t calibration_count = 128;
|
||||
for (int i = 0; i < calibration_count; ++i) {
|
||||
uint16_t val;
|
||||
touch_pad_read(pad, &val);
|
||||
avg += val;
|
||||
}
|
||||
avg /= calibration_count;
|
||||
const int min_reading = 300;
|
||||
if (avg < min_reading) {
|
||||
printf("Touch pad #%d average reading is too low: %d (expecting at least %d). "
|
||||
"Not using for deep sleep wakeup.\n", pad, avg, min_reading);
|
||||
touch_pad_config(pad, 0);
|
||||
} else {
|
||||
int threshold = avg - 100;
|
||||
printf("Touch pad #%d average: %d, wakeup threshold set to %d.\n", pad, avg, threshold);
|
||||
touch_pad_config(pad, threshold);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void example_deep_sleep_register_touch_wakeup(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// Initialize touch pad peripheral.
|
||||
// The default fsm mode is software trigger mode.
|
||||
ESP_ERROR_CHECK(touch_pad_init());
|
||||
// If use touch pad wake up, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
|
||||
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
|
||||
// Set reference voltage for charging/discharging
|
||||
// In this case, the high reference voltage will be 2.4V - 1V = 1.4V
|
||||
// The low reference voltage will be 0.5
|
||||
// The larger the range, the larger the pulse count value.
|
||||
touch_pad_set_voltage(TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
|
||||
//init RTC IO and mode for touch pad.
|
||||
touch_pad_config(TOUCH_PAD_NUM8, TOUCH_THRESH_NO_USE);
|
||||
touch_pad_config(TOUCH_PAD_NUM9, TOUCH_THRESH_NO_USE);
|
||||
calibrate_touch_pad(TOUCH_PAD_NUM8);
|
||||
calibrate_touch_pad(TOUCH_PAD_NUM9);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
/* Initialize touch pad peripheral. */
|
||||
touch_pad_init();
|
||||
/* Only support one touch channel in sleep mode. */
|
||||
touch_pad_config(TOUCH_PAD_NUM9);
|
||||
/* Denoise setting at TouchSensor 0. */
|
||||
touch_pad_denoise_t denoise = {
|
||||
/* The bits to be cancelled are determined according to the noise level. */
|
||||
.grade = TOUCH_PAD_DENOISE_BIT4,
|
||||
.cap_level = TOUCH_PAD_DENOISE_CAP_L4,
|
||||
};
|
||||
touch_pad_denoise_set_config(&denoise);
|
||||
touch_pad_denoise_enable();
|
||||
printf("Denoise function init\n");
|
||||
/* Filter setting */
|
||||
touch_filter_config_t filter_info = {
|
||||
.mode = TOUCH_PAD_FILTER_IIR_16,
|
||||
.debounce_cnt = 1, // 1 time count.
|
||||
.noise_thr = 0, // 50%
|
||||
.jitter_step = 4, // use for jitter mode.
|
||||
.smh_lvl = TOUCH_PAD_SMOOTH_IIR_2,
|
||||
};
|
||||
touch_pad_filter_set_config(&filter_info);
|
||||
touch_pad_filter_enable();
|
||||
printf("touch pad filter init %d\n", TOUCH_PAD_FILTER_IIR_8);
|
||||
/* Set sleep touch pad. */
|
||||
touch_pad_sleep_channel_enable(TOUCH_PAD_NUM9, true);
|
||||
touch_pad_sleep_channel_enable_proximity(TOUCH_PAD_NUM9, false);
|
||||
/* Reducing the operating frequency can effectively reduce power consumption. */
|
||||
touch_pad_sleep_channel_set_work_time(1000, TOUCH_PAD_MEASURE_CYCLE_DEFAULT);
|
||||
/* Enable touch sensor clock. Work mode is "timer trigger". */
|
||||
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
|
||||
touch_pad_fsm_start();
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
/* set touchpad wakeup threshold */
|
||||
uint32_t touch_value, wake_threshold;
|
||||
touch_pad_sleep_channel_read_smooth(TOUCH_PAD_NUM9, &touch_value);
|
||||
wake_threshold = touch_value * 0.1; // wakeup when touch sensor crosses 10% of background level
|
||||
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM9, wake_threshold);
|
||||
printf("Touch pad #%d average: %"PRIu32", wakeup threshold set to %"PRIu32"\n",
|
||||
TOUCH_PAD_NUM9, touch_value, (uint32_t)(touch_value * 0.1));
|
||||
#endif
|
||||
printf("Enabling touch pad wakeup\n");
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_touchpad_wakeup());
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
|
||||
#endif
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_TOUCH_WAKEUP
|
@@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import logging
|
||||
import time
|
||||
@@ -6,9 +6,6 @@ import time
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
touch_wake_up_support = ['esp32', 'esp32s2']
|
||||
|
||||
|
||||
CONFIGS = [
|
||||
pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]),
|
||||
pytest.param(
|
||||
@@ -33,18 +30,12 @@ CONFIGS = [
|
||||
@pytest.mark.generic
|
||||
def test_deep_sleep(dut: Dut) -> None:
|
||||
def expect_enable_deep_sleep_touch() -> None:
|
||||
# different targets configure different wake pin(s)
|
||||
wake_pads = {
|
||||
'esp32': [8, 9],
|
||||
'esp32s2': [9],
|
||||
}[dut.target]
|
||||
|
||||
logging.info('Expecting to see wakeup configured on pad(s): {}'.format(wake_pads))
|
||||
|
||||
expect_items = ['Enabling timer wakeup, 20s']
|
||||
for pad in wake_pads:
|
||||
expect_items += [r'Touch pad #{} average: \d+, wakeup threshold set to \d+.'.format(pad)]
|
||||
expect_items += ['Enabling touch pad wakeup']
|
||||
expect_items += ['Enabling touch wakeup']
|
||||
expect_items += [r'Touch \[CH [0-9]+\] enabled on GPIO[0-9]+']
|
||||
if dut.target != 'esp32':
|
||||
expect_items += [r'Touch channel [0-9]+ \(GPIO[0-9]+\) is selected as deep sleep wakeup channel']
|
||||
expect_items += ['touch wakeup source is ready']
|
||||
|
||||
for exp in expect_items:
|
||||
dut.expect(exp, timeout=10)
|
||||
@@ -52,7 +43,7 @@ def test_deep_sleep(dut: Dut) -> None:
|
||||
def expect_enable_deep_sleep_no_touch() -> None:
|
||||
dut.expect_exact('Enabling timer wakeup, 20s', timeout=10)
|
||||
|
||||
if dut.target in touch_wake_up_support:
|
||||
if dut.app.sdkconfig.get('SOC_TOUCH_SUPPORT_SLEEP_WAKEUP'):
|
||||
expect_enable_deep_sleep = expect_enable_deep_sleep_touch
|
||||
else:
|
||||
expect_enable_deep_sleep = expect_enable_deep_sleep_no_touch
|
||||
|
@@ -4,21 +4,12 @@ set(srcs "light_sleep_example_main.c"
|
||||
"gpio_wakeup.c"
|
||||
"timer_wakeup.c"
|
||||
"uart_wakeup.c")
|
||||
set(includes ".")
|
||||
|
||||
set(priv_reqs esp_driver_uart esp_driver_gpio esp_timer)
|
||||
|
||||
set(TOUCH_ELEMENT_COMPATIBLE_TARGETS "esp32s2" "esp32s3")
|
||||
|
||||
if(${target} IN_LIST TOUCH_ELEMENT_COMPATIBLE_TARGETS)
|
||||
list(APPEND srcs "touch_wakeup.c")
|
||||
list(APPEND priv_reqs touch_element)
|
||||
endif()
|
||||
|
||||
if("${target}" STREQUAL "esp32p4")
|
||||
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED AND CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP)
|
||||
list(APPEND srcs "touch_sens_wakeup.c")
|
||||
list(APPEND priv_reqs esp_driver_touch_sens)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES ${priv_reqs}
|
||||
INCLUDE_DIRS ".")
|
||||
PRIV_REQUIRES esp_driver_uart esp_driver_gpio esp_timer esp_driver_touch_sens
|
||||
INCLUDE_DIRS ${includes})
|
||||
|
3
examples/system/light_sleep/main/idf_component.yml
Normal file
3
examples/system/light_sleep/main/idf_component.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
touch_sens_examples_common:
|
||||
path: ${IDF_PATH}/examples/peripherals/touch_sensor/touch_sens_examples_common
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -12,8 +12,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TODO: [ESP32P4] add P4 when runner is ready
|
||||
#define EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define TOUCH_LSLEEP_SUPPORTED (SOC_TOUCH_SENSOR_SUPPORTED && SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP)
|
||||
|
||||
void example_wait_gpio_inactive(void);
|
||||
|
||||
@@ -23,7 +22,7 @@ esp_err_t example_register_timer_wakeup(void);
|
||||
|
||||
esp_err_t example_register_uart_wakeup(void);
|
||||
|
||||
#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT
|
||||
#if TOUCH_LSLEEP_SUPPORTED
|
||||
void example_register_touch_wakeup(void);
|
||||
#endif
|
||||
|
||||
|
@@ -50,7 +50,7 @@ static void light_sleep_task(void *args)
|
||||
* Otherwise the chip may fall sleep again before running uart task */
|
||||
vTaskDelay(1);
|
||||
break;
|
||||
#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT
|
||||
#if TOUCH_LSLEEP_SUPPORTED
|
||||
case ESP_SLEEP_WAKEUP_TOUCHPAD:
|
||||
wakeup_reason = "touch";
|
||||
break;
|
||||
@@ -83,7 +83,7 @@ void app_main(void)
|
||||
example_register_timer_wakeup();
|
||||
/* Enable wakeup from light sleep by uart */
|
||||
example_register_uart_wakeup();
|
||||
#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT
|
||||
#if TOUCH_LSLEEP_SUPPORTED
|
||||
/* Enable wakeup from light sleep by touch element */
|
||||
example_register_touch_wakeup();
|
||||
#endif
|
||||
|
@@ -1,18 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/touch_sens.h"
|
||||
#include "touch_sens_example_config.h"
|
||||
|
||||
static const char *TAG = "touch_wakeup";
|
||||
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM 1
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 5
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 3
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
// If you want to change the wake-up channels, please make sure the channel GPIOs won't conflict to the EXT wakeup GPIOs
|
||||
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {7, 8, 9};
|
||||
|
||||
// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio))
|
||||
static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
[0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.02f, // 2%
|
||||
@@ -20,13 +24,13 @@ static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
|
||||
static bool example_touch_on_active_cb(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("isr", "ch %d active", (int)event->chan_id);
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d active", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool example_touch_on_inactive_cb(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("isr", "ch %d inactive", (int)event->chan_id);
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d inactive", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -48,13 +52,25 @@ static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle,
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
/* Read the initial benchmark of the touch channel */
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#else
|
||||
/* Read smooth data instead if the hardware does not support benchmark */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark));
|
||||
#endif // SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Calculate the proper active thresholds regarding the initial benchmark */
|
||||
printf("[CH %d]", i);
|
||||
touch_channel_config_t chan_cfg = {};
|
||||
printf("Touch [CH %d]", s_channel_id[i]);
|
||||
/* Generate the default channel configuration and then update the active threshold based on the real benchmark */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[j]);
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
// Touch V1 (ESP32) uses absolute threshold.
|
||||
chan_cfg.abs_active_thresh[j] = (uint32_t)(benchmark[j] * (1 - s_thresh2bm_ratio[i]));
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.abs_active_thresh[j]);
|
||||
#else
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[i]);
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]);
|
||||
#endif // SOC_TOUCH_SENSOR_VERSION == 1
|
||||
}
|
||||
printf("\n");
|
||||
/* Update the channel configuration */
|
||||
@@ -64,39 +80,46 @@ static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle,
|
||||
|
||||
esp_err_t example_register_touch_wakeup(void)
|
||||
{
|
||||
/* Handles of touch sensor */
|
||||
touch_sensor_handle_t sens_handle = NULL;
|
||||
touch_sensor_sample_config_t sample_cfg[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {
|
||||
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(1, 1, 1),
|
||||
};
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
|
||||
/* Step 1: Create a new touch sensor controller handle with default sample configuration */
|
||||
touch_sensor_sample_config_t sample_cfg[TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg);
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle));
|
||||
|
||||
/* Step 2: Create and enable the new touch channel handles with default configurations */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, s_channel_id[i], &chan_cfg, &chan_handle[i]));
|
||||
/* Display the touch channel corresponding GPIO number, you can also know from `touch_sensor_channel.h` */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[i], &chan_info));
|
||||
printf("Touch [CH %d] enabled on GPIO%d\n", s_channel_id[i], chan_info.chan_gpio);
|
||||
}
|
||||
|
||||
/* Step 3: Confiture the default filter for the touch sensor (Note: Touch V1 uses software filter) */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg));
|
||||
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
touch_channel_config_t chan_cfg = {
|
||||
.active_thresh = {5000}, // Initial threshold
|
||||
|
||||
};
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, i, &chan_cfg, &chan_handle[i]));
|
||||
}
|
||||
|
||||
/* (Optional) Do the initial scanning to initialize the touch channel data
|
||||
* Without this step, the channel data in the first read will be invalid
|
||||
*/
|
||||
example_touch_do_initial_scanning(sens_handle, chan_handle);
|
||||
|
||||
/* (Optional) Register the callbacks, optional for light sleep wakeup */
|
||||
touch_event_callbacks_t callbacks = {
|
||||
.on_active = example_touch_on_active_cb,
|
||||
.on_inactive = example_touch_on_inactive_cb,
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL));
|
||||
|
||||
/* Step 4: Enable the light sleep wake-up with the basic configuration */
|
||||
touch_sleep_config_t light_slp_cfg = TOUCH_SENSOR_DEFAULT_LSLP_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &light_slp_cfg));
|
||||
|
||||
/* Step 5: Enable touch sensor controller and start continuous scanning before entering light sleep */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle));
|
||||
|
||||
|
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "touch_element/touch_button.h"
|
||||
|
||||
static const char *TAG = "touch_wakeup";
|
||||
|
||||
#define TOUCH_BUTTON_NUM 5
|
||||
|
||||
/* Touch buttons handle */
|
||||
static touch_button_handle_t button_handle[TOUCH_BUTTON_NUM];
|
||||
|
||||
|
||||
/* Touch buttons channel array */
|
||||
static const touch_pad_t channel_array[TOUCH_BUTTON_NUM] = {
|
||||
TOUCH_PAD_NUM1,
|
||||
TOUCH_PAD_NUM2,
|
||||
TOUCH_PAD_NUM3,
|
||||
TOUCH_PAD_NUM4,
|
||||
TOUCH_PAD_NUM5,
|
||||
};
|
||||
|
||||
/* Touch buttons channel sensitivity array */
|
||||
static const float channel_sens_array[TOUCH_BUTTON_NUM] = {
|
||||
0.03F,
|
||||
0.03F,
|
||||
0.03F,
|
||||
0.03F,
|
||||
0.03F,
|
||||
};
|
||||
|
||||
/* Button event handler task */
|
||||
static void button_handler_task(void *arg)
|
||||
{
|
||||
(void) arg; //Unused
|
||||
touch_elem_message_t element_message;
|
||||
while (1) {
|
||||
/* Waiting for touch element messages */
|
||||
touch_element_message_receive(&element_message, portMAX_DELAY);
|
||||
if (element_message.element_type != TOUCH_ELEM_TYPE_BUTTON) {
|
||||
continue;
|
||||
}
|
||||
/* Decode message */
|
||||
const touch_button_message_t *button_message = touch_button_get_message(&element_message);
|
||||
if (button_message->event == TOUCH_BUTTON_EVT_ON_PRESS) {
|
||||
ESP_LOGI(TAG, "Button[%"PRIu32"] Press", (uint32_t)element_message.arg);
|
||||
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
|
||||
ESP_LOGI(TAG, "Button[%"PRIu32"] Release", (uint32_t)element_message.arg);
|
||||
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
|
||||
ESP_LOGI(TAG, "Button[%"PRIu32"] LongPress", (uint32_t)element_message.arg);
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
esp_err_t example_register_touch_wakeup(void)
|
||||
{
|
||||
/* Initialize Touch Element library */
|
||||
touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_element_install(&global_config));
|
||||
ESP_LOGI(TAG, "Touch element library installed");
|
||||
|
||||
touch_button_global_config_t button_global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_button_install(&button_global_config));
|
||||
ESP_LOGI(TAG, "Touch button installed");
|
||||
for (int i = 0; i < TOUCH_BUTTON_NUM; i++) {
|
||||
touch_button_config_t button_config = {
|
||||
.channel_num = channel_array[i],
|
||||
.channel_sens = channel_sens_array[i]
|
||||
};
|
||||
/* Create Touch buttons */
|
||||
ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i]));
|
||||
/* Set EVENT as the dispatch method */
|
||||
ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
|
||||
/* Subscribe touch button events (On Press, On Release, On LongPress) */
|
||||
ESP_ERROR_CHECK(touch_button_subscribe_event(button_handle[i],
|
||||
TOUCH_ELEM_EVENT_ON_PRESS |
|
||||
TOUCH_ELEM_EVENT_ON_RELEASE |
|
||||
TOUCH_ELEM_EVENT_ON_LONGPRESS,
|
||||
(void *)channel_array[i]));
|
||||
}
|
||||
ESP_LOGI(TAG, "Touch buttons created");
|
||||
|
||||
touch_elem_sleep_config_t sleep_config = {
|
||||
.sample_count = global_config.hardware.sample_count,
|
||||
.sleep_cycle = global_config.hardware.sleep_cycle,
|
||||
};
|
||||
/* Enable one of registered touch button as light/deep sleep wake-up source */
|
||||
ESP_ERROR_CHECK(touch_element_enable_light_sleep(&sleep_config));
|
||||
|
||||
touch_element_start();
|
||||
xTaskCreate(&button_handler_task, "button_handler_task", 4 * 1024, NULL, 6, NULL);
|
||||
ESP_LOGI(TAG, "touch wakeup source is ready");
|
||||
return ESP_OK;
|
||||
}
|
Reference in New Issue
Block a user