极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 21865|回复: 4

红外遥控库IRremote的IRsend类sendRaw函数溢出问题及其解决方法

[复制链接]
发表于 2014-5-15 15:08:23 | 显示全部楼层 |阅读模式
本帖最后由 254213048 于 2014-5-15 15:37 编辑

最近在调试红外遥控格力空调,在论坛中学到了不少东西。参考:
(1)《解决问题系列(4)——红外编码分析利器使用》
(2)《315Mhz模块传输替代315Mhz遥控器》

问题分析
我使用的遥控器型号是YAD0F。
在使用逻辑分析仪dump出原始码之后,使用sendRaw函数来发送原始码,发现空调没有反应。原始码如下:
  1. 9004,4499,699,1609,697,511,695,511,695,510,693,1611,697,1612,696,510,695,510,695,1610,696,1609,696,512,695,1609,696,512,695,511,695,511,694,512,694,511,695,510,694,512,694,512,694,511,695,1611,696,512,693,512,694,512,694,511,694,511,694,512,694,1611,696,512,694,1610,696,512,694,511,694,1609,698,510,694,19942,698,511,694,512,694,511,694,511,694,511,694,511,695,510,695,511,694,511,696,510,692,513,694,511,694,511,694,1611,696,511,693,512,694,511,693,512,694,512,695,511,694,512,694,511,694,511,695,511,694,511,694,512,695,511,694,511,693,512,694,511,695,511,695,1609,698,39952,9037,4443,698,1609,697,511,695,511,694,510,695,1610,696,1609,697,512,693,512,694,1610,698,1610,695,511,694,1611,696,512,695,511,694,512,694,512,692,512,694,511,695,511,694,512,695,511,695,1608,697,512,694,511,693,512,692,512,693,538,694,512,694,1610,697,1610,697,1612,697,511,694,511,694,1611,697,512,695,19941,698,511,694,511,693,512,693,512,695,511,693,512,696,510,694,511,695,511,695,510,695,511,693,512,694,511,695,511,694,511,694,511,694,512,693,512,694,511,693,512,694,1610,697,511,695,1610,695,513,694,511,693,512,694,511,693,512,693,1611,698,1610,697,511,695,1610,696
复制代码

受到文章《Arduino红外遥控格力空调的问题》的启发,认为有可能是溢出的问题。

将这段原始码使用sendRaw发送,然后使用逻辑分析仪dump出它的原始码:
  1. 9103,4478,750,1589,702,505,746,491,660,547,660,1644,750,1590,703,525,669,547,660,1648,745,1565,691,547,660,1646,691,547,661,547,741,463,691,547,661,547,660,565,669,548,660,547,703,498,694,1647,663,547,745,463,745,489,660,542,687,525,744,489,698,1601,757,489,660,1649,712,498,744,490,660,1651,742,464,745,3560,663,546,701,506,745,490,660,547,704,502,746,490,660,547,708,494,692,521,744,489,660,547,739,469,743,491,660,1638,699,547,661,547,660,547,745,489,660,547,660,547,745,464,742,490,661,546,745,464,744,490,660,547,710,496,744,491,660,547,710,493,691,547,661,1647,745,7185,9073,4494,729,1600,747,489,705,496,693,548,660,1647,747,1564,747,489,697,508,690,1648,664,1648,746,464,743,1592,708,501,744,490,660,546,743,463,690,547,660,547,660,545,689,548,661,547,708,1595,752,489,660,547,746,461,745,490,660,574,660,545,747,1590,663,1643,753,1590,663,544,747,489,660,1648,748,462,746,3533,748,489,661,544,689,522,744,489,700,499,695,547,660,548,660,547,745,489,660,547,660,547,712,497,744,489,697,510,743,462,689,547,661,547,697,508,689,547,660,548,660,1643,753,489,660,1647,747,489,660,547,684,524,746,489,659,548,697,1604,755,1588,700,507,689,1648,663
复制代码


对比两段原始码,发现了溢出的值:
遥控发送后接收的
原始码
  sendRaw发送后再次接收的
原始码
备注
19942 356019942除以16383的余数为3558,溢出1次
39952 7185  39952除以16383的余数为7184,溢出2次
199413533 19941除以16383的余数为3557,溢出1次
      
                     
通过分析IRremote的库文件之后,共发现了两处会导致溢出的地方:
(1)void delayMicrosecond(us)函数。delayMicroseconds函数的参数取值范围是0-16383。
(2)void space(int usec)函数和void mark(int usec)函数。参数的类型为int, 其取值范围为-32768-32767。



