LAGSILVA
Published © CC BY-NC-ND

Reaction Timer - F1 Style

Would you like to train your reaction time in milliseconds? Now you can with a timer inspired by the F1 race start lights.

BeginnerShowcase (no instructions)30 minutes8,787

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Maxim Integrated 8 Dig x 7 Seg LED Display with MAX72XX
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×2
Solderless Breadboard Half Size
Solderless Breadboard Half Size
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Schematic - Reaction Timer

Breadboard schematic

Code

Reaction_Timer_F1_Style_with_8_Dig_x_7_Seg_MAX7219_V1_1.ino

Arduino
/*
   Project:     Rection Timer - F1 Style
   Author:      LAGSILVA
   Hardware:    Arduino UNO-R3 - 8 Dig x 7 Seg MAX7219 Display
   Revision:    1.1
   Date:        06.Mar.2019
   License:     CC BY-NC-ND 4.0
                (Attribution-NonCommercial-NoDerivatives 4.0 International)
*/

#include <LedControl.h>       // Library for LED control with MAX72XX
#include <Bounce2.h>          // Library for Bounce of switches

/*
  Pins of Arduino Nano for LedControl:
  Pin #7 is connected to DataIn (DIN)
  Pin #8 is connected to CLK (CLK)
  Pin #9 is connected to LOAD (CS)
*/

// LedControl(int dataPin, int clkPin, int csPin, int numDevices)
LedControl lc = LedControl(7, 8, 9, 1);

long ti, diffTime;
int milhar, centena, dezena, unidade;
int recorde = 10000;

byte pinStartStop = 4;        // Start-Stop Pin
byte pinLapse = 3;            // Time Lapse Pin

bool statusSW1 = false;
bool statusSW2 = false;

Bounce SW1 = Bounce();        // Define Bounce to read StartStop switch
Bounce SW2 = Bounce();        // Define Bounce to read Lapse switch



void setup() {

  pinMode (pinStartStop, INPUT_PULLUP);
  pinMode (pinLapse, INPUT_PULLUP);

  randomSeed(analogRead(0));

  // After setting up the button, setup the Bounce instance
  SW1.attach(pinStartStop);   // Sets the pin (Internal Pull-Up)and matches the internal state to that of the pin
  SW1.interval(4);            // Sets the debounce time in milliseconds for SW1
  SW2.attach(pinLapse);       // Sets the pin (Internal Pull-Up)and matches the internal state to that of the pin
  SW2.interval(4);            // Sets the debounce time in milliseconds for SW2

  lc.shutdown(0, false);      // The MAX72XX is in power-saving mode on startup, we have to do a wakeup call
  lc.setIntensity(0, 2);      // Set the brightness of display between 0 and 15
  lc.clearDisplay(0);         // Clear the display

  lc.setRow(0, 7, 1);         // Waiting indicator: "-"
  lc.setRow(0, 6, 1);         // Waiting indicator: "-"
  lc.setRow(0, 5, 1);         // Waiting indicator: "-"
  lc.setRow(0, 4, 1);         // Waiting indicator: "-"
  lc.setRow(0, 3, 1);         // Waiting indicator: "-"
  lc.setRow(0, 2, 1);         // Waiting indicator: "-"
  lc.setRow(0, 1, 1);         // Waiting indicator: "-"
  lc.setRow(0, 0, 1);         // Waiting indicator: "-"

}


void loop() {

  SW1.update();   // Start-Stop

  if (SW1.fell()) {
    statusSW1 = !statusSW1;
    ti = random(200, 3000);               // Random time after lights off (200 to 3000 milliseconds)
    lc.clearDisplay(0);
  }

  if (statusSW1 == true) {

    statusSW1 = false;
    statusSW2 = true;

    for (byte k = 7; k >= 3; k--) {
      for (byte k1 = 1; k1 <= 20; k1++) {
        SW2.update();
        if (SW2.fell()) {
          lc.setRow(0, 1, 60);            // Jump Start Warning: "J"
          lc.setRow(0, 0, 103);           // Jump Start Warning: "P"
          statusSW2 = false;
          return (0);
        }
        delay(1000 / 20);                 // Time control between lights on
      }
      lc.setRow(0, k, 29);
    }

    for (byte k1 = 1; k1 <= 40; k1++) {
      SW2.update();
      if (SW2.fell()) {
        lc.setRow(0, 1, 60);              // Jump Start Warning: "J"
        lc.setRow(0, 0, 103);             // Jump Start Warning: "P"
        statusSW2 = false;
        return (0);
      }
      delay(ti / 40);                     // Time control before lights off
    }

    lc.clearDisplay(0);

    ti = millis();                        // Start time after display off

  }


  SW2.update();   // Lap Time

  if (SW2.fell() && statusSW2 == true) {

    diffTime = millis() - ti;             // Reaction time after display off

    statusSW2 = false;

    if (diffTime >= 20 && diffTime <= 9999) {   // Overflow verification

      milhar = diffTime / 1000;
      centena = (diffTime / 100) % 10;
      dezena = (diffTime / 10) % 10;
      unidade = diffTime % 10;

      lc.setDigit(0, 3, milhar, true);
      lc.setDigit(0, 2, centena, false);
      lc.setDigit(0, 1, dezena, false);
      lc.setDigit(0, 0, unidade, false);

      if (diffTime < recorde) {           // Best mark (minimum reaction time)
        recorde = diffTime;
      }

      milhar = recorde / 1000;
      centena = (recorde / 100) % 10;
      dezena = (recorde / 10) % 10;
      unidade = recorde % 10;

      lc.setDigit(0, 7, milhar, true);    // Print the best mark
      lc.setDigit(0, 6, centena, false);
      lc.setDigit(0, 5, dezena, false);
      lc.setDigit(0, 4, unidade, false);

    }
    else {
      lc.clearDisplay(0);
      lc.setRow(0, 3, 1);   // Overflow warning: " - "
      lc.setRow(0, 2, 1);   // Overflow warning: " - "
      lc.setRow(0, 1, 1);   // Overflow warning: " - "
      lc.setRow(0, 0, 1);   // Overflow warning: " - "
    }

  }

}

Credits

LAGSILVA

LAGSILVA

7 projects • 338 followers
Mechanical Engineer in automotive industry since 1989. Coding and Arduino are my hobbies.

Comments