From dbdac3707b47afedecc79766507504b493718428 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 12 Jun 2025 10:00:49 -0500 Subject: [PATCH] fixes --- .../components/esp32_touch/esp32_touch.cpp | 120 ++++++------------ esphome/components/esp32_touch/esp32_touch.h | 6 +- 2 files changed, 41 insertions(+), 85 deletions(-) diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index 8318a9e1fb..f7c4818396 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -10,8 +10,6 @@ // Include HAL for ISR-safe touch reading on all variants #include "hal/touch_sensor_ll.h" -// Include for ISR-safe printing -#include "rom/ets_sys.h" // Include for RTC clock frequency #include "soc/rtc.h" @@ -22,13 +20,6 @@ static const char *const TAG = "esp32_touch"; void ESP32TouchComponent::setup() { ESP_LOGCONFIG(TAG, "Running setup"); - ESP_LOGI(TAG, "Number of touch pads configured: %d", this->children_.size()); - - if (this->children_.empty()) { - ESP_LOGE(TAG, "No touch pads configured!"); - this->mark_failed(); - return; - } touch_pad_init(); @@ -39,15 +30,12 @@ void ESP32TouchComponent::setup() { #endif // Create queue for touch events - size based on number of touch pads - // Each pad can have at most a few events queued (press/release) + // Each pad can have at most a few press events queued // Use 4x the number of pads to handle burst events size_t queue_size = this->children_.size() * 4; if (queue_size < 8) queue_size = 8; // Minimum queue size - // QUEUE SIZE likely doesn't make sense if its really ratelimited - // to 1 per second, but this is a good starting point - this->touch_queue_ = xQueueCreate(queue_size, sizeof(TouchPadEvent)); if (this->touch_queue_ == nullptr) { ESP_LOGE(TAG, "Failed to create touch event queue of size %d", queue_size); @@ -121,46 +109,17 @@ void ESP32TouchComponent::setup() { // Get actual RTC clock frequency uint32_t rtc_freq = rtc_clk_slow_freq_get_hz(); -#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - // For S2/S3, calculate based on actual sleep cycle since they use timer mode + // Calculate based on actual sleep cycle since they use timer mode this->release_timeout_ms_ = (this->sleep_cycle_ * 1000 * 3) / (rtc_freq * 2); if (this->release_timeout_ms_ < 100) { this->release_timeout_ms_ = 100; // Minimum 100ms } -#else - // For ESP32 in software mode, we're triggering manually - // Since we're triggering every 1 second in the debug loop, use 1500ms timeout - this->release_timeout_ms_ = 1500; // 1.5 seconds -#endif // Calculate check interval this->release_check_interval_ms_ = std::min(this->release_timeout_ms_ / 4, (uint32_t) 50); - // Read back the actual configuration to verify - uint16_t actual_sleep_cycle = 0; - uint16_t actual_meas_cycle = 0; -#if ESP_IDF_VERSION_MAJOR >= 5 && defined(USE_ESP32_VARIANT_ESP32) - touch_pad_get_measurement_interval(&actual_sleep_cycle); - touch_pad_get_measurement_clock_cycles(&actual_meas_cycle); -#else - touch_pad_get_meas_time(&actual_sleep_cycle, &actual_meas_cycle); -#endif - - ESP_LOGI(TAG, "Touch timing config - requested: sleep=%u, meas=%u | actual: sleep=%u, meas=%u", this->sleep_cycle_, - this->meas_cycle_, actual_sleep_cycle, actual_meas_cycle); - ESP_LOGI(TAG, "Touch release timeout: %u ms, check interval: %u ms (RTC freq: %u Hz)", this->release_timeout_ms_, - this->release_check_interval_ms_, rtc_freq); - // Enable touch pad interrupt touch_pad_intr_enable(); - ESP_LOGI(TAG, "Touch pad interrupts enabled"); - - // Check FSM state for debugging - touch_fsm_mode_t fsm_mode; - touch_pad_get_fsm_mode(&fsm_mode); - ESP_LOGI(TAG, "FSM mode: %s", fsm_mode == TOUCH_FSM_MODE_TIMER ? "TIMER" : "SW"); - - ESP_LOGI(TAG, "Initial touch status: 0x%04x", touch_pad_get_status()); // Log which pads are configured and initialize their state ESP_LOGI(TAG, "Configured touch pads:"); @@ -183,17 +142,9 @@ void ESP32TouchComponent::setup() { this->last_touch_time_[child->get_touch_pad()] = App.get_loop_component_start_time(); } } - - ESP_LOGI(TAG, "ESP32 Touch setup complete"); } void ESP32TouchComponent::dump_config() { - ESP_LOGCONFIG(TAG, - "Config for ESP32 Touch Hub:\n" - " Meas cycle: %.2fms\n" - " Sleep cycle: %.2fms", - this->meas_cycle_ / (8000000.0f / 1000.0f), this->sleep_cycle_ / (150000.0f / 1000.0f)); - const char *lv_s; switch (this->low_voltage_reference_) { case TOUCH_LVOLT_0V5: @@ -212,7 +163,6 @@ void ESP32TouchComponent::dump_config() { lv_s = "UNKNOWN"; break; } - ESP_LOGCONFIG(TAG, " Low Voltage Reference: %s", lv_s); const char *hv_s; switch (this->high_voltage_reference_) { @@ -232,7 +182,6 @@ void ESP32TouchComponent::dump_config() { hv_s = "UNKNOWN"; break; } - ESP_LOGCONFIG(TAG, " High Voltage Reference: %s", hv_s); const char *atten_s; switch (this->voltage_attenuation_) { @@ -252,7 +201,18 @@ void ESP32TouchComponent::dump_config() { atten_s = "UNKNOWN"; break; } - ESP_LOGCONFIG(TAG, " Voltage Attenuation: %s", atten_s); + ESP_LOGCONFIG(TAG, + "Config for ESP32 Touch Hub:\n" + " Meas cycle: %.2fms\n" + " Sleep cycle: %.2fms\n" + " Low Voltage Reference: %s\n" + " High Voltage Reference: %s\n" + " Voltage Attenuation: %s\n" + " ISR Configuration:\n" + " Release timeout: %" PRIu32 "ms\n" + " Release check interval: %" PRIu32 "ms", + this->meas_cycle_ / (8000000.0f / 1000.0f), this->sleep_cycle_ / (150000.0f / 1000.0f), lv_s, hv_s, + atten_s, this->release_timeout_ms_, this->release_check_interval_ms_); #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) if (this->filter_configured_()) { @@ -406,25 +366,13 @@ uint32_t ESP32TouchComponent::component_touch_pad_read(touch_pad_t tp) { void ESP32TouchComponent::loop() { const uint32_t now = App.get_loop_component_start_time(); - bool should_print = now - this->setup_mode_last_log_print_ > 1000; // Log every second + bool should_print = this->setup_mode_ && now - this->setup_mode_last_log_print_ > 250; - // Always check touch status periodically + // Print debug info for all pads in setup mode if (should_print) { - uint32_t current_status = touch_pad_get_status(); - uint32_t hal_status; - touch_ll_read_trigger_status_mask(&hal_status); - - // Check if FSM is still in timer mode - touch_fsm_mode_t fsm_mode; - touch_pad_get_fsm_mode(&fsm_mode); - - ESP_LOGD(TAG, "Current touch status: 0x%04x (HAL: 0x%04x), FSM: %s", current_status, hal_status, - fsm_mode == TOUCH_FSM_MODE_TIMER ? "TIMER" : "SW"); - - // Try a manual software trigger to see if measurements are working at all - if (current_status == 0 && hal_status == 0) { - ESP_LOGD(TAG, "No touch status, trying manual trigger..."); - touch_pad_sw_start(); + for (auto *child : this->children_) { + ESP_LOGD(TAG, "Touch Pad '%s' (T%" PRIu32 "): %" PRIu32, child->get_name().c_str(), + (uint32_t) child->get_touch_pad(), child->value_); } this->setup_mode_last_log_print_ = now; } @@ -529,23 +477,33 @@ void ESP32TouchComponent::on_shutdown() { void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) { ESP32TouchComponent *component = static_cast(arg); - // Log that ISR was called - ets_printf("Touch ISR triggered!\n"); - uint32_t pad_status = touch_pad_get_status(); touch_pad_clear_status(); - // Always log the status - ets_printf("Touch ISR: raw status=0x%04x\n", pad_status); - // Process all configured pads to check their current state // Send events for ALL pads with valid readings so we catch both touches and releases for (auto *child : component->children_) { touch_pad_t pad = child->get_touch_pad(); - // Read current value - // We should be using touch_pad_read_filtered here - uint32_t value = touch_ll_read_raw_data(pad); + // Read current value using ISR-safe API + uint32_t value; +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + if (component->filter_configured_()) { + touch_pad_read_raw_data(pad, &value); + } else { + // Use low-level HAL function when filter is not configured + value = touch_ll_read_raw_data(pad); + } +#else + if (component->iir_filter_enabled_()) { + uint16_t temp_value = 0; + touch_pad_read_raw_data(pad, &temp_value); + value = temp_value; + } else { + // Use low-level HAL function when filter is not enabled + value = touch_ll_read_raw_data(pad); + } +#endif // Skip pads with 0 value - they haven't been measured in this cycle if (value == 0) { @@ -559,8 +517,6 @@ void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) { bool is_touched = value < child->get_threshold(); #endif - ets_printf(" Pad %d: value=%d, threshold=%d, touched=%d\n", pad, value, child->get_threshold(), is_touched); - // Always send the current state - the main loop will filter for changes TouchPadEvent event; event.pad = pad; diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 130b5affba..218ac26453 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -68,9 +68,9 @@ class ESP32TouchComponent : public Component { static void touch_isr_handler(void *arg); QueueHandle_t touch_queue_{nullptr}; - uint32_t last_touch_time_[SOC_TOUCH_SENSOR_NUM] = {0}; // Track last time each pad was seen as touched - uint32_t release_timeout_ms_{1500}; // Calculated timeout for release detection - uint32_t release_check_interval_ms_{50}; // How often to check for releases + uint32_t last_touch_time_[TOUCH_PAD_MAX] = {0}; // Track last time each pad was seen as touched + uint32_t release_timeout_ms_{1500}; // Calculated timeout for release detection + uint32_t release_check_interval_ms_{50}; // How often to check for releases #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);