Measuring the reaction time


For a lot of purposes, not only when driving a car, it is important to know the reaction time of a person. A simple way to do this is to show him or her a signal and measure the time he or she needs to respond, e.g. by hitting a key.

With the Arduino, it is done by displaying a message and reading the status of the key. As LCDs sometimes are a bit slow we decide to use an LED display. Those displays were designed to show numbers, but some letters also can be displayed. The first message will be

 
  .  
 
(As this message does not fit into a 4-digit display is is displayed in ticker mode.)

When the person hits the key, the Arduino acknowledges this by showing the message

 
   
 
and starts waiting for a random time. Then, suddenly it will show

 
   
 
and begins to count the time.
When the person hits the key the reaction time is calculated and displayed.
After a while the whole procedure will restart again.

If the person is cheating, hitting the key before the

 
   
 
message was displayed, the message

 
   
 
will be displayed.

    When you attach a key to the system you will find there are two kinds of keys: some offer a break contact (normally closed), some offer a make contact (normally open). Two handle both types of buttons the state is read on start-up, assuming the key is not pressed on power-on.

    const byte button   =  2;  
    boolean activeLow = digitalRead(button);
    

    So the keyPressed()-procedure can be simply coded like this;

    boolean keyPressed(byte pin) {
      return digitalRead(pin) ^ activeLow;
    }
    

So, the complete system will pass through 5 states. The following diagram shows which transitions from one state to another are possible.

The procedure handleEvent has to check if the time elapsed or the key was hit, and setting the next state and message.

void handleEvent(boolean time) {
  // mode control: 1) set next mode, 2) set display, 3) set next time
  disPlay = "xxxx"; 
  // if disPlay is NOT modified in switch() it will be set to standard at the end
  static long t;
  int dt;
  switch (mode) {
    // --- display the instructions, waiting for first hit:
    case start:      delay(debounce);         // the key was pressed, debouncing
            /* 1 */  mode = wait_rand;        // acknowledge, show " AH "
            /* 3 */  nextEvent(dt3 + random(dt4)); // Now wait for a random time 
                     break;
     // --- the person should not press during that time ---
    case wait_rand:  if (time) {
            /* 1 */    mode = wait4hit2;
            /* 3 */    nextEvent(9999);          
                       t = millis();            // from now on time is running
                     } else {
            /* 1 */    mode = error;            // key pressed too early
                       delay(debounce);
            /* 3 */    nextEvent(dt5);
                     }
                     break;
    // --- the key was pressed before the message was displayed  
    case error:                           
            /* 1 */  mode = start;              // restart the game
            /* 3 */  nextEvent(dt6);
                     break;
    // --- the key was pressed. now display the time:                  
    case wait4hit2:  
            /* 1 */  mode = showResult;          
                     dt = millis() - t;
                     if (dt > 9999) dt = 9999;
            /* 2 */  int2string(dt);            // setting the display
                     delay(debounce);           // debouncing
            /* 3 */  nextEvent(dt6);
                     break;
    case showResult: 
                     mode = start; 
                     nextEvent(0);
                     break;
  }
  if (disPlay.charAt(0) == 'x') disPlay = msg[mode]; 
}

Download the main program

Download constants and routines to handle the 7-segment display
This file contains defines for the displays
LC204 (common cathode)
and
LTC46454 (common anode)
If you got a different one you have to modify the const values.


contact: nji(at)gmx.de