跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
RustAI算法

基于 ESP32 和 Rust 的简易语音助手开发

基于 ESP32-S3 和 Rust 语言开发简易语音助手的全过程。内容涵盖硬件选型(麦克风、喇叭)、开发环境搭建(WSL、esp-idf-svc)、I2S 音频接口连接、WiFi 配置及 HTTP 服务实现。重点讲解了模型调用流程(STT、LLM、TTS),并解决了 TLS 证书配置、线程阻塞及片外 RAM 扩展等常见问题。适合希望从软件转向嵌入式开发的开发者参考。

DevStack发布于 2026/3/26更新于 2026/9/1076 浏览
基于 ESP32 和 Rust 的简易语音助手开发

ESP32 + Rust 开发的简易语音助手

本文分享使用 ESP32 和 Rust 开发简易语音助手的经验与踩坑记录。虽然涉及嵌入式开发,但主要聚焦于应用层逻辑,适合从纯软件开发转向嵌入式的开发者参考。

项目地址:https://github.com/xgpxg/esp32-voice-assistant-demo

硬件准备

由于需要在几十块的板子上运行语音功能,ESP32 自带 WiFi、蓝牙并支持 I2S,是合适的选择。本次选择 ESP32-S3。

语音输入需要麦克风和喇叭,常用型号为 INM441 和 MAX98357A。

硬件连接示意图

开发环境准备

ESP32 官方提供了 Rust SDK esp-idf-svc,环境配置可参考:https://github.com/esp-rs/esp-idf-template。

环境示例:Windows + WSL2。

安装依赖

# 依赖包
sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0

# 工具包
cargo install cargo-generate
cargo install ldproxy
cargo install espup
cargo install espflash

# 安装 esp
espup install

# 安装 usbipd(用于将 Windows 的 USB 设备提供给 WSL)
winget install usbipd

烧录程序直接执行 cargo run -r 即可,无需 debug 模式以减小体积。

连接麦克风

麦克风使用 INM441,引脚功能如下:

  • VDD:电源输入,3.3V。
  • GND:接地。
  • SD:数据输入。
  • L/R:左声道/右声道,默认接地为左声道。
  • WS:字选择时钟。
  • SCK:BCLK,数据位同步。

麦克风实物图

连接到 ESP32-S3 时,SD、WS 和 SCK 需与代码中分配的 IO 口保持一致。

连接喇叭

喇叭包含解码器 MAX98357A 和小喇叭。

  • LRC:左声道/右声道时钟。
  • BCLK:数据位同步。
  • DIN:数据输入。
  • VDD:电源输入,2.5V - 5.5V。

喇叭模块图

编写代码

创建项目

使用 cargo generate 快速生成模板:

cargo generate esp-rs/esp-idf-template

在 WSL 下烧录前,需在 Windows 上绑定 USB 设备:

# 查看设备
usbipd list

# 绑定并转移到 WSL
usbipd bind --busid=1-4
usbipd attach --wsl --busid=1-4

# 在 WSL 查看连接的设备
ls /dev/ttyACM*

连接 WiFi

ESP32 支持 STA 和 AP 模式。整体思路为启动 HTTP 服务提供配置页面,WiFi 同时启用 STA 和 AP,配置信息写入 NVS 以便下次自动连接。

// 创建 HTTP 服务
let mut server = EspHttpServer::new(&Configuration::default()).unwrap();
// 注册静态文件
server::register_static_files(&mut server).unwrap();
// 网络相关接口
server::network::register(&mut server, wifi.clone(), nvs.clone()).unwrap();

前端建议使用轻量版框架如 Petite-Vue 以减少体积。

WiFi 初始化代码示例:

fn init_wifi(wifi: &mut EspWifi<'static>, nvs: &EspDefaultNvs) -> anyhow::Result<()> {
    let ssid = Config::get_wifi_ssid(nvs);
    let password = Config::get_wifi_password(nvs);
    // 混合模式,同时支持 AP 和 STA
    let cfg = wifi::Configuration::Mixed(
        ClientConfiguration {
            ssid: ssid.as_str().try_into().unwrap(),
            password: password.as_str().try_into().unwrap(),
            ..Default::default()
        },
        AccessPointConfiguration {
            ssid: SSID.try_into().unwrap(),
            ssid_hidden: false,
            auth_method: AuthMethod::WPA2Personal,
            password: PASSWORD.try_into().unwrap(),
            channel: CHANNEL,
            ..Default::default()
        },
    );
    wifi.set_configuration(&cfg)?;
    wifi.start()?;
    if !ssid.is_empty() {
        log::info!("Wifi 连接中:{}", ssid);
        wifi.connect()?;
    }
    Ok(())
}

