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

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

最近在调试红外遥控格力空调,在论坛中学到了不少东西。参考:

(1)《解决问题系列(4)——红外编码分析利器使用

2)《315Mhz模块传输替代315Mhz遥控器

 

调试环境:

软件:Arduino IDE 1.0

硬件:Arduino uno r3

问题分>

我使用的遥控器型号是YAD0F。

在使用逻辑分析仪dump出原始码之后,使用sendRaw函数来发送原始码,发现空调没有反应。原始码如下:

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出它的原始码:

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

3560

19942除以16383的余数为3558,溢出1次

39952

7185

39952除以16383的余数为7184,溢出2次

19941

3533

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个函数定义:

void sendRaw2(unsigned int buf[], int len, int hz);
VIRTUAL void mark2(unsigned int usec);
VIRTUAL void space2(unsigned int usec);

 

 

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

 

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

    if(time < 16384)
    {
        delayMicroseconds(time);
    }
    else  
    {
        unsigned int v = time / 16384;    // 取商数
        unsigned int m = time % 16384;  // 取余数
        for( int j = 0; j < v; j++ )  // 暂停(v ×16383)秒
        {
            delayMicroseconds(16383);
        }
        delayMicroseconds(m);  // 暂停m秒
    }
} 


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

    if(time < 16384)
    {
        delayMicroseconds(time);
    }
    else
    {
        unsigned int v = time / 16384;     // 取商数
        unsigned int m = time % 16384;   // 取余数
        for( int j = 0; j < v; j++ )  // 暂停(v ×16383)秒
        {
            delayMicroseconds(16383);
        }
        delayMicroseconds(m); // 暂停m秒
    }
}


void IRsend::sendRaw2(unsigned int buf[], int len, int hz)
{
    enableIROut(hz);
    for (int i = 0; i < len; i++) 
    {
        if (i & 1) 
        {
             space2(buf[i]);
        } 
        else 
        {
            mark2(buf[i]);
        }
    }
    space(0); // Just to be sure
}

 

 

调用方法

需要注意的是,信号线要接在3号接口上。

调用方法与调用sendRaw函数一样。

(1)引用IRremote.h库,

(2)新建一个IRsend对象;

(3)定义一个unsigned int数组用以存放原始码,

(4)调用IRsend对象的sendRaw2函数。

 

示例代码如下:

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

void setup()
{
}

void loop()
{
     // 原始码  
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};

irsend.sendRaw2(open27, 279, 38); // 调用sendRaw2函数 delay(2000); }

 

库文件下载