零知开源——基于ESP8266(ESP-12F)驱动YS-IR05F红外控制空调
通过网页界面和OLED显示屏实时显示空调状态,打造一个智能红外遥控系统。
目录
一、硬件设计
1.1 硬件清单与选型
1.2 接线方案
1.3 详细接线图
1.4 接线实物图
二、软件设计
2.1 所需库依赖
2.2 初始化框架
2.3 温度设置及展示
2.4 Web服务器实现
2.5 编码库详解
三、操作过程及展示
3.1 红外编码录制与处理
3.2 系统搭建与调试
3.3 效果展示
3.4 视频操作展示
四、YS-IR05F红外模块通信协议
4.1 数据包格式
4.2 指令集说明
4.3 工作原理
五、常见问题解答
Q1:红外编码录制不成功怎么办?
Q2:网页控制无响应?
Q3:红外控制距离短?
(1)项目概述
本项目基于零知ESP8266开发板(ESP-12F模组) 和YS-IR05F红外编解码模块,构建了一套完整的智能空调遥控系统。系统不仅支持通过Web界面远程控制TCL空调的开关和温度调节,还集成了OLED显示屏用于实时状态显示。本项目深入讲解了红外编码的获取方法、ESP8266与红外模块的通信协议、Web服务器搭建以及多外设驱动整合。
(2)项目亮点
>同时提供Web网页控制和OLED本地显示,支持移动端和PC端访问
>详细讲解如何捕获、解析和重发红外编码
>使用串口通信协议与YS-IR05F模块进行数据交互
>采用现代化CSS设计,适配各种屏幕尺寸
(3)项目难点及解决方案
问题分析:不同空调品牌/型号的红外编码需要正确解析才能有效重发
解决方案:使用USB转TTL模块 + STC-ISP软件录制原始红外数据,替换operation.h
中的数组。
一、硬件设计
1.1 硬件清单与选型
组件 | 型号 | 数量 | 选型理由 |
---|---|---|---|
主控制器 | 零知ESP8266(ESP-12F) | 1 | 集成WiFi功能,GPIO丰富,成本低廉 |
红外模块 | YS-IR05F | 1 | 支持学习和发射,兼容多种红外协议 |
OLED显示屏 | SSD1306 0.96寸 | 1 | I2C接口,低功耗,高对比度 |
USB转TTL | CH340G | 1 | 用于红外编码录制和调试 |
杜邦线 | 母对母 | 若干 | 方便连接和调试 |
1.2 接线方案
零知ESP8266(ESP-12F) | SSD1306 OLED显示屏 | YS-IR05F红外模块 |
---|---|---|
3V3 | VCC | 3.3V |
GND | GND | GND |
D4(软串口RX) | / | TXD |
D5(软串口TX) | / | RXD |
SCL | SCL | / |
SDA | SDA | / |
🔌 注意:YS-IR05F的KEY引脚可不接,我们使用串口指令进入学习模式。
1.3 详细接线图
1.4 接线实物图
ESP8266与YS-IR05F通过杜邦线连接,OLED显示屏通过I2C连接。
二、软件设计
2.1 所需库依赖
Adafruit SSD1306:用于OLED显示
Adafruit GFX Library:图形库依赖
ESPAsyncWebServer:异步Web服务器库
SoftwareSerial:软件模拟串口依赖
2.2 初始化框架
#include "operation.h"
#include "ESP8266WiFi.h"
#include "SoftwareSerial.h"
#include <ESPAsyncWebServer.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>// 创建软件串口对象,假设使用GPIO4(RX)和GPIO5(TX)
SoftwareSerial mySerial(D4, D5); // RX, TXWiFiServer wifi_server(80);
String status = "空调关闭"; //默认状态
String statu = "Pausing"; //默认状态
int temperature = 20;
String header;#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);//配置自己的WIFI名称和密码
const char* ssid = "";
const char* password = "";//读取JSON
String val = "";void setup() {Serial.begin(115200);mySerial.begin(9600); // 初始化软件串口,波特率9600Wire.begin(); // SDA, SCLoled.begin(SSD1306_SWITCHCAPVCC, 0x3C);oled.clearDisplay();oled.setTextSize(1);oled.setTextColor(WHITE);oled.setCursor(0, 0);oled.println("Starting...");oled.display();Serial.print("Connecting to ");Serial.println(ssid);WiFi.mode(WIFI_STA);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.println("Connecting to WiFi..");oled.print(".");oled.display();}Serial.println(WiFi.localIP());oled.clearDisplay();oled.setCursor(0, 0);oled.println("IP: " + WiFi.localIP().toString());oled.display();wifi_server.begin();Serial.println("红外控制就绪,使用软件串口通信");
}
库文件引用、变量参数及设备初始化
2.3 温度设置及展示
void set_TCL(int temperature) {switch (temperature) {case 16: mySerial.write(cold_16, 236); break;case 17: mySerial.write(cold_17, 236); break;case 18: mySerial.write(cold_18, 236); break;case 19: mySerial.write(cold_19, 236); break;case 20: mySerial.write(cold_20, 236); break;case 21: mySerial.write(cold_21, 236); break;case 22: mySerial.write(cold_22, 236); break;case 23: mySerial.write(cold_23, 236); break;case 24: mySerial.write(cold_24, 236); break;case 25: mySerial.write(cold_25, 236); break;case 26: mySerial.write(cold_26, 236); break;case 27: mySerial.write(cold_27, 236); break;case 28: mySerial.write(cold_28, 236); break;case 29: mySerial.write(cold_29, 236); break;case 30: mySerial.write(cold_30, 236); break;default:;}// 更新OLED显示oled.clearDisplay();oled.setCursor(0, 3);oled.println("TCL AC Control");oled.println(" ");oled.println("Status: " + statu);oled.println("Temp : " + String(temperature) + " C");oled.display();
}
2.4 Web服务器实现
void loop() {WiFiClient client = wifi_server.available();if (client) {String currentLine = "";while (client.connected()) {if (client.available()) {char c = client.read();header += c;if (c == '\n') {if (currentLine.length() == 0) {client.println("HTTP/1.1 200 OK");client.println("Content-type:text/html");client.println("Connection: close");client.println();if (header.indexOf("GET /TCL/on") >= 0) {Serial.println("空调开启");mySerial.write(on, 238);status = "空调开启";statu = "Running";delay(1000);temperature = 20;mySerial.write(cold_20, 236);// 更新OLED显示oled.clearDisplay();oled.setCursor(0, 3);oled.println("TCL AC Control");oled.println(" ");oled.println("Status: " + statu);oled.println("Temp : " + String(temperature) + " C");oled.display();}if (header.indexOf("GET /TCL/off") >= 0) {Serial.println("空调关闭");mySerial.write(off, 236);status = "空调关闭";statu = "Pausing";oled.clearDisplay();}if (header.indexOf("GET /TCL/descend") >= 0) {if (temperature > 16) temperature -= 1;Serial.print("设置空调温度为:");Serial.println(temperature);set_TCL(temperature);}if (header.indexOf("GET /TCL/ascend") >= 0) {if (temperature < 30) temperature += 1;Serial.print("设置空调温度为:");Serial.println(temperature);set_TCL(temperature);}// 网页界面代码保持不变client.println("<!DOCTYPE html><html lang='zh-CN'>");client.println("<head>");client.println("<meta charset='UTF-8'>");client.println("<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'>");client.println("<title>TCL空调控制</title>");client.println("<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css'>");client.println("<style>");client.println("* { margin: 0; padding: 0; box-sizing: border-box; }");client.println("body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d); height: 100vh; display: flex; justify-content: center; align-items: center; color: #fff; }");client.println(".container { background: rgba(0, 0, 0, 0.7); border-radius: 20px; padding: 30px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); max-width: 400px; width: 90%; text-align: center; }");client.println(".header { margin-bottom: 20px; }");client.println(".header h1 { font-size: 28px; margin-bottom: 5px; }");client.println(".status { font-size: 18px; margin: 10px 0; }");client.println(".status span { color: #4ECDC4; font-weight: bold; }");client.println(".temp-display { background: rgba(255, 255, 255, 0.1); border-radius: 50%; width: 180px; height: 180px; margin: 20px auto; display: flex; flex-direction: column; justify-content: center; align-items: center; border: 5px solid #4ECDC4; }");client.println(".temperature { font-size: 48px; font-weight: bold; }");client.println(".unit { font-size: 24px; margin-top: 5px; }");client.println(".controls { display: flex; justify-content: space-between; margin: 20px 0; }");client.println(".btn { background: #4ECDC4; border: none; border-radius: 50%; width: 60px; height: 60px; color: white; font-size: 24px; cursor: pointer; transition: all 0.3s; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); display: flex; justify-content: center; align-items: center; }");client.println(".btn:hover { background: #2a8c85; transform: translateY(-3px); }");client.println(".btn:active { transform: translateY(1px); }");client.println(".power-btns { display: flex; justify-content: space-around; margin-top: 20px; }");client.println(".power-btn { padding: 12px 25px; border: none; border-radius: 30px; font-size: 16px; font-weight: bold; cursor: pointer; transition: all 0.3s; }");client.println(".power-on { background: linear-gradient(to right, #00b09b, #96c93d); color: white; }");client.println(".power-off { background: linear-gradient(to right, #ff416c, #ff4b2b); color: white; }");client.println(".power-btn:hover { opacity: 0.9; transform: translateY(-2px); }");client.println("@media (max-width: 480px) { .container { padding: 20px; } .temp-display { width: 150px; height: 150px; } .temperature { font-size: 40px; } }");client.println("</style>");client.println("</head>");client.println("<body>");client.println("<div class='container'>");client.println("<div class='header'>");client.println("<h1><i class='fas fa-wind'></i> TCL空调控制</h1>");client.println("<div class='status'>状态: <span>" + status + "</span></div>");client.println("</div>");client.println("<div class='temp-display'>");client.println("<div class='temperature'>" + String(temperature) + "</div>");client.println("<div class='unit'>°C</div>");client.println("</div>");client.println("<div class='controls'>");client.println("<a href='/TCL/descend' class='btn'><i class='fas fa-minus'></i></a>");client.println("<a href='/TCL/ascend' class='btn'><i class='fas fa-plus'></i></a>");client.println("</div>");client.println("<div class='power-btns'>");client.println("<a href='/TCL/on' class='power-btn power-on'><i class='fas fa-power-off'></i> 开启</a>");client.println("<a href='/TCL/off' class='power-btn power-off'><i class='fas fa-power-off'></i> 关闭</a>");client.println("</div>");client.println("</div>");client.println("</body>");client.println("</html>");client.println();break;} else {currentLine = "";}} else if (c != '\r') {currentLine += c;}}}header = "";client.stop();// Serial.println("");}
}
发送ESP8266红外控制空调的静态网页页面
2.5 编码库详解
#ifndef OPERATION_H
#define OPERATION_H#include <Arduino.h>// TCL空调红外编码数据
// 注意:这些编码需要根据您的具体空调型号进行录制和替换const uint8_t on[] = { 0xFD, 0xFD, 0x30, 0x03, 0x79, 0xE3, 0x00, 0x34, 0x5F, 0x00, 0xC1, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x0B, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x12, 0x22, 0x12, 0x21, 0x12, 0x12, 0x21, 0x12, 0x11, 0x22, 0x12, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x21, 0x12, 0x22, 0x22, 0x21, 0x11, 0x12, 0x22, 0x21, 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x12, 0x21, 0x23, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x76, 0x3E, 0x15, 0xDF, 0xDF};const uint8_t off[] = { 0xFD, 0xFD, 0x30, 0x03, 0x79, 0xE3, ... , 0xDF, 0xDF};//制冷模式温度设置(16-30度)
const uint8_t cold_16[] = { 0xFD, 0xFD, 0x30, 0x03, 0x79, 0xE3, ... , 0xDF, 0xDF};//其他设置编码省略#endif
🔧 如何获取这些数据?
使用USB转TTL连接YS-IR05F,按下KEY键进入学习模式,用遥控器对准发射头按下按键,STC-ISP串口助手会显示236字节的16进制数据,复制并替换相应数组即可。
数据格式转换示例
(1)原始串口数据:
FD FD 30 03 79 E3 ... DF DF
(2)转换为C数组:
const uint8_t cool_24[] PROGMEM = {
0xFD, 0xFD, 0x30, 0x03, 0x79, 0xE3, ... , 0xDF, 0xDF };
三、操作过程及展示
3.1 红外编码录制与处理
(1)硬件连接
使用USB转TTL模块连接YS-IR05F
VCC接3.3V,GND接GND,TXD接RXD,RXD接TXD
连接红外接收头到YS-IR05F的IR_IN接口
(2)软件配置
>打开STC-ISP软件或其他串口调试工具
>选择正确的COM口,设置波特率为9600,数据位8,停止位1,无校验位
>选择"十六进制显示"模式
接收缓冲区接收236个字节红外编码,将原始串口数据转换为C数组格式后,替换operation.h库文件中相关操作的对应数组
3.2 系统搭建与调试
(1)软件烧录
修改代码中的WiFi配置,选择正确的开发板和端口,编译并上传代码
(2)系统测试
观察OLED显示的系统状态,打开浏览器访问ESP8266的IP地址,测试各项控制功能
3.3 效果展示
(1) Web控制界面
网页控制空调开启后设置初始温度为20℃的页面
(2) OLED显示效果
TCL AC Control
Status: Running
Temp : 20℃
3.4 视频操作展示
ESP8266驱动YS-IR05F红外控制空调
网页控制ESP8266红外发送开启空调、调节温度和关闭空调等操作指令
四、YS-IR05F红外模块通信协议
4.1 数据包格式
模块使用固定的串口通信协议:
波特率:9600bps、数据位:8位、停止位:1位、校验位:无
数据包格式:
[起始码] [起始码] [命令码] [数据段] [结束码][结束码]0xFD 0xFD 0x30 228字节 0xDF 0xDF
4.2 指令集说明
>学习指令:0xFD 0xFD 0x30 0x03 + 228字节任意数据 + 0xDF 0xDF
>发射指令:直接发送236字节红外数据
4.3 工作原理
YS-IR05F采用高性能红外处理芯片,能够接收、解析和发射红外信号。其工作流程如下:
(1)接收模式:红外接收头将38KHz的调制信号转换为电信号,经过放大、滤波和解调后,得到原始数字信号
(2)学习模式:模块记录原始波形的时序信息,转换为236字节的数据包
(3)发射模式:将数据包还原为红外波形,通过发射管发出
五、常见问题解答
Q1:红外编码录制不成功怎么办?
A:可能原因及解决方案:
距离太近或太远,保持50cm左右距离
环境光干扰,避免在强光环境下录制
遥控器电池电量不足,更换电池
串口设置错误,确认波特率为9600,十六进制显示
Q2:网页控制无响应?
A:排查步骤:
重启ESP8266,检查OLED显示的IP地址是否正确
确认设备与手机/电脑在同一局域网
检查防火墙设置,是否阻止了局域网访问
Q3:红外控制距离短?
A:增强方法:
使用多个红外发射管并联,增加发射功率
调整发射管角度,对准空调接收器
检查电源供电能力,确保工作电压稳定
项目资源:
YS-IR05F使用手册、串口助手、源码下载链接: ESP8266红外控制
本项目成功实现了一套基于ESP8266和YS-IR05F的智能空调控制系统。如有疑问或建 议,欢迎在评论区留言讨论!