From 599e28e1cb7bc11e662449ff6701487ba4deabad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 12 Jun 2025 20:02:39 -0500 Subject: [PATCH] fixes --- esphome/components/esp32_touch/esp32_touch.h | 3 + .../components/esp32_touch/esp32_touch_v2.cpp | 68 ++++++------------- 2 files changed, 25 insertions(+), 46 deletions(-) diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 041549c519..d7b1a8068f 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -160,6 +160,9 @@ class ESP32TouchComponent : public Component { // Returns the current touch pad value using either filtered or raw reading // based on the filter configuration uint32_t read_touch_value(touch_pad_t pad) const; + + // Helper to read touch value and update state for a given child + void check_and_update_touch_state_(ESP32TouchBinarySensor *child); #endif // Helper functions for dump_config - common to both implementations diff --git a/esphome/components/esp32_touch/esp32_touch_v2.cpp b/esphome/components/esp32_touch/esp32_touch_v2.cpp index 331021feed..dd009ada0f 100644 --- a/esphome/components/esp32_touch/esp32_touch_v2.cpp +++ b/esphome/components/esp32_touch/esp32_touch_v2.cpp @@ -10,6 +10,22 @@ namespace esp32_touch { static const char *const TAG = "esp32_touch"; +// Helper to read touch value and update state for a given child +void ESP32TouchComponent::check_and_update_touch_state_(ESP32TouchBinarySensor *child) { + // Read current touch value + uint32_t value = this->read_touch_value(child->get_touch_pad()); + + // ESP32-S2/S3 v2: Touch is detected when value > threshold + bool is_touched = value > child->get_threshold(); + + if (child->last_state_ != is_touched) { + child->last_state_ = is_touched; + child->publish_state(is_touched); + ESP_LOGD(TAG, "Touch Pad '%s' %s (value: %d %s threshold: %d)", child->get_name().c_str(), + is_touched ? "touched" : "released", value, is_touched ? ">" : "<=", child->get_threshold()); + } +} + void ESP32TouchComponent::setup() { // Create queue for touch events first if (!this->create_touch_queue_()) { @@ -103,15 +119,11 @@ void ESP32TouchComponent::setup() { // Read current value uint32_t value = this->read_touch_value(child->get_touch_pad()); - // IMPORTANT: ESP32-S2/S3 v2 touch detection logic - INVERTED compared to v1! - // ESP32-S2/S3 v2: Touch is detected when capacitance INCREASES, causing the measured value to INCREASE - // Therefore: touched = (value > threshold) - // This is opposite to original ESP32 v1 where touched = (value < threshold) + // Set initial state and publish bool is_touched = value > child->get_threshold(); child->last_state_ = is_touched; child->publish_initial_state(is_touched); - // Note: ESP32-S2/S3 v2 uses inverted logic compared to v1 - touched when value > threshold ESP_LOGD(TAG, "Touch Pad '%s' initial state: %s (value: %d %s threshold: %d)", child->get_name().c_str(), is_touched ? "touched" : "released", value, is_touched ? ">" : "<=", child->get_threshold()); } @@ -260,56 +272,20 @@ void ESP32TouchComponent::loop() { if (event.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { // Resume measurement after timeout touch_pad_timeout_resume(); - - // For timeout events, we should check if the pad is actually touched - // Timeout occurs when a pad stays above threshold for too long - for (auto *child : this->children_) { - if (child->get_touch_pad() != event.pad) { - continue; - } - - // Read current value to determine actual state - uint32_t value = this->read_touch_value(event.pad); - bool is_touched = value > child->get_threshold(); - - // Update state if changed - if (child->last_state_ != is_touched) { - child->last_state_ = is_touched; - child->publish_state(is_touched); - ESP_LOGD(TAG, "Touch Pad '%s' %s via timeout (value: %d %s threshold: %d)", child->get_name().c_str(), - is_touched ? "touched" : "released", value, is_touched ? ">" : "<=", child->get_threshold()); - } - break; - } + // For timeout events, always check the current state + } else if (!(event.intr_mask & (TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE))) { + // Skip if not an active/inactive/timeout event continue; } - // Skip if not an active/inactive event - if (!(event.intr_mask & (TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE))) { - continue; - } - - bool is_touch_event = (event.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) != 0; - // Find the child for the pad that triggered the interrupt for (auto *child : this->children_) { if (child->get_touch_pad() != event.pad) { continue; } - // Skip if state hasn't changed - if (child->last_state_ == is_touch_event) { - break; - } - - // Read current value - uint32_t value = this->read_touch_value(event.pad); - - child->last_state_ = is_touch_event; - child->publish_state(is_touch_event); - // Note: ESP32-S2/S3 v2 uses inverted logic compared to v1 - touched when value > threshold - ESP_LOGD(TAG, "Touch Pad '%s' %s (value: %d %s threshold: %d)", child->get_name().c_str(), - is_touch_event ? "touched" : "released", value, is_touch_event ? ">" : "<=", child->get_threshold()); + // Check and update state + this->check_and_update_touch_state_(child); break; } }