解决方法
(1)在头文件IRremote.h中添加3个函数定义:


  1. void sendRaw2(unsigned int buf[], int len, int hz);
  2. VIRTUAL void mark2(unsigned int usec);
  3. VIRTUAL void space2(unsigned int usec);
复制代码


(2)在源文件IRremote.cpp中添加3个函数实现:

  1. void IRsend::mark2(unsigned int time)  // time的类型为unsigned int
  2. {
  3.         TIMER_ENABLE_PWM;

  4.         if(time < 16384)
  5.         {
  6.                 delayMicroseconds(time);
  7.         }
  8.         else  
  9.         {
  10.                 unsigned int v = time / 16384;        // 取商数
  11.                 unsigned int m = time % 16384;  // 取余数
  12.                 for( int j = 0; j < v; j++ )  // 暂停(v ×16383)秒
  13.                 {
  14.                         delayMicroseconds(16383);
  15.                 }
  16.                 delayMicroseconds(m);  // 暂停m秒
  17.         }
  18. }


  19. void IRsend::space2(unsigned int time)  // time的类型为unsigned int
  20. {
  21.         TIMER_DISABLE_PWM;

  22.         if(time < 16384)
  23.         {
  24.                 delayMicroseconds(time);
  25.         }
  26.         else
  27.         {
  28.                 unsigned int v = time / 16384;         // 取商数
  29.                 unsigned int m = time % 16384;   // 取余数
  30.                 for( int j = 0; j < v; j++ )  // 暂停(v ×16383)秒
  31.                 {
  32.                         delayMicroseconds(16383);
  33.                 }
  34.                 delayMicroseconds(m); // 暂停m秒
  35.         }
  36. }


  37. void IRsend::sendRaw2(unsigned int buf[], int len, int hz)
  38. {
  39.         enableIROut(hz);
  40.         for (int i = 0; i < len; i++)
  41.         {
  42.                 if (i & 1)
  43.                 {
  44.                          space2(buf[i]);
  45.                 }
  46.                 else
  47.                 {
  48.                         mark2(buf[i]);
  49.                 }
  50.         }
  51.         space(0); // Just to be sure
  52. }
复制代码

调用方法
需要注意的是,信号线要接在3号接口上。
调用方法与调用sendRaw函数一样。
(1)引用IRremote.h库,
(2)新建一个IRsend对象;
(3)定义一个unsigned int数组用以存放原始码,
(4)调用IRsend对象的sendRaw2函数。

示例代码如下:

  1. #include <IRremote.h>                  // 引用 IRRemote 函数库
  2. IRsend irsend;                         // 新建一个IRsend对象,

  3. void setup()
  4. {

  5. }

  6. void loop()
  7. {
  8.     unsigned int close27[279] =  {9004,4499,699,1609,697,511,695,511,695,510,693,1611,697,1612,696,510,695,510,695,1610,696,1609,696,512,695,1609,696,512,695,511,695,511,694,512,694,511,695,510,694,512,694,512,694,511,695,1611,696,512,693,512,694,512,694,511,694,511,694,512,694,1611,696,512,694,1610,696,512,694,511,694,1609,698,510,694,19942,698,511,694,512,694,511,694,511,694,511,694,511,695,510,695,511,694,511,696,510,692,513,694,511,694,511,694,1611,696,511,693,512,694,511,693,512,694,512,695,511,694,512,694,511,694,511,695,511,694,511,694,512,695,511,694,511,693,512,694,511,695,511,695,1609,698,39952,9037,4443,698,1609,697,511,695,511,694,510,695,1610,696,1609,697,512,693,512,694,1610,698,1610,695,511,694,1611,696,512,695,511,694,512,694,512,692,512,694,511,695,511,694,512,695,511,695,1608,697,512,694,511,693,512,692,512,693,538,694,512,694,1610,697,1610,697,1612,697,511,694,511,694,1611,697,512,695,19941,698,511,694,511,693,512,693,512,695,511,693,512,696,510,694,511,695,511,695,510,695,511,693,512,694,511,695,511,694,511,694,511,694,512,693,512,694,511,693,512,694,1610,697,511,695,1610,695,513,694,511,693,512,694,511,693,512,693,1611,698,1610,697,511,695,1610,696}; // 原始码
  9.      irsend.sendRaw2(open27, 279, 38);  // 调用sendRaw2函数
  10.      delay(2000);
  11. }
复制代码


