用 IRremote 函式庫也可以做紅外線物體偵測,方法是用 IRremote 讓紅外線發射器 (IR LED) 產生 38 kHz 的脈波,然後用一般 38 kHz 的紅外線接收器來偵測訊號。
註: 在「紅外線物體偵測(1)」(反射型)和「紅外線物體偵測(2)」(遮光型)這兩篇的範例程式中,紅外線發射器(IR LED) 38 kHz 的脈波是利用 tone() 函式產生的。
線路的接法還是一樣,如下圖,把紅外線發射器串接一顆 100 歐姆的電阻接到 pin 3,然後把紅外線接收器接到 pin 2:
程式
底下這支程式(IRRemoteObjDetect.pde)示範用 IRremote 函式庫做紅外線物體偵測:
要產生 38 kHz 的脈波,只要呼叫 irsend.enableIROut(38); 設定 PWM 的頻率,接著再呼叫 irsend.mark(0); 打開輸出讓 IR LED 開始輸出訊號,這樣就可以了。
就看你的發射器與接收器的接法為何,如果是反射型的,在偵測到物體時 pin 13 上的指示燈會閃爍,如果是遮光型的,那麼 pin 13 上的指示燈平常會一直閃爍,在偵測到物體時會熄滅。
IRsend這個函式除了enableIROut和mark之外, 還
回覆刪除有哪些方法可以使用?
IRsend 除了 sendXXX() 這系列方法跟 enableIROut, mark 外, 還有一個 space() 方法。space() 的作用正好與 mark() 相反。
回覆刪除這是 IRsend 的定義 (可以在 IRRemote.h 裏找到):
class IRsend
{
public:
IRsend() {}
void sendNEC(unsigned long data, int nbits);
void sendSony(unsigned long data, int nbits);
void sendRaw(unsigned int buf[], int len, int hz);
void sendRC5(unsigned long data, int nbits);
void sendRC6(unsigned long data, int nbits);
void sendDISH(unsigned long data, int nbits);
void sendSharp(unsigned long data, int nbits);
// private:
void enableIROut(int khz);
VIRTUAL void mark(int usec);
VIRTUAL void space(int usec);
}
如果我要接4組這樣的反射型物體偵測,
回覆刪除電路和程式該如何做?
你要接 4 組?
回覆刪除我不確定 IRRemote 能不能同時用多組紅外線接收器
不過你可以試試看,紅外線接收器不限定接哪支腳位
所以你只要照這篇的接線圖增加幾顆紅外線接收器就可以了
至於程式的話,把它當 digital input 來看用 digitalRead() 來讀訊號就行
只是要注意訊號會反,0 代表有物體,1 代表沒有物體
是不是無法同時發射2組以上的脈波? 底下的程式只有第1組可以正常動作:
回覆刪除/*
* irObjectDetection.pde: 紅外線物體偵測
*/
const int irRec1 = 2; // 紅外線接收器
const int irLed1 = 3; // 紅外線發射器
const int ledPin1 = 12; // 紅外線指示燈
const int irRec2 = 4; // 紅外線接收器
const int irLed2 = 5; // 紅外線發射器
const int ledPin2 = 13; // 紅外線指示燈
const unsigned int frequency = 38000; // 發射頻率(單位: Hz)
void setup() {
pinMode(irRec1, INPUT); // 把 irReceiver 接腳設置為 INPUT
pinMode(irLed1, OUTPUT); // 把 irLed 接腳設置為 INPUT
pinMode(ledPin1, OUTPUT); // 把 ledPin 設置為 OUTPUT
pinMode(irRec2, INPUT); // 把 irReceiver 接腳設置為 INPUT
pinMode(irLed2, OUTPUT); // 把 irLed 接腳設置為 INPUT
pinMode(ledPin2, OUTPUT); // 把 ledPin 設置為 OUTPUT
tone(irLed1, frequency); // 產生指定頻率的脈波 (Pulses)
tone(irLed2, frequency); // 產生指定頻率的脈波 (Pulses)
}
// 讓指示燈閃爍幾下
void blinkLED(int ledPin) {
for (int i=1; i<= 3; i++) {
digitalWrite(ledPin, HIGH); // 打開指示燈
delay(100);
digitalWrite(ledPin, LOW); // 關掉指示燈
delay(100);
}
}
void loop() {
int ir1 = digitalRead(irRec1); // 讀取 irReceiver 的狀態
if (ir1 == 0) blinkLED(ledPin1); // 讓指示燈閃爍幾下
int ir2 = digitalRead(irRec2); // 讀取 irReceiver 的狀態
if (ir2 == 0) blinkLED(ledPin2); // 讓指示燈閃爍幾下
}
arduino.cc 討論區有人在討論能不能用 tone() 多個聲音:
回覆刪除http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1266588204
scswift 分享了他的經驗 "I tried using tone() today, with two piezos hooked up to different pins, and I found that when you call tone() to play a tone on one pin, you must call noTone() for that pin before calling tone() on another pin... even if the sound on the first pin has stopped playing.
"
所以我想可能沒辦法用 tone() 同時播放聲音或送脈波。只能一個接一個送,而且送完一個脈波後,還要用 noTone() 結束脈波的傳送。
呵~~視頻是做一隻會唱歌的晨鳥.
回覆刪除我的第一個作品是只要敲鍵盤任意鍵Arduino就會發出一個音符,所以當使用者在打鍵盤時樂曲就會流洩出來,我想做的東西就是一個"陪伴電腦使用者"的裝置.
剛開始還蠻新鮮的, 但那種合成的聲音是很死硬的, 聽久就膩了, 所以我後來就改成透過馬達驅動實體音樂盒, 這樣的聲音效果好多了.
既然Arduino無法同時使用2個tone()發出38KHz脈波或發出複音, 那麼我想應該有下列兩種方法解決這個問題:
回覆刪除1.模仿cpu分時多工的觀念, 透過適時地切換tone()與noTone()來達成.
2.用硬體方式解決, 利用IC555發出38KHz脈波或音頻訊號.
底下是2組紅外線偵測物體的程式碼:
回覆刪除/*
* irObjectDetection.pde: 紅外線物體偵測
*/
const int irRec1 = 2; // 紅外線接收器
const int irLed1 = 3; // 紅外線發射器
const int ledPin1 = 12; // 紅外線指示燈
const int irRec2 = 4; // 紅外線接收器
const int irLed2 = 5; // 紅外線發射器
const int ledPin2 = 13; // 紅外線指示燈
const unsigned int frequency = 38000; // 發射頻率(單位: Hz)
void setup() {
pinMode(irRec1, INPUT); // 把 irReceiver 接腳設置為 INPUT
pinMode(irLed1, OUTPUT); // 把 irLed 接腳設置為 INPUT
pinMode(ledPin1, OUTPUT); // 把 ledPin 設置為 OUTPUT
pinMode(irRec2, INPUT); // 把 irReceiver 接腳設置為 INPUT
pinMode(irLed2, OUTPUT); // 把 irLed 接腳設置為 INPUT
pinMode(ledPin2, OUTPUT); // 把 ledPin 設置為 OUTPUT
}
// 讓指示燈閃爍
void blinkLED(int ledPin) {
digitalWrite(ledPin, HIGH); // 打開指示燈
delay(100);
digitalWrite(ledPin, LOW); // 關掉指示燈
delay(100);
}
void loop() {
tone(irLed1, frequency); // 產生指定頻率的脈波 (Pulses)
delay(100);
int ir1 = digitalRead(irRec1); // 讀取 irReceiver 的狀態
if (ir1 == 0) blinkLED(ledPin1); // 讓指示燈閃爍幾下
noTone(irLed1);
//
tone(irLed2, frequency); // 產生指定頻率的脈波 (Pulses)
delay(100);
int ir2 = digitalRead(irRec2); // 讀取 irReceiver 的狀態
if (ir2 == 0) blinkLED(ledPin2); // 讓指示燈閃爍幾下
noTone(irLed2);
}
這種方式有缺點, 所以看來似乎應該用硬體方式解決會比較好.
Arduino除了tone()這個函數可以發出38KHz脈波之外, 還有其它函數可以做到嗎?
回覆刪除Arduino core library 裏只有 tone() 這個函數可以產生各種頻率的脈波。如果要發複音,可能利用 timer 的 pwm 功能,可能要研究一下 tone() 的程式碼,然後看看有沒有多餘的 timer 可供使用。
回覆刪除簡易播複音的方法:
回覆刪除Simple Polyphonic Synth - Just WIth Arduino
http://little-scale.blogspot.com/2008/02/simple-polyphonic-synth-with-just.html
最近看到兩位的討論使我受益良多,我試實作出發射兩組38kHz使用切換tone()與noTone(),做出的是2個遮光型的紅外線感測器,程式部分修改 芭蕉葉上聽雨聲前輩所說之有缺點的方式。
回覆刪除/*
* irObjectDetection.pde: 紅外線物體偵測
*/
const int irRec1 = 2; // 紅外線接收器
const int irLed1 = 3; // 紅外線發射器
const int ledPin1 = 12; // 紅外線指示燈
const int irRec2 = 4; // 紅外線接收器
const int irLed2 = 5; // 紅外線發射器
const int ledPin2 = 13; // 紅外線指示燈
const unsigned int frequency = 38000; // 發射頻率(單位: Hz)
void setup() {
pinMode(irRec1, INPUT); // 把 irReceiver 接腳設置為 INPUT
pinMode(irLed1, OUTPUT); // 把 irLed 接腳設置為 INPUT
pinMode(ledPin1, OUTPUT); // 把 ledPin 設置為 OUTPUT
pinMode(irRec2, INPUT); // 把 irReceiver 接腳設置為 INPUT
pinMode(irLed2, OUTPUT); // 把 irLed 接腳設置為 INPUT
pinMode(ledPin2, OUTPUT); // 把 ledPin 設置為 OUTPUT
}
// 讓指示燈閃爍
void blinkLED(int ledPin) {
digitalWrite(ledPin, HIGH); // 打開指示燈
delay(100);
digitalWrite(ledPin, LOW); // 關掉指示燈
delay(100);
}
void loop() {
tone(irLed1, frequency); // 產生指定頻率的脈波 (Pulses)
delay(100);
int ir1 = digitalRead(irRec1); // 讀取 irReceiver 的狀態
if (ir1 == 1) blinkLED(ledPin1); // 讓指示燈閃爍幾下
noTone(irLed1);
//
tone(irLed2, frequency); // 產生指定頻率的脈波 (Pulses)
delay(100);
int ir2 = digitalRead(irRec2); // 讀取 irReceiver 的狀態
if (ir2 == 1) blinkLED(ledPin2); // 讓指示燈閃爍幾下
noTone(irLed2);
}
修改完似乎沒有什麼問題出現@@
依照這個程式來走的話是,irRec2被遮住的話ledPin2閃爍,irRec1被遮住的畫ledPin1閃爍,兩個一起遮住,兩個一起閃爍。
我想如果想要使用兩個tone()的話,使用tone()與noTone()這個方法可行。
LCW恭喜你實做成功.
回覆刪除請問你的紅外線發射與接收, 有效距離最遠是幾公尺?
芭蕉葉上聽雨聲你好
回覆刪除我只是在麵包板上把電路實作出來...
所以發射端與接收端的距離,僅僅只有14cm而已@@
有效最遠距離的話,因為手邊沒有兩塊麵包板所以沒辦法實測...
LCW 恭禧你實作成功
回覆刪除歡迎兩位常來啊!^o^