diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index fb1973e26f..812c746301 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -243,6 +243,16 @@ class ESP32TouchBinarySensor : public binary_sensor::BinarySensor { uint32_t get_wakeup_threshold() const { return this->wakeup_threshold_; } +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + /// Ensure benchmark value is read (v2 touch hardware only). + /// Called from multiple places - kept as helper to document shared usage. + void ensure_benchmark_read() { + if (this->benchmark_ == 0) { + touch_pad_read_benchmark(this->touch_pad_, &this->benchmark_); + } + } +#endif + protected: friend ESP32TouchComponent; diff --git a/esphome/components/esp32_touch/esp32_touch_common.cpp b/esphome/components/esp32_touch/esp32_touch_common.cpp index a0b1df38c1..429b5173be 100644 --- a/esphome/components/esp32_touch/esp32_touch_common.cpp +++ b/esphome/components/esp32_touch/esp32_touch_common.cpp @@ -102,7 +102,16 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) { uint32_t value = this->read_touch_value(child->get_touch_pad()); // Store the value for get_value() access in lambdas child->value_ = value; - ESP_LOGD(TAG, "Touch Pad '%s' (T%d): %d", child->get_name().c_str(), child->get_touch_pad(), value); + // Read benchmark if not already read + child->ensure_benchmark_read(); + // Calculate difference to help user set threshold + // For ESP32-S2/S3 v2: touch detected when value > benchmark + threshold + // So threshold should be < (value - benchmark) when touched + int32_t difference = static_cast(value) - static_cast(child->benchmark_); + ESP_LOGD(TAG, + "Touch Pad '%s' (T%d): value=%d, benchmark=%" PRIu32 ", difference=%" PRId32 " (set threshold < %" PRId32 + " to detect touch)", + child->get_name().c_str(), child->get_touch_pad(), value, child->benchmark_, difference, difference); #endif } this->setup_mode_last_log_print_ = now; diff --git a/esphome/components/esp32_touch/esp32_touch_v2.cpp b/esphome/components/esp32_touch/esp32_touch_v2.cpp index 9662b009f6..b34ca1abd3 100644 --- a/esphome/components/esp32_touch/esp32_touch_v2.cpp +++ b/esphome/components/esp32_touch/esp32_touch_v2.cpp @@ -105,8 +105,10 @@ void ESP32TouchComponent::setup() { touch_pad_set_charge_discharge_times(this->meas_cycle_); touch_pad_set_measurement_interval(this->sleep_cycle_); - // Configure timeout if needed - touch_pad_timeout_set(true, TOUCH_PAD_THRESHOLD_MAX); + // Disable hardware timeout - it causes continuous interrupts with high-capacitance + // setups (e.g., pressure sensors under cushions). The periodic release check in + // loop() handles state detection reliably without needing hardware timeout. + touch_pad_timeout_set(false, TOUCH_PAD_THRESHOLD_MAX); // Register ISR handler with interrupt mask esp_err_t err = @@ -314,8 +316,7 @@ void ESP32TouchComponent::loop() { size_t pads_off = 0; for (auto *child : this->children_) { - if (child->benchmark_ == 0) - touch_pad_read_benchmark(child->touch_pad_, &child->benchmark_); + child->ensure_benchmark_read(); // Handle initial state publication after startup this->publish_initial_state_if_needed_(child, now); @@ -354,7 +355,7 @@ void ESP32TouchComponent::loop() { void ESP32TouchComponent::on_shutdown() { // Disable interrupts - touch_pad_intr_disable(static_cast(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_TIMEOUT)); + touch_pad_intr_disable(TOUCH_PAD_INTR_MASK_ACTIVE); touch_pad_isr_deregister(touch_isr_handler, this); this->cleanup_touch_queue_();