构建定制ESP32音频播放器
我们最近完成了一个项目,将嵌入式系统、定制硬件和移动开发整合到一个专注的设备中:一款完全通过智能手机控制的便携式音频播放器。客户希望这款设备能放置在教堂大厅,甚至用于健身房会员的定制自动售货机——它是一款低成本、耐用的设备,无需依赖Wi-Fi或云端服务即可播放精选的音频内容。
这是我们是如何构建它的。
问题
客户原本设想的是一个物理分发模式。想象一下,像健身房或教堂大厅的自动售货机一样,用户只需轻触手机,选择一首曲目,设备便会通过内置扬声器或耳机播放。无需触摸屏,无需复杂的用户界面——仅需通过蓝牙触发一个简单可靠的音频播放器即可。
挑战在于:将BOM成本控制在12美元以内,支持离线音频存储,并通过手机应用实现整体控制。无需云服务,无需更换SD卡,仅需稳定的固件和简洁的PCB板。
PCB设计
我们在KiCad 7中绘制了PCB。该电路板为双层,尺寸为50x40mm,所有元件均位于顶层。ESP32位于中央,右侧是MAX98357A和闪存芯片。TP4056和电池连接器位于左侧,与音频路径隔离,以降低噪声。
关键设计决策:
•I2S线路通过地线屏蔽走线,以防止数字噪声进入音频信号。
•通过ESP32 ADC(经由分压器)监测电池电压,用于低电量警报。
•USB-C 仅用于供电和闪存,无需数据线。
•天线与地面保持一定距离,位于顶层。我们使用了带匹配网络的芯片天线(AN9520)。
我们制作了三个版本的原型。第一版存在放大器发出明显嘶嘶声的问题,我们通过在放大器的旁路引脚上加装一个10µF电容解决了这一问题。第二版运行完美。第三版增加了WS2812B LED灯,用于视觉反馈。
软件组件
固件栈非常简单,无需实时操作系统——ESP32的双核可同时处理蓝牙和音频解码。
音频文件以16位、16kHz的单声道WAV格式存储在SPI闪存中。我们编写了一个Python脚本,将MP3文件转换为该格式,并通过USB串口上传。ESP32从FAT分区读取这些文件,并通过I2S进行流式传输。
移动应用程序(Flutter)通过蓝牙经典SPP进行连接,发送简单的文本指令:
•播放3——播放第3首曲目
•`STOP` — 停止播放
•音量80% — 将音量设置为80%
•`LIST` — 返回可用曲目的列表
该应用还会显示电池电量和当前轨迹名称。无需云端,无需网络——所有功能均通过本地BLE/SPP实现。
硬件组件
•Espressif ESP32S
•Maxim Integrated DS18B20 可编程分辨率 1 线数字温度传感器
•SparkFun Electronics LilyPad 电池座 - 切换式 - 20mm
•Adafruit USB 锂离子电池充电器
•Seeed Studio Grove - 音箱
•Bitcraze LED环形甲板
工作原理
1. 用户打开应用,扫描附近设备并连接。
2. 应用发送一个 `LIST` 命令,ESP32 回应轨道名称。
3. 用户点击曲目。手机发送 `PLAY 5`。
4. ESP32 从闪存读取 WAV 文件,并通过 I2S 将其传输到 MAX98357A。
5. 扬声器播放音频。音量可通过应用程序或硬件按钮进行调节。
该设备会在重启后记住上一次的曲目和音量设置(存储在NVS中)。
这对健身房自动售货机有何意义
客户希望将这些设备部署到健身房的定制自动售货机中。想象一下,一个小型服务亭,健身会员只需轻触手机,选择一段圣经音频,就能在原地播放——无需佩戴耳机。该设备价格低廉,若丢失可一次性丢弃,同时具备足够的耐用性,适合日常使用。
同样的硬件可以轻松用于其他音频内容——如指导型健身课程、冥想音乐,甚至有声书。ESP32的蓝牙功能使其能与任何智能手机轻松配对,且无需依赖云端服务,因此完全免去持续的运营成本。
测试与发货
我们对原型机进行了为期两周的测试,共涉及20名用户。在70%音量下,电池续航时间平均为5.5小时。扬声器音量足够大,适合小房间使用(1米处85分贝)。蓝牙信号通过墙壁传输的距离约为15米,对于大厅或健身房地面来说已足够。
我们已向客户发货了50台完全组装好的设备。每台均附带:
•带ESP32、DAC、放大器和电池的定制PCB
•3D打印外壳(PLA材质,两半拼接,卡扣式连接)
•USB-C 数据线
•预装20首圣经音频轨道
客户目前正在三个试点地点进行测试。初步反馈积极,用户认为该应用易于使用,音频质量也足够清晰,适合语音内容播放。
经验总结
•I2S 接地噪声是真实存在的。请在 PCB 上将数字地和模拟地分开。
•SPI闪存磨损对音频文件没有影响——WAV文件在初始写入后为只读状态。
•对于这种应用场景,蓝牙经典比BLE更简单。无需配对开销,只需连接并发送字符串即可。
•音量控制应设在放大器上,而不是软件中。我们使用了MAX98357A的增益引脚来避免削波。
本文编译自hackster.io





