ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ESP32-S3-N16R8打造麦金塔AI小机器人:从硬件选型到固件调试全攻略

ESP32-S3-N16R8打造麦金塔AI小机器人:从硬件选型到固件调试全攻略 1. 为什么我选了ESP32-S3-N16R8来做这台麦金塔小机器人1.1 从一堆吃灰的开发板里翻出这块模组去年年底收拾工作台翻出来好几块开发板ESP8266、ESP32-C3、STM32F103还有一块买了好久一直没动的ESP32-S3-N16R8。当时买它纯粹是因为看到参数眼馋16MB Flash加8MB PSRAM双核LX7跑到240MHz还带向量指令支持Wi-Fi和蓝牙5.0。这个配置放在桌面级AI机器人项目里属于杀鸡用牛刀的级别但恰恰是这种冗余让我后面省了很多事。很多人做桌面小机器人第一反应是树莓派理由很直接Linux环境、Python生态、跑大模型方便。我一开始也这么想但实际搭起来发现几个问题。树莓派Zero 2W跑一个语音唤醒加云端API调用功耗在1.5W到2.5W之间需要持续供电电池方案要么笨重要么续航短。而且Linux启动慢从通电到能响应语音指令快的话也要二十多秒。桌面摆件这种东西用户的心理预期是碰一下就有反应不是等它开机。ESP32-S3-N16R8的方案就完全不一样。上电到Wi-Fi连接完成、语音服务就绪实测在3秒以内。深度睡眠模式下电流可以压到几十微安用一块2000mAh的锂电池能撑好几天。最关键的是8MB PSRAM让它可以缓存音频数据、跑轻量级的本地关键词识别模型不需要所有东西都往云端扔。1.2 麦金塔外壳不只是情怀它解决了散热和结构问题选麦金塔造型一开始确实是情怀驱动。那个经典的方正造型、CRT屏幕的位置、软驱口的开口放在桌面上辨识度极高。但真正动手之后发现这个造型在工程上意外地合理。麦金塔的机身厚度足够内部空间能塞下一块3.7V锂电池、一个1.5英寸的圆形LCD、一个I2S数字麦克风、一个MAX98357功放模块和一个小尺寸扬声器。CRT屏幕的位置刚好用来放LCD软驱口的开口尺寸正好可以引出USB-C充电口和几个按键。机身背面的散热孔原本是给CRT用的现在用来给ESP32-S3散热刚刚好连续跑几个小时语音交互模组表面温度稳定在45度左右不会触发降频。外壳我一开始想3D打印但后来发现用激光切割亚克力板加胶水拼接更省事。3D打印的层纹在麦金塔这种方正造型上特别明显后期打磨很费时间。亚克力板切割边缘用砂纸过一遍再用亚克力胶水粘合出来的效果干净利落。屏幕窗口和按键开孔用激光切割精度足够不需要二次加工。1.3 这个项目适合谁动手如果你有基本的焊接经验能看懂简单的电路图会用Arduino IDE或者PlatformIO烧录固件这个项目完全可以自己搞定。不需要你会画PCB所有模块都是现成的开发板加杜邦线连接。不需要你会写AI模型语音识别和对话逻辑走的是现成的云端API固件里已经封装好了调用逻辑。整个项目的物料成本大概在150到200元之间具体取决于你手头已经有哪些零件。ESP32-S3-N16R8模组大概40到50元LCD屏幕30元左右麦克风和功放模块加起来20元锂电池和充电管理模块30元外壳材料20元剩下的就是杂七杂八的线材和螺丝。我见过很多人卡在选什么屏幕用什么麦克风这种问题上纠结好几天。这篇内容会把每个模块的选型理由和接线方式都讲清楚你照着做就行。固件我会提供编译好的bin文件也会说明怎么自己从源码编译。2. 物料清单与模块选型每一分钱花在哪里2.1 核心模组ESP32-S3-N16R8的引脚分配策略ESP32-S3-N16R8的引脚比普通ESP32多不少但实际用起来还是会紧张。我先把整个项目的引脚需求列出来再分配。需要占用的引脚包括I2S麦克风3根BCLK、WS、DATA、I2S功放3根BCLK、WS、DATA、LCD屏幕SPI接口5根SCK、MOSI、CS、DC、RST再加一根背光控制、按键2根、电池电压检测1根ADC、状态LED1根。加起来一共15根。ESP32-S3-N16R8可用的GPIO有三十多个但要注意有些引脚有特殊功能。GPIO0是BOOT按键GPIO19和GPIO20是USB D/D-GPIO43和GPIO44是UART0的TX/RX。这些引脚尽量避开或者确认不影响功能后再用。我的分配方案是这样的麦克风I2S用GPIO4、5、6功放I2S用GPIO7、8、9LCD的SPI用GPIO10到14按键用GPIO1和GPIO2电池检测用GPIO3状态LED用GPIO21。这样分配的好处是所有外设的引脚都连续走线整齐杜邦线不容易插错。注意ESP32-S3的I2S外设有两个可以同时使用。麦克风和功放各用一个I2S控制器互不干扰。如果你把两个设备挂在同一个I2S上需要做时分复用固件复杂度会上升很多。2.2 显示模块1.5英寸圆形LCD还是方形IPS麦金塔的CRT屏幕区域是方形的但实际显示区域可以做成圆形或者方形。我试过两种方案。圆形LCD的好处是视觉上更像一个眼睛或者脸配合机器人的表情动画很自然。缺点是圆形屏幕的驱动IC通常是GC9A01SPI接口分辨率240x240刷新率有限做复杂动画会卡。而且圆形屏幕的可视角度一般从侧面看颜色偏白。方形IPS屏幕我选的是1.5英寸240x240的ST7789V驱动SPI接口刷新率比GC9A01高不少颜色也更正。方形屏幕在麦金塔的方形窗口里刚好填满看起来更像原版CRT的显示区域。表情动画用方形画布做边缘留黑边效果也不错。最后我选了方形IPS。理由是固件里做表情动画需要频繁刷新屏幕ST7789V的SPI时钟可以跑到80MHzGC9A01通常只能到40MHz。刷新率差一倍动画流畅度差别很明显。2.3 音频输入输出I2S麦克风与功放模块的搭配麦克风我用的INMP441I2S接口24位ADC信噪比61dB。这个麦克风在桌面环境下拾音效果很好三米内正常说话音量就能触发唤醒。它的灵敏度可以通过固件里的增益参数调整默认增益下安静房间里连翻书的声音都能拾到所以实际使用时我把增益调低了6dB避免误触发。功放用的MAX98357I2S输入D类功放最大输出3.2W。搭配一个4欧姆3W的小扬声器音量足够一个房间使用。MAX98357的好处是只需要I2S的三根线加电源不需要额外的DAC或者滤波电路。它的增益可以通过SD引脚和GAIN引脚配置我设的是9dB增益再高会有底噪。麦克风和功放的I2S时钟需要分开配置。麦克风是输入ESP32-S3作为I2S主机产生时钟功放是输出ESP32-S3也作为主机产生时钟。两个I2S控制器独立工作互不干扰。固件里我用的是ESP-IDF的I2S标准模式驱动配置起来比老版的I2S驱动清晰很多。2.4 电源方案锂电池与充电管理的取舍电源部分我一开始想用18650电池容量大放电曲线平稳。但18650电池加电池座太占空间麦金塔机身内部放不下。后来换成一块2000mAh的软包锂电池尺寸刚好塞在机身底部。充电管理用的是TP4056模块带保护板。TP4056的充电电流可以通过PROG电阻设置我设的是1A充2000mAh电池大概两个半小时充满。模块上自带蓝色和红色LED指示充电状态我把LED用导线引到机身背面透过亚克力板能看到充电指示。电池电压检测用ESP32-S3的ADC引脚通过一个100k和100k的电阻分压把电池电压降到ADC量程范围内。固件里定期读取ADC值换算成电池百分比显示在屏幕角落。分压电阻用1%精度的金属膜电阻普通碳膜电阻的误差太大电量显示会跳。提示锂电池放电到3.3V以下时ESP32-S3的Wi-Fi模块可能会工作不稳定。固件里我设了3.4V低压警告3.2V自动关机。不要等到电池完全放空再充电对电池寿命不好。3. 电路连接与外壳组装从散件到整机3.1 接线图与焊接注意事项整个项目的接线分三部分电源部分、I2S音频部分、SPI显示部分。我建议先接电源部分确认供电正常后再接其他模块。电源部分的接线锂电池的正负极接到TP4056模块的B和B-TP4056的OUT和OUT-接到ESP32-S3的5V和GND。注意TP4056模块的输出电压是电池电压不是稳定的5V。ESP32-S3的5V引脚内部有LDO稳压到3.3V所以电池电压在3.4V到4.2V之间时模组都能正常工作。I2S麦克风的接线INMP441的VDD接3.3VGND接GNDSCK接GPIO4WS接GPIO5SD接GPIO6L/R接GND选择左声道。麦克风的时钟线要尽量短超过10厘米容易引入噪声。我用的是10厘米的杜邦线实际测试底噪在可接受范围内。I2S功放的接线MAX98357的VIN接5VGND接GNDBCLK接GPIO7LRC接GPIO8DIN接GPIO9。GAIN引脚悬空默认9dB增益SD引脚悬空使能输出。功放的电源线要粗一点我用的是22AWG的线细线在大音量时会有压降导致声音失真。SPI屏幕的接线ST7789V的VCC接3.3VGND接GNDSCL接GPIO12SDA接GPIO11RES接GPIO13DC接GPIO14CS接GPIO10BLK接GPIO15背光控制。屏幕的背光LED需要限流电阻我用的100欧姆背光电流大概15mA亮度足够。焊接的时候注意ESP32-S3-N16R8模组的引脚间距是2.54mm普通烙铁头就能焊。但模组底部的散热焊盘需要焊到PCB上如果你用的是模组而不是开发板这个焊盘必须焊否则大负载时模组会过热。我直接买的开发板散热焊盘已经处理好了省事。3.2 麦金塔外壳的切割与组装外壳我用的是3mm厚的黑色亚克力板激光切割。图纸是我自己画的参考了原版麦金塔的尺寸比例整体缩小到大约三分之一。机身尺寸是120mm宽、140mm高、100mm深。前面板需要开三个孔屏幕窗口40mm x 40mm、软驱口30mm x 10mm用来引出USB-C、按键孔两个6mm圆孔。屏幕窗口的位置要精确偏1mm就会露出屏幕边框。我在图纸上标了定位孔切割后用屏幕实际比对了一下刚好卡住。侧板和顶板用亚克力胶水粘合。胶水涂薄薄一层压紧后等24小时完全固化。粘合的时候用直角夹具固定保证机身方正。背板用螺丝固定方便后期拆开维护。背板上开散热孔用3mm钻头打一排孔间距5mm。屏幕用热熔胶固定在前面板内侧。热熔胶的好处是固化快后期要拆的话用酒精就能软化。麦克风用双面胶贴在机身顶部内侧靠近前面板的位置拾音效果最好。扬声器用螺丝固定在机身底部出声孔朝下利用桌面反射声音更饱满。3.3 上电前的检查清单接线完成后不要急着上电先做一遍检查。我列了一个清单每次装新机器都过一遍。用万用表测电池电压确认在3.7V到4.2V之间测TP4056输出端电压应该和电池电压一致测ESP32-S3的3.3V引脚对GND的电阻正常应该在几百欧姆以上如果接近0说明有短路检查所有I2S和SPI线是否插紧杜邦线有时候会松动确认麦克风的L/R引脚接GND如果悬空会导致声道错乱确认屏幕的背光限流电阻已接直接接3.3V会烧背光上电后先看状态LED是否亮起然后听扬声器有没有底噪。如果底噪很大检查功放的电源线和地线是否接触良好。如果屏幕不亮先测背光电压再测SPI信号。ESP32-S3的SPI引脚在启动时会有短暂的电平变化这是正常的。4. 固件烧录与配置让机器人开口说话4.1 固件下载与烧录工具的选择固件我提供了两个版本一个是编译好的bin文件直接用esptool烧录另一个是完整的源码工程用PlatformIO编译。bin文件的烧录地址是0x0包含bootloader、分区表和应用程序。烧录命令是这样的esptool.py --chip esp32s3 --port /dev/ttyUSB0 --baud 921600 write_flash 0x0 firmware.binWindows下端口号可能是COM3或者COM4在设备管理器里看。Linux下通常是/dev/ttyUSB0或者/dev/ttyACM0。烧录前需要按住BOOT键按一下RST键进入下载模式。烧录完成后按RST键重启。如果你要自己编译源码需要安装PlatformIO。在VSCode里装PlatformIO插件打开工程目录它会自动下载ESP-IDF和依赖库。编译命令是pio run烧录命令是pio run --target upload。第一次编译会下载几百MB的工具链耐心等。注意ESP32-S3-N16R8的Flash是16MB分区表要选对。我用的分区表是16MB Flash (3MB APP/9.9MB FATFS)应用程序分区3MB足够放语音识别模型和表情动画资源。如果你自己改分区表注意APP分区不要小于2MB否则固件放不下。4.2 Wi-Fi与云端API配置固件第一次启动时会进入配网模式屏幕上显示一个二维码用手机扫码连接机器人的热点然后输入你家Wi-Fi的SSID和密码。配网信息保存在NVS里下次启动自动连接。云端API我用的是一个语音对话服务支持语音识别、对话生成和语音合成。固件里封装了API调用逻辑你只需要在配置文件中填入API Key和API Secret。配置文件在源码的main/config.h里bin文件版本的话配网时在手机页面上填入。API的调用流程是这样的麦克风采集音频经过降噪和VAD语音活动检测后把音频数据通过WebSocket传到云端云端返回识别文本和对话回复固件再把回复文本通过TTS合成语音用功放播放出来。整个流程的延迟在1.5秒到2.5秒之间取决于网络状况。如果你不想用云端API固件也支持本地关键词识别。ESP-SR是乐鑫的离线语音识别库支持自定义唤醒词和命令词。本地识别只能处理预设的命令比如打开灯播放音乐不能做自由对话。本地识别的延迟在200ms以内响应很快。4.3 表情动画与交互逻辑的调整屏幕上的表情动画是用LVGL做的。LVGL是一个轻量级图形库在ESP32-S3上跑240x240的界面很流畅。我做了几组表情待机时是眨眼的圆形眼睛识别到语音时变成放大的瞳孔思考时是转圈的眼睛说话时是跳动的波形。表情切换的逻辑在main/face.c里。待机状态每3秒随机眨眼一次识别到唤醒词后切换到聆听表情云端返回结果后切换到思考表情TTS播放时切换到说话表情。这些状态之间的切换用了一个简单的状态机代码不复杂你可以根据自己的喜好调整。按键的功能是这样的短按第一个键切换表情主题短按第二个键切换对话模式云端/本地长按第一个键进入配网模式长按第二个键重启。按键消抖用的是ESP-IDF的GPIO中断加软件定时器消抖时间20ms。5. 调试过程中遇到的几个坑5.1 I2S时钟冲突导致音频断断续续第一次跑通的时候麦克风和功放单独测试都正常但一起工作的时候扬声器里的声音会每隔几秒卡一下。用逻辑分析仪抓I2S波形发现麦克风的BCLK和功放的BCLK有相位差偶尔会冲突。原因是两个I2S控制器的时钟源虽然独立但ESP32-S3的I2S时钟树有共享的PLL。当两个I2S的采样率不一致时PLL会重新锁定导致短暂的时钟丢失。解决办法是把麦克风和功放的采样率设成一样的都用16kHz。麦克风采集16kHz功放播放16kHzPLL不需要切换冲突就消失了。如果你需要用不同的采样率比如麦克风16kHz、功放48kHz那就需要把其中一个I2S设成从模式用外部时钟。但这样需要额外的时钟芯片电路复杂度上升。对于桌面机器人这种场景16kHz的语音质量已经足够没必要折腾。5.2 锂电池供电时Wi-Fi频繁掉线用USB供电调试的时候一切正常换成锂电池供电后Wi-Fi每隔几分钟就掉一次。一开始以为是电池电量不足但测电压还有3.8V。后来用示波器看电源纹波发现Wi-Fi发射瞬间电池电压会瞬间跌到3.2V以下导致模组复位。原因是TP4056模块的输出端没有大电容电池的内阻在瞬间大电流下产生压降。解决办法是在TP4056的输出端并一个470uF的电解电容加一个100nF的陶瓷电容。电解电容提供瞬态电流陶瓷电容滤高频噪声。加上之后Wi-Fi发射时的电压跌落从600mV降到了100mV以内掉线问题解决。提示如果你用的电池内阻比较大比如拆机电池电容还要加大。我试过用1000uF的电容效果更好。但电容体积也大麦金塔机身里要找个位置放。5.3 屏幕SPI干扰麦克风导致识别率下降屏幕刷新的时候麦克风的底噪会明显增大语音识别率从90%掉到60%。用频谱分析仪看屏幕SPI的时钟频率是40MHz谐波刚好落在麦克风的音频频段内通过电源线和空间辐射耦合到了麦克风。解决办法有两个一是降低SPI时钟到20MHz刷新率降一半但表情动画还能接受二是在麦克风的电源引脚上加一个LC滤波10uH电感和100nF电容组成低通滤掉高频干扰。我两个都做了SPI降到20MHz麦克风电源加LC滤波识别率恢复到92%以上。屏幕的排线也要尽量远离麦克风。我一开始把屏幕排线和麦克风线捆在一起干扰特别严重。后来把屏幕排线走机身左侧麦克风线走右侧中间隔了电池干扰小了很多。5.4 云端API的音频格式匹配问题云端API要求的音频格式是16kHz、16bit、单声道PCM但INMP441输出的是24bit数据。固件里需要做位深转换把24bit截断成16bit。我一开始直接取高16位结果音量很小因为低8位被丢弃了。正确的做法是取高16位后根据低8位的值做舍入或者直接右移8位再加抖动。TTS返回的音频是MP3格式需要解码成PCM才能用I2S播放。固件里集成了一个轻量级的MP3解码器解码后的PCM数据缓存到PSRAM里再通过I2S输出。PSRAM的8MB容量在这里派上了用场可以缓存好几秒的音频避免网络抖动导致播放卡顿。如果你用的云端API返回的是其他格式比如Opus或者AAC需要换对应的解码器。Opus的解码器比MP3复杂一些但压缩率更高适合网络状况不好的场景。6. 几个可以继续折腾的方向6.1 加一个舵机做头部转动现在的机器人是固定不动的只能通过屏幕表情和声音交互。如果想让它更生动可以加一个小型舵机让头部能左右转动。SG90舵机体积小扭矩够用用ESP32-S3的LEDC外设驱动占一个GPIO就行。舵机的电源要从电池直接取不要从3.3V取舵机启动瞬间的电流会拉低3.3V导致模组复位。控制信号用GPIO16PWM频率50Hz脉宽500us到2500us对应0到180度。固件里可以根据对话内容控制头部转动比如识别到声音从左边来头就转向左边。6.2 本地唤醒词的自定义训练ESP-SR支持自定义唤醒词但需要用乐鑫的工具链训练模型。训练过程不复杂在乐鑫的语音识别平台上上传几段唤醒词的录音等几分钟就能生成模型文件。把模型文件放到固件的分区里改一下配置就能用。我训练了一个小智小智的唤醒词识别率在安静环境下95%以上有背景音乐的时候会降到80%左右。如果你想要更高的识别率可以多录几组不同口音和语速的样本。训练模型的大小在200KB左右放在3MB的APP分区里绰绰有余。6.3 用MQTT接入智能家居ESP32-S3的Wi-Fi可以同时维持WebSocket和MQTT两个连接。固件里加一个MQTT客户端把语音识别的结果发布到MQTT主题就可以控制家里的智能设备了。比如你说打开客厅的灯固件识别到灯和开两个关键词就往MQTT发一条消息Home Assistant收到后执行动作。MQTT的配置在main/mqtt.c里填上Broker地址、端口、用户名和密码就行。我用的Mosquitto Broker跑在本地服务器上延迟在100ms以内。如果你没有本地服务器也可以用公共的MQTT Broker但要注意数据安全不要发敏感信息。6.4 电池续航的进一步优化现在的续航在连续对话模式下大概4小时待机模式下2天。如果想更长可以做几个优化。一是把屏幕背光亮度调低从15mA降到5mA续航能多出几个小时。二是把Wi-Fi的省电模式打开ESP32-S3支持Modem-sleep在不需要通信的时候自动降低Wi-Fi功耗。三是把CPU频率从240MHz降到160MHz语音识别和LVGL刷新都够用功耗降低30%左右。我实测过背光降到5mA、Wi-Fi开省电、CPU降到160MHz连续对话续航能到6小时待机续航4天。代价是屏幕在强光下看起来有点暗语音识别的响应速度稍微慢一点点但都在可接受范围内。最后分享一个我在装配时的小技巧所有杜邦线连接好后用热熔胶在接插件根部点一下固定住。桌面机器人会经常被碰到杜邦线松动是最高频的故障。热熔胶固定后即使用力晃动机身线也不会掉。后期要拆的话用酒精棉签擦一下热熔胶就软化了不会损坏接插件。
返回列表