diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index 0e864773e7..64aacfcefd 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -404,22 +404,30 @@ void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) { uint32_t pad_status = touch_pad_get_status(); touch_pad_clear_status(); - // pad_status contains the current trigger state of all pads - // Send status update for all configured pads + // Find which pads have changed state + uint32_t changed_pads = pad_status ^ component->last_touch_status_; + component->last_touch_status_ = pad_status; + + // Only process pads that have actually changed state for (auto *child : component->children_) { touch_pad_t pad = child->get_touch_pad(); - TouchPadEvent event; - event.pad = pad; - // Check if this pad is currently triggered (1) or not (0) - event.triggered = (pad_status >> pad) & 0x01; - // Read current value using HAL function (safe for all variants) - event.value = touch_ll_read_raw_data(pad); - // Send to queue from ISR - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xQueueSendFromISR(component->touch_queue_, &event, &xHigherPriorityTaskWoken); - if (xHigherPriorityTaskWoken) { - portYIELD_FROM_ISR(); + // Check if this pad has changed + if ((changed_pads >> pad) & 0x01) { + bool is_touched = (pad_status >> pad) & 0x01; + + TouchPadEvent event; + event.pad = pad; + event.triggered = is_touched; + // Read current value using HAL function (safe for all variants) + event.value = touch_ll_read_raw_data(pad); + + // Send to queue from ISR + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xQueueSendFromISR(component->touch_queue_, &event, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); + } } } } diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 1aca72d623..824e44a7ac 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -68,6 +68,7 @@ class ESP32TouchComponent : public Component { static void touch_isr_handler(void *arg); QueueHandle_t touch_queue_{nullptr}; + uint32_t last_touch_status_{0}; // Track last interrupt status to detect changes #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) bool filter_configured_() const { return (this->filter_mode_ != TOUCH_PAD_FILTER_MAX) && (this->smooth_level_ != TOUCH_PAD_SMOOTH_MAX);