ESP32 数据闭环实操:现成练习数据怎么用,命令怎么敲,代码写了啥
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
按提示:
- 前约 8 秒 安静
- 后约 8 秒 说话/拍手
- 自动后面全套;最后约 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:推理灯不跟手
排查顺序:
- 固件是不是带
LED:1解析的stream_sensor - COM 是否被占
- 窗口是否凑满 16 个点(刚开始几秒可能还不亮)
- 模型是不是刚训完的那个
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 → 再上真机 |
更多推荐




所有评论(0)