#include "adc_manager.h" #include "application.h" #include #include #include #include #include #include #include #include #include #define TAG "AdcManager" // 检测时间定义(毫秒) #define PRESSURE_DETECTION_TIME_MS 2000 // 压力检测持续时间:2秒 #define LOW_VALUE_DETECTION_TIME_MS 2000 // 低值检测持续时间:2秒 AdcManager &AdcManager::GetInstance() { static AdcManager instance; return instance; } bool AdcManager::Initialize() { if (initialized_) { ESP_LOGW(TAG, "AdcManager already initialized"); return true; } ESP_LOGI(TAG, "Initializing AdcManager..."); // 初始化ADC数组 memset(pressure_adc_values_, 0, sizeof(pressure_adc_values_)); InitializeAdc(); // InitializeDigitalOutput(); // 暂时注释掉DO初始化 // 先设置初始化状态,再启动任务 initialized_ = true; // 初始化后立刻读取一次,便于快速确认链路 int init_read_raw = -1; esp_err_t init_read_ret = adc_oneshot_read( adc1_handle_, PRESSURE_SENSOR_ADC_CHANNEL, &init_read_raw); if (init_read_ret != ESP_OK) { ESP_LOGE(TAG, "Initial ADC read failed: %s", esp_err_to_name(init_read_ret)); } else { ESP_LOGI(TAG, "Initial ADC read ok: Raw=%d", init_read_raw); } // 启动ADC任务 StartAdcTask(); ESP_LOGI(TAG, "AdcManager initialized successfully"); return true; } void AdcManager::InitializeAdc() { ESP_LOGI(TAG, "Initializing ADC for pressure sensor on GPIO4 (ADC1_CH3)..."); // 初始化ADC驱动 adc_oneshot_unit_init_cfg_t init_config1 = { .unit_id = ADC_UNIT_1, }; esp_err_t ret = adc_oneshot_new_unit(&init_config1, &adc1_handle_); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize ADC unit: %s", esp_err_to_name(ret)); return; } ESP_LOGI(TAG, "ADC unit initialized successfully"); // 配置ADC通道 adc_oneshot_chan_cfg_t chan_config = { .atten = ADC_ATTEN_DB_12, .bitwidth = ADC_BITWIDTH_12, }; ret = adc_oneshot_config_channel(adc1_handle_, PRESSURE_SENSOR_ADC_CHANNEL, &chan_config); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to configure ADC channel %d: %s", PRESSURE_SENSOR_ADC_CHANNEL, esp_err_to_name(ret)); return; } ESP_LOGI(TAG, "ADC channel %d configured successfully", PRESSURE_SENSOR_ADC_CHANNEL); // 初始化ADC校准 adc_cali_curve_fitting_config_t cali_config = { .unit_id = ADC_UNIT_1, .atten = ADC_ATTEN_DB_12, .bitwidth = ADC_BITWIDTH_12, }; ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_handle_); if (ret != ESP_OK) { ESP_LOGW(TAG, "ADC calibration not available: %s", esp_err_to_name(ret)); adc1_cali_handle_ = NULL; } else { ESP_LOGI(TAG, "ADC calibration initialized successfully"); } ESP_LOGI(TAG, "ADC initialized for pressure sensor monitoring on GPIO4"); } void AdcManager::ReadPressureSensorData() { if (!initialized_) { return; } int adc_value; esp_err_t ret = adc_oneshot_read(adc1_handle_, PRESSURE_SENSOR_ADC_CHANNEL, &adc_value); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to read pressure sensor ADC: %s", esp_err_to_name(ret)); return; } // 直接使用原始ADC值,不进行电压转换 current_pressure_value_ = adc_value; // 压力检测触发音乐播放 static bool last_pressure_state = false; static int64_t pressure_start_time = 0; static bool pressure_triggered = false; if (last_pressure_state) { // 长时间不动检测逻辑 CheckLongTimeNoMovement(current_pressure_value_); } // 每隔5次打印一次详细日志(便于定位问题) static int adc_log_counter = 0; adc_log_counter++; if (adc_log_counter >= 10) { ESP_LOGI(TAG, "ADC read: Raw=%d", adc_value); adc_log_counter = 0; } bool current_pressure_state = IsPressureDetected(); if (current_pressure_state && !last_pressure_state) { // 压力开始检测,记录开始时间 pressure_start_time = esp_timer_get_time(); pressure_triggered = false; ESP_LOGI(TAG, "Pressure detection started"); } else if (current_pressure_state && last_pressure_state) { // 压力持续检测中,检查是否超过2秒 int64_t current_time = esp_timer_get_time(); int64_t duration_ms = (current_time - pressure_start_time) / 1000; // 转换为毫秒 if (duration_ms >= PRESSURE_DETECTION_TIME_MS && !pressure_triggered) { ESP_LOGI(TAG, "Pressure detected for %ld ms! Triggering music playback...", (long)duration_ms); // 触发音乐播放 TriggerMusicPlayback(); pressure_triggered = true; // 防止重复触发 } } else if (!current_pressure_state && last_pressure_state) { // 压力结束检测 ESP_LOGI(TAG, "Pressure detection ended"); pressure_triggered = false; } last_pressure_state = current_pressure_state; // ADC值小于100时的暂停检测(也需要持续2秒) static int64_t low_value_start_time = 0; static bool low_value_triggered = false; if (adc_value < 100) { if (low_value_start_time == 0) { // 第一次检测到小于100的值,记录开始时间 low_value_start_time = esp_timer_get_time(); low_value_triggered = false; ESP_LOGI(TAG, "ADC low value detection started (value: %d)", adc_value); } else { // 持续检测小于100的值,检查是否超过2秒 int64_t current_time = esp_timer_get_time(); int64_t duration_ms = (current_time - low_value_start_time) / 1000; // 转换为毫秒 if (duration_ms >= LOW_VALUE_DETECTION_TIME_MS && !low_value_triggered) { ESP_LOGI(TAG, "ADC low value detected for %ld ms! (value: %d) Triggering music pause...", (long)duration_ms, adc_value); TriggerMusicPauseback(); low_value_triggered = true; // 防止重复触发 } } } else { // ADC值大于等于100,重置低值检测 if (low_value_start_time != 0) { ESP_LOGI(TAG, "ADC low value detection ended (value: %d)", adc_value); low_value_start_time = 0; low_value_triggered = false; } } } void AdcManager::StartAdcTask() { if (!initialized_) { ESP_LOGE(TAG, "AdcManager not initialized"); return; } BaseType_t ret = xTaskCreate(AdcTask, "adc_task", 4096, this, 2, &adc_task_handle_); if (ret != pdPASS) { ESP_LOGE(TAG, "Failed to create ADC task"); } else { ESP_LOGI(TAG, "ADC task created successfully"); } } void AdcManager::StopAdcTask() { if (adc_task_handle_) { vTaskDelete(adc_task_handle_); adc_task_handle_ = nullptr; } } void AdcManager::AdcTask(void *pvParameters) { AdcManager *manager = static_cast(pvParameters); ESP_LOGI(TAG, "ADC task started"); while (true) { if (manager->initialized_) { manager->ReadPressureSensorData(); } vTaskDelay(pdMS_TO_TICKS(100)); // 100ms间隔 } } int AdcManager::GetCurrentPressureValue() const { return current_pressure_value_; } const int *AdcManager::GetPressureAdcValues() const { return pressure_adc_values_; } size_t AdcManager::GetPressureSampleCount() const { return (pressure_data_index_ == 0) ? kPressureAdcDataCount : pressure_data_index_; } bool AdcManager::IsPressureDetected() const { if (!initialized_) { return false; } return current_pressure_value_ > 1000; // 压力阈值:100 } bool AdcManager::IsLightPressure() const { if (!initialized_) { return false; } return current_pressure_value_ > 500; // 轻压阈值:500 } void AdcManager::CheckLongTimeNoMovement(int adc_value) { uint32_t current_time = esp_timer_get_time() / 1000000; // 转换为秒 // 计算ADC值变化 int adc_change = abs(adc_value - last_stable_value_); if (adc_change > kMovementThreshold) { // 有显著变化,重置不动检测 last_stable_value_ = adc_value; no_movement_start_time_ = current_time; is_no_movement_detected_ = false; } else { // 变化很小,检查是否长时间不动 if (no_movement_start_time_ == 0) { no_movement_start_time_ = current_time; } uint32_t no_movement_duration = current_time - no_movement_start_time_; if (no_movement_duration >= kLongTimeThreshold && !is_no_movement_detected_) { is_no_movement_detected_ = true; ESP_LOGW(TAG, "Long time no movement detected! Duration: %lu seconds, ADC: %d", no_movement_duration, adc_value); // 停止音乐播放和语音交互 TriggerMusicPauseback(); } } } bool AdcManager::IsLongTimeNoMovement() const { if (!initialized_) { return false; } return is_no_movement_detected_; } uint32_t AdcManager::GetNoMovementDuration() const { if (!initialized_ || no_movement_start_time_ == 0) { return 0; } uint32_t current_time = esp_timer_get_time() / 1000000; return current_time - no_movement_start_time_; } void AdcManager::TriggerMusicPauseback() { ESP_LOGI(TAG, "Triggering music pauseback"); auto music = Board::GetInstance().GetMusic(); if (!music) { ESP_LOGI(TAG, "No music player found"); return; } // 检查音乐状态,避免重复操作 if (!music->IsPlaying() && !music->IsPaused()) { ESP_LOGI(TAG, "Music is not playing or paused, skipping pause operation"); return; } music->PauseSong(); // 停止语音交互 auto &app = Application::GetInstance(); app.GetAudioService().EnableWakeWordDetection(false); ESP_LOGI(TAG, "Stopped wake word detection due to long time no movement"); } void AdcManager::TriggerMusicPlayback() { ESP_LOGI(TAG, "Triggering music playback"); // 确保音频输出已启用 auto& board = Board::GetInstance(); auto codec = board.GetAudioCodec(); if (!codec) { ESP_LOGE(TAG, "Audio codec not available"); return; } codec->EnableOutput(true); ESP_LOGI(TAG, "Audio output enabled"); // 通过Board接口获取音乐播放器并触发播放 auto music = board.GetMusic(); if (!music) { ESP_LOGI(TAG, "No music player found"); return; } if (music->IsPlaying()) { ESP_LOGI(TAG, "Music is already playing"); return; } if (music->IsDownloading()) { ESP_LOGI(TAG, "Music is already downloading"); return; } if (music->IsPaused()) { ESP_LOGI(TAG, "Music is already paused"); music->ResumeSong(); return; } auto song_name = "稻香"; auto artist_name = ""; if (!music->Download(song_name, artist_name)) { ESP_LOGI(TAG, "获取音乐资源失败"); return; } auto download_result = music->GetDownloadResult(); ESP_LOGI(TAG, "Music details result: %s", download_result.c_str()); }