Projects · Fitness AI Agents · FitnessAI Watch
The Build
It is also the second life of a competition entry. The first version was built for PhysTech 2026 and was the first hardware Matt had ever built. After that submission the surrounding project pivoted to a multi-source data platform, and the firmware was restarted from scratch in June 2026 on the lessons from the first build.
Hardware
ESP32-C3 SuperMini
MCU and Wi-Fi radio on one ~$3 board. Chosen because it has Wi-Fi built in, so the watch needs no phone to reach the internet.
SSD1306 128×64 OLED
Shared I2C bus at address 0x3C. An LCD1602 with a PCF8574 backpack is supported as an alternative panel on the same pins.
MPU6050
Accelerometer and gyroscope at 0x68. Drives step counting and, in the current firmware, auto-rotates the display so it stays upright.
MAX30102
Heart rate and SpO₂ at 0x57, plus a die-temperature reading. Polled every loop rather than using its interrupt line.
NEO-6M GPS (optional)
Route tracking over UART1. Optional — the watch is fully functional without it.
Board
A KiCad schematic and PCB layout exist in the repo alongside the firmware, so the hand-wired prototype has a route to a real board.
What Works Today
- Five button-navigable screens — Home, Heart Rate, Steps, Sync, and sensor status.
- On-device BPM and step counting from the MAX30102 and MPU6050.
- A real clock synchronised over NTP — there is no RTC module in the design.
- Direct Wi-Fi upload to the backend /ingest endpoint.
- Two ways to pair from a phone: a self-hosted Wi-Fi captive portal, and a Bluetooth LE control peripheral that appears as “FitnessAI Watch” in any BLE scanner.
- Display auto-rotation driven by the accelerometer and gyro.
Not Built Yet
The power design does have one genuinely non-obvious trap already worked out on paper: on the SuperMini the 5V pin is USB VBUS, so tying a TP4056 charger input to it while injecting a boost converter creates a loop that charges the battery from itself. It never terminates, the cell drains faster than with no charger at all, and nothing visibly fails — which is what makes it worth documenting before building it.
Bugs Worth Keeping
The display driver. The 0.96″ SSD1306 must be initialised as NONAME, not ALT0. The ALT0 init makes a sparse test pattern look completely fine, then interleaves the rows with real text so every UI line is squashed on top of the next — a fault that only appears once you draw something realistic.
The bus clock. The shared I2C bus has to run at 100 kHz, but MAX30105.begin(Wire, I2C_SPEED_FAST, ...) silently raises it back to 400 kHz. The OLED then flickers or blanks for reasons that look nothing like a clock-speed problem. The clock is now re-asserted after the sensor init block.
What to Inspect Next
- Fitness AI Agents — the platform this watch feeds, and where the analysis happens.
- PhysTech 2026 — the competition entry this build grew out of.
- Cyberdeck — the other hardware project, a Raspberry Pi portable computer.
- All projects and About.
View the firmware on GitHub