2016年7月31日

Arudino的光電閘計時裝置

前陣子突然很想用Arduino來作一些物理實驗的量測,一想到就來作個光電閘計時裝置吧。拼拼湊湊,一下子就完成了。

整個裝置運作的過程是這樣的。

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


IMAG2180

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


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

IMAG2183

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

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


按鈕用了10k電阻
IMAG2254


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


程式碼如下,比較特別的是用了中斷(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;
}