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 
     // --- 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
            /* 3 */    nextEvent(dt5);
    // --- the key was pressed before the message was displayed  
    case error:                           
            /* 1 */  mode = start;              // restart the game
            /* 3 */  nextEvent(dt6);
    // --- 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);
    case showResult: 
                     mode = start; 
  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)
LTC46454 (common anode)
If you got a different one you have to modify the const values.

contact: nji(at)