最近在調試紅外遙控格力空調,在論壇中學到了不少東西。參考:
調試環境:
軟件: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); }
↓庫文件下載↓