1. 选型分析为什么是 ESP32-C3 SU03T NPN 红外1.1 主控选择ESP32-C3 的优势与取舍很多人一上来会选 ESP8266毕竟便宜、资料多、生态也成熟。但放在语音遥控空调这个场景里ESP8266 有几个短板特别明显单核 80MHz 跑得慢GPIO 紧张还没法直接用 USB 烧录得外接 USB-TTL 转接器对新手来说多了一道坎。ESP32-C3 的优势在于它是 RISC-V 核心单核最高 160MHzFlash 通常有 4MBGPIO 数量足够用关键是自带 USB 烧录功能Type-C 线插上就能刷固件完全不需要额外买烧录器。语音空调遥控这个项目里ESP32-C3 的性能其实是溢出的但性能有余量带来的好处很实在即便你在处理红外发射的同时还要跑串口接收、按键消抖、状态灯控制代码写得不够精简也不会卡顿。另外ESP32-C3 保留 Wi-Fi 能力。后期如果想做个手机 App 控制界面、或者把语音遥控功能接进家庭自动化系统不需要换主控板直接在现有硬件上加代码就行。这是 ESP8266 很难做到的因为它的可玩性上限摆在那。1.2 语音识别模块SU03T 为什么值得用SU03T 是国内 DIY 圈子里用得相当多的离线语音识别模块。它的核心价值在“离线”两个字词条识别全部在本地完成不连网、不上云响应速度快不会因为家里路由器重启或者宽带故障就罢工。这个模块支持自定义词条你可以把“打开空调”“关掉空调”“制冷模式”“风速加大”这些口语化指令烧录进去。词条数量可以配置对空调遥控来说8 到 12 个词条完全够用。识别到词条后SU03T 会通过串口输出一组预设的数据主控拿到数据后就能执行对应动作。整个链路清晰简单没有任何云端的中间环节。SU03T 最大的“坑”在于它的串口输出需要和主控之间建立约定。出厂默认波特率是 9600返回格式也可以自行配置。很多人拿到模块去试发现 ESP32-C3 收到的一堆乱码其实就是波特率不一致或者共地没做好。这两个问题我会在后面的接线和调试章节专门展开。1.3 红外发射方案为什么选 NPN 三极管红外发射电路看起来简单一颗 940nm 红外发射管加一颗限流电阻就能发光。但问题在于 GPIO 驱动能力。ESP32-C3 的 GPIO 输出高电平时电流很有限直接推红外发射管压降和电流都撑不起来实际发射距离会短得可怜隔着一两米空调都可能收不到。所以这里需要用 NPN 三极管做开关放大。我选用的是 S8050 这类常见小功率 NPN 三极管基极串一颗 1kΩ 电阻接到 GPIO集电极接红外发射管负极发射管正极接 3.3V发射极接地。GPIO 输出高电平时基极电流让三极管进入饱和导通状态红外管获得几十毫安的驱动电流遥控距离轻松到 3 到 5 米对室内空调场景绰绰有余。要注意不要把红外管直接用 5V 驱动。ESP32-C3 的 GPIO 电平体系是 3.3V如果外部电路按 5V 电平设计长期使用的可靠性会受影响。3.3V 供电配合三极管放大是最稳妥的方案。2. 硬件接线与供电细节2.1 三块硬件的连接思路整个系统由三部分组成ESP32-C3 开发板、SU03T 语音模块、红外发射电路。我用的 ESP32-C3 是常见 Type-C 口的合宙开发板SU03T 是常见的 8PIN 封装小板红外发射电路自己在面包板上搭。接线规则如下SU03T 的 VCC 接 5V 或 3.3V。我推荐从 ESP32-C3 的 5V 引脚取电因为语音模块驱动扬声器的瞬时电流较大单独从 USB 5V 供电更稳。SU03T 的 GND 必须与 ESP32-C3 的 GND 连接这是串口通信稳定工作的前提。SU03T 的 TX 接 ESP32-C3 的 RX我使用的是 GPIO20。SU03T 的 RX 接 ESP32-C3 的 TX我使用的是 GPIO21。红外发射管正极接 3.3V负极接 S8050 的集电极。S8050 基极串联 1kΩ 电阻后接 ESP32-C3 的 GPIO10。S8050 发射极接地。画接线图时一定要把 TX 和 RX 交叉连接这件事标注清楚。SU03T 的 TX 发数据ESP32-C3 从 RX 收数据两边一交叉数据才能流动。如果 TX 接 TX等于两边都想往同一条线上发数据直接废掉。2.2 共地最容易翻车的细节关于共地我多说几句。SU03T 和 ESP32-C3 如果分别供电它们的“地”之间可能并不等电位。USB 供电时所有 GND 都来自同一个电源基本没有问题但如果一个用电池、一个用充电头或者两个用不同的适配器地电位差会导致串口数据乱码甚至直接损坏模块。我踩过一回很典型的坑SU03T 接了一个独立充电头ESP32-C3 插在电脑 USB 口上两个 GND 没接。结果串口收到的数据全是 0xFF 或者完全随机。后来把两边的 GND 接到一起问题立刻消失。从那以后我凡是做多模块串口通信第一件事就是检查共地。建议把 SU03T、ESP32-C3、红外驱动电路三者的 GND 统一连接到 ESP32-C3 的 GND 排针上。这样既保证串口电平参考一致也让红外发射电路有了统一的回流路径。2.3 电源稳定性与电流余量如果你直接把 ESP32-C3 插在电脑 USB 口上调试要留意电脑 USB 口的供电能力一般只有 500mA。启动瞬间 ESP32-C3 加上 SU03T 的电流峰值偶尔会出现掉电重启的现象。我建议调试阶段使用带供电的 USB HUB或者直接用 5V 2A 的电源适配器给开发板供电SU03T 再从开发板的 5V 引脚取电。SU03T 播报提示音时扬声器驱动电路会突然拉高电流如果电源线压降大可能会让 ESP32-C3 的电源电压产生波动进而干扰红外发射时序。因此电源线尽量短、线径粗一点电源适配器的电流余量留足 1A 以上不要让整个系统在极限电流下工作。3. 红外码的抓取、识别与存储思路3.1 为什么不能直接找现成的码库空调遥控器和电视遥控器不一样空调没有统一标准的红外协议。不同品牌、不同型号、不同年份的产品协议差异很大。有些是 NEC 协议的变种有些是类似 Mitsubishi 的帧格式还有更多品牌使用自己私有的编码方式。就算是同一个品牌不同系列的空调很可能用不同协议直接套用网上的码表大概率失灵。正确做法是先抓自己家里遥控器的码然后让 ESP32-C3 照着码的时序原样发射。很多教程会介绍 IRremote 库直接解码但 IRremote 库只支持常见协议碰到私有协议会解码失败或者得到残缺数据。我的做法是使用 ESP32-C3 内部 RMT 外设以微秒级精度记录遥控器发出的每个高低电平持续时间拿到完整的原始时序而不是依赖协议解析层。3.2 抓码硬件怎么搭抓码需要一颗红外接收头型号通常选 VS1838B 或 TL1838。这颗接收头内置了 38kHz 载波解调电路能够把遥控器发射的载波信号还原成串行电平。接线非常简单接收头有三个引脚VCC 接 3.3VGND 接 GNDOUT 接 ESP32-C3 的 GPIO9。接好后先用 RMT 接收模式写一小段测试程序把每次收到的脉冲时间数组打印到串口助手上。下面是一个 RMT 接收逻辑的示意#include driver/rmt_rx.h // RMT 接收回调 // 红外数据本质上是连续的电平翻转每个翻转间隔对应一个时间单位 // 将每次收到的 duration 存入数组等待后续打印或分析我在这里不贴完整代码因为不同版本的 ESP-IDF 或 Arduino 库函数接口差异很大。重点是理解原理红外遥控码本质上就是一连串“高电平持续时间 低电平持续时间”的时间数组。抓住这个数组发送时按相同时间序列翻转 GPIO 即可。3.3 空调码太大怎么压缩存储空调码比电视码复杂得多。电视码往往只有几十个脉冲空调码常常有几百甚至上千个脉冲而且很多协议需要在一帧内发送多段数据。比如某些品牌空调的完整红外帧可以长达 1400 个时间单位直接存数组也不一定会爆内存但如果你想存十几组码还是要注意空间。我采用的方法是先用 RMT 抓出完整时间数组再分析其中的重复规律。很多空调协议会把一帧分成“引导码 头码 数据 尾码”数据部分又是按位组织的。如果你能总结出规律可以写一个编码函数用几十字节压缩信息生成完整波形。但对于个人 DIY 项目我反而不建议过度压缩。ESP32-C3 的 Flash 空间足够直接定义多个uint16_t数组存脉冲时间一个码顶多占 2KB存十几组码也就 20KB 左右。真正需要关心的是载波频率不同空调可能使用 38kHz 或 40kHz。抓码时要知道你用的接收头中心频率是多少发送时配置 RMT 的载波频率与空调匹配。4. 固件逻辑从语音词条到红外动作的完整链路4.1 固件功能框架固件逻辑可以拆成三个部分语音接收层、指令解析层、红外发射层。语音接收层从串口读取 SU03T 的识别结果指令解析层通过识别结果映射到具体动作红外发射层把动作对应的红外码通过 RMT 发送出去。我写的程序骨架大致如下void setup() { Serial.begin(9600); // 与 SU03T 通信 pinMode(IR_LED_PIN, OUTPUT); rmtInit(); // 初始化红外发送通道 } void loop() { if (Serial.available()) { String cmd Serial.readStringUntil(\n); cmd.trim(); int action parseCommand(cmd); if (action 0) { sendACCode(action); // 发送对应动作的红外码 } } }这里有个关键点SU03T 的串口输出格式是可以配置的但你必须先弄清楚当前模块实际返回的格式。我配置时把返回格式简化为十进制数字“打开空调”对应 1“关闭空调”对应 2这样解析逻辑最简单不会因为字符串匹配出错。4.2 SU03T 自定义词条配置细节SU03T 的词条配置必须通过配套的上位机软件完成。你需要在软件里新建产品、添加词条、设置唤醒词、配置串口输出格式然后重新烧录模块固件。我实际配置的词条列表如下唤醒词小雅小雅打开空调 - 输出 1关闭空调 - 输出 2制冷模式 - 输出 3制热模式 - 输出 4风速加大 - 输出 5风速减小 - 输出 6温度上调 - 输出 7温度下调 - 输出 8摆风开关 - 输出 9烧录完成后先用 USB-TTL 模块单独测试 SU03T 的串口输出确保每个词条都能触发相应数字输出再接上 ESP32-C3此时问题排查范围会小很多。4.3 RMT 发送红外的实现要点红外发送部分我是用 ESP32-C3 的 RMT 外设实现的。RMT 可以精确生成高低电平切换时序不需要 CPU 持续介入这对于 38kHz 载波调制来说非常重要。如果用普通digitalWrite加delayMicroseconds去软件模拟时序很容易出现抖动空调可能不认。配置 RMT 发送时设置载波频率为 38kHz然后把之前抓到的脉冲时间数组写入发送缓冲区启动发送即可。RMT 支持一次发送多段数据正好对应空调红外帧中的引导码、数据段、尾码。另外空调码通常需要“重复发送”。原厂遥控器在按住按键时会持续重复同一帧有些空调对帧间间隔非常敏感。抓码时如果能抓到遥控器连续发帧的间隔就把它一并记录。发送时按相同间隔重复多次成功率最高。5. 调试与避坑串口乱码、红外距离短、程序不稳5.1 SU03T 串口输出乱码排查链路如果你发现 ESP32-C3 收到的数据不是预期数字按下面这个顺序排查能省掉大量时间单独给 SU03T 供电用 USB-TTL 转接模块接它的 TX打开串口助手观察识别结果。这一步能排除 ESP32-C3 程序的问题。检查波特率是否一致。SU03T 默认 9600如果 ESP32-C3 的Serial.begin写成了 115200数据必乱。检查共地是否做好。两个模块之间必须共地这是最容易被忽略的一步。检查 RX/TX 有无交叉接反。SU03T 的 TX 接 ESP32-C3 的 RX反了也收不到数据。检查 SU03T 的触发模式。有些固件默认是按键触发不是一直监听语音必须在上位机里改成语音唤醒模式。第 5 条最容易踩。我第一次用 SU03T默认固件需要按压模块上的按键才会开始识别不是上电就处于监听状态。如果你唤醒后听不到提示音先查触发模式再查硬件连接。5.2 红外距离近从驱动和载波频率两个方向查红外发射距离短通常有三个原因。第一驱动电流不足。如果限流电阻选得太大比如 100Ω 以上红外发射管的电流可能只有十几毫安发射功率很低。我实测把限流电阻从 100Ω 降到 33Ω在发射管允许的峰值电流范围内遥控距离明显提升。第二载波频率错位。空调接收头对载波频率敏感部分品牌用 38kHz部分用 40kHz。如果你发送时配置的载波频率和空调实际使用的频率不一致接收灵敏度会急剧下降。解决方法是发送前确认抓码接收头的中心频率并让 RMT 发送配置与之匹配。第三发射管角度和朝向。红外发射管有较强的方向性哪边对着空调室内机的接收窗口哪边效果最好。安装时尽量把发射管朝向空调接收窗或者使用两颗红外发射管并联来扩大覆盖角度。提示如果把两颗红外发射管并联建议把 NPN 三极管的基极驱动电流适当加大让集电极电流达到 80mA 以上保证每颗管子都能获得足够的驱动电流。5.3 程序不稳定与内存问题ESP32-C3 的 RMT 外设发送几百个脉冲没有压力真正的问题是如果一直在循环里动态分配发送缓冲区时间一长会出现内存碎片。我的做法是在setup里初始化发送缓冲区和 RMT 通道运行时只更新数据不反复创建任务。另外ESP32-C3 本身带蓝牙如果同时开启 BLE串口中断和 RMT 定时器偶尔会发生微秒级冲突。在语音遥控空调这个项目里完全用不到 BLE所以我直接在配置里关闭蓝牙功能把 CPU 中断负担降到最低。我还给系统加了一颗状态指示灯SU03T 识别到词条后ESP32-C3 会点亮 LED 表示收到了指令红外发射后再灭掉。这样调试时不用盯着串口看用眼睛余光就能判断链路是否通畅。6. 进阶改造模块化码表与多台空调适配6.1 让一套硬件控制多台空调如果家里不止一台空调你可以让一套硬件控制多台设备。思路是把红外码按照品牌和型号组织成二维结构用 SU03T 的词条切换当前目标设备。在 SU03T 里增加“客厅空调”“卧室空调”两个设备选择词条。ESP32-C3 收到设备选择指令后把内部变量currentDevice设置成对应设备号。后续用户说“打开空调”时主控根据currentDevice选择合适的红外码数组发送。这样新增一台空调只需要抓取它的遥控码再增加一组码表和一个设备词条。6.2 本地优先延续扩展能力这套方案最大的优势是本地优先。从语音识别到红外发射全程不依赖任何云服务。你可以把整个系统做成一个独立小盒子放在空调附近只接电源就可以运行。不会因为厂商服务器维护导致设备失效也不会把家里的使用习惯数据上传出去。如果后续想进一步扩展可以在 ESP32-C3 上挂一颗温湿度传感器让空调根据室内温度和用户语音指令自动调节模式。语音指令作为最高优先级的手动干预传感器数据作为自动调节依据本质上是从“遥控器”升级为“控制器”。6.3 温度调节与多段按键实现的技巧空调遥控器上的温度调节通常只有“升温”和“降温”两个按键。想实现“调到 25 度”这样的语音指令有两个思路。第一种是抓取 16 到 30 度之间每一档温度的完整红外码语音识别后直接发射对应的那一组第二种是模拟多次按键识别到“调到 25 度”后如果当前是 28 度就连续发送三次降温键。我实际选择的是第二种原因是抓 15 组完整温度码工作量太大而模拟多次按键操作实现简单。不过要注意连续发送多个按键码后空调可能需要一点处理时间如果发送间隔太短可能会漏掉一两度。我的做法是在每组按键码之间加 200ms 左右的延时发送结束后再让 SU03T 播报一句“温度已调整”给用户明确反馈。收个尾吧。这套 ESP32-C3 SU03T NPN 红外的方案我从立项到跑通用了大概三个晚上。最难的不是焊接也不是写代码而是理解空调红外协议的多变性以及 SU03T 串口配置和主控程序之间必须建立明确约定。如果你也要复现我强烈建议把所有红外码全部抓完、整理好之后再开始写发送逻辑。顺序一旦颠倒后面很容易陷入“改代码烧录-测试-再改再烧录”的低效循环。最后分享一个小技巧调试红外码的时候最烦人的是每次改完发送参数都要重新插拔 USB 烧录。我的做法是在 ESP32-C3 上留一个 GPIO 按键作为“调试模式开关”按下后进入循环发送同一帧红外码省去反复烧录的麻烦。这样整个项目虽然不大但调试体验会舒服很多。