Arduino Reaction Speed Game

by ArduinoPrints3D in Circuits > Arduino

354 Views, 2 Favorites, 0 Comments

Arduino Reaction Speed Game

vidar-nordli-mathisen-QckdmETcdXs-unsplash.jpg
cover screen.png

In many olympic sports reaction time can be vital for a successful race. They are often so short that a few hundred milliseconds can make a huge difference. That is why I made this reaction timer. This device measures in milliseconds how fast you can respond to sound, light, or both.

Photo by Vidar Nordli-Mathisen on Unsplash

Supplies

IMG_1152.JPG

To make this project you need:

  1. Computer with Arduino IDE link
  2. Access to a 3D printer
  3. Slicer software (I used Orca Slicer) link
  4. hot glue
  5. Arduino Uno (I used the R4 WIFI model but any model should work) link
  6. 8x32 led matrix module link
  7. Female/Female Jumper Wires link
  8. Extra-long break-away male header link
  9. 28 mm arcade button (mine was from this kit but you may be able to find them induvidually for cheaper) link
  10. active buzzer
  11. 10k Ω resistor
  12. 100 uF electolytic capacitor
  13. 0.1 uF ceramic Capacitor
  14. M3 - 0.5 x 16mm machine screws link
  15. M3 - 0.5 hex nut link

Print the Models

Screenshot 2026-03-10 121941.png
Screenshot 2026-03-10 122002.png
Screenshot 2026-03-10 121948.png
Screenshot 2026-03-10 121955.png

For this step all files need to be downloaded, sliced, and printed.

The model is divided into four parts:

  1. The base is the main body of the timer.
  2. The diffuser scatters the light of the led matrix and serves as a front cover.
  3. The Bracket holds the led matrix onto the diffuser.
  4. The Lid covers up the side of the timer.

The print settings I used are 0.2 mm layer height, precise wall, PLA at 200℃ , and brim. The diffuser needs to be printed in white but you can choose the other parts' colors.

Before you put in any electronics you should test that the diffuser is not too loose in the base. If it is you can use a heat gun or hair dryer to heat the base and bend the walls in a little

Feel free to edit any parts as you need.

Assemble Electronics

circuit_image.png
IMG_1153.JPG
IMG_1155.JPG
IMG_1156.JPG
IMG_1157.JPG
IMG_1158.JPG
IMG_1160.JPG
IMG_1162.JPG
IMG_1164.JPG
IMG_1165.JPG
IMG_1166.JPG
IMG_1167.JPG
IMG_1168.JPG
IMG_1169.JPG

Please refer to the above images and wiring guide for help with these steps.

  1. Slide the Arduino into the base.
  2. Glue the breadboard close to the Arduino.
  3. Wire the 5v and GND of the Arduino to the + and - rails on the breadboard.
  4. Add the capacitors to the power rails.
  5. Add the resistor connecting the - rail to a standard row on the breadboard.
  6. Add the buzzer to the breadboard with the GND side on the - rail.
  7. Add a row of five headers to the arduino between D13 and D9 on the Arduino.
  8. Connect D9 from the Arduino to the + pin of the buzzer.
  9. Connect the arcade button to D10 of the Arduino and the - rail on the breadboard.
  10. Connect the VCC and GND from the led matrix to the + and - rails on the breadboard.
  11. Connect DIN, CS, and CLK from the led matrix to D11, D12, and D13 on the Arduino respectively.
  12. To make the wires long enough to reach the lid you may need to extend them with another wire as shown in the eleventh photo.
  13. Once you are done with the wiring you can secure the wires and components down with hot glue and/or tape.

Assemble the 3D Prints

IMG_1171.JPG
IMG_1172.JPG
IMG_1174.JPG
IMG_1173.JPG
IMG_1175.JPG
  1. Screw the arcade button into the hole in the diffuser.
  2. Attatch the led matrix to the diffuser with the bracket, four screws, and four hex nuts.
  3. Slide hex nuts into the slot in the base.
  4. Slide the diffuser into the base.
  5. Screw the lid on.

Code

This is the code to upload to the Arduino. The full explanation for the code is in the comments of the code.

The code uses these libraries:

  1. Chrono
  2. MD_Parola
  3. SPI
  4. CTRL
////////////////////--LIBRARIES--////////////////////

#include <Chrono.h> // used for the stopwatches
#include <LightChrono.h> // this is part of Chrono
#include <MD_Parola.h> // library for the led matrix
#include <SPI.h> // this is the communication library for the MAX7219
#include <CtrlBtn.h> // this is used for the button and debounce logic

////////////////////--VARIABLES--////////////////////

uint16_t randomTime; // used to store the random time before the stimulus
uint16_t reactionTime; // stores the time it takes for the user to react

////////////////////--SETTINGS--////////////////////

char STIMULUS_TYPE = 'L';
//S for sound, L for light, B for both
//STIMULUS_TYPE will stay at its original value unless it is
//changed over serial with checkForModeChange()
#define BUTTON_PIN 9 // change to pin of your button
#define BUZZER_PIN 10 // change to pin of you buzzer
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW // led matrix type
#define MAX_DEVICES 4 // number of MAX devices
#define CS_PIN 12 // change to your chip select pin
#define MIN_RANDOM_DELAY 1000 // set to you desired lower bound of random timer length
#define MAX_RANDOM_DELAY 5001 // set to you desired upper bound of random timer length

////////////////////--Parola--////////////////////

MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // define the Parola object with hardware spi

////////////////////--Chrono--////////////////////

Chrono timerForRandomDelay; // this timer is used to randimize the delay before before stimulus
Chrono reactionStopwatch; // this timer is used to record how long it takes you to press the button

