I'm a fan of Rhythm games & I've played many throughout the years, especially osu!
For this week's task, we needed to work with a Bluetooth module, So I thought what If I could make a game on PC that would connect to an Arduino through bluetooth and become output to the player's input? It could react via sound and light to the player's Inputs to provide visual and auditory feedback to their gameplay.
The main idea of rhythm games is to test the player's ability to react on time, In my game, notes fall from 4 different locations, and once they line up on the green bar, you hit the corresponding key, If you get it perfectly, you get a PERFECT score, the LED lights up green and the buzzer sing the note, if you're hit it too early or too late, you get an OKAY score, the led lights up yellow, and buzzer singes it off-beat, if you completely miss it, you get a MISS score, LED lights up red, and buzzer does not sing the note at all.
Used to design the complete circuit.
Used to export code to the Arduino hardware
Used to create the Game GUI with Pygame & Serial libraries.
Arduino UNO: Main controller to receive Serial commands and drive outputs (LED + buzzer).
Bluetooth Module (HC-05): Enables wireless Serial communication between the laptop game and Arduino.
RGB LED (Common Cathode): Visual feedback (green = perfect, yellow = okay, red = miss).
Three 220 Ω Resistors: Current limiting for each LED channel.
Buzzer: Plays short tones mapped to keys.
9V Power Supply: External source to power the circuit.
Voltage Regulator (9V → 5V): Provides safe 5V supply to Arduino and Bluetooth module.
Mini Breadboard: For assembling and wiring all components.
Jumper Wires: To connect components and modules together.
USB Cable (optional): For uploading code to Arduino before switching to Bluetooth communication.
(Follow along if you want to make the same circuit)
Add the parts:
Arduino UNO
RGB LED (common cathode)
3x220Ω resistors
Buzzer
Bluetooth module (HC-05)
9V power supply
9V → 5V voltage regulator
Wire the RGB LED (common cathode):
COM → Arduino GND
R → Arduino pin 4 through 220Ω resistor
G → Arduino pin 3 through 220Ω resistor
B → Arduino pin 2 through 220Ω resistor
Wire the Buzzer:
(+) → Arduino pin 11
(–) → Arduino GND
Wire the Bluetooth Module:
VCC → Arduino 5V
GND → Arduino GND
TX (Bluetooth) → Arduino pin 0 (RX)
RX (Bluetooth) → Arduino pin 1 (TX) through a voltage divider
Built using three 1 kΩ resistors: two in series on one side, one on the other.
This drops the Arduino’s 5V TX signal down to ~3.3 V, which is safe for the Bluetooth module’s RX pin.
Wire the Voltage Regulator and Power Supply:
9V supply → Regulator input
Regulator output → Arduino VIN (regulated to 5V)
Regulator GND → Arduino GND
This way, the Arduino runs safely from a stable 5V line while powered by an external 9V source, and the Bluetooth module can communicate with the laptop over Serial.
The Arduino runs a simple Serial interpreter. It listens for characters sent from the PC over Bluetooth or USB Serial.
If it receives d, f, j, or k, it plays a short tone on the buzzer with different frequencies, creating note sounds.
If it receives R, G, or Y, it lights the RGB LED in Red (miss), Green (perfect), or Yellow (okay).
The LED automatically turns off after 1 second to avoid staying stuck on.
On the PC side, a game was developed in Python using Pygame and the serial library.
Notes spawn in one of four lanes (d, f, j, k) based on the rhythm (BPM).
The player must press the corresponding keyboard key when the note reaches the hit line.
Depending on timing accuracy:
Perfect: sends G and the note’s key to Arduino → LED turns green + buzzer plays.
Okay: sends Y and the note’s key → LED turns yellow + buzzer plays
Miss: sends R → LED turns red, no note sound.
Missed notes falling off-screen also trigger R.
Pygame handles all graphics (lanes, notes, hit line, feedback text), while Arduino handles the physical feedback (lights + sound).
This step is very important, To make the Python game GUI talk to the Arduino, I had to specify the correct COM port in the code.
Paired the Arduino the HC-05 Bluetooth module.
Opened Device Manager → Ports (COM & LPT) on Windows.
Found my device listed as Arduino Uno (COM8).
Edited my Python code from:
ser = serial.Serial("COM5", 9600, timeout=1)
to:
ser = serial.Serial("COM8", 9600, timeout=1)
Tested communication by sending characters from my PC and checking that the LED & buzzer responded.
NOTE: There might be two COMs listed in the Device Manager, one is for Output and one for Input, try both to see which one works.
After you've done, that, you should now be able to simply call ser.write() anywhere in your game, for example:
We have the circuit, we have its code logic, now let's actually make them!
Let's define our pins:
Also define the specific sounds for the buzzer:
Variables to keep track of time:
Setup function:
Loop function: Main logic of note and led triggers here, as well as timer for leds:
Helper functions:
I placed the Arduino UNO on the table and uploaded the code sketch to it via Arduino IDE. and placed a mini breadboard next to it.
I mounted the 9V → 5V regulator and connected the 9V supply to its input. I routed the regulator output to the Arduino 5V rail and to the breadboard 5V rail, and tied the regulator ground to the breadboard ground.
I placed the HC-05 module on the breadboard near the Arduino and wired:
HC-05 VCC → 5V rail
HC-05 GND → GND
I built the RX voltage divider for HC-05 RX using three 1 kΩ resistors: two 1k in series to GND and one 1k from Arduino TX to the divider node that feeds HC-05 RX (this brings the ~5V TX down to ≈3.3V).
I connected HC-05 TX directly to Arduino RX (pin 0).
I inserted the common-cathode RGB LED into the breadboard and added three 220 Ω resistors:
R → Arduino pin 4 through 220 Ω
G → Arduino pin 3 through 220 Ω
B → Arduino pin 2 through 220 Ω
COM → GND
I placed the buzzer on the breadboard and wired:
(+) → Arduino pin 11
(–) → GND
I disconnected the HC-05 TX/RX jumpers before uploading the sketch, uploaded the Arduino code over USB, and used the Serial Monitor (9600) to verify basic responses.
After a successful upload, I reconnected the HC-05 Bluetooth Module TX/RX (with the RX through the resistor divider) and powered the regulator from the 9V supply so the Arduino ran from the breadboard 5V.
I paired the HC-05 with my laptop, noted the assigned COM port, and updated the Python serial.Serial() port string to match.
I ran a quick serial check from the laptop (open COM at 9600, send G, R, and a key like d) to confirm the LED and buzzer responded.
Finally, I launched the Pygame program, tested gameplay keys (d, f, j, k), and observed the HC-05 → Arduino feedback (LED color + buzzer) during play.
My friend helped me a lot to understand how Serial communication actually works, and why we can’t leave the TX/RX pins connected while uploading code, this saved me a lot of headaches later.
Think of Serial as a stream of data moving at an agreed speed. That’s why we start with:
Serial.begin(9600);
Both sides need to “speak” at the same rate.
On boards like the Arduino Uno or Nano, the USB connection to your computer and the TX/RX pins both share the same Serial hardware. When you upload code, the bootloader uses that Serial link.
If a Bluetooth module (or any other device) is still connected to TX/RX, it can interfere with this process by sending or holding signals, which prevents the upload from working. That’s why we usually disconnect it while programming.
I learned this from searching on Stack overflow, linked here
I also learned that boards with multiple Serial ports (like the Mega) don’t have this problem, since you can keep one port for uploads and another for external modules.
If you're stuck, Here's a couple helpful tutorials that I used:
Python Communication to Arduino Tutorial
Python Communication Bluetooth (Open source)
When I first started, I had no idea how I could communicate with the Bluetooth module directly from my laptop. we were only shown how to use a phone app with a Bluetooth terminal, but my project required something completely different, a full PC app with a custom GUI for a rhythm game.
This was the point where I had to stop and dig deeper. I researched how Serial communication actually works, and how data from the Bluetooth module can be accessed on the laptop through a virtual COM port. That led me to learning Python’s serial library, which finally gave me control over the data stream. From there, I combined it with pygame to build my own game interface that could react to Bluetooth input.
The biggest pitfall others can avoid is assuming the phone-only method is the only way to work with Bluetooth modules. Once you understand that they just act like a Serial port, you can use them with any programming language or platform that supports Serial.
Another challenge is making sure not to leave the module connected to TX/RX while uploading, since it will block code uploads, something that confused me until I learned how Arduino’s Serial works.
My code quality improved significantly from this project, Optimized for clarity and performance, which will certainly come in handy for my final project.