2026寒假练 -基于 Seeed XIAO ESP32S3 Sense实现——智能语音氛围灯带
本项目旨在设计并实现一款基于ESP32-S3开发板的语音控制氛围灯系统,通过语音指令实现对WS2812 RGB灯带的开关、亮度调节及灯光模式切换,同时搭配OLED显示屏实时显示系统状态,蜂鸣器提供指令响应反馈,整体实现便捷、直观的智能灯光控
标签
OLED显示
ESP32-S3
语音控制
氛围灯
Edge Impulse语音识别
萝卜兔
更新2026-03-24
19

语音控制氛围灯项目任务介绍


一、项目介绍

本项目旨在设计并实现一款基于ESP32-S3开发板的语音控制氛围灯系统,通过语音指令实现对WS2812 RGB灯带的开关、亮度调节及灯光模式切换,同时搭配OLED显示屏实时显示系统状态,蜂鸣器提供指令响应反馈,整体实现便捷、直观的智能灯光控制体验。项目核心依托Edge Impulse平台训练的语音识别模型,精准识别预设拼音指令,结合嵌入式编程实现硬件联动,可应用于家庭氛围营造、桌面装饰等场景,兼具实用性与趣味性。


二、使用到的硬件介绍

本项目所用硬件均为嵌入式开发常用器件,选型兼顾性价比与易用性,具体介绍如下:

1. ESP32-S3开发板:核心控制单元,选用XIAO_ESP32S3或ESP32-S3 Dev Module,集成WiFi/蓝牙功能,支持FreeRTOS实时操作系统,具备丰富的GPIO引脚和I2S接口,用于运行语音识别算法、接收处理语音指令及控制各外设。

2. WS2812 RGB灯带:发光执行单元,选用10颗灯珠版本,控制引脚为GPIO8,采用NEO_GRB色彩编码和800KHz通信频率,支持单个灯珠独立控色,可实现跑马灯、彩虹灯、呼吸灯等多种氛围模式,通过Adafruit_NeoPixel库驱动。

3. OLED显示屏(128*64):状态显示单元,采用I2C通信方式,地址0x3C,SDA引脚接D4(GPIO4)、SCL引脚接D5(GPIO5),无复位引脚(OLED_RESET=-1),用于实时显示当前灯光模式、亮度、速度等系统状态。

4. 蜂鸣器:反馈单元,控制引脚为GPIO9,采用有源蜂鸣器设计,指令识别并执行后,短鸣100ms作为响应提示,告知用户指令已生效。

5. 板载麦克风:语音采集单元,集成于ESP32-S3开发板,采用I2C接口(BCK=GPIO42、DATA_IN=GPIO41),用于采集环境中的语音指令,通过I2S驱动,将模拟语音信号转换为数字信号,供语音识别模型处理。

6. 杜邦线、电源适配器:辅助配件,杜邦线用于各模块之间的引脚连接,电源适配器为整个系统提供稳定供电(5V/1A),确保设备正常运行。


三、方案框图和项目设计思路介绍

(一)方案框图

本项目采用“采集-处理-控制-反馈”的闭环设计,整体方案图如下:1.jpg

具体模块连接:

 ESP32-S3主控:连接所有外设,作为系统核心,运行语音识别算法和控制逻辑。

 麦克风→ ESP32-S3:通过I2C接口(BCK、DATA_IN)传输语音采集数据。

 ESP32-S3 → WS2812灯带:通过GPIO8传输控制信号,驱动灯带发光。

 ESP32-S3 → OLED显示屏:通过I2C接口(SDA、SCL)传输显示数据。

 ESP32-S3 → 蜂鸣器:通过GPIO9输出高低电平,控制蜂鸣器发声。


(二)项目设计思路

本项目核心思路是“以语音识别为入口,以嵌入式控制为核心,以外设联动为目标”,分5个阶段完成设计与实现,具体思路如下:

1. 需求分析与方案选型:明确项目核心功能(语音控制开关、亮度调节、模式切换),选型适配的硬件和软件,确定采用ESP32-S3作为主控,Edge Impulse训练语音模型,Adafruit系列库驱动外设。

2. 硬件连接与初始化:按方案框图连接各模块,确定引脚定义,完成ESP32-S3、OLED、WS2812灯带、蜂鸣器、麦克风的硬件接线,确保各外设供电稳定、通信正常。

3. 语音模型训练与移植:在Edge Impulse平台采集预设语音指令(kaideng、guandeng、liangyidian、qiehuan)的样本,训练语音识别模型,生成a111_inferencing.h头文件,移植到Arduino项目中,实现语音指令的采集与识别。

