前言
好久没更新了哈,并不是我停下了学习探索的脚步,而是有点懒,没有写博客了。
最近天气热了,宿舍要开空调,但是遥控器坏了,全宿舍能开空调的就两个人,就会很不方便(万一都不在就开不了咯)。然后之前也是做过一个门锁,能够实现刷卡开门,就想着再弄个遥控器吧,反正能用的上。
一、格力红外编码协议
网上介绍的挺多哈,其实重点了解一下电平的定义就可以,下面我也总结了。可以look look。
1. 电平定义
0的电平宽度为:600us低电平+600us高电平,
1的电平宽度为:600us低电平+1600us高电平
起始码S电平宽度为:9000us低电平+4500us高电平
连接码C电平宽度为:600us低电平+20000us高电平
下面这些可能你在其他博客见不到,我自己定义,具体什么意思什么作用呢?你看到下面就知道了。
长连接码CC电平宽度为:600us低电平+40000us高电平
结束码P电平宽度为:600us低电平+0us高电平
2. 完整通讯顺序
网上很多都是基于35+32的模式,其实这个理解并不是完全的正确,我觉得实际的通讯是32+3+32的模式。
这里我先给出红外一次发送的完整格式的通讯顺序:
起始码S + 4字节数据 + 3个固定数据的bit位 + 连接码C + 4字节数据 + 长连接码CC + 起始码S + 4字节数据 + 3个固定数据的bit位 + 连接码C + 4字节数据 + 结束码P
为什么说是32+2+32的模式呢,红外一次发送的完整格式可以拆分成两串指令(有起始信号S就代表一个指令,完整格式有两个起始信号S,所以是两串指令),一串指令发送8个字节,但是并不是8个字节的数据连着发送哦。而是将这8个字节拆分两个4字节,并且在中间,插入3个bit位的数据:010。4个字节是32个bit位,所以就得出32+3+32。有些空调只发送第一串指令就可以响应,但是建议是发送完整的格式。
二、数据定义
通过IRRemoteESP8266的项目源码的ir_Gree.h文件,找到数据结构的定义:
struct {
// Byte 0
uint8_t Mode :3; //模式
uint8_t Power :1; //开关
uint8_t BasicFan :2; //风速
uint8_t SwingAuto :1; //自动扫风
uint8_t :1;
// Byte 1
uint8_t Temp :4; //温度
uint8_t :4;
// Byte 2
uint8_t :4;
uint8_t Turbo :1; //强劲
uint8_t Light :1; //灯光
uint8_t IonFilter :1; //负离子
uint8_t XFan :1; //根据模式的不同,有不同的含义。当模式为除湿和制冷模式时,这一位表示是否启用干燥模式,0为关闭,1为启用。而当模式为制热时,这一位代表是否启用电辅热,是反过来的,0代表启用电辅热,而1则代表的是关闭电辅热。
// Byte 3
uint8_t :4;
uint8_t :2; //可能与定时器相关,通常是01
uint8_t :2; //命令结束 01
// (B010 marker and a gap of 20ms)
// Byte 4
uint8_t SwingV :4;
uint8_t SwingH :1;
uint8_t :3;
// Byte 5~6
uint8_t pad0[2]; //定时器相关,通常为0
// Byte 7
uint8_t :4; //用于定时器模式
uint8_t Sum1 :4; //第一个校验位
第一部分的校验码,四个bits,计算方式为:
基础值为10,然后将前面四个字节的低位相加,再加上紧接着三个字节的高位相加,最后结果对256取余,然后取结果的低4位。如果定义为uint8_t的话,溢出之后相当于是取余了,可以不用取余。
//间隔40ms
// (重新发送起始信号)
// Byte 8~10
uint8_t pad1[3]; // Repeat of byte 0~2
// Byte 11
uint8_t :4;
uint8_t :2; // 可能与定时器有关 (通常设置为 11)
uint8_t :2; // 命令块结束 (设置为01)
// (B010 marker and a gap of 20ms)
// Byte 12
uint8_t :1; // 睡眠
uint8_t :6; // (在休眠模式下使用, 通常全0 0b000000)
uint8_t Quiet :1;
// Byte 13
uint8_t :8; // (通常 0x00)
// Byte 14
uint8_t :4; // (通常 0b0000)
uint8_t Fan :3;
// Byte 15
uint8_t :4;
uint8_t Sum2 :4; // 前一个字节的校验和 (8-14)第二部分的校验码,计算方式和第一部分的一样,只不过起始位置是从第八个字节开始算的。
};
具体哪些bit位表示什么功能,我在上面也标识了,没有名字的我猜应该是保留的。
从上面也可以看到,从Byte0-Byte15一共有16
个字节,也就是说这就是完整通信所发送的所有数据(8+8嘛)。Byte0-Byte7是第一串指令发送的数据,Byte8-Byte15是第二串指令发送的数据,而每串指令都会带有一个校验码Sum,分别在Byte7
的高四位和Byte15
的高四位。
三、校验公式计算环节
网上很多的计算公式其实都是错的,也导致我在做这个的时候,一直不行,一气之下,我找到了IRRemoteESP8266中ir_Gree的源码的校验计算的部分。
没错,就是这个函数,关于计算校验码的,不难看出,sum首先有个初始值,然后不断累加。我通过上下文得出最后的计算结论:
校验码1的计算和填充
:
Byte7 |= (10 + Byte0到Byte3的低四位的和 + Byte4到Byte6高四位的和) & 0x0F;
校验码2的计算和填充
:
Byte15 |= (10 + Byte8到Byte11的低四位的和 + Byte12到Byte14高四位的和) & 0x0F;
我可是有捕获数据验证过的 [狗头]。
四、代码实现部分
好了好了,最想知道的环节来了,哔哩吧啦说那么多,这估计也是你们最想要的环节了。像格力这种厂家,ardinuo里面肯定有库实现的啦,底层就不用我们自己写咯。所以就算前面那些你看不懂,也一样可以调库(我一开始并没有直接调库,学习嘛,学的细致一点)。
使用的就是IRremoteESP8266库
,前面有提过啦。我们需要的头文件是ir_Gree.h,当然里面空调的品牌可多了,一大堆,你想控制什么空调就去引入具体的头文件就好了。(我以格力为例)
我简单给段示例代码,估计你就能够看懂了。
#include <Arduino.h>
#include <Gree.h>
#define IR_GPIO 4
IRGreeAC gree_ac(IR_GPIO);
void setup() {
Serial.begin(115200);
gree_ac.begin();
delay(1000);
}
void loop() {
gree_ac.on(); //打开空调
gree_ac.send(); //发送红外
delay(2000);
}
}
具体设置模式啊,设置温度这些,看.h文件就好啦。
最后
到这里就结束咯,如果需要我空调遥控器的源码,关注这篇博客就好了,后续我会将资源网址发布出来(因为还没写好,现在发不了)