整個裝置運作的過程是這樣的。
按下按鈕之後,立架上的電磁鐵會釋放鐵球,鐵球通過光電閘的同時,液晶螢幕會顯示從釋放鐵球到鐵球通過光電閘的時間,單位是微秒。

電磁鐵的部份,就是去書店買那種給小學生玩的電磁鐵勞作,一包裡頭有一根鐵釘和漆包線,這要自己繞成電磁鐵。一開始我還老老實實的用手繞,但是繞了幾圈就想偷懶,乾脆把鐵釘裝在電鑽上面,一秒鐘直接繞好線。

立架是用4分的PVC水管組成的,而光電閘則是用了6片Scibrick的H板,兩片用來夾住垂直立柱,另外四片就是延伸閘口,而H板中的螺絲孔,剛好可以塞IR的發射與接收器,用這樣來作光電閘。


接線的方式,我參考了Photoduino的一些接線,像是連接電磁鐵或是光電閘的,因為剛好都是Photoduino有用過得。

連接電磁鐵,用了另外一顆9V電池,還有以下零件
IRL 520
1N4004
10k電阻

按鈕用了10k電阻

光電閘的紅外發射和接收,用了100歐姆和10k歐姆的電阻,另外IR接收的接法要注意

程式碼如下,比較特別的是用了中斷(interrupt),Arduino的D3會一直偵測是否有電壓下降,如果有就會立刻計算釋放到通過的時間,然後loop的迴圈會讓時間呈現在LCD上。
在9V電池上電之後,電磁鐵會立刻有磁性,所以可以把鐵球吸附上去(或是使用迴紋針包覆黏土成球),按下按鈕之後,會立刻斷電磁鐵的電,所以球就會掉下。
這個量測裝置目前有些問題
1.我覺得電磁鐵可能很耗電,平常不要讓9V電池一直上電
2.調整落下到通過的鉛直線有點耗時,可能可以用水滴或是什麼東西來協助定位。
3.時間量測不太穩定,理論上裝置固定,應該量出來的通過時間都一致,但實際上量測時,數據沒有那麼漂亮。
------------------------------------------------------------------------------------------
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
unsigned long startTime;
unsigned long duration; // 持續時間
const int ledPin = 13; // the number of the LED pin
const int EMPin = 7;
const byte buttonPin = 2;
const byte barrierPin = 3;
volatile byte state = LOW;
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(EMPin, OUTPUT);
pinMode(barrierPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(barrierPin), showTime, FALLING);
Serial.begin(9600); // 開啟 Serial port, 通訊速率為 9600 bps
lcd.begin();
lcd.backlight();
lcd.clear();
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
lcd.clear();
duration = 0;
startTime = micros();
digitalWrite(ledPin, HIGH);
digitalWrite(EMPin, LOW);
} else {
digitalWrite(ledPin, LOW);
digitalWrite(EMPin, HIGH);
}
Serial.println(duration);
lcd.setCursor(0, 0);
lcd.print(duration);
}
void showTime() {
duration = micros() - startTime;
}