1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-07 04:13:47 +01:00
This commit is contained in:
J. Nick Koston
2025-06-12 10:00:49 -05:00
parent bd89a88e34
commit dbdac3707b
2 changed files with 41 additions and 85 deletions

View File

@@ -10,8 +10,6 @@
// Include HAL for ISR-safe touch reading on all variants // Include HAL for ISR-safe touch reading on all variants
#include "hal/touch_sensor_ll.h" #include "hal/touch_sensor_ll.h"
// Include for ISR-safe printing
#include "rom/ets_sys.h"
// Include for RTC clock frequency // Include for RTC clock frequency
#include "soc/rtc.h" #include "soc/rtc.h"
@@ -22,13 +20,6 @@ static const char *const TAG = "esp32_touch";
void ESP32TouchComponent::setup() { void ESP32TouchComponent::setup() {
ESP_LOGCONFIG(TAG, "Running 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(); touch_pad_init();
@@ -39,15 +30,12 @@ void ESP32TouchComponent::setup() {
#endif #endif
// Create queue for touch events - size based on number of touch pads // 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 // Use 4x the number of pads to handle burst events
size_t queue_size = this->children_.size() * 4; size_t queue_size = this->children_.size() * 4;
if (queue_size < 8) if (queue_size < 8)
queue_size = 8; // Minimum queue size 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)); this->touch_queue_ = xQueueCreate(queue_size, sizeof(TouchPadEvent));
if (this->touch_queue_ == nullptr) { if (this->touch_queue_ == nullptr) {
ESP_LOGE(TAG, "Failed to create touch event queue of size %d", queue_size); 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 // Get actual RTC clock frequency
uint32_t rtc_freq = rtc_clk_slow_freq_get_hz(); uint32_t rtc_freq = rtc_clk_slow_freq_get_hz();
#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) // Calculate based on actual sleep cycle since they use timer mode
// For S2/S3, calculate based on actual sleep cycle since they use timer mode
this->release_timeout_ms_ = (this->sleep_cycle_ * 1000 * 3) / (rtc_freq * 2); this->release_timeout_ms_ = (this->sleep_cycle_ * 1000 * 3) / (rtc_freq * 2);
if (this->release_timeout_ms_ < 100) { if (this->release_timeout_ms_ < 100) {
this->release_timeout_ms_ = 100; // Minimum 100ms 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 // Calculate check interval
this->release_check_interval_ms_ = std::min(this->release_timeout_ms_ / 4, (uint32_t) 50); 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 // Enable touch pad interrupt
touch_pad_intr_enable(); 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 // Log which pads are configured and initialize their state
ESP_LOGI(TAG, "Configured touch pads:"); 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(); 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() { 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; const char *lv_s;
switch (this->low_voltage_reference_) { switch (this->low_voltage_reference_) {
case TOUCH_LVOLT_0V5: case TOUCH_LVOLT_0V5:
@@ -212,7 +163,6 @@ void ESP32TouchComponent::dump_config() {
lv_s = "UNKNOWN"; lv_s = "UNKNOWN";
break; break;
} }
ESP_LOGCONFIG(TAG, " Low Voltage Reference: %s", lv_s);
const char *hv_s; const char *hv_s;
switch (this->high_voltage_reference_) { switch (this->high_voltage_reference_) {
@@ -232,7 +182,6 @@ void ESP32TouchComponent::dump_config() {
hv_s = "UNKNOWN"; hv_s = "UNKNOWN";
break; break;
} }
ESP_LOGCONFIG(TAG, " High Voltage Reference: %s", hv_s);
const char *atten_s; const char *atten_s;
switch (this->voltage_attenuation_) { switch (this->voltage_attenuation_) {
@@ -252,7 +201,18 @@ void ESP32TouchComponent::dump_config() {
atten_s = "UNKNOWN"; atten_s = "UNKNOWN";
break; 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 defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
if (this->filter_configured_()) { if (this->filter_configured_()) {
@@ -406,25 +366,13 @@ uint32_t ESP32TouchComponent::component_touch_pad_read(touch_pad_t tp) {
void ESP32TouchComponent::loop() { void ESP32TouchComponent::loop() {
const uint32_t now = App.get_loop_component_start_time(); 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) { if (should_print) {
uint32_t current_status = touch_pad_get_status(); for (auto *child : this->children_) {
uint32_t hal_status; ESP_LOGD(TAG, "Touch Pad '%s' (T%" PRIu32 "): %" PRIu32, child->get_name().c_str(),
touch_ll_read_trigger_status_mask(&hal_status); (uint32_t) child->get_touch_pad(), child->value_);
// 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();
} }
this->setup_mode_last_log_print_ = now; this->setup_mode_last_log_print_ = now;
} }
@@ -529,23 +477,33 @@ void ESP32TouchComponent::on_shutdown() {
void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) { void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) {
ESP32TouchComponent *component = static_cast<ESP32TouchComponent *>(arg); ESP32TouchComponent *component = static_cast<ESP32TouchComponent *>(arg);
// Log that ISR was called
ets_printf("Touch ISR triggered!\n");
uint32_t pad_status = touch_pad_get_status(); uint32_t pad_status = touch_pad_get_status();
touch_pad_clear_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 // Process all configured pads to check their current state
// Send events for ALL pads with valid readings so we catch both touches and releases // Send events for ALL pads with valid readings so we catch both touches and releases
for (auto *child : component->children_) { for (auto *child : component->children_) {
touch_pad_t pad = child->get_touch_pad(); touch_pad_t pad = child->get_touch_pad();
// Read current value // Read current value using ISR-safe API
// We should be using touch_pad_read_filtered here uint32_t value;
uint32_t value = touch_ll_read_raw_data(pad); #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 // Skip pads with 0 value - they haven't been measured in this cycle
if (value == 0) { if (value == 0) {
@@ -559,8 +517,6 @@ void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) {
bool is_touched = value < child->get_threshold(); bool is_touched = value < child->get_threshold();
#endif #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 // Always send the current state - the main loop will filter for changes
TouchPadEvent event; TouchPadEvent event;
event.pad = pad; event.pad = pad;

View File

@@ -68,7 +68,7 @@ class ESP32TouchComponent : public Component {
static void touch_isr_handler(void *arg); static void touch_isr_handler(void *arg);
QueueHandle_t touch_queue_{nullptr}; 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 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_timeout_ms_{1500}; // Calculated timeout for release detection
uint32_t release_check_interval_ms_{50}; // How often to check for releases uint32_t release_check_interval_ms_{50}; // How often to check for releases
#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)