Reaction Trainer is an embedded reflex testing and training game implemented on the ATmega328P-XMINI development board.
The project generates game rounds in which the user must react as quickly as possible to visual signals shown using two LEDs: one red LED and one yellow LED. The user must press the button corresponding to the active LED. The microcontroller measures the reaction time, detects wrong or premature button presses and calculates the final score.
The idea started from a simple reaction timer game, but the project was extended to include multiple hardware and software concepts used in embedded systems: GPIO, ADC, UART, timers and a finite state machine.
The project is useful because it demonstrates how a microcontroller can interact with external components, measure real-time events and provide feedback to the user. It is also useful for learning how to write firmware using AVR registers instead of only using high-level functions.
The system is based on the ATmega328P-XMINI board, which controls the game logic, reads the buttons, measures the reaction time and controls the visual feedback.
At startup, the system is in the idle state. The user starts the game by pressing the START button. After that, the microcontroller waits for a pseudo-random amount of time, turns on either the red LED or the yellow LED and starts measuring the reaction time.
The user must press the correct button as fast as possible. If the correct button is pressed, the reaction time is sent to the PC through UART. A point is awarded only if the response is correct and the reaction time is below 600 ms.
The difficulty is controlled using a potentiometer connected to an ADC pin. The ADC value changes the maximum allowed reaction time.
The project also includes a display module, which will be used to show the current round, reaction time and score directly on the device. Until the display arrives and is integrated, the results are shown through UART in the Serial Monitor.
The main modules of the project are:
The hardware components interact with the microcontroller through digital and analog pins. The LEDs are controlled as digital outputs, the buttons are read as digital inputs with internal pull-up resistors, and the potentiometer is read through the ADC. The results are currently transmitted to the PC using UART through the virtual COM port. The display module will later be used as the local output interface.
The software is organized as a finite state machine. Each state represents a different part of the game: waiting for start, waiting before a signal, active signal, round result and game over.
| Component | Quantity | Role in the project |
|---|---|---|
| ATmega328P-XMINI | 1 | Main development board and controller |
| Red LED | 1 | Visual signal for one reaction option |
| Yellow LED | 1 | Visual signal for the second reaction option |
| Push-buttons | 3 | START button and two answer buttons |
| Potentiometer 10kΩ | 1 | Difficulty control using ADC |
| Display module | – | – |
| Resistors 330Ω | 2 | Current limiting resistors for LEDs |
| Resistors 10kΩ | 3 | Optional pull-up/pull-down resistors for buttons |
| Breadboard | 1 | Prototype circuit assembly |
| Jumper wires | Several | Connections between components |
| Component | Microcontroller Pin | Description |
|---|---|---|
| Yellow LED | PB1 | Digital output for yellow LED |
| Red LED | PB2 | Digital output for red LED |
| START button | PD2 | Digital input with internal pull-up |
| Red button | PD3 | Digital input with internal pull-up |
| Yellow button | PD4 | Digital input with internal pull-up |
| Potentiometer | PC0 / ADC0 | Analog input for difficulty control |
| Display module | – | – |
| UART | USB / Virtual COM | Temporary output for displaying results on the PC |
The main timing signal in the project is the reaction time interval. This interval starts when one of the LEDs is turned on and stops when the user presses one of the answer buttons.
The reaction time is calculated as:
reaction time = current time - signal start time
The system also detects premature button presses, which happen when the user presses an answer button before the visual signal appears.
No simulation results are currently available.
The firmware was developed using PlatformIO for the ATmega328P microcontroller.
The final version of the code uses direct AVR register access instead of Arduino-style functions. This makes the firmware closer to the hardware and shows how the microcontroller peripherals are configured.
The project uses standard AVR headers:
No external third-party libraries are used in the final firmware.
The firmware is divided into several functional modules:
The LEDs are controlled through PORTB pins. PB1 controls the yellow LED and PB2 controls the red LED.
The buttons are connected to PORTD pins and use the internal pull-up resistors. This means that an unpressed button reads as logic 1, while a pressed button reads as logic 0.
The potentiometer is connected to PC0 / ADC0. The ADC value is used to modify the maximum allowed reaction time.
A small ADC value gives a larger reaction time window, making the game easier. A large ADC value gives a smaller reaction time window, making the game harder.
UART is currently used to display the game status, reaction times and final score on the PC. This is a temporary output method used during development and testing, because the display module has not arrived yet.
After the display module is integrated, the main game information will be shown directly on the device, while UART can still be used for debugging.
Timer1 is configured in CTC mode to generate an interrupt every 1 ms. Inside the interrupt service routine, a global millisecond counter is incremented.
This counter is used for:
The game logic is implemented as a finite state machine.
| State | Description |
|---|---|
| IDLE | Waits for the START button |
| WAIT_RANDOM | Waits for a pseudo-random interval before showing the signal |
| SIGNAL_ACTIVE | Turns on one LED and measures the reaction time |
| ROUND_RESULT | Displays the result of the current round and updates the score |
| GAME_OVER | Displays the final score and waits for restart |
A point is awarded only if:
If the user presses the wrong button, presses too early or exceeds the maximum allowed reaction time, no point is awarded.
The project currently implements a working reaction trainer game using LEDs, buttons, a potentiometer and UART output.
The user can start the game using the START button. During each round, the system turns on either the red LED or the yellow LED. The user must press the corresponding button as fast as possible.
At the current stage, the results are displayed through UART in the Serial Monitor because the display module has not arrived yet. The display will be added later in order to show the round number, reaction time and score directly on the device.
The system detects:
The reaction time and score are displayed through UART in the serial monitor.
Example output:
=== reaction trainer start === runda 1 / 5 corect, timp reactie = 421 ms punct acordat
runda 2 / 5 gresit, timp reactie = 730 ms
=== final joc === scor final: 3 / 5
The project demonstrates the use of several ATmega328P peripherals in a practical embedded application.
The firmware uses GPIO for LEDs and buttons, ADC for reading the potentiometer, UART for communication with the PC and Timer1 for measuring time. The game logic is implemented using a finite state machine, which makes the program easier to understand and extend.
The project was initially tested using simpler high-level code, then rewritten using AVR registers in order to better reflect the hardware-level programming concepts required for the course.
Possible future improvements include:
| Date | Activity |
|---|---|
| April 2026 | Project idea selection: Reaction Trainer |
| 04.05.2026 | Block diagram created and initial wiki documentation written |
| 18.05.2026 | Software implementation still incomplete - some hardware components had not arrived yet |