资讯动态

ESP32C3自制WiFi万能遥控:红外编码捕获与Web控制全解析

发布时间:2026/10/9 1:28:13 来源:尧图企业网站定制
1. 从一块九块九的ESP32C3说起为什么我要做这个万能遥控手里攒了好几块ESP32C3开发板都是之前做小项目剩下的。这芯片便宜、体积小、自带WiFi和蓝牙拿来做个万能遥控器再合适不过。起因很简单家里客厅的空调遥控器又找不到了电视盒子、风扇、灯带各一个遥控器茶几上堆得跟小山似的。我就琢磨着能不能用一块ESP32C3把这些红外设备统一管起来手机浏览器打开一个网页就能控制。这个项目我给它起名叫RemodazWifi核心思路就是让ESP32C3连上家里的WiFi跑一个轻量级的Web服务手机或电脑通过浏览器访问它的IP地址就能发送红外指令。不需要装App不需要额外的网关一块板子加一个红外发射管就能跑起来。适合谁参考呢如果你手头有ESP32系列开发板想入门物联网控制、红外编解码或者单纯想折腾一个能用的万能遥控这篇内容应该能帮你少走不少弯路。我先把最终形态说清楚ESP32C3上电后自动连接指定WiFi串口打印出分配到的IP地址浏览器打开这个IP看到一个简洁的控制页面上面有空调开关、温度加减、风扇摇头等按钮点击按钮板子通过红外发射管发出对应的编码设备响应。整个过程延迟在几百毫秒以内体验跟原装遥控器差别不大。2. 硬件选型与电路连接别小看那颗红外发射管2.1 ESP32C3开发板的引脚分配与供电考量ESP32C3的开发板市面上有好几种我手头这块是合宙的C3迷你板引脚排布紧凑3.3V逻辑电平。选它主要是因为体积小、价格低而且自带USB转串口烧录方便。红外发射管我选的是5mm封装的940nm波长管这个波长是绝大多数家电红外遥控的标准载波频率。发射管的正极通过一个限流电阻接到ESP32C3的某个GPIO上负极接地。限流电阻的取值需要算一下。ESP32C3的GPIO最大输出电流大约是40mA但为了安全我一般控制在20mA左右。红外发射管的正向压降大约1.2VGPIO输出高电平是3.3V那么电阻上的压降是3.3V减去1.2V等于2.1V。根据欧姆定律电阻值等于2.1V除以20mA大约是105欧姆。我手头有100欧姆的电阻直接用上了实测电流在21mA左右发射管工作正常板子也没有发热异常。注意红外发射管有极性长脚是正极短脚是负极。接反了不会烧但不会发射。如果你不确定可以用万用表的二极管档测一下正向导通时会有压降读数。2.2 红外接收管在调试阶段的作用虽然最终产品只需要发射但调试阶段我强烈建议接一个红外接收管。原因很简单你需要知道原装遥控器发出的编码到底是什么。红外接收管一般是三脚封装正面接收窗口引脚分别是OUT、GND、VCC。把OUT接到ESP32C3的另一个GPIO上用Arduino的IRremote库就能读出原始编码。我一开始没接接收管直接凭猜测发NEC编码结果空调毫无反应。后来接上接收管用库里的示例程序一读发现这台空调用的是一种变长的编码协议跟标准的NEC完全不一样。所以这一步不能省接收管也就几毛钱但能帮你省下大量试错时间。2.3 供电与稳定性USB供电够不够ESP32C3在WiFi工作时的峰值电流可能达到200mA以上加上红外发射管瞬间的20mA整体功耗不大。我用普通的USB充电头供电实测稳定运行。但如果你用的是电脑USB口同时还在串口打印调试信息偶尔会出现电压跌落导致重启的情况。我的建议是调试阶段用带独立供电的USB Hub或者直接用一个5V/1A的充电头。另外红外发射管在发射时是脉冲工作的载波频率38kHz占空比三分之一左右。这意味着瞬时电流是脉冲式的对电源的纹波要求不高普通滤波电容就能应付。我在板子的3.3V和GND之间并了一个100微法的电解电容进一步稳定供电实测连续发射几十次也没有出现复位。3. 红外编码的捕获与解析从遥控器到数据3.1 用接收管抓取原始时序数据接好接收管之后我烧录了一个简单的红外接收示例程序。这个程序的作用是监听接收管输出的电平变化把高低电平的持续时间记录下来打印到串口。按下空调遥控器的开关机键串口输出了一长串数字每个数字代表一段微秒级的时间。这里有个关键点红外接收管输出的信号是反相的。也就是说当有38kHz载波时接收管输出低电平没有载波时输出高电平。所以你在分析数据时要把这个逻辑反过来理解。我一开始没注意把高低电平搞反了解码出来的数据完全对不上。3.2 识别编码协议NEC、RC5还是自定义拿到原始时序数据后下一步是判断它属于哪种协议。常见的红外协议有NEC、RC5、RC6、Sony SIRC等。NEC协议的特征是引导码9ms低电平加4.5ms高电平然后是地址和命令字节每个字节8位位0是560微秒低加560微秒高位1是560微秒低加1.69毫秒高。RC5则是曼彻斯特编码位时长固定1.778毫秒。我抓到的这台空调数据引导码是4.5ms低加4.5ms高后面跟着一串不等长的高低电平明显不是标准NEC。查了一些资料后确认这是格力空调常用的一种自定义协议数据长度不固定跟温度、模式、风速都有关。这种情况下最稳妥的做法不是去逆向协议而是直接把原始时序数据存下来发射时原样重放。3.3 原始数据重放最省事的万能方案原始数据重放的好处是不需要理解协议细节只要把接收到的时序数组原封不动地发给发射管就行。IRremote库提供了sendRaw函数接收一个数组和数组长度以及载波频率。我把抓到的时序数据整理成数组调用sendRaw空调果然响应了。但这里有个坑原始数据里包含了接收管反相后的逻辑而sendRaw期望的是发射时的逻辑。所以你需要把数组里的高低电平标记反过来。具体来说接收时记录的是“低电平持续时间”和“高电平持续时间”发射时你要先发载波再发空闲。IRremote库的sendRaw函数内部会处理载波调制你只需要传入以微秒为单位的时间数组以及一个标记数组指明每段是载波还是空闲。我一开始直接把接收数据传进去结果发射管只是微微闪了一下设备毫无反应。后来把标记数组反过来立刻就好了。提示不同版本的IRremote库API略有差异。我用的版本是3.xsendRaw的参数是(uint16_t buf[], uint8_t len, uint16_t hz)其中buf数组里奇数索引是载波持续时间偶数索引是空闲持续时间。如果你用的是2.x版本参数顺序可能不同建议先看库里的示例。4. 搭建Web控制界面手机浏览器直接操作4.1 ESP32C3上的轻量Web服务器选型ESP32C3跑Web服务器有好几种方案ESP-IDF自带的httpd、Arduino的WebServer库、或者第三方库如ESPAsyncWebServer。我选的是ESPAsyncWebServer原因是它支持异步处理不会阻塞主循环响应速度快而且可以方便地处理多个并发请求。虽然ESP32C3的内存只有400KB左右但跑一个简单的控制页面绰绰有余。页面本身我放在PROGMEM里也就是Flash中不占用宝贵的RAM。HTML、CSS、JavaScript全部内联在一个字符串里通过server.on(/, HTTP_GET, ...)返回。页面大小控制在几KB以内加载速度很快。4.2 控制页面的交互设计按钮与状态反馈页面设计得很简单顶部显示当前温度和模式下面是一组按钮包括电源、温度加、温度减、模式切换、风速调节。每个按钮点击时JavaScript发送一个HTTP GET请求到对应的URL比如/ir?cmdpower。ESP32C3收到请求后调用对应的红外发射函数然后返回一个简单的JSON响应页面根据响应更新状态显示。这里有个细节红外发射是阻塞操作发射一帧数据大约需要几十毫秒。如果同时有多个请求进来可能会冲突。我的做法是在发射函数里加一个简单的互斥锁用xSemaphoreTake和xSemaphoreGive保证同一时间只有一个发射任务在执行。实测下来即使快速连点按钮也不会出现指令丢失或错乱。4.3 用ESP Web Tools实现一键烧录ESP Web Tools是一个基于Web Serial API的工具可以让用户直接在浏览器里给ESP32C3烧录固件不需要安装任何软件。我把编译好的bin文件放在一个静态页面上用户用Chrome或Edge打开点击“连接”按钮选择串口然后点击“安装”就能把固件刷进去。这个功能对于分享项目特别有用。你不需要教别人怎么装Arduino IDE、怎么配置开发板、怎么选端口只要发一个链接对方点几下就能用上你的固件。我在项目里集成了这个工具把固件和烧录页面一起打包朋友拿到板子后五分钟就能跑起来。注意ESP Web Tools需要浏览器支持Web Serial API目前Chrome、Edge、Opera支持Firefox和Safari不支持。另外烧录时需要把ESP32C3置于下载模式有些板子需要按住BOOT键再按RESET键有些板子自动处理。建议在页面上写清楚操作步骤。5. 固件代码结构从WiFi连接到红外发射5.1 WiFi连接与IP地址获取的稳健实现WiFi连接部分我用了WiFi.begin(ssid, password)然后在一个循环里等待WL_CONNECTED状态。这里有个经验不要用delay死等而是用millis做超时判断同时让出CPU时间给其他任务。我设置了15秒超时如果连不上就进入AP模式自己开一个热点让用户通过热点配置WiFi。获取IP地址后我通过串口打印出来同时在OLED屏幕上显示如果有的话。这样用户就知道该访问哪个地址了。我还加了mDNS功能注册了一个remodaz.local的主机名这样用户可以直接在浏览器输入http://remodaz.local不用记IP地址。mDNS在大多数家庭网络里都能用偶尔在有些路由器上会被屏蔽所以IP地址还是要保留。5.2 红外发射函数的封装与调用红外发射我封装成了一个函数sendIRCommand(uint16_t *rawData, uint8_t len)内部调用IrSender.sendRaw。每个设备对应一个独立的数组比如空调的开关机、温度加、温度减各一个数组。这些数组我放在一个头文件里用const uint16_t修饰编译时直接进Flash。调用逻辑很简单Web服务器收到请求后根据URL参数选择对应的数组调用发射函数。为了支持多个设备我加了一个设备选择的下拉菜单页面刷新时带上设备ID服务器根据ID和命令组合查找对应的数组。5.3 内存与性能的平衡ESP32C3的资源管理ESP32C3的RAM不大跑WiFi和Web服务器之后剩余可用堆内存大约100KB左右。红外编码数组如果太多会占用不少Flash但Flash有4MB问题不大。真正需要注意的是字符串处理Arduino的String类在频繁拼接时容易产生内存碎片。我在Web响应里尽量用const char*和snprintf避免动态分配。另外异步Web服务器会为每个请求分配一个小缓冲区如果并发请求太多内存会紧张。我限制了最大并发连接数为4对于家庭使用场景足够了。实测在手机、平板、电脑同时打开控制页面的情况下响应依然流畅。6. 实测中的坑与解决方案6.1 红外发射距离短不是功率不够是角度问题一开始我把红外发射管直接焊在板子上朝向正前方。实测控制距离只有一米左右稍微偏一点角度就失灵。后来查资料发现红外发射管的发射角度一般在20到30度之间而且光强随距离平方衰减。解决办法很简单把发射管从板子上引出来用导线延长贴在电视柜边缘朝向房间中央。这样覆盖角度大了很多五米以内都能稳定控制。如果你需要更远的距离可以加一个三极管驱动电路用2N2222或者S8050基极通过1k电阻接GPIO集电极接发射管负极发射极接地。这样GPIO只需要提供很小的基极电流发射管可以得到更大的驱动电流距离能提升到十米以上。6.2 空调响应但温度不对编码与状态同步问题空调遥控器有个特点它发送的编码包含了当前的所有状态比如温度、模式、风速。也就是说你按“温度加”时遥控器并不是只发一个“加一度”的指令而是发送“当前温度加一度后的完整状态”。这意味着ESP32C3必须知道空调当前的状态才能发送正确的编码。我一开始没注意这一点每次按“温度加”都发送固定的“26度”编码结果空调温度乱跳。后来我在代码里维护了一个状态变量记录当前温度、模式、风速每次操作时先更新状态再根据新状态查找对应的编码数组。这样就对了。提示不同品牌的空调编码逻辑不同。有些品牌是状态码有些是增量码。最稳妥的办法是抓取原装遥控器在不同状态下的所有编码建立一个查找表。虽然工作量大但一劳永逸。6.3 Web页面在手机上显示错位视口与CSS的适配控制页面在电脑浏览器上显示正常但在手机上按钮挤成一团。原因是缺少viewport meta标签。加上meta nameviewport contentwidthdevice-width, initial-scale1.0之后页面按手机屏幕宽度渲染按钮自动换行。另外我把按钮的最小尺寸设为44x44像素符合手指点击的舒适范围。CSS方面我用的是flex布局按钮容器设置display: flex; flex-wrap: wrap; justify-content: center;这样在不同屏幕宽度下都能自动排列。颜色方案用了深色背景配浅色文字在客厅灯光较暗的环境下也能看清。7. 进阶玩法从单设备到全屋红外覆盖7.1 多设备管理与场景联动单个ESP32C3可以管理多个红外设备只要它们的编码不冲突。我在代码里定义了一个设备结构体包含设备名称、编码数组指针、数组长度。Web页面根据设备列表动态生成按钮。更进一步我加了“场景”功能一个按钮可以依次发送多个设备的编码比如“观影模式”会同时打开电视、关闭灯带、把空调调到24度。场景联动的实现很简单在服务器端定义一个场景数组每个场景包含一系列命令。收到场景请求后依次调用发射函数中间加50毫秒延时避免红外信号重叠。实测下来三个设备连续发射总耗时不到200毫秒体验很流畅。7.2 接入语音助手与自动化平台ESP32C3可以通过MQTT接入Home Assistant等自动化平台。我在固件里加了MQTT客户端把每个红外命令映射成一个MQTT主题。Home Assistant里配置一个开关发送MQTT消息到对应主题ESP32C3收到后发射红外信号。这样就能用语音助手控制空调了。MQTT的配置需要注意ESP32C3的内存有限MQTT库选轻量级的比如PubSubClient。连接时设置keepalive为60秒避免频繁重连。另外MQTT消息的payload尽量简短用一个字节表示命令ID减少解析开销。7.3 固件OTA升级不用拆机也能更新项目做多了之后每次改代码都要插USB线烧录很麻烦。我给固件加了OTA功能通过Web页面上传新的bin文件ESP32C3自己完成升级。ArduinoOTA库或者ElegantOTA库都能实现我用的ElegantOTA因为它跟AsyncWebServer集成得很好几行代码就能搞定。OTA升级时要注意上传过程中不能断电否则板子会变砖。另外固件分区要预留足够的空间ESP32C3的默认分区表可能不够需要在Arduino IDE里选择“Minimal SPIFFS”或者自定义分区表。我选的是“Huge APP”分区方案给固件留了1.5MB空间足够用了。8. 一些个人体会与后续折腾方向这个项目从起意到跑通前后花了大概两个周末。最大的感受是红外遥控这东西协议五花八门但原始数据重放几乎能通吃所有设备。与其花时间去逆向协议不如老老实实抓码、存码、重放。虽然看起来笨但稳定可靠维护成本低。另一个体会是ESP32C3的性价比确实高。十几块钱的板子能跑WiFi、能跑Web服务器、能发红外还能OTA升级。对于家庭自动化的入门玩家来说它是最好的起点之一。我后面打算把外壳用3D打印做一个把发射管和板子固定在一起贴在墙上彻底告别遥控器。如果你也在做类似的项目我的建议是先把最小闭环跑通一块板子、一个发射管、一个接收管抓一个按键的码重放成功。然后再逐步加Web界面、多设备、场景联动。不要一上来就想着做全屋控制那样容易卡在细节里出不来。先把一个设备控制好后面的都是复制粘贴的事。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