修正后的IRremote库


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2014-7-31 10:58:14 | 显示全部楼层
楼主你好,我用的遥控器也是YAD0F。
这是采集到的遥控器调温度的数据:
  1. 9091,4472,700,1621,702,514,698,516,700,1620,701,1622,701,1621,702,514,700,515,697,1624,701,1622,697,518,699,1621,701,514,699,516,697,517,699,515,699,514,696,517,699,516,698,516,699,513,698,1623,700,516,700,513,702,514,697,518,698,517,698,516,700,1622,700,516,699,1620,697,520,701,515,698,1623,700,515,698,20079,702,512,700,515,700,515,698,515,700,1621,701,514,699,515,699,515,695,518,701,1621,701,513,700,516,699,515,698,1622,701,514,699,517,697,516,698,517,699,516,701,514,699,515,701,514,700,514,701,513,701,515,696,519,697,516,700,514,701,1622,700,516,698,516,699,515,701,40218,9095,4472,701,1624,701,515,698,515,699,1622,622,1701,699,1623,702,515,699,516,698,1622,700,1624,696,519,702,1621,699,517,698,515,695,520,702,515,698,516,698,516,701,515,698,517,701,514,700,1622,701,514,697,519,701,513,700,515,701,513,701,515,697,1624,701,1621,702,1622,701,515,701,514,700,1624,701,515,699,20076,700,516,696,517,698,516,699,515,701,515,700,513,700,517,698,516,699,515,701,515,700,514,701,514,698,517,700,514,700,516,700,514,701,514,698,516,699,515,701,514,700,1623,700,515,702,1622,700,517,700,515,696,519,701,513,700,515,697,1626,703,1621,702,515,700,514,701
复制代码
这是采集到我发的数据:
  1. 8999,4421,682,1590,682,540,682,538,652,1617,685,1588,653,1617,682,542,655,565,654,1615,657,1614,655,568,681,1588,684,540,656,562,685,536,678,543,679,542,682,538,682,538,676,544,683,539,655,1615,654,568,658,563,653,565,678,545,681,538,681,539,683,1587,683,540,654,1614,684,542,656,563,653,1617,682,541,681,19988,684,539,656,563,654,566,683,540,678,1591,680,542,681,540,655,564,651,569,681,1590,683,542,677,540,680,541,653,1617,682,540,679,544,679,543,677,541,683,539,655,564,653,568,679,542,681,541,681,539,682,539,675,545,676,545,678,544,681,1586,683,540,680,541,649,572,651,40218,8969,4450,684,1588,681,542,653,568,678,1590,680,1592,682,1588,684,538,683,537,681,1589,654,1617,656,567,681,1587,685,537,681,540,652,569,651,570,683,538,682,539,655,565,656,566,683,540,679,1587,683,540,655,566,651,569,653,568,681,540,656,563,656,1615,682,1589,678,1593,651,572,652,569,683,1587,682,543,679,19988,681,541,683,538,679,541,652,568,677,543,681,543,680,540,681,541,654,564,676,546,678,542,681,540,683,537,655,564,678,544,680,542,683,538,681,537,678,542,658,566,651,1615,682,542,682,1587,683,539,679,544,676,543,651,570,682,540,680,1588,683,1589,656,565,657,565,680
复制代码
站在凳子上,发射管对着空调,遥控器无反应。
请问可能是什么原因?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-15 10:09:53 | 显示全部楼层
mayouyou 发表于 2014-7-31 10:58
楼主你好,我用的遥控器也是YAD0F。
这是采集到的遥控器调温度的数据:这是采集到我发的数据:站在凳子上, ...

你好!你可以尝试一下以下的调试方法(解决问题的思路):
(1)逻辑分析仪在导出数据的时候,可以将文件保存为excel或者csv格式。分别保存两次的结果,其结果在excel中被显示成一列数据。
(2)将这两列数据复制到一个新的excel文件中。然后对比这两列数据的差别。对比的方法是:两个数减,然后取绝对值。
(3)查看差别列。一般绝对值在100左右应当是正常的。若是发现了明显异常的值,那么它就是问题所在。然后,再尝试着再找引发问题的原因吧。

   我就是使用这个方法发现了数据异常的地方(这是问题点),然后假设引发问题的原因是由于数值溢出(假设),然后去验证假设。
回复 支持 反对

使用道具 举报

发表于 2014-8-24 09:15:18 | 显示全部楼层
254213048 发表于 2014-8-15 10:09
你好!你可以尝试一下以下的调试方法(解决问题的思路):
(1)逻辑分析仪在导出数据的时候,可以将文件 ...

你好,我也使用使用了,你的方法控制空调,用在格力上秒开了,可是用在三星上不行,然后我也用逻辑分析仪采集了我发送的原始码数据,发现比原始码少了几位,现在搞了好几天都没搞好。详情可以看看我发的帖子,请你帮帮忙啊。
回复 支持 反对

使用道具 举报

发表于 2014-8-24 09:18:00 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 21:47 , Processed in 0.041210 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表