麦克风输入以及扬声器输出

使用标准 I2S 协议,芯片已封装好,调用 read 和 write 即可。

let std_config = StdConfig::new(Config::default(), StdClkConfig::from_sample_rate_hz(Self::SAMPLE_RATE), StdSlotConfig::philips_slot_default(DataBitWidth::Bits16, SlotMode::Mono), StdGpioConfig::new(false, false, false));
let mclk = AnyIOPin::none();
let mut i2s = I2sDriver::<I2sRx>::new_std_rx(i2s1, &std_config, bclk, sd, mclk, ws)?;

注意 SlotMode 应为 Mono,且采样率需与模型匹配。

调用模型

语音对话流程:STT(语音识别)-> LLM(语言模型)-> TTS(文本转语音)。STT 和 TTS 使用 Websocket,LLM 使用 HTTP。

SDK 默认未启用 Websocket,需在 sdkconfig.defaults 中开启:

CONFIG_HTTPD_WS_SUPPORT=y
HTTPS 和 WSS 的 TLS 配置

需启用 TLS,否则可能报错。建议配置全局 CA 存储:

let mut config = EspWebSocketClientConfig::default();
config.crt_bundle_attach = Some(esp_idf_svc::sys::esp_crt_bundle_attach);
config.use_global_ca_store = true;

需增加依赖:

[critical-section]
version = "1.1"
features = ["std"]
default-features = false
线程阻塞问题

处理 WebSocket 事件时,避免多个地方调用 rx.recv() 导致阻塞,可使用 embassy-sync 或循环加 try_recv。

loop {
    if let Ok(event) = rx.try_recv() {
        match event {
            WsEvent::ResultGenerated(text) => result.push_str(&text),
            _ => break,
        }
    }
    Timer::after_millis(100).await;
}

启用片外 RAM

ESP32-S3 内存较小,可通过启用 PSRAM 扩展。需在 sdkconfig.defaults 中启用:

CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y

注意启用 PSRAM 后 33-37 号 GPIO 不可用,否则可能导致重启。

目录

  1. ESP32 + Rust 开发的简易语音助手
  2. 硬件准备
  3. 开发环境准备
  4. 安装依赖
  5. 依赖包
  6. 工具包
  7. 安装 esp
  8. 安装 usbipd(用于将 Windows 的 USB 设备提供给 WSL)
  9. 连接麦克风
  10. 连接喇叭
  11. 编写代码
  12. 创建项目
  13. 查看设备
  14. 绑定并转移到 WSL
  15. 在 WSL 查看连接的设备
  16. 连接 WiFi
  17. 麦克风输入以及扬声器输出
  18. 调用模型
  19. HTTPS 和 WSS 的 TLS 配置
  20. 线程阻塞问题
  21. 启用片外 RAM

更多推荐文章

查看全部
  • Python 技能变现指南:合法合规的兼职方向与技术实践
  • 基于 Coze Skills 与 OpenClaw 的 AI 智能体自动化实战指南
  • Python 开发中应淘汰的旧模块与新替代方案指南
  • Whisper 语音识别库安装与配置指南
  • C++ STL 进阶:unordered_set 与 unordered_map 模拟实现
  • Query 处理流程与数据结构解析
  • Dify 简介:低代码 AI 应用开发平台解析
  • 大模型算法面试完全指南:从基础理论到实战应用
  • AI 大模型核心知识点梳理与原理分析
  • IntelliJ IDEA 接入 AI 编程助手:Copilot、DeepSeek 与 GPT-4o Mini
  • Llama-Factory 文本纠错任务实测:拼音错别字纠正
  • 初学者如何入门大语言模型开发
  • 基于 Python 的流处理与 RAG 驱动智能 ETL 框架设计
  • Vite 代理与 Nginx 代理:开发与生产环境的配置差异
  • PyTorch 时序预测 Dataloader 构建:GRU 与 Shuffle 机制解析
  • 前端 EME DRM 防录屏原理及实战代码
  • Windows 安装 OpenClaw 配置 Qwen 及 Ollama 本地模型并接入飞书机器人
  • 大模型人才年薪百万引关注,行业需求旺盛
  • Java 模拟算法实战:五道经典题解
  • Graylog 开源日志管理平台:从零部署到高级应用

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online