ESPHome 2025.5.0
Loading...
Searching...
No Matches
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
10namespace esphome {
11namespace esp32_touch {
12
13static 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 && defined(USE_ESP32_VARIANT_ESP32)
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 = App.get_loop_component_start_time();
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
345ESP32TouchBinarySensor::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
void feed_wdt(uint32_t time=0)
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
ESP32TouchBinarySensor(touch_pad_t touch_pad, uint32_t threshold, uint32_t wakeup_threshold)
uint32_t component_touch_pad_read(touch_pad_t tp)
touch_pad_shield_driver_t waterproof_shield_driver_
Definition esp32_touch.h:93
std::vector< ESP32TouchBinarySensor * > children_
Definition esp32_touch.h:75
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
Application App
Global storage of Application pointer - only one Application can exist.