| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /* Touch Pad Interrupt Example
- This example code is in the Public Domain (or CC0 licensed, at your option.)
- Unless required by applicable law or agreed to in writing, this
- software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- CONDITIONS OF ANY KIND, either express or implied.
- */
- #include <stdio.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "esp_log.h"
- #include "driver/touch_pad.h"
- #include "soc/rtc_cntl_reg.h"
- #include "soc/sens_reg.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: %d; init val: %d", 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()
- {
- 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()
- {
- // Initialize touch pad peripheral, it will start a timer to run a filter
- ESP_LOGI(TAG, "Initializing touch pad");
- 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", 2048, NULL, 5, NULL);
- }
|