• 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); }

    库文件下载

  • 相关阅读:
    AGC027F Grafting
    JAVA框架 Spring 依赖注入
    JAVA框架 Spring 约束配置本地资源
    JAVA框架 Spring 入门
    JAVA框架Struts2 数据封装
    JAVA框架Struts2 结果页配置
    JAVA框架Struts2 servlet API
    JAVA框架Struts2 Action类
    JAVA框架Struts2--配置讲解
    JAVA框架Struts2(二)
  • 原文地址:https://www.cnblogs.com/dehai/p/3730156.html
Copyright © 2020-2023  润新知