A smart, interactive basketball scorekeeping system powered by the Arduino Nano ESP32 and Modulino nodes. This project creates a local Wi-Fi Access Point to host a live web-based scoreboard while using physical sensors to detect baskets and manage game flow.
Key Features:
- Wireless Scoreboard: Hosts a standalone Web Server (Access Point) visible on any smartphone.
- Auto-Scoring: Uses a ToF (Time of Flight) Distance sensor to detect when a ball passes through the hoop.
- Multiplayer Support: specific game modes for 1 to 8 players.
- Visual Feedback: LED animations for player selection and victory celebration.
- Physical Controls: Tactile buttons for setting up the game and managing turns.
- Microcontroller: Arduino Nano ESP32
- Carrier: Nano Connector Carrier
- Sensors:
- Modulino Distance (ToF)
- Modulino Buttons
- Modulino Pixels (RGB LEDs)
- Cables: Qwiic / I2C cables for daisy-chaining modules.
The Modulino ecosystem relies on the I2C protocol. Connect the components in a daisy chain on the Carrier:
- Nano ESP32 -> Mount on the Connector Carrier.
- Carrier I2C Port -> Connect to Modulino Distance.
- Modulino Distance -> Connect to Modulino Buttons.
- Modulino Buttons -> Connect to Modulino Pixels.
Note: The order of the modules in the chain does not strictly matter as they function via I2C addresses.
Ensure your Nano ESP32 is flashed with the MicroPython firmware. You can use the Arduino MicroPython Installer.
Download the Arduino Lab for MicroPython for building your MicroPython scripts.
On the Arduino Lab for MicroPython editor, with the main.py there, click on the Run button.
When the device powers on, it enters Setup Mode.
- Button A: Increase number of players (Max 8).
- Button C: Decrease number of players (Min 1).
- LEDs: The number of green LEDs lit indicates the player count.
- Button B: Confirm selection and Start Game.
- On your smartphone or PC, search for Wi-Fi networks.
- Connect to SSID:
BasketballScore(No password). - Open a browser and go to
http://192.168.4.1. - The page will auto-refresh every second to show the score.
- Scoring: Place the Modulino Distance sensor inside or above the hoop. When the distance reading drops below the threshold (ball detected), the active player gets a point.
- Turn Based: After a score, the turn automatically passes to the next player.
- Skipping: Press Button B to skip the current player's turn without scoring.
- Winning: The first player to reach 8 points wins!
- The system detects a winner.
- The LEDs flash Gold (Yellow) on the specific index of the winning player.
- The Web Interface updates to display the final results.
You can adjust the global variables at the top of main.py to tweak gameplay:
score_threshold = 5 # Distance in cm to trigger a "basket"
winning_score = 8 # Points needed to winThis MicroPython script transforms the Arduino Nano ESP32 into a standalone server and game controller. It manages Wi-Fi connectivity, sensor readings, and game logic simultaneously. Here is the breakdown of the logic:
The code utilizes standard MicroPython libraries alongside specific hardware drivers:
- Network & Socket (
network,socket): These manage the Wi-Fi hardware to create an Access Point and handle HTTP requests for the scoreboard. - Modulino Drivers (
modulino): Custom classes that abstract the I2C communication for the Distance, Button, and Pixel nodes.
We define three key hardware objects:
distance: Reads the Time-of-Flight sensor to detect the ball.buttons: Handles user input for setup and gameplay.pixels: Controls the visual feedback (LEDs).
The initialization happens in three steps:
- Access Point Creation: The device turns off Station mode (Wi-Fi client) and activates Access Point mode, creating the SSID
BasketballScoreat IP192.168.4.1. - Hardware Initialization: The Modulino objects are instantiated, establishing the I2C connection.
- Player Selection Loop: Before the game begins, the code enters a
whileloop (current_mode == 1) where the user selects the number of players using Buttons A and C, visualized by the LEDs. Pressing Button B locks the configuration and moves to the game phase.
Once the game starts (current_mode == 2), the code enters a continuous loop that handles multitasking between the physical game and the digital scoreboard.
A. Game Logic (run_game)
- Scoring: The code continuously reads
distance.distance. If the value drops belowscore_threshold(default 5cm), it registers a basket. It usesticks_diffto ensure a single ball isn't counted twice (debounce). - Turn Management: When a point is scored,
active_playerincrements. If Button B is pressed, the turn is skipped manually. - Win Condition: If a player reaches
winning_score, thegame_over()function is triggered.
B. Web Server Handling
- The loop checks
server.accept()with a short timeout. - When a smartphone requests the page, the code generates the current HTML via
make_html()and sends it back. - The HTML includes a
<meta refresh>tag, forcing the browser to reload every second to see the latest score.
make_html(): Dynamically builds a string containing HTML code. It inserts the Python listplayer_scoreinto the HTML list items so the webpage reflects the real-time game state.update_pixels(count): A visual helper used during setup to light up the specific number of LEDs corresponding to the selected player count.game_over(winner_index): Handles the victory sequence. It prints the result to the console, updates the game mode to prevent further scoring, and flashes the LEDs gold to celebrate the winner.
All credits to its author: Hannes Siebeneicher

