Update to 2.0.1

This commit is contained in:
2025-09-15 22:04:01 +08:00
parent 5c43129024
commit 7d7f5eae3d
74 changed files with 5253 additions and 439 deletions

View File

@@ -0,0 +1,376 @@
#include "adc_manager.h"
#include "application.h"
#include <board.h>
#include <cmath>
#include <cstring>
#include <esp_adc/adc_cali.h>
#include <esp_adc/adc_oneshot.h>
#include <esp_log.h>
#include <esp_timer.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#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<AdcManager *>(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());
}