4. 软件逻辑开发:基于Arduino框架,编写主控程序,包括外设驱动(OLED、WS2812、蜂鸣器、麦克风)、语音指令处理、灯光模式实现、系统状态显示等模块,确保指令识别准确、外设响应及时。

5. 调试与优化:对系统进行整体调试,解决硬件接线错误、软件逻辑漏洞、语音识别准确率低等问题,优化灯光渐变效果和指令响应速度,确保系统稳定运行,满足设计需求。


四、调试软件及使用的编程语言说明、软件流程图及关键代码介绍


(一)调试软件及编程语言

1. 调试软件

 Arduino IDE 1.8.19:核心开发与调试软件,用于编写、编译、上传程序,支持ESP32-S3开发板,可通过串口监视器查看系统运行日志(如指令识别结果、错误信息),便于调试软件逻辑。

 Edge Impulse Studio:语音模型训练平台,用于采集语音样本、训练识别模型、生成适配ESP32-S3的模型头文件,调试语音识别准确率。

 串口监视器:集成于Arduino IDE,波特率设置为115200,用于查看系统初始化信息、指令执行日志,辅助定位软件逻辑错误(如外设初始化失败、指令识别异常)。


2. 编程语言:主要采用C/C++语言,基于Arduino框架开发,结合ESP32-S3的FreeRTOS实时操作系统,实现多任务协同(如语音采集、指令处理、灯光控制),兼顾代码的可读性和执行效率。同时,在Edge Impulse平台训练模型时,采用图形化操作+少量Python脚本,完成语音样本的预处理和模型训练。


3. 依赖库

 Adafruit_SSD1306.h、Adafruit_GFX.h:驱动OLED显示屏,实现状态显示功能。

 Adafruit_NeoPixel.h:驱动WS2812 RGB灯带,实现多种灯光模式。

 a111_inferencing.h:Edge Impulse平台生成的语音识别模型头文件,用于语音指令的识别与解析。

 freertos/FreeRTOS.h、freertos/task.h:ESP32-S3的实时操作系统库,用于实现多任务管理。

 driver/i2s.h:I2C接口驱动库,用于驱动麦克风采集语音数据。


(二)软件流程图

系统软件采用模块化设计,核心流程如下:

2.jpg


        

 kaideng:灯带从关闭状态切换为跑马灯模式,蜂鸣器短鸣,OLED更新模式显示。

 guandeng:灯带关闭,蜂鸣器短鸣,OLED更新模式显示为“Off”。

 liangyidian:灯带亮度增加30(上限255),蜂鸣器短鸣,OLED更新亮度显示。

 qiehuan:循环切换跑马灯→彩虹灯→呼吸灯模式,蜂鸣器短鸣,OLED更新模式显示。

5. 状态更新与循环:实时更新WS2812灯带的发光状态和OLED的显示内容,返回语音采集步骤,持续等待下一条语音指令,形成闭环运行。


(三)关键代码介绍

本项目关键代码主要集中在语音指令处理、WS2812灯光模式实现、OLED显示更新三个模块,以下为核心代码片段及说明:

1. 语音指令处理代码:负责识别语音指令并执行对应操作,核心是getHighestPrediction函数(提取识别结果)和processVoiceCommand函数(解析并执行指令)。


        // 提取语音识别结果(获取置信度最高的指令)
String getHighestPrediction(const ei_impulse_result_t& result) {
  float max_value = 0;
  int max_index = 0;
  for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
    if (result.classification[ix].value > max_value) {
      max_value = result.classification[ix].value;
      max_index = ix;
    }
  }
  return String(result.classification[max_index].label);
}

// 解析并执行语音指令
void processVoiceCommand(String command) {
  if (command == "kaideng") {
    if (currentMode == MODE_OFF) {
      currentMode = MODE_RUNNING;
      beep();
      Serial.println("执行指令:开灯");
    }
  }
  else if (command == "guandeng") {
    if (currentMode != MODE_OFF) {
      currentMode = MODE_OFF;
      beep();
      Serial.println("执行指令:关灯");
    }
  }
  else if (command == "liangyidian") {
    brightness = min(255, brightness + 30);
    beep();
    Serial.println("执行指令:亮一点,当前亮度:" + String(brightness));
  }
  else if (command == "qiehuan") {
    currentMode = (LightMode)((int)currentMode + 1);
    if (currentMode >= MODE_OFF) {
      currentMode = MODE_RUNNING;
    }
    beep();
    String modeName = (currentMode == MODE_RUNNING) ? "跑马灯" : (currentMode == MODE_RAINBOW) ? "彩虹灯" : "呼吸灯";
    Serial.println("执行指令:切换模式,当前模式:" + modeName);
  }
}

