diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index af516efc5d..0c620a2b8e 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -15,6 +15,11 @@ namespace esphome { namespace esp32_touch { +// IMPORTANT: Touch detection logic differs between ESP32 variants: +// - ESP32 v1 (original): Touch detected when value < threshold (capacitance increase causes value decrease) +// - ESP32-S2/S3 v2: Touch detected when value > threshold (capacitance increase causes value increase) +// This inversion is due to different hardware implementations between chip generations. + static const uint32_t SETUP_MODE_LOG_INTERVAL_MS = 250; class ESP32TouchBinarySensor; diff --git a/esphome/components/esp32_touch/esp32_touch_v1.cpp b/esphome/components/esp32_touch/esp32_touch_v1.cpp index 27aa5fc5f4..f5410f910e 100644 --- a/esphome/components/esp32_touch/esp32_touch_v1.cpp +++ b/esphome/components/esp32_touch/esp32_touch_v1.cpp @@ -142,7 +142,8 @@ void ESP32TouchComponent::loop() { child->last_state_ = new_state; child->publish_state(new_state); // Original ESP32: ISR only fires when touched, release is detected by timeout - ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 ", threshold: %" PRIu32 ")", + // Note: ESP32 v1 uses inverted logic - touched when value < threshold + ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 " < threshold: %" PRIu32 ")", child->get_name().c_str(), event.value, child->get_threshold()); } break; diff --git a/esphome/components/esp32_touch/esp32_touch_v2.cpp b/esphome/components/esp32_touch/esp32_touch_v2.cpp index 0f3b3f5ebf..dba8d0355a 100644 --- a/esphome/components/esp32_touch/esp32_touch_v2.cpp +++ b/esphome/components/esp32_touch/esp32_touch_v2.cpp @@ -258,8 +258,9 @@ void ESP32TouchComponent::loop() { child->last_state_ = is_touched; child->publish_state(is_touched); - ESP_LOGD(TAG, "Touch Pad '%s' initial state: %s (value: %d, threshold: %d)", child->get_name().c_str(), - is_touched ? "touched" : "released", value, child->get_threshold()); + // 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()); } } @@ -301,8 +302,9 @@ void ESP32TouchComponent::loop() { child->last_state_ = is_touch_event; child->publish_state(is_touch_event); - ESP_LOGD(TAG, "Touch Pad '%s' %s (value: %d, threshold: %d)", child->get_name().c_str(), - is_touch_event ? "touched" : "released", value, child->get_threshold()); + // 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()); break; } }