2017年12月18日 星期一

人體反應時間測量裝置

傳統生物課測量反應時間,是用接尺的反應來作實驗的。但這個接尺反應,只能測量視覺的反應時間,聽覺和觸覺的反應時間就無法測量。

用Arduino + Ywrobot EMS,可以做出視覺、聽覺、觸覺的反應時間測量裝置。效果和說明如下影片所示。

如果單純視覺的話,可以google "reaction time",就可以找到很多可以用的網頁服務甚至app喔






但是裝置自己會有反應時間,所以第一次按下D2開始之後,先持續按著D3不放,測量反應時間=0的情況。這時會發現,其實還是有一點時間差。以我的機器來說,是大約27ms。所以就在輸出反應時間的時候,扣掉27ms就行了

另外一個問題是:伺服馬達轉動會有聲音,所以無法避掉聲音的干擾。不過可能可以讓學生戴耳機聽音樂避掉。只是又多了其他變因就是了

程式碼和說明如下:

#include <LiquidCrystal_I2C.h>
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // 設定 LCD I2C 位址
//以上是驅動LCD的部分

#include <Servo.h>      //這是伺服馬達要用的library


#define pushbutton1 2   //設定腳位們
#define pushbutton2 3
#define buzzer 5
#define LED1 12

unsigned long time;     //計算時間需要的東西

int time1;              //設定變數們
int time2;
int reactiontime;
int starttime;
int start;
int reaction;
int VR;

Servo myservo1;         //伺服馬達取個名字叫做myservo1


void setup(){
  lcd.begin(16,2);                
  lcd.clear();
  lcd.print("press 2 to start");
  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(12,OUTPUT);
  pinMode(5, OUTPUT);
}

void loop(){
  time = millis();                  //時間用milli second當單位
  myservo1.attach(7, 500, 2400);    //設定伺服馬達的腳位

  VR= analogRead(0);
  VR= map (VR,0,1024,1,4);          //設定可變電阻VR控制訊息模式,這樣VR數字會從1~3變化
  Serial.print(VR);
  Serial.print(",");
  Serial.println(analogRead(0));
  if (VR ==1){
    lcd.setCursor(4,1);
    lcd.print("hearing mode        ");
  }
  
  if (VR ==2){
    lcd.setCursor(4,1);
    lcd.print("visual mode       ");
  }
  
  if(VR ==3){
    lcd.setCursor(4,1);
    lcd.print("tactile mode       ");
  }

  start = digitalRead(2);           //數位二號按鈕按下去就開始
  reaction = digitalRead(3);        //數位三號按鈕按下去就停止計算時間
  
  if (start == 0){
    delay(300);
    starttime = random(3000,10000); //等待時間設定為從3s~10s之間

    lcd.clear();                    //讓LCD螢幕倒數三秒之後,顯示START
    lcd.setCursor(0,0);
    lcd.print("3");
    delay(1000);
    lcd.setCursor(0,0);
    lcd.print("2");
    delay(1000);
    lcd.setCursor(0,0);
    lcd.print("1");
    delay(1000);
    lcd.setCursor(0,0);
    lcd.print("START");
    delay(starttime);               //等待starttime的長度之後,判斷模式發出訊號
    time1= time;                    //抓啟始時間點
    if (VR ==1){                    //VR較小時,送出聲音訊號
    tone(5,200);
    }
    if (VR ==2){                    //VR中間時,送出光亮訊號
      digitalWrite(12,HIGH);
    }
    if (VR ==3){                    //VR較大時,讓伺服馬達振動
        myservo1.write(120);
    }                    
  }

  if (reaction == 0){               //如果按下了D3就抓第二個時間點
    time2 = time;
    Serial.println(time2);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("reaction time=");
    lcd.setCursor(0,1);
    reactiontime = time2-time1-3300-starttime-27;  
    //顯示反應時間,是兩個時間點相減之後,再扣掉之前倒數三秒和按鈕的延遲時間,再減掉隨機的等待時間。最後15是系統運作遲滯的時間,需要檢測之後才知道

    lcd.print(reactiontime);                  //顯示反應時間,單位為毫秒
    lcd.print(" ms");
    digitalWrite(12,LOW);                     //關掉LED燈和蜂鳴器,清除LCD螢幕,重新顯示
    noTone(5);
    myservo1.write(30);
    delay(5000);
    lcd.clear();
    lcd.print("press 2 to start");
    }
}

沒有留言: