arduino紅外遙控庫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); }

 

庫文件下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM