2017-03-09 339 views
2

我試圖用Arduino Uno/ESP8266在載波頻率(38KHz)上產生紅外信號來取代紅外遙控器。Arduino/Esp8266紅外遙控器載波頻率

首先,我試圖使用IRremote.h庫,但是當使用「irsend.sendNEC(0x8F4567A2,32)」發送代碼時,實際接收的IR代碼不是8F4567A2(使用IRrecvDump示例)。因此,我使用示波器與變送器引腳聯繫,以檢查Arduino/Esp8266產生的信號是什麼。我注意到載波脈衝持續時間超過100us(38KHz應該有〜26us)。

然後,我發現youtube教程教學如何手動生成信號,而不使用IRremote庫作爲以下代碼。我還是用發射器引腳連接了示波器,發現載波脈衝持續時間超過了100us而不是26us,即使我在草圖中設置了26us,即使設置了方波脈衝,我也無法看到平坦的脈衝寬度。但是,如果我只是簡單地將「IRcarrier(260)」放在循環()中10個脈衝週期並刪除循環中的所有其他代碼(),則示波器每5秒顯示正確的脈衝持續時間,並且脈衝如期望的那樣顯示有方形脈衝。

我有點卡在這裏與我的紅外項目,試圖用arduino/esp8266取代電視紅外遙控器。

#define IRLEDpin 2    //the arduino pin connected to IR LED to ground. HIGH=LED ON 
#define BITtime 562   //length of the carrier bit in microseconds 
//put your own code here - 4 bytes (ADDR1 | ADDR2 | COMMAND1 | COMMAND2) 
unsigned long IRcode=0b11000001110001111100000000111111; 

// SOME CODES: 
// Canon WL-D89 video remote START/STOP button = 0b11000001110001111100000000111111 

void setup() 
{ 
} 

void IRsetup(void) 
{ 
    pinMode(IRLEDpin, OUTPUT); 
    digitalWrite(IRLEDpin, LOW); //turn off IR LED to start 
} 

// Ouput the 38KHz carrier frequency for the required time in microseconds 
// This is timing critial and just do-able on an Arduino using the standard I/O functions. 
// If you are using interrupts, ensure they disabled for the duration. 
void IRcarrier(unsigned int IRtimemicroseconds) 
{ 
    for(int i=0; i < (IRtimemicroseconds/26); i++) 
    { 
    digitalWrite(IRLEDpin, HIGH); //turn on the IR LED 
    //NOTE: digitalWrite takes about 3.5us to execute, so we need to factor that into the timing. 
    delayMicroseconds(9);   //delay for 13us (9us + digitalWrite), half the carrier frequnecy 
    digitalWrite(IRLEDpin, LOW); //turn off the IR LED 
    delayMicroseconds(9);   //delay for 13us (9us + digitalWrite), half the carrier frequnecy 
    } 
} 

//Sends the IR code in 4 byte NEC format 
void IRsendCode(unsigned long code) 
{ 
    //send the leading pulse 
    IRcarrier(9000);   //9ms of carrier 
    delayMicroseconds(4500); //4.5ms of silence 

    //send the user defined 4 byte/32bit code 
    for (int i=0; i<32; i++)   //send all 4 bytes or 32 bits 
    { 
    IRcarrier(BITtime);    //turn on the carrier for one bit time 
    if (code & 0x80000000)   //get the current bit by masking all but the MSB 
     delayMicroseconds(3 * BITtime); //a HIGH is 3 bit time periods 
    else 
     delayMicroseconds(BITtime);  //a LOW is only 1 bit time period 
    code<<=1;      //shift to the next bit for this byte 
    } 
    IRcarrier(BITtime);     //send a single STOP bit. 
} 

void loop()       //some demo main code 
{ 
    IRsetup();       //Only need to call this once to setup 
    IRsendCode(IRcode);     
    delay(5000); 
} 
+0

無論如何,通過使用IRremote庫的「IRrecvDump」示例作爲檢查接收到的代碼的一種方式,IR接收器方不能使用兩種方法中的任何一種方法接收草圖中匹配的IR代碼集。 –

+0

我還沒有嘗試過,但[這篇文章在esp8266.com上](http://www.esp8266.com/viewtopic.php?f=24&t=832)討論了使用變量和表格查找的gpio性能與使用實際值(例如1代替HIGH),並且表示使用實際值有很大的速度改進。儘管他正在使用Lua。另外,你的CPU速度是多少? – leetibbett

+0

[這裏是討論](https:// github。com/esp8266/Arduino/issues/1536)關於i2c速度,他們正在實現更快的計時,看看他們的代碼 – leetibbett

回答

0

一般來說,對於這樣的定時,我寧願直接寫入端口,並使用定時器中斷進行定時。例如,digitalWrite()(反正速度很慢)取決於MCU頻率將花費更多或更少的時間。

還要確保(定義的)F_CPU的值與您的MCU運行頻率相同。

for(int i=0; i < (IRtimemicroseconds/26); i++) 

部門可以採取很多的CPU週期,所以我會改變,要

for(int i=0; i < IRtimemicroseconds; i += 26) 

但如果我只是簡單地說 「IRcarrier(260)」 中的迴路()10脈衝 週期並刪除循環中的所有其他代碼(),示波器 顯示了正確的脈衝持續時間,每5秒鐘一次,並且脈衝如預期的那樣顯示有一個方形脈衝。

現在這很奇怪,因爲調用完全相同的函數來生成脈衝。

您確定BITtime仍然有IRsendCode()裏面的正確值嗎? (同樣,BITtime不是26的精確倍數,但這不會產生很大的差異)

IRcarrier(9000);生成什麼脈衝?或者你還有其他一些代碼可能會與延遲功能相沖突嗎?