#ifdef USE_ESP32 #include "esp32_touch.h" #include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" #include namespace esphome { namespace esp32_touch { static const char *const TAG = "esp32_touch"; void ESP32TouchComponent::setup() { ESP_LOGCONFIG(TAG, "Running setup"); touch_pad_init(); // set up and enable/start filtering based on ESP32 variant #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) if (this->filter_configured_()) { touch_filter_config_t filter_info = { .mode = this->filter_mode_, .debounce_cnt = this->debounce_count_, .noise_thr = this->noise_threshold_, .jitter_step = this->jitter_step_, .smh_lvl = this->smooth_level_, }; touch_pad_filter_set_config(&filter_info); touch_pad_filter_enable(); } if (this->denoise_configured_()) { touch_pad_denoise_t denoise = { .grade = this->grade_, .cap_level = this->cap_level_, }; touch_pad_denoise_set_config(&denoise); touch_pad_denoise_enable(); } if (this->waterproof_configured_()) { touch_pad_waterproof_t waterproof = { .guard_ring_pad = this->waterproof_guard_ring_pad_, .shield_driver = this->waterproof_shield_driver_, }; touch_pad_waterproof_set_config(&waterproof); touch_pad_waterproof_enable(); } #else if (this->iir_filter_enabled_()) { touch_pad_filter_start(this->iir_filter_); } #endif #if ESP_IDF_VERSION_MAJOR >= 5 && defined(USE_ESP32_VARIANT_ESP32) touch_pad_set_measurement_clock_cycles(this->meas_cycle_); touch_pad_set_measurement_interval(this->sleep_cycle_); #else touch_pad_set_meas_time(this->sleep_cycle_, this->meas_cycle_); #endif touch_pad_set_voltage(this->high_voltage_reference_, this->low_voltage_reference_, this->voltage_attenuation_); for (auto *child : this->children_) { #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) touch_pad_config(child->get_touch_pad()); #else // Disable interrupt threshold touch_pad_config(child->get_touch_pad(), 0); #endif } #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); touch_pad_fsm_start(); #endif } void ESP32TouchComponent::dump_config() { ESP_LOGCONFIG(TAG, "Config for ESP32 Touch Hub:\n" " Meas cycle: %.2fms\n" " Sleep cycle: %.2fms", this->meas_cycle_ / (8000000.0f / 1000.0f), this->sleep_cycle_ / (150000.0f / 1000.0f)); const char *lv_s; switch (this->low_voltage_reference_) { case TOUCH_LVOLT_0V5: lv_s = "0.5V"; break; case TOUCH_LVOLT_0V6: lv_s = "0.6V"; break; case TOUCH_LVOLT_0V7: lv_s = "0.7V"; break; case TOUCH_LVOLT_0V8: lv_s = "0.8V"; break; default: lv_s = "UNKNOWN"; break; } ESP_LOGCONFIG(TAG, " Low Voltage Reference: %s", lv_s); const char *hv_s; switch (this->high_voltage_reference_) { case TOUCH_HVOLT_2V4: hv_s = "2.4V"; break; case TOUCH_HVOLT_2V5: hv_s = "2.5V"; break; case TOUCH_HVOLT_2V6: hv_s = "2.6V"; break; case TOUCH_HVOLT_2V7: hv_s = "2.7V"; break; default: hv_s = "UNKNOWN"; break; } ESP_LOGCONFIG(TAG, " High Voltage Reference: %s", hv_s); const char *atten_s; switch (this->voltage_attenuation_) { case TOUCH_HVOLT_ATTEN_1V5: atten_s = "1.5V"; break; case TOUCH_HVOLT_ATTEN_1V: atten_s = "1V"; break; case TOUCH_HVOLT_ATTEN_0V5: atten_s = "0.5V"; break; case TOUCH_HVOLT_ATTEN_0V: atten_s = "0V"; break; default: atten_s = "UNKNOWN"; break; } ESP_LOGCONFIG(TAG, " Voltage Attenuation: %s", atten_s); #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) if (this->filter_configured_()) { const char *filter_mode_s; switch (this->filter_mode_) { case TOUCH_PAD_FILTER_IIR_4: filter_mode_s = "IIR_4"; break; case TOUCH_PAD_FILTER_IIR_8: filter_mode_s = "IIR_8"; break; case TOUCH_PAD_FILTER_IIR_16: filter_mode_s = "IIR_16"; break; case TOUCH_PAD_FILTER_IIR_32: filter_mode_s = "IIR_32"; break; case TOUCH_PAD_FILTER_IIR_64: filter_mode_s = "IIR_64"; break; case TOUCH_PAD_FILTER_IIR_128: filter_mode_s = "IIR_128"; break; case TOUCH_PAD_FILTER_IIR_256: filter_mode_s = "IIR_256"; break; case TOUCH_PAD_FILTER_JITTER: filter_mode_s = "JITTER"; break; default: filter_mode_s = "UNKNOWN"; break; } ESP_LOGCONFIG(TAG, " Filter mode: %s\n" " Debounce count: %" PRIu32 "\n" " Noise threshold coefficient: %" PRIu32 "\n" " Jitter filter step size: %" PRIu32, filter_mode_s, this->debounce_count_, this->noise_threshold_, this->jitter_step_); const char *smooth_level_s; switch (this->smooth_level_) { case TOUCH_PAD_SMOOTH_OFF: smooth_level_s = "OFF"; break; case TOUCH_PAD_SMOOTH_IIR_2: smooth_level_s = "IIR_2"; break; case TOUCH_PAD_SMOOTH_IIR_4: smooth_level_s = "IIR_4"; break; case TOUCH_PAD_SMOOTH_IIR_8: smooth_level_s = "IIR_8"; break; default: smooth_level_s = "UNKNOWN"; break; } ESP_LOGCONFIG(TAG, " Smooth level: %s", smooth_level_s); } if (this->denoise_configured_()) { const char *grade_s; switch (this->grade_) { case TOUCH_PAD_DENOISE_BIT12: grade_s = "BIT12"; break; case TOUCH_PAD_DENOISE_BIT10: grade_s = "BIT10"; break; case TOUCH_PAD_DENOISE_BIT8: grade_s = "BIT8"; break; case TOUCH_PAD_DENOISE_BIT4: grade_s = "BIT4"; break; default: grade_s = "UNKNOWN"; break; } ESP_LOGCONFIG(TAG, " Denoise grade: %s", grade_s); const char *cap_level_s; switch (this->cap_level_) { case TOUCH_PAD_DENOISE_CAP_L0: cap_level_s = "L0"; break; case TOUCH_PAD_DENOISE_CAP_L1: cap_level_s = "L1"; break; case TOUCH_PAD_DENOISE_CAP_L2: cap_level_s = "L2"; break; case TOUCH_PAD_DENOISE_CAP_L3: cap_level_s = "L3"; break; case TOUCH_PAD_DENOISE_CAP_L4: cap_level_s = "L4"; break; case TOUCH_PAD_DENOISE_CAP_L5: cap_level_s = "L5"; break; case TOUCH_PAD_DENOISE_CAP_L6: cap_level_s = "L6"; break; case TOUCH_PAD_DENOISE_CAP_L7: cap_level_s = "L7"; break; default: cap_level_s = "UNKNOWN"; break; } ESP_LOGCONFIG(TAG, " Denoise capacitance level: %s", cap_level_s); } #else if (this->iir_filter_enabled_()) { ESP_LOGCONFIG(TAG, " IIR Filter: %" PRIu32 "ms", this->iir_filter_); } else { ESP_LOGCONFIG(TAG, " IIR Filter DISABLED"); } #endif if (this->setup_mode_) { ESP_LOGCONFIG(TAG, " Setup Mode ENABLED"); } for (auto *child : this->children_) { LOG_BINARY_SENSOR(" ", "Touch Pad", child); ESP_LOGCONFIG(TAG, " Pad: T%" PRIu32, (uint32_t) child->get_touch_pad()); ESP_LOGCONFIG(TAG, " Threshold: %" PRIu32, child->get_threshold()); } } uint32_t ESP32TouchComponent::component_touch_pad_read(touch_pad_t tp) { #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) uint32_t value = 0; if (this->filter_configured_()) { touch_pad_filter_read_smooth(tp, &value); } else { touch_pad_read_raw_data(tp, &value); } #else uint16_t value = 0; if (this->iir_filter_enabled_()) { touch_pad_read_filtered(tp, &value); } else { touch_pad_read(tp, &value); } #endif return value; } void ESP32TouchComponent::loop() { const uint32_t now = App.get_loop_component_start_time(); bool should_print = this->setup_mode_ && now - this->setup_mode_last_log_print_ > 250; for (auto *child : this->children_) { child->value_ = this->component_touch_pad_read(child->get_touch_pad()); #if !(defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) child->publish_state(child->value_ < child->get_threshold()); #else child->publish_state(child->value_ > child->get_threshold()); #endif if (should_print) { ESP_LOGD(TAG, "Touch Pad '%s' (T%" PRIu32 "): %" PRIu32, child->get_name().c_str(), (uint32_t) child->get_touch_pad(), child->value_); } App.feed_wdt(); } if (should_print) { // Avoid spamming logs this->setup_mode_last_log_print_ = now; } } void ESP32TouchComponent::on_shutdown() { bool is_wakeup_source = false; #if !(defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) if (this->iir_filter_enabled_()) { touch_pad_filter_stop(); touch_pad_filter_delete(); } #endif for (auto *child : this->children_) { if (child->get_wakeup_threshold() != 0) { if (!is_wakeup_source) { is_wakeup_source = true; // Touch sensor FSM mode must be 'TOUCH_FSM_MODE_TIMER' to use it to wake-up. touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); } #if !(defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) // No filter available when using as wake-up source. touch_pad_config(child->get_touch_pad(), child->get_wakeup_threshold()); #endif } } if (!is_wakeup_source) { touch_pad_deinit(); } } ESP32TouchBinarySensor::ESP32TouchBinarySensor(touch_pad_t touch_pad, uint32_t threshold, uint32_t wakeup_threshold) : touch_pad_(touch_pad), threshold_(threshold), wakeup_threshold_(wakeup_threshold) {} } // namespace esp32_touch } // namespace esphome #endif