注意,该码库仅供学习和研究,请勿用于商业用途,irext官网
想快速上手万能遥控器的同学可直接看第三节,前面是对irext的详细讲解,关于esp32如何发射/接收红外遥控信号,参考我另一篇文章:https://blog.csdn.net/weixin_44821644/article/details/108592858
支持红外遥控的设备,一般都会有自己的一套红外编码协议,而这个协议一般的厂家是不开源的。例如格力空调就有大约40套的编码协议。开发者如果要开发一个红外遥控器,就需要知道这些协议才能发射特定的信号。
网上的码库基本都需要公司进行合作,这对个人开发者不友好,irext就是一个开源的红外码库,他提供了多种电器,不同品牌的红外协议,把这些协议打包成二进制文件,并提供解码API,使开发者能解码打包的二进制代码,根据解码出的数据进行红外发射。该码库仅供学习和研究,请勿用于商业用途.
本文以esp32为例介绍irext的简单使用。首先需要获得二进制文件,并使用irext提供的解码API将其解码,解码会得到一个数组,这个数组保存的数据就是红外发射所需的脉冲序列。
例如:解析格力空调的二进制码库得到的数组如下:
[8967,4499,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,598,598,598,598,1671,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,598,598,1671,598,598,598,598,598,1671,598,598,598,19984,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,598,598,1671,598,598,598,40150,8967,4499,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,598,598,598,598,1671,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,1671,598,1671,598,598,598,598,598,1671,598,598,598,19984,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,1671,598,1671,598,598,598,598,598]
第一个数据8969表示的是一个持续时间为8967us的电平,第二个数据表示持续时间为4499us的电平,熟悉主流红外协议的同学马上就知道,这两个数据组成了红外协议的起时码。
有了这个数组,我们就能在自己的设备上产生特定的脉冲序列。
IRext提供了多种方式获取二进制文件,具体如下:
直接下载指定的二进制文件到电脑,或者点我下载码库二进制文件包
优点是简单暴力,但是需要再烧录到嵌入式设备中。
IRext支持Web API ,用户可以通过公有云发起http连接,获取电器分类,电器品牌以及具体的电器品牌下所有的红外编码二进制文件等。
具体的API可以查看其文档https://cc.irext.net/doc/
解码方式有在线解码与离线解码,在线解码使用的是Web API,具体参考文档,本文主要介绍离线解码。
离线解码需要使用解码仓库:https://irext.tech/irext/core
设备有文件系统下,以下代码实现了将my_ir_code_file.bin文件解码,解码出的数组存放在user_data中,decode_len是数组的长度。category是电器类型代号,sub_category命令类编码的样本类型。(电器类型代号在文末)
ir_file_open(category, sub_category, "/path/my_ir_code_file.bin");
uint16_t decode_len=ir_decode(key_code, user_data, ac_status, 0);
ir_close();
这里重点介绍一下ac_status,通过对ac_status的成员赋值,可以产生对应数组。例如以下的代码,产生的是,制冷模式,打开,26℃,开启扫风的红外命令数组。
ac_status.ac_mode = AC_MODE_COOL;
ac_status.ac_power = AC_POWER_OFF;
ac_status.ac_temp = AC_TEMP_26;
ac_status.ac_wind_dir = AC_SWING_ON;
ac_status.ac_wind_speed = AC_WS_LOW;
使用ir_binary_open()代替ir_file_open(),其他的内容与文件系统下的操作一样。
ir_binary_open(category, sub_category, buffer, buffer_length);
使用esp32进行红外发射的实现,我以前的博客讲过,ESP32 红外遥控 发射与接收的实现 IR_TX IR_RX 基于idf3.3,接下来就在这个博客的基础上,用irext解析出来的数组来构建item。
首先将irext_core解码仓库
添加进项目,然后将二进制文件烧录进esp32的文件系统,最后在代码中解码出数组,使用数组构建item
。
github上下载该仓库 https://github.com/irext/core,如果速度太慢,解决办法:提升github下载速度最新解决方案
然后添加到项目文件夹下,记得修改CMakeLists.txt
的内容。
在main.c中添加,ir_decode.h
是irext解码的接口。是我们需要使用的唯一头文件。
#include "ir_decode.h"
如何烧录spiffs文件系统请参考:三分钟上马 ESP32 spiffs文件系统
例如将xxx.bin放入根目录下的xxx文件夹,然后烧录进esp32,使用时路径名称:
char *filepath = "/spiffs/xxx/xxx.bin";
以下是一个示例的流程,具体逻辑看注释。
uint16_t decoded[1024] = { 0 }; //二进制文件解码的数据
t_remote_ac_status ac_status; //编码红外的状态(用于开关温度调节)
void demo()
{
char *filepath = "/spiffs/xxx/xxx.bin";
ac_status.ac_mode = AC_MODE_COOL;
ac_status.ac_power = AC_POWER_OFF;
ac_status.ac_temp = AC_TEMP_26;
ac_status.ac_wind_dir = AC_SWING_ON;
ac_status.ac_wind_speed = AC_WS_LOW;
ir_file_open(1,0,filepath); //打开文件。空调代号1
uint16_t decode_len = ir_decode(KEY_AC_POWER, decoded, &ac_status, 0); //获得编码数组
ir_close(); //关闭文件
//格力的代码会发送两帧一模一样的数据,这里我只取第一帧
if(decode_len > 200)
{
decode_len = (decode_len + 1) / 2;
}
item_num = (decode_len / 2); //item数量是数组长度的一半
size = (sizeof(rmt_item32_t) * item_num);
item = (rmt_item32_t *)malloc(size);
irext_build(item, item_num); //根据数组构建item
rmt_write_items(tx_channel, item, item_num, true); //将item集合写入通道对应的RAM并进入阻塞
rmt_wait_tx_done(tx_channel, portMAX_DELAY); //等待发送完成 进入阻塞
free(item);
}
主要的是irext_build()函数,nec_fill_item_level()在之前的文章也提过了。
/*
* irext_build
* brief:通过irext构建item 使用全局变量
*/
static void irext_build(rmt_item32_t* item,size_t item_num)
{
int i = 0;
nec_fill_item_level(item, decoded[0], decoded[1]);
for (i = 1; i < item_num;i++)
{
item++;
nec_fill_item_level(item, decoded[2*i], decoded[2*i + 1]);
}
}
nec_fill_item_level()接收的参数是单位是us,所以我直接将数组里的数据放进去就行
/*
* @brief 填充item的电平和电平时间 需要将时间转换成计数器的计数值 /10*RMT_TICK_10_US
*/
static inline void nec_fill_item_level(rmt_item32_t* item, int high_us, int low_us)
{
item->level0 = 1;
item->duration0 = (high_us) / 10 * RMT_TICK_10_US;
item->level1 = 0;
item->duration1 = (low_us) / 10 * RMT_TICK_10_US;
}
本文的例子只展示了如何在esp32上使用irext,其他设备也是可以的,irext支持的平台很多。
irext可能是唯一一个开源的红外码库,使用也方便,对开发者还是非常友好的,但是网上的相关资料有点少,希望你点个赞,让更多使用红外的开发者能发现这个宝库。
{
"id": 1,
"name": "空调",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 2,
"name": "电视机",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 3,
"name": "机顶盒",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 4,
"name": "网络盒子",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 5,
"name": "IPTV",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 6,
"name": "DVD",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 7,
"name": "风扇",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 8,
"name": "投影仪",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 9,
"name": "音响",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 10,
"name": "灯",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 11,
"name": "机顶盒",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 12,
"name": "扫地机器人",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 13,
"name": "空气净化器",
"status": 1,
"updateTime": "2016-11-27 11:00:00"
},
{
"id": 14,
"name": "Dyson",
"status": 1,
"updateTime": "2017-01-20"
}