2. WS2812灯光模式代码:基于Adafruit_NeoPixel库,实现跑马灯、呼吸灯两种核心模式,复用项目预设的RED、YELLOW、OFF颜色定义。
       

 // 跑马灯模式(使用预设RED颜色)
void runningLight() {
  static int pixelIndex = 0;
  pixels.fill(OFF); // 清空灯珠(使用预设OFF)
  pixels.setPixelColor(pixelIndex, RED); // 设置当前灯珠为红色
  pixels.show();
  delay(200 / speed);
  pixelIndex = (pixelIndex + 1) % NUMPIXELS; // 循环切换灯珠
}

// 呼吸灯模式(使用预设YELLOW颜色,基于cos函数实现平滑渐变)
void breathingLight() {
  static unsigned long lastUpdate = 0;
  static float phase = 0;
  if(millis() - lastUpdate > (20 / speed)) {
    float breath = (cosf(phase) + 1) / 2; // 0~1平滑渐变值
    int currentBreathBright = breath * brightness;
    uint32_t breathColor = pixels.Color(255 * breath, 255 * breath, 0); // 黄色渐变
    pixels.fill(breathColor);
    pixels.show();
    phase += 0.1;
    if(phase > 2 * PI) phase = 0;
    lastUpdate = millis();
  }
}
3. OLED显示更新代码:基于Adafruit_SSD1306库,实时显示系统状态,包括灯光模式、亮度、速度。
        void updateOLED() {
  display.clearDisplay(); // 清空屏幕
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Ambient Light"); // 标题
  display.setCursor(0, 16);
  // 显示当前模式
  String modeStr;
  switch(currentMode) {
    case MODE_RUNNING: modeStr = "Mode: Running"; break;
    case MODE_RAINBOW: modeStr = "Mode: Rainbow"; break;
    case MODE_BREATHING: modeStr = "Mode: Breathing"; break;
    case MODE_OFF: modeStr = "Mode: Off"; break;
  }
  display.println(modeStr);
  display.setCursor(0, 32);
  display.print("Brightness: ");
  display.println(brightness); // 显示亮度
  display.setCursor(0, 48);
  display.print("Speed: ");
  display.println(speed); // 显示速度
  display.display(); // 刷新显示
}


五、功能展示图及说明


本项目功能展示分为实物展示和软件调试展示两部分,清晰呈现系统的运行效果和调试过程:

(一)实物展示及说明

1. 系统整体实物ESP32-S3开发板固定在面包板上,通过杜邦线连接OLED显示屏、WS2812灯带、蜂鸣器,板载麦克风裸露在外,便于采集语音指令;电源适配器连接开发板,为整个系统供电,整体布局简洁、接线规范,无松动现象。

2dd621c5ef5b85eaabaf94d19a002854.png

2. 灯光模式展示 

 跑马灯模式:收到“kaideng”指令后,WS2812灯带的10颗灯珠以红色(RED)依次点亮、熄灭,循环移动,速度可通过系统默认参数调节,灯光切换流畅。

 彩虹灯模式:收到“qiehuan”指令切换至该模式后,灯带呈现彩虹渐变效果,每颗灯珠颜色不同,且整体色相缓慢变化,色彩鲜艳、过渡自然。

 呼吸灯模式:切换至该模式后,灯带以黄色(YELLOW)实现平滑呼吸效果,亮度从0逐渐增加至当前设定亮度,再逐渐降低至0,循环往复,渐变效果柔和。

 关灯状态:收到“guandeng”指令后,灯带所有灯珠熄灭(OFF),OLED显示模式为“Mode: Off”,系统进入低功耗状态。

3. OLED显示展示OLED显示屏实时显示系统状态,顶部为标题“Ambient Light”,中间显示当前灯光模式,底部两行分别显示亮度和速度数值,指令执行后,显示内容实时更新,清晰直观。

60ca1666d1f7454756dec5ed5ae6a4e7_FjhX-M2jZs111A_E6z6pZRmSUOZG_attname=2e36bb99ede300f1015417692e8a6d1c.jpg.jpg

