zoukankan      html  css  js  c++  java
  • 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); }

    库文件下载

  • 相关阅读:
    NBUT 1120 Reimu's Teleport (线段树)
    NBUT 1119 Patchouli's Books (STL应用)
    NBUT 1118 Marisa's Affair (排序统计,水)
    NBUT 1117 Kotiya's Incantation(字符输入处理)
    NBUT 1115 Cirno's Trick (水)
    NBUT 1114 Alice's Puppets(排序统计,水)
    188 Best Time to Buy and Sell Stock IV 买卖股票的最佳时机 IV
    187 Repeated DNA Sequences 重复的DNA序列
    179 Largest Number 把数组排成最大的数
    174 Dungeon Game 地下城游戏
  • 原文地址:https://www.cnblogs.com/dehai/p/3730156.html
Copyright © 2011-2022 走看看