Arduino上的IR转码器

由红外遥控器控制的设备已紧密集成到我们的生活中。有时电视或古老的音频系统的遥控器丢失了,从旧时代开始购买新的遥控器已经不可能了。不一定总是可以订购一个新的遥控器,也可以制作一个克隆,但是有了捐赠者或有关它的信息,您可以制造一个转换器。这种代码转换器将从一个控制台接收命令,并将其转换为另一种格式。

对于Arduino,有一个出色的IRemote,使构建各种IR控制系统非常容易。但是,即使解决了诸如转码器之类的简单任务,总会有一些有趣的问题需要解决。
因此,对于初学者而言,我们需要集成的红外接收器,例如TSOP312或对应的Arduino屏蔽。不要忘记,有很多红外接收器,它们的引脚排列随机变化。例如,我使用了某种与TSOP382匹配的无名元素,但是在简化情况下,没有分隔键。

我们需要组装好的电路来从两个控制台接收命令代码,不幸的是,从丢失了控制台的设备中删除命令更为复杂。您仍然可以找到供体遥控器,使用通用遥控器选择代码(为什么要使用转码器,因为遥控器已经出现了?),或者尝试使用IR代码使用Internet数据库中的数据。对我来说最简单的事情是使用一个应用程序来模拟我需要的遥控器。
要读取数据,我们使用IRremote交付中的IRrecvDumpV2示例,如果您的遥控器属于可识别的库,则您不需要原始扫描结果,尽管例如LG遥控器被错误地识别为Samsung,并且当我尝试通过sendLG发送命令时不起作用。
在扰流器下获得的数据示例:
Encoding: SAMSUNG
Code: 34346897 (32 bits)
Timing[67]:
+4450, -4350 + 600, — 500 + 600, — 500 + 600, -1600
+ 600, -1600 + 600, — 500 + 600, -1600 + 600, — 500
+ 600, — 500 + 600, — 500 + 600, — 500 + 600, -1600
+ 600, -1600 + 600, — 500 + 600, -1600 + 600, — 500
+ 600, — 500 + 600, — 500 + 600, -1600 + 600, -1600
+ 600, — 500 + 600, -1600 + 600, — 500 + 600, — 500
+ 600, — 500 + 550, -1650 + 550, — 550 + 550, — 550
+ 550, -1650 + 550, — 550 + 550, -1650 + 550, -1600
+ 600, -1600 + 600
unsigned int rawData[67] = {4450,4350, 600,500, 600,500, 600,1600, 600,1600, 600,500, 600,1600, 600,500, 600,500, 600,500, 600,500, 600,1600, 600,1600, 600,500, 600,1600, 600,500, 600,500, 600,500, 600,1600, 600,1600, 600,500, 600,1600, 600,500, 600,500, 600,500, 550,1650, 550,550, 550,550, 550,1650, 550,550, 550,1650, 550,1600, 600,1600, 600}; // SAMSUNG 34346897
unsigned int data = 0x34346897;

如果捕获显示消息“ IR码太长。编辑IRremoteInt.h并增加RAWLEN”该库将必须修复一点-增加命令缓冲区的大小。对于您计划控制的控制台,知道32位命令代码就足够了,值得注意的是,在某些遥控器上,按下键的代码不同于按下和释放模式下的同一按钮。这些按钮将需要两个值。我们将收到的代码减少到一个方便您使用的表中。在同一表中,我们以原始形式保存了供体遥控器的代码。
我们将红外LED连接到Arduino,并编写一个简单程序,该程序接收具有给定代码的红外信号,并通过LED发送另一个代码。选择82电阻作为当前可用的电阻。对于嵌入式设备,可以安全地将其增加到200欧姆,如果发射器应是远程发射器,则必须使用简单的晶体管级联对其进行补充,否则来自Arduino的电流将不足。

如果两个遥控器都有命令代码,则代码转换器代码采用以下形式

void loop() {
if (irrecv.decode(&results)) {
    switch(results.value){
      case(0x845E5420):{
	irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz);
      }break;
    }
  }
  irrecv.resume();
  irrecv.enableIRIn();
}

我们开始绘制草图,并将其填充到Arduino中。奇怪的是,在开始执行一个命令之后,所有后续设备都将被忽略。为了不影响调试,我们在周期的第13个引脚上添加了一个闪烁的指示灯,并看到在第一次尝试发送命令后,板卡冻结了。好吧,这意味着在一个项目中同时使用发送和接收IR信号时,并不是所有事情都那么顺利。在使用的计时器中稍作改动后,事实证明,由于发送和接收都使用一个公共计时器,因此在发送开始之后,代码必须等待直到发送结束。您可以凭经验添加一个半秒的延迟(延迟(500)),然后一切都会起作用,但是如果知道我们国家的原始数据是以毫秒为单位的时间样本,则可以简单地添加一个具有延迟的send函数。 Irsend模块中甚至还有一个合适的custom_delay_usec函数,我最初使用不正确,却忘记将延迟乘以库中的USECPERTICK系数(50毫秒)。

void sendDelayed(unsigned int array[]){
  irsend.sendRaw(array, sizeof(array) / sizeof(array[0]), khz);
    int array_size = sizeof(array) / sizeof(array[0]);
    for(int i=0;i<array_size;i++){
      // Using usec, so multiply raw to usec
      irsend.custom_delay_usec(array[i]*USECPERTICK);
    }
}

这样的代码可以正常工作,在切换时,只需输入必要数量的按钮外壳即可,一切正常。但是它不在那里。 RawData代码被编写为一个int数组,并且我们在微控制器上有一个平台。五个长度为100个元素的命令已经占用了变量的内存。但是遥控器上有25个按钮。
如果您不使用数据的原始表示形式就没有问题,为此,该库可以将命令发送到众所周知的协议,例如,对于与Sony兼容的遥控器,它是sendSony。该库已经实现了知名制造商的遥控器,但是我无法立即处理我的遥控器。因此,我们继续采用更原始的方法来节省内存,这将对那些拥有完全非标准遥控器的人有所帮助。
我想到的第一件事不是将rawData设置为int形式,而是切换为byte形式。此数组中的所有值都是由计时器以50毫秒的周期读取IR信号的结果,并且由于此数据是50的倍数,因此将它们除以50将不会丢失任何内容。上限将限制为50 * 255 = 12750,这是12秒,即使需要解码悠闲的摩尔斯电码也足够了。
库中增加了一种接受字节输入的方法,从而将内存消耗减少了一半

IRsend::sendRaw (byte buf[],  unsigned int len,  unsigned int hz)

只有Arduino的变量存储空间只有2 KB,最多40条命令(每条50字节)。我们需要更多的内存。然后,我们将从命令段中提取该内存。在发送一系列作业之前,保留一个足够大的数组并填充它就足够了。总的来说,在代码段中的单个命令上将花费大约100个字节,但是毕竟,我们至少有10 KB的代码空间。因此,对于具有一百个按钮的普通遥控器而言,我们已经足够了。
为了避免用手塞住分配,将示例IRrecvDumpRawByte添加到库中,该库不仅以字节的形式显示原始数据,还以分配块的形式显示原始数据
扰流板下的示例
rawData[0]=87;rawData[1]=87;rawData[2]=10;rawData[3]=9;rawData[4]=10;rawData[5]=9;rawData[6]=10;rawData[7]=10;rawData[8]=10;rawData[9]=9;rawData[10]=10;rawData[11]=9;rawData[12]=10;rawData[13]=29;rawData[14]=10;rawData[15]=9;rawData[16]=10;rawData[17]=9;rawData[18]=10;rawData[19]=10;rawData[20]=10;rawData[21]=9;rawData[22]=10;rawData[23]=9;rawData[24]=10;rawData[25]=10;rawData[26]=10;rawData[27]=9;rawData[28]=10;rawData[29]=9;rawData[30]=10;rawData[31]=10;rawData[32]=10;rawData[33]=9;rawData[34]=10;rawData[35]=86;rawData[36]=10;rawData[37]=9;rawData[38]=11;rawData[39]=9;rawData[40]=10;rawData[41]=9;rawData[42]=10;rawData[43]=9;rawData[44]=10;rawData[45]=28;rawData[46]=10;rawData[47]=29;rawData[48]=10;rawData[49]=28;rawData[50]=10;rawData[51]=9;rawData[52]=10;rawData[53]=28;rawData[54]=10;rawData[55]=10;rawData[56]=10;rawData[57]=9;rawData[58]=10;rawData[59]=28;rawData[60]=10;rawData[61]=10;rawData[62]=10;rawData[63]=9;rawData[64]=10;rawData[65]=9;rawData[66]=10;rawData[67]=28;rawData[68]=10;rawData[69]=9;rawData[70]=11;rawData[71]=27;rawData[72]=10;rawData[73]=29;rawData[74]=10;rawData[75]=9;rawData[76]=10;

示例中,名称为DaewooR40A01toDVDHR755Transcoder的草图示例允许您使用Daewoo R40A01遥控器控制Samsung DVD HR-755。没有人接受将请求添加到常规分支的Pull请求,因此您可以从fork下载经过修改的库
重做记录器上的许多照片











在这只猫的底下是Arduino Nano集成到此DVD刻录机中的照片,Arduino Mini占用的空间肯定要小得多,但只有Nano可用。我从控制面板上取电。来自内置接收器的信号已连接到Arduino,并且将位于第一个接收器另一侧的另一个IR接收器并行焊接到该接收器。在相同的安装位置上,将IR LED焊接到其上。原则上,可以避免这种重复-但来自IR接收器的信号是反相的-因此我无法将TTL信号直接传送到设备-并且我没有开始将逻辑或晶体管上的反相器反相。

尽管在我的情况下,原始数据运行良好,但是对其他家用设备的实验表明,在尝试控制特定设备时并非所有捕获的信号都能正常工作。打开空调的命令不起作用,尽管如果已经打开它,则模式更改也可以正常工作。 LG的专栏也拒绝接受原始命令,但是对通过sendSamsung发送代码的反应很好。同时,从熟人那里收集的五台电视对原始数据的反应非常好。我尝试了使用不同信号频率的选件-它没有帮助。也许问题出在50 ms的信号采样率上。从三星格式小组在LG技术上的可操作性来看,应通过类似于ir_LG.cpp ir_JVC.cpp ir_Dish.cpp将该协议形式化为单独的模块,为特定设备选择零和一的标头和编码参数。大概解析此类协议的编写将成为本文的一个不错的话题。

好吧,此外,用于Arduino的第二个大型IR库是IRLib它具有类似的功能,甚至还有一个现成的模块,用于解析台式机的IR协议。进行了读取原始数据的快速比较测试,该测试没有显示与IRemote相比样品中的差异。在优点中,IRLIb已具有确定红外发射器工作频率的示例。示例Samsung36实际上使用来自Internet的数据来实现协议分析。此外,该文档还完美地描述了如何将IR接收器与级联等连接起来。尽管我认为,IRemote更易于理解和使用。

Source: https://habr.com/ru/post/zh-CN391001/


All Articles