4. 指令响应展示:每执行一条语音指令,蜂鸣器短鸣100ms,同时串口监视器输出指令执行日志,如“执行指令:开灯”“执行指令:亮一点,当前亮度:130”,用户可通过听觉和串口信息确认指令已生效。


(二)软件/工具调试展示及说明

1. Arduino IDE调试:打开Arduino IDE,加载项目代码,选择对应开发板(XIAO_ESP32S3)和端口,点击“上传”按钮,代码编译通过后上传至开发板,上传成功后,串口监视器显示“系统初始化完成,等待语音指令...”,表明系统正常启动。

#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoPixel.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"

// ====== I2C & OLED 配置 ======
#define I2C_SDA_PIN D4
#define I2C_SCL_PIN D5
#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ====== WS2812 配置 ======
#define PIN_NEOPIXEL 8 // 控制引脚
#define NUMPIXELS 10 // 灯珠数量
Adafruit_NeoPixel pixels(NUMPIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
// 灯光颜色定义
#define YELLOW pixels.Color(255, 255, 0) // 黄色
#define RED pixels.Color(255, 0, 0) // 红色
#define OFF pixels.Color(0, 0, 0) // 关闭

2. 串口日志展示:串口监视器设置波特率115200,可实时查看语音识别结果和指令执行情况,例如:当说出“kaideng”时,串口输出“识别指令:kaideng”“执行指令:开灯”;说出“liangyidian”时,输出“识别指令:liangyidian”“执行指令:亮一点,当前亮度:130”,便于调试语音识别准确率和指令执行逻辑。

bed25feeecba30e2dd069ed80b055dcd.png

3. Edge Impulse模型调试:在Edge Impulse Studio中,可查看语音样本采集情况、模型训练准确率,通过“Live Classification”功能实时测试语音识别效果,调整模型参数(如样本数量、训练迭代次数),确保模型在ESP32-S3上的识别准确率达到90%以上,避免指令识别错误。

a4ac97bac45f8dfec389ba1ee4dc9f97.png


六、项目中遇到的难题及解决方法


本项目在开发和调试过程中,遇到了硬件接线、软件逻辑、语音识别等方面的多个难题,通过查阅资料、反复调试,均得到有效解决,具体如下:


难题1:语音指令识别准确率低,经常误识别或无法识别

 原因:一是Edge Impulse模型训练样本不足,仅采集了少量语音样本,且未涵盖不同语速、不同环境噪音的情况;二是麦克风采集的语音信号音量过小,未进行放大处理;三是语音识别的置信度阈值未设置,导致误识别。

 解决方法:在Edge Impulse平台补充语音样本,每种指令采集4~5个样本,涵盖不同语速、不同距离的情况,添加少量环境噪音样本,重新训练模型;在代码中添加语音信号放大逻辑(sampleBuffer[x] = (int16_t)(sampleBuffer[x]) * 8),增强信号强度;在getHighestPrediction函数中添加置信度判断(仅当max_value > 0.8时,才确认识别结果),降低误识别率,优化后识别准确率达到90%以上。


难题2:呼吸灯模式渐变不流畅,出现卡顿现象

 原因:最初采用简单的亮度递增/递减逻辑,步长固定,导致渐变不连贯;同时,主循环中延时时间过长,影响呼吸灯的更新频率。

 解决方法:改用cos函数实现平滑渐变,通过相位控制亮度变化,使亮度从0到最大值再到0的过渡更自然;优化主循环逻辑,减少不必要的延时,将呼吸灯的更新频率与速度参数关联(speed越大,更新越频繁),解决卡顿问题,渐变效果更加流畅。


七、心得体会

通过本次语音控制氛围灯项目的设计、开发与调试,我不仅提升了嵌入式开发的实践能力,更深刻体会到了“理论结合实践”的重要性,同时也收获了许多宝贵的经验和感悟

最后,我不仅掌握了ESP32-S3开发板的使用、Adafruit系列库的应用、Edge Impulse语音模型的训练与移植,还提升了编程能力和嵌入式系统的综合设计能力。同时,我也认识到了自己的不足,例如对硬件底层原理的理解还不够深入,对复杂算法的优化能力还有待提升。在今后的学习和实践中,我将继续加强学习,不断积累经验,提升自己的专业能力,努力打造出更多实用、有趣的嵌入式项目。

附件下载
sketch_feb22a.ino
主程序
ei-111-arduino-1.0.3.zip
训练模型压缩包
Adafruit_GFX.h
Adafruit_NeoPixel.h
Adafruit_SSD1306.h
团队介绍
萝卜兔----电子爱好者
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号