From 5818d033784996f04434380d966ae70916b035da Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Feb 2026 14:26:47 -0500 Subject: [PATCH] [esp32_touch] Fix zero readings on GPIO33/GPIO32 (channels 8/9) Work around ESP-IDF bug where touch_ll_enable_channel_mask() and touch_ll_set_charge_speed() don't apply the channel 8/9 bit swap required by the ESP32 hardware. The legacy driver's equivalent functions (touch_ll_set_channel_mask, etc.) correctly applied TOUCH_LL_BITS_SWAP, but the new unified API omits it. This caused channels 8 (GPIO33) and 9 (GPIO32) to not be properly enabled for measurement, resulting in reads always returning zero. Co-Authored-By: Claude Opus 4.6 --- .../components/esp32_touch/esp32_touch.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index 8cc0298e67..c866dddb00 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -7,6 +7,12 @@ #include +#if defined(USE_ESP32_VARIANT_ESP32) && ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 5, 2) +// Workaround for ESP-IDF bug: touch_ll_enable_channel_mask() doesn't apply the +// channel 8/9 bit swap. Fixed in ESP-IDF v5.5.3 via MR !43531. +#include +#endif + namespace esphome::esp32_touch { static const char *const TAG = "esp32_touch"; @@ -203,6 +209,19 @@ void ESP32TouchComponent::setup() { return; } +#if defined(USE_ESP32_VARIANT_ESP32) && ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 5, 2) + // Workaround for ESP-IDF bug: touch_ll_enable_channel_mask() doesn't apply the + // bit swap for channels 8 and 9. The ESP32 hardware has these two channels + // physically swapped in the SENS peripheral registers. The legacy API applied + // TOUCH_LL_BITS_SWAP() but the new unified API omits it, causing channels 8 + // (GPIO33) and 9 (GPIO32) to not be enabled for measurement (reads return zero). + // Fixed in ESP-IDF v5.5.3 via MR !43531. + { + uint16_t worken = SENS.sar_touch_enable.touch_pad_worken; + SENS.sar_touch_enable.touch_pad_worken = TOUCH_LL_BITS_SWAP(worken); + } +#endif + // Do initial oneshot scans to populate baseline values for (int i = 0; i < 3; i++) { touch_sensor_trigger_oneshot_scanning(this->sens_handle_, 2000);