ESPHome  2025.2.0
esp32_touch.cpp
Go to the documentation of this file.
1 #ifdef USE_ESP32
2 
3 #include "esp32_touch.h"
5 #include "esphome/core/log.h"
6 #include "esphome/core/hal.h"
7 
8 #include <cinttypes>
9 
10 namespace esphome {
11 namespace esp32_touch {
12 
13 static const char *const TAG = "esp32_touch";
14 
16  ESP_LOGCONFIG(TAG, "Setting up ESP32 Touch Hub...");
17  touch_pad_init();
18 // set up and enable/start filtering based on ESP32 variant
19 #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
20  if (this->filter_configured_()) {
21  touch_filter_config_t filter_info = {
22  .mode = this->filter_mode_,
23  .debounce_cnt = this->debounce_count_,
24  .noise_thr = this->noise_threshold_,
25  .jitter_step = this->jitter_step_,
26  .smh_lvl = this->smooth_level_,
27  };
28  touch_pad_filter_set_config(&filter_info);
29  touch_pad_filter_enable();
30  }
31 
32  if (this->denoise_configured_()) {
33  touch_pad_denoise_t denoise = {
34  .grade = this->grade_,
35  .cap_level = this->cap_level_,
36  };
37  touch_pad_denoise_set_config(&denoise);
38  touch_pad_denoise_enable();
39  }
40 
41  if (this->waterproof_configured_()) {
42  touch_pad_waterproof_t waterproof = {
43  .guard_ring_pad = this->waterproof_guard_ring_pad_,
44  .shield_driver = this->waterproof_shield_driver_,
45  };
46  touch_pad_waterproof_set_config(&waterproof);
47  touch_pad_waterproof_enable();
48  }
49 #else
50  if (this->iir_filter_enabled_()) {
51  touch_pad_filter_start(this->iir_filter_);
52  }
53 #endif
54 
55 #if ESP_IDF_VERSION_MAJOR >= 5
56  touch_pad_set_measurement_clock_cycles(this->meas_cycle_);
57  touch_pad_set_measurement_interval(this->sleep_cycle_);
58 #else
59  touch_pad_set_meas_time(this->sleep_cycle_, this->meas_cycle_);
60 #endif
61  touch_pad_set_voltage(this->high_voltage_reference_, this->low_voltage_reference_, this->voltage_attenuation_);
62 
63  for (auto *child : this->children_) {
64 #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
65  touch_pad_config(child->get_touch_pad());
66 #else
67  // Disable interrupt threshold
68  touch_pad_config(child->get_touch_pad(), 0);
69 #endif
70  }
71 #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
72  touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
73  touch_pad_fsm_start();
74 #endif
75 }
76 
78  ESP_LOGCONFIG(TAG, "Config for ESP32 Touch Hub:");
79  ESP_LOGCONFIG(TAG, " Meas cycle: %.2fms", this->meas_cycle_ / (8000000.0f / 1000.0f));
80  ESP_LOGCONFIG(TAG, " Sleep cycle: %.2fms", this->sleep_cycle_ / (150000.0f / 1000.0f));
81 
82  const char *lv_s;
83  switch (this->low_voltage_reference_) {
84  case TOUCH_LVOLT_0V5:
85  lv_s = "0.5V";
86  break;
87  case TOUCH_LVOLT_0V6:
88  lv_s = "0.6V";
89  break;
90  case TOUCH_LVOLT_0V7:
91  lv_s = "0.7V";
92  break;
93  case TOUCH_LVOLT_0V8:
94  lv_s = "0.8V";
95  break;
96  default:
97  lv_s = "UNKNOWN";
98  break;
99  }
100  ESP_LOGCONFIG(TAG, " Low Voltage Reference: %s", lv_s);
101 
102  const char *hv_s;
103  switch (this->high_voltage_reference_) {
104  case TOUCH_HVOLT_2V4:
105  hv_s = "2.4V";
106  break;
107  case TOUCH_HVOLT_2V5:
108  hv_s = "2.5V";
109  break;
110  case TOUCH_HVOLT_2V6:
111  hv_s = "2.6V";
112  break;
113  case TOUCH_HVOLT_2V7:
114  hv_s = "2.7V";
115  break;
116  default:
117  hv_s = "UNKNOWN";
118  break;
119  }
120  ESP_LOGCONFIG(TAG, " High Voltage Reference: %s", hv_s);
121 
122  const char *atten_s;
123  switch (this->voltage_attenuation_) {
124  case TOUCH_HVOLT_ATTEN_1V5:
125  atten_s = "1.5V";
126  break;
127  case TOUCH_HVOLT_ATTEN_1V:
128  atten_s = "1V";
129  break;
130  case TOUCH_HVOLT_ATTEN_0V5:
131  atten_s = "0.5V";
132  break;
133  case TOUCH_HVOLT_ATTEN_0V:
134  atten_s = "0V";
135  break;
136  default:
137  atten_s = "UNKNOWN";
138  break;
139  }
140  ESP_LOGCONFIG(TAG, " Voltage Attenuation: %s", atten_s);
141 
142 #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
143  if (this->filter_configured_()) {
144  const char *filter_mode_s;
145  switch (this->filter_mode_) {
146  case TOUCH_PAD_FILTER_IIR_4:
147  filter_mode_s = "IIR_4";
148  break;
149  case TOUCH_PAD_FILTER_IIR_8:
150  filter_mode_s = "IIR_8";
151  break;
152  case TOUCH_PAD_FILTER_IIR_16:
153  filter_mode_s = "IIR_16";
154  break;
155  case TOUCH_PAD_FILTER_IIR_32:
156  filter_mode_s = "IIR_32";
157  break;
158  case TOUCH_PAD_FILTER_IIR_64:
159  filter_mode_s = "IIR_64";
160  break;
161  case TOUCH_PAD_FILTER_IIR_128:
162  filter_mode_s = "IIR_128";
163  break;
164  case TOUCH_PAD_FILTER_IIR_256:
165  filter_mode_s = "IIR_256";
166  break;
167  case TOUCH_PAD_FILTER_JITTER:
168  filter_mode_s = "JITTER";
169  break;
170  default:
171  filter_mode_s = "UNKNOWN";
172  break;
173  }
174  ESP_LOGCONFIG(TAG, " Filter mode: %s", filter_mode_s);
175  ESP_LOGCONFIG(TAG, " Debounce count: %" PRIu32, this->debounce_count_);
176  ESP_LOGCONFIG(TAG, " Noise threshold coefficient: %" PRIu32, this->noise_threshold_);
177  ESP_LOGCONFIG(TAG, " Jitter filter step size: %" PRIu32, this->jitter_step_);
178  const char *smooth_level_s;
179  switch (this->smooth_level_) {
180  case TOUCH_PAD_SMOOTH_OFF:
181  smooth_level_s = "OFF";
182  break;
183  case TOUCH_PAD_SMOOTH_IIR_2:
184  smooth_level_s = "IIR_2";
185  break;
186  case TOUCH_PAD_SMOOTH_IIR_4:
187  smooth_level_s = "IIR_4";
188  break;
189  case TOUCH_PAD_SMOOTH_IIR_8:
190  smooth_level_s = "IIR_8";
191  break;
192  default:
193  smooth_level_s = "UNKNOWN";
194  break;
195  }
196  ESP_LOGCONFIG(TAG, " Smooth level: %s", smooth_level_s);
197  }
198 
199  if (this->denoise_configured_()) {
200  const char *grade_s;
201  switch (this->grade_) {
202  case TOUCH_PAD_DENOISE_BIT12:
203  grade_s = "BIT12";
204  break;
205  case TOUCH_PAD_DENOISE_BIT10:
206  grade_s = "BIT10";
207  break;
208  case TOUCH_PAD_DENOISE_BIT8:
209  grade_s = "BIT8";
210  break;
211  case TOUCH_PAD_DENOISE_BIT4:
212  grade_s = "BIT4";
213  break;
214  default:
215  grade_s = "UNKNOWN";
216  break;
217  }
218  ESP_LOGCONFIG(TAG, " Denoise grade: %s", grade_s);
219 
220  const char *cap_level_s;
221  switch (this->cap_level_) {
222  case TOUCH_PAD_DENOISE_CAP_L0:
223  cap_level_s = "L0";
224  break;
225  case TOUCH_PAD_DENOISE_CAP_L1:
226  cap_level_s = "L1";
227  break;
228  case TOUCH_PAD_DENOISE_CAP_L2:
229  cap_level_s = "L2";
230  break;
231  case TOUCH_PAD_DENOISE_CAP_L3:
232  cap_level_s = "L3";
233  break;
234  case TOUCH_PAD_DENOISE_CAP_L4:
235  cap_level_s = "L4";
236  break;
237  case TOUCH_PAD_DENOISE_CAP_L5:
238  cap_level_s = "L5";
239  break;
240  case TOUCH_PAD_DENOISE_CAP_L6:
241  cap_level_s = "L6";
242  break;
243  case TOUCH_PAD_DENOISE_CAP_L7:
244  cap_level_s = "L7";
245  break;
246  default:
247  cap_level_s = "UNKNOWN";
248  break;
249  }
250  ESP_LOGCONFIG(TAG, " Denoise capacitance level: %s", cap_level_s);
251  }
252 #else
253  if (this->iir_filter_enabled_()) {
254  ESP_LOGCONFIG(TAG, " IIR Filter: %" PRIu32 "ms", this->iir_filter_);
255  } else {
256  ESP_LOGCONFIG(TAG, " IIR Filter DISABLED");
257  }
258 #endif
259 
260  if (this->setup_mode_) {
261  ESP_LOGCONFIG(TAG, " Setup Mode ENABLED");
262  }
263 
264  for (auto *child : this->children_) {
265  LOG_BINARY_SENSOR(" ", "Touch Pad", child);
266  ESP_LOGCONFIG(TAG, " Pad: T%" PRIu32, (uint32_t) child->get_touch_pad());
267  ESP_LOGCONFIG(TAG, " Threshold: %" PRIu32, child->get_threshold());
268  }
269 }
270 
272 #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
273  uint32_t value = 0;
274  if (this->filter_configured_()) {
275  touch_pad_filter_read_smooth(tp, &value);
276  } else {
277  touch_pad_read_raw_data(tp, &value);
278  }
279 #else
280  uint16_t value = 0;
281  if (this->iir_filter_enabled_()) {
282  touch_pad_read_filtered(tp, &value);
283  } else {
284  touch_pad_read(tp, &value);
285  }
286 #endif
287  return value;
288 }
289 
291  const uint32_t now = millis();
292  bool should_print = this->setup_mode_ && now - this->setup_mode_last_log_print_ > 250;
293  for (auto *child : this->children_) {
294  child->value_ = this->component_touch_pad_read(child->get_touch_pad());
295 #if !(defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3))
296  child->publish_state(child->value_ < child->get_threshold());
297 #else
298  child->publish_state(child->value_ > child->get_threshold());
299 #endif
300 
301  if (should_print) {
302  ESP_LOGD(TAG, "Touch Pad '%s' (T%" PRIu32 "): %" PRIu32, child->get_name().c_str(),
303  (uint32_t) child->get_touch_pad(), child->value_);
304  }
305 
306  App.feed_wdt();
307  }
308 
309  if (should_print) {
310  // Avoid spamming logs
311  this->setup_mode_last_log_print_ = now;
312  }
313 }
314 
316  bool is_wakeup_source = false;
317 
318 #if !(defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3))
319  if (this->iir_filter_enabled_()) {
320  touch_pad_filter_stop();
321  touch_pad_filter_delete();
322  }
323 #endif
324 
325  for (auto *child : this->children_) {
326  if (child->get_wakeup_threshold() != 0) {
327  if (!is_wakeup_source) {
328  is_wakeup_source = true;
329  // Touch sensor FSM mode must be 'TOUCH_FSM_MODE_TIMER' to use it to wake-up.
330  touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
331  }
332 
333 #if !(defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3))
334  // No filter available when using as wake-up source.
335  touch_pad_config(child->get_touch_pad(), child->get_wakeup_threshold());
336 #endif
337  }
338  }
339 
340  if (!is_wakeup_source) {
341  touch_pad_deinit();
342  }
343 }
344 
345 ESP32TouchBinarySensor::ESP32TouchBinarySensor(touch_pad_t touch_pad, uint32_t threshold, uint32_t wakeup_threshold)
346  : touch_pad_(touch_pad), threshold_(threshold), wakeup_threshold_(wakeup_threshold) {}
347 
348 } // namespace esp32_touch
349 } // namespace esphome
350 
351 #endif
std::vector< ESP32TouchBinarySensor * > children_
Definition: esp32_touch.h:75
touch_pad_denoise_cap_t cap_level_
Definition: esp32_touch.h:91
ESP32TouchBinarySensor(touch_pad_t touch_pad, uint32_t threshold, uint32_t wakeup_threshold)
uint32_t component_touch_pad_read(touch_pad_t tp)
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
touch_pad_shield_driver_t waterproof_shield_driver_
Definition: esp32_touch.h:93
Application App
Global storage of Application pointer - only one Application can exist.
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
touch_pad_denoise_grade_t grade_
Definition: esp32_touch.h:90