ESP32 数据闭环实操:现成练习数据怎么用,命令怎么敲,代码写了啥

承接上篇。上篇讲原理和坑;这篇默认你已经知道「板子手脚、电脑大脑」。
重点:仓库里已经有一套操作好的练习数据——先用它把流程跑顺,再插板子采真数。
创作不易,点个关注不迷路,博主会持续更新


0. 先说明:你手里「已经有的」是什么

很多人一上来就接硬件,卡在驱动上,心态炸。
所以我在 python/data/ 里先放好了合成但结构真实的数据:

0.1 练习集 Fixtures(不插板也能用)

python/data/fixtures/
├── ep_good/            # 正常一集:约 200 个点,能量有起伏
├── ep_drop_frames/     # 坏集:中间故意挖空,模拟丢包
├── ep_clock_skew/      # 坏集:时间间隔乱跳
└── ep_silence/         # 坏集:几乎静音

每一集里面大致有:

文件 人话含义
ts_ms.npy 每个点的时间(毫秒)
mic_rms.npy 每个点有多响
mic_peak.npy 峰值
led.npy 灯状态(练习用)
frames/*.png 用能量画的小色块图(假装视觉帧)
meta.json 这集从哪来、多少点

真机引导采集时,还会多一个很重要的:

文件 含义
label.npy 0=安静段,1=出声段(人定的标签)

0.2 已经画好的波形图

python/data/viz/
├── ep_good_wave.png           # 正常起伏 ← 发博客首选
├── ep_silence_wave.png        # 几乎没声,和 good 对比很明显
├── ep_drop_frames_wave.png
└── *_frame.png                # 中间某一帧小图预览

怎么结合理解:

  • ep_good_wave:横轴时间,纵轴响度 → 这就是模型要「看」的时间序列
  • ep_silence_wave:纵轴只有一点点 → 质检应判「太安静,别拿去当好样本」
  • ep_drop_frames 跑质检 → 应报丢包 / 不合格

也就是说:一半内容,不插电也能在电脑上完成。


1. 下篇总流程(操作视角)

A. 用现成 fixtures 跑通:质检 → 画图 → 训练 → (可选)单测
                │
                ▼
B. 硬件就绪后:烧固件 → 引导采集 → 同一套质检/训练 → 实时回控

A 解决「我懂不懂这条链路」;
B 解决「我的板子能不能接入这条链路」。


2. 事前准备清单(操作版)

2.1 只跑 A(现成数据)需要

准备 说明
本仓库 esp32-data-pipeline-lab/python 含 fixtures
Python 3.10+
pip 依赖 见下一节
(可选)看一眼 viz 里的 PNG 建立直觉

2.2 要跑 B(真机)额外需要

准备 说明
ESP32 + 数据线 COM 口能出现
INMP441 按上篇接线表接好 3.3V / 21·22·25
Arduino CLI + 乐鑫核心 能 compile/upload
无人打扰的 20 秒 前安静后出声

3. 需要什么包

文件:python/requirements.txt

pyserial>=3.5          # 真机串口才强依赖;只跑 fixtures 也可装上
numpy>=1.24
opencv-python-headless>=4.8
matplotlib>=3.7
torch>=2.0             # 无独显用 CPU 版即可
pytest>=7.0
cd C:\Users\ts\Desktop\zcy\esp32-data-pipeline-lab\python
pip install -r requirements.txt

CPU 版 PyTorch 示例:

pip install torch --index-url https://download.pytorch.org/whl/cpu

板端不靠 pip,靠乐鑫核心里的:

#include <Arduino.h>
#include <driver/i2s.h>

4. 操作 A:现成数据跑通(建议你先做)

python 目录下:

4.1 如需重新生成 fixtures(一般不用)

python 02_make_fixture.py --out data/fixtures

会覆盖生成 good / drop / skew / silence 四集。

4.2 质检:看好的过、坏的拦

python 03_qc_pipeline.py --episode data/fixtures/ep_good
python 03_qc_pipeline.py --episode data/fixtures/ep_drop_frames
python 03_qc_pipeline.py --episode data/fixtures/ep_silence

结合理解:

你期望看到
ep_good ok: true
ep_drop_frames ok: false,原因含丢包类
ep_silence ok: false,太安静
ep_clock_skew ok: false,时钟不稳

4.3 单测(把质检逻辑钉死)

python -m pytest tests -q

全绿说明:不是「我感觉质检对了」,而是 脚本保证坏样本会被抓住

4.4 再画一波波形(或直接用现成 png)

python 05_visualize.py --episode data/fixtures/ep_good --out data/viz

输出:data/viz/ep_good_wave.png
发 CSDN 时把 good 和 silence 两张对比着贴,读者秒懂。

4.5 用 ep_good 试训练

python 06_train_toy.py --episode data/fixtures/ep_good --epochs 30

你会看到 loss 下降、准确率上升(玩具任务很容易)。
权重写到:

data/models/tiny_mic_net.pt

人话解释:
电脑已经用「现成的一盘好带子」练过一次了。
真机采回来的带子,只要格式一样(同样那些 npy),训练命令不用改,只改 --episode 路径。

4.6 看 Dataset 长什么样(可选)

python 04_dataset.py --episode data/fixtures/ep_good

打印 batch 形状,帮助理解:模型一次吃多少 mic、图是什么尺寸。


5. 操作 B:真机接入(板子就绪后)

5.1 查端口

C:\Users\ts\Desktop\zcy\tools\arduino-cli.exe board list

记下 COMx(我常用过 COM4)。

5.2 烧采集固件

cd C:\Users\ts\Desktop\zcy\esp32-data-pipeline-lab\firmware
build-upload.bat COM4

监视(另开窗口;推理时请先关掉监视,避免占口):

arduino-cli monitor -p COM4 -c baudrate=115200

应出现 # i2s_ok 和不断刷的 JSON。说话时 mic_rms 变大。

5.3 一键:采集→质检→训练→回控

cd ..\python
python run_esp_project.py --port COM4

按提示:

  1. 前约 8 秒 安静
  2. 后约 8 秒 说话/拍手
  3. 自动后面全套;最后约 20 秒实时推理亮灯

真机数据默认落在类似:

data/raw/esp_ep001/

5.4 手动拆开跑(好排查)

python 08_collect_guided.py --port COM4 --quiet 8 --sound 8 --out data/raw/esp_ep001
python 03_qc_pipeline.py --episode data/raw/esp_ep001
python 05_visualize.py --episode data/raw/esp_ep001 --out data/viz
python 06_train_toy.py --episode data/raw/esp_ep001
python 09_infer_live.py --port COM4 --seconds 20 --ckpt data/models/tiny_mic_net.pt

和 fixtures 的关系:
质检/可视化/训练脚本完全同一套
差别只是数据从 fixtures/ep_good 换成 raw/esp_ep001


6. 要写什么代码(按文件说人话)

不必背源码,知道「改需求时进哪个文件」即可。

文件 写它干什么
firmware/stream_sensor/stream_sensor.ino 板子:读 I2S、算 RMS、打 JSON、听 LED 命令
02_make_fixture.py 生成 good/坏样本,供练习和 pytest
08_collect_guided.py 真机两段标注采集
03_qc_pipeline.py 质检规则(丢包/静音/时钟)
04_dataset.py 切 16 点窗口,优先读 label.npy
05_visualize.py 出波形 PNG
06_train_toy.py 小 MLP + 保存 .pt
09_infer_live.py 实时预测并 LED:0/1
run_esp_project.py 把上面串成一键
tests/test_qc.py 保证坏 fixtures 一定被抓到
build-upload.bat 编译烧录两条命令

固件侧你真正要「写对」的点

// 灯
GPIO 2

// 麦(I2S)
BCK=21  WS=22  SD=25  16kHz

串口一行:

{"ts_ms":...,"mic_rms":...,"mic_peak":...,"led":0,"n":256}

回控:

LED:1 / LED:0 / LED:AUTO

训练侧最小网络(概念)

16 个 mic 点 → Linear → ReLU → Linear → 2 类(安静/有声)

CPU 就能跑。训完是权重文件,不是「一条公式曲线」。


7. 下篇相关的坑(操作时最容易撞)

坑 A:一边开着串口监视器,一边跑采集/推理

现象: Python 报串口占用、读不到数据。
避法: 采数和 09_infer_live 时,先关掉 arduino-cli monitor/其它串口工具。


坑 B:fixtures 训通了,以为真机不用标注

fixtures 的标签是脚本造的;真机若只用 rms>阈值 当标签,又变回「背阈值」。
避法: 真机走 08_collect_guided.py,让 label.npy 来自「安静/出声」行为。


坑 C:反复 make_fixture 却不删旧 frames

旧版曾出现:点数变少了,PNG 还留着旧的,质检报「帧数对不上」。
现在脚本会清 frames;若你手改数据,记得帧和 npy 条数一致


坑 D:推理灯不跟手

排查顺序:

  1. 固件是不是带 LED:1 解析的 stream_sensor
  2. COM 是否被占
  3. 窗口是否凑满 16 个点(刚开始几秒可能还不亮)
  4. 模型是不是刚训完的那个 tiny_mic_net.pt

坑 E:把「玩具准确率 100%」写进简历过度吹嘘

ep_good 任务很简单,高准确率正常。
简历应强调:闭环与质检能力,而不是刷分。


坑 F:上篇那些硬件坑,操作时仍有效

灯脚、COM、I2S ≠ I2C、21/22 别再给 I2C——真机阶段随时会再犯。
串口 RMS 突然归零,优先回想软件占脚,别先砸模块。


8. 验收清单(打勾用)

只跑现成数据

  • ep_good 质检 OK
  • ep_silence / ep_drop_frames 质检 FAIL(符合预期)
  • pytest 通过
  • 看过 / 生成了 ep_good_wave.png
  • 训练产出 data/models/tiny_mic_net.pt

加上真机

  • 串口 JSON 连续,i2s_ok
  • 引导采集后 label.npy 两段都有
  • 真机 episode 质检可解释
  • 说话灯亮、安静灯灭

9. 总结

上篇 下篇(本文)
问题 这是什么?为什么?坑在哪? 怎么做?现成数据怎么用?
输出 概念 + 清单 + 坑点故事 命令 + 文件职责 + 验收
数据 知道 fixtures / viz 存在 动手跑 fixtures → 再上真机
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