////////////////////--CTRL buttons--////////////////////

CtrlBtn button(BUTTON_PIN, 30, nullptr, nullptr); //CTRL handler with debounce duration

////////////////////--Setup--////////////////////

void setup() {
randomSeed(analogRead(A0)); // Set random seed to the value of a floating pin
Serial.begin(115200); // Start serial communication
P.begin(); // innitiate parola
P.setIntensity(0); // set the brightness to the lowest 0-15
pinMode(BUZZER_PIN, OUTPUT); // set the pinmode for the buzzer
}

////////////////////--Loop--////////////////////

void loop() {
randomTime = random(MIN_RANDOM_DELAY, MAX_RANDOM_DELAY); // set the random time for the stimulus
if (waitForStimulus(randomTime) == false) { // activate the delay and restart if the button was pressed
return;
}
activateStimulus(STIMULUS_TYPE); // start the stimulus with whatever mode it is set to
reactionTime = recordReactionTime(); // record the time it takes for the user to press the button and set reactionTime to that value
deactivateStimulus(); // turn off the stimulus whenever the user has reacted
printTime(reactionTime); // print the reaction time to the serial
waitForRelease(); // make sure the user isn't stll pressing
checkForModeChange(); // checks if the user has used the serial monitor to change the mode
}

bool waitForStimulus(uint16_t waitTime) {
timerForRandomDelay.restart(); // restart the timer
while (timerForRandomDelay.elapsed() < waitTime) { // wait until the rimer is done
button.process(); // check the button while the timer is going
if (button.isPressed()) { // if the button was pressed too early
P.print("EARLY!"); // print "EARLY!" on the screen
delay(500);
P.displayClear();
return false; // return false so the rest of the code knows the user pressed early
}
}
return true; // otherwise return true
}

void activateStimulus(char stimulus) {
switch (stimulus) {
case 'S': // if the stimulus = 'S'
digitalWrite(BUZZER_PIN, HIGH); // turn the buzzer on
break;
case 'L': // if the stimulus = 'L'
P.setInvert(true); // turn the screen on by inverting it
P.displayClear();
break;
default: // if the stimulus = anything else
P.setInvert(true); // turn on buzzer and screen
P.displayClear();
digitalWrite(BUZZER_PIN, HIGH);
break;
}
}

uint16_t recordReactionTime() {
reactionStopwatch.restart(); // start the reaction stopwatch
while (button.isReleased() && reactionStopwatch.elapsed() < 1000) { // while the button is not pressed and the timer is belo 1000 milliseconds
button.process(); // check the button for presses
}
return reactionStopwatch.elapsed(); // return the value of the stopwatch
}

void deactivateStimulus() {
P.setInvert(false); // turn off the buzzer and screen
P.displayClear();
digitalWrite(BUZZER_PIN, LOW);
}

void printTime(uint16_t time) {
Serial.println(time); // print the time on the serial monitor
}

void waitForRelease() {
while (button.isPressed()) { // wait until the button is pressed
button.process();
}
}

void checkForModeChange() {
if(Serial.available() > 0){ // if there is any message sent to the arduino
char serialData = Serial.read(); // set serialData to that value
switch (serialData) {
case 'S': // if serialData = 'S'
STIMULUS_TYPE = 'S'; // set the stimulus type to sound
Serial.println("STIMULUS_TYPE set to sound.");
break;
case 'L': // if serialData = 'L'
STIMULUS_TYPE = 'L'; // set the stimulus type to light
Serial.println("STIMULUS_TYPE set to light.");
break;
case 'B': // if serialData = 'B'
STIMULUS_TYPE = 'B'; // set the stimulus type to sount + light
Serial.println("STIMULUS_TYPE set to sound + light.");
break;
case 'P': // if serialData = 'P'
Serial.println("Paused."); // puase the game
while (Serial.available() > 0) { // clear the serial cache
Serial.read();
}
while (true) { // wait until the loop is broken out of
if(Serial.available() > 0){ // if a serial message is availabe
char serialData = Serial.read(); // set serialData to the new message
if (serialData == 'P'){ // if serialData = 'P'
Serial.println("Unpaused."); // unpause the game
break; // break out of the while loop
}
}
}
break;
default: // if the serial message is not equal to 'S', 'L', 'B', or 'P'
Serial.println("Not a valid stimulus type."); // print the proper instructions for the settings
Serial.println("'S' = sound");
Serial.println("'L' = light");
Serial.println("'B' = sound + light");
Serial.println("'P' = pause/unpause");
break;
}
while (Serial.available() > 0) { // clear the serial cache
Serial.read();
}
}
}

Usage

just a demo of me using the reaction speed game

This is how you use the device.

  1. Plug the timer into any device with a serial monitor or plotter (your could use Arduino IDE or an online option like https://web-serial-plotter.atomic14.com/)
  2. Set baud rate on your device to 115200
  3. Press the button whenever the screen lights up or the buzzer beeps.
  4. If you want to switch to a different mode send:
  5. 'L' to switch to light.
  6. 'S' to switch to sound.
  7. 'B' to switch to light+sound.
  8. 'P' to pause, unpause the game.
  9. Note that these settings will only be triggered at the end of the loop.

Final Thoughts

Screenshot 2026-03-11 122737.png
Screenshot 2026-03-11 123533.png

I really enjoyed making this project and I hope you liked reading this documentation of me making it. Maybe it could help you improve your reaction time. I learned about how your brain processes stimulus and how you can react to sound faster than light. I tested each mode for 20 rounds and I ended up getting a score slightly faster on average for sound.