1. 基于ESP32的唤醒词检测入门
任务目标
在ESP32上实现一个基于唤醒词检测的LED控制原型:当麦克风捕捉到预设唤醒词“Hi, 乐鑫”时,开发板上的LED点亮;未检测到唤醒词时LED保持熄灭。本案例聚焦于唤醒词检测的完整最小链路,不涉及命令词识别或多轮对话。
环境与依赖
- 硬件:ESP32-S3-Korvo-2开发板(板载ES7210双麦克风阵列与ES8311音频编解码器)
- 软件框架:ESP-SR(乐鑫语音识别库)v1.2及以上,ESP-IDF v5.2及以上
- 唤醒词模型:使用ESP-SR预置的“Hi, 乐鑫”中文唤醒词模型(
wakenet7) - LED连接:开发板GPIO 4(板载RGB LED的绿色通道,低电平点亮)
实现原理
ESP-SR的WakeNet模型持续从麦克风采集音频流并执行本地唤醒词检测。当模型置信度超过阈值时,回调函数被触发。本案例在回调中翻转LED状态,实现唤醒即点亮的直观反馈。音频采样率16kHz、单声道、16bit,由编解码器驱动自动完成。
关键完整代码
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_afe_sr_models.h"
#include "esp_wakenet.h"
#include "esp_audio_processing.h"
#include "board.h"
#define LED_GPIO 4
#define WAKE_WORD "Hi, 乐鑫"
static const char *TAG = "wake_demo";
static bool led_state = false;
// 唤醒回调:检测到唤醒词时翻转LED
static void wake_word_cb(void *arg)
{
led_state = !led_state;
gpio_set_level(LED_GPIO, led_state ? 0 : 1); // 低电平点亮
ESP_LOGI(TAG, "Wake word detected! LED %s", led_state ? "ON" : "OFF");
}
void app_main(void)
{
// 配置LED GPIO
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << LED_GPIO),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_conf);
gpio_set_level(LED_GPIO, 1); // 初始熄灭
// 初始化音频前端(AFE)
afe_config_t afe_config = {
.aec_init = true,
.aec_dereverb = false,
.se_init = true,
.vad_init = true,
.wakenet_init = true,
.voice_activation_init = false,
.vtsv_init = false,
.afe_mode = AFE_MODE_LOW_COST,
.afe_perferred_core = 0,
.afe_perferred_priority = 5,
.afe_ringbuf_size = 10,
.memory_alloc_mode = AFE_MEMORY_ALLOC_MODE_AGGRESSIVE,
.agc_init = true,
.agc_gain = 10,
.pcm_config = {
.total_ch_num = 2,
.mic_num = 2,
.ref_num = 0,
.sample_rate = 16000,
.bits = 16,
.channel = 2,
}
};
// 加载WakeNet7模型(支持"Hi, 乐鑫")
model_info_t *model_info = esp_wakenet_get_model_info(WAKE_WORD);
if (model_info == NULL) {
ESP_LOGE(TAG, "Wake word model not found");
return;
}
// 创建AFE句柄
afe_handle_t afe_handle = esp_afe_create(model_info, &afe_config);
if (afe_handle == NULL) {
ESP_LOGE(TAG, "Failed to create AFE");
return;
}
// 注册唤醒回调
esp_afe_register_wakenet_callback(afe_handle, wake_word_cb, NULL);
// 启动音频采集与处理
esp_afe_start(afe_handle);
ESP_LOGI(TAG, "Wake word detection started. Say \"%s\"", WAKE_WORD);
// 主循环保持运行
while (1) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
编译与烧录
# 在ESP-IDF环境中执行
idf.py set-target esp32s3
idf.py menuconfig # 在"ESP-SR"菜单中确认WakeNet7模型已启用
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
验证方法
- 烧录完成后,开发板串口输出日志显示
Wake word detection started。 - 在距开发板约0.5~1米处清晰说出“Hi,乐鑫”(注意与模型训练口音匹配)。
- 观察板载LED:检测成功时绿色LED点亮,同时串口打印
Wake word detected! LED ON。 - 再次说出唤醒词,LED熄灭,日志显示
LED OFF。 - 说其他词语(如“你好”)不应触发LED变化。
通过标准:连续测试10次唤醒词,至少8次成功触发LED翻转;非唤醒词不触发。若触发率偏低,可调整麦克风增益(agc_gain)或缩短说话距离。
常见问题
- 编译报错找不到模型:确认在menuconfig中启用了
CONFIG_ESP_SR_WAKENET7,且模型文件已通过idf.py flash烧录到spiffs分区。 - 唤醒无响应:检查串口日志是否有AFE初始化错误;确认开发板麦克风阵列未被遮挡,且音频编解码器驱动(
board_init())已在更早的初始化中调用。 - 误唤醒频繁:可尝试在AFE配置中启用
vad_init并调整VAD阈值,或更换为更严格的WakeNet8模型。