TaserDerby
✨ Inspiration
The project was inspired by the desire to create a fun, high-stakes bridge between the digital world and a physical consequence. We wanted a seemingly trivial betting game to have immediate, tangible, and slightly humorous stakes. The idea was to take the abstract concept of a microscopic sperm race using a dark, blurry "microscope" aesthetic and connect the moment of defeat to a physical penalty relay, making the outcome of the digital simulation matter in the real world.
🕹️ What it does
GoonHacks: Pretty Derby runs a full-screen, physics-based simulation of microscopic racers (sperms) moving toward a top-right goal zone.
- Race Setup: The user sets a difficulty threshold $T$ (Top 1 to Top 8) and places a bet on one racer.
- Simulation: The game uses randomized, biased physics to drive the racers toward the goal.
- Defeat Trigger: If the user's chosen racer fails to finish within the Top $T$ positions, the application sends an HTTP POST request to the linked ESP32-C3 microcontroller.
- Physical Penalty: The ESP32 receives the signal and momentarily activates a connected 5V relay, administering a physical consequence (the "penalty pulse") to a separate load.
🏗️ How we built it
The project is split into two distinct parts:
Frontend (Web App)
Built using React and Vite, with all styling handled by Tailwind CSS.
- We used the HTML Canvas API within a React component to handle all real-time rendering and physics simulation (a biased random walk).
- The UI logic manages fullscreen modals for betting and results.
- The defeat logic sends a JavaScript Fetch API POST request to the pre-configured IP address of the ESP32.
Backend (Hardware)
Powered by an ESP32-C3 running an Arduino sketch.
- The code uses the ESPAsyncWebServer library to set up a lightweight Wi-Fi server.
- The server listens specifically for the
/loseendpoint. - Upon receiving the POST request, the code pulses a designated GPIO pin (connected to the relay's control pin) from LOW to HIGH for 2 seconds, then back to LOW.
🚧 Challenges we ran into
The primary challenge was debugging and fixing the Brownout Detection (BOD) resets on the ESP32.
- When the high-current 5V relay coil was powered directly from the ESP32's VDD (5V) pin, the sudden current draw caused the voltage to drop below the chip's minimum threshold.
- This caused the ESP32 to instantly crash and reboot whenever the "penalty" was triggered.
- Solution: We had to implement full power isolation by removing the JD-VCC jumper on the relay module and connecting the coil power (
JD-VCC) to a separate, dedicated 5V power supply. This fixed the instability.
🎉 Accomplishments that we're proud of
- Successfully implementing a reliable digital-to-physical trigger using a simple HTTP request on a low-power microcontroller.
- Creating a surprisingly smooth and visually engaging real-time physics simulation entirely within the HTML Canvas.
- Overcoming the complex hardware-level power interference issue (the brownout) to ensure the system is robust and stable under load.
💡 What we learned
We gained valuable experience in embedded networking, particularly in:
- Asynchronous server handling on microcontrollers (using
ESPAsyncWebServer). - The critical necessity of power isolation and common grounding when interfacing high-current components (relays, motors) with sensitive logic components (ESP32).
- Optimizing canvas rendering performance within a modern React application structure.
🚀 What's next for GoonHacks: Pretty Derby
- Expand Physics: Introduce obstacles and power-ups into the microscopic environment to make the race visually more complex and strategically deeper.
- Persistent Scoreboard: Add a database layer (like Firebase) to track user history and total penalties delivered.
- External Data Integration: Pull external randomized data (weather, stock market fluctuations) to influence racer speeds, making the "microscope" seem like it's reacting to the world.
Built With
- c++
- esp32-c3
- espasyncwebserver
- fetchapi
- javascript
- react
- tailwind
- vite
Log in or sign up for Devpost to join the conversation.