首页 > 代码库 > 红外遥控库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); }
↓库文件下载↓