A bicycle (and general outdoor) activity tracker built around an ESP32‑S3 AMOLED display device with onboard GPS and battery, paired with an iOS companion app for syncing, storage, and review.
The device works fully standalone — you can ride without your phone — and syncs recorded activities to the iPhone over Bluetooth Low Energy whenever it's in range.
Bixy has two pieces of software in this repo:
- Firmware (
firmware/) — runs on the ESP32‑S3 AMOLED handlebar device. Lets the rider pick an activity, tracks distance/speed/duration via GPS, shows live stats on the AMOLED display, stores activities locally, and syncs them to the phone over BLE. - iOS app (
ios/) — a SwiftUI companion that pairs with the device, pulls recorded activities, stores them, and presents a dashboard, a live view during a ride, and per‑activity detail with a map.
A shared BLE protocol spec (protocol/) is the contract between the two and is the
source of truth for services, characteristics, and on‑wire data formats.
- Connects to the iPhone over Bluetooth Low Energy (device is the GATT peripheral).
- Lets the user select an activity (e.g. Ride, Commute) and start/stop/pause tracking.
- During tracking:
- Accumulates distance traveled from GPS fixes (haversine between samples).
- Shows current speed and trip stats on the AMOLED display.
- Samples GPS periodically (configurable, ~5–10 s) rather than continuously, to save battery. Speed and distance are computed from those periodic samples.
- Works without a phone connection — activities are stored on device flash and uploaded later when a phone is available.
- Monitors battery level and manages power (display dimming/timeout, light sleep between samples).
- (Future) When connected to the phone and a navigation route is selected in the app, displays the next navigation directive on screen.
- Dashboard of past activities (type, date, distance, duration, avg speed).
- Live view mirroring the device's stats while an activity is underway.
- Activity detail with the route drawn on a map and summary statistics.
- Sync engine that discovers, transfers, and de‑duplicates activities from the device.
- Unit preferences, device pairing management, and GPX export / share.
- Upload to Strava — push a recorded ride to Strava via the API (OAuth 2.0 + GPX upload).
| Component | Choice |
|---|---|
| MCU + display | Waveshare ESP32‑S3 AMOLED dev board (QSPI AMOLED; confirm panel controller) |
| GPS | Onboard Quectel LC76G multi-GNSS over I²C/DDC; external ceramic antenna (U.FL/IPEX) |
| Battery | LiPo with onboard charging on the dev board |
| Connectivity | BLE (to iPhone); Wi‑Fi available on the SoC but unused in v1 |
Hardware specifics (exact panel controller, GPS module, pinout) are confirmed in the M0 bring‑up tasks and documented under
docs/.
┌──────────────────────────┐ BLE GATT ┌─────────────────────┐
│ ESP32‑S3 AMOLED device │ ───────────────────────► │ iPhone app │
│ (Arduino + LVGL) │ activities, live stats │ (SwiftUI) │
│ │ ◄─────────────────────── │ │
│ • Activity state machine│ time sync, (nav route) │ • Dashboard │
│ • GPS sampling loop │ │ • Live view │
│ • Distance/speed calc │ │ • Activity detail │
│ • LVGL UI on AMOLED │ │ (MapKit route) │
│ • LittleFS activity log │ │ • SwiftData store │
│ • BLE peripheral │ │ • Core Bluetooth │
│ • Power management │ │ • Sync engine │
└──────────────────────────┘ └─────────────────────┘
The device is authoritative for recording; the phone is authoritative for long‑term storage and review. Sync is one‑way for activity data (device → phone), with the phone optionally pushing time sync and, later, navigation routes back.
Bixy/
├── README.md # This file
├── AGENTS.md # Conventions & guidance for contributors / AI agents
├── firmware/ # ESP32‑S3 PlatformIO project (Arduino framework + LVGL)
│ ├── platformio.ini
│ ├── src/
│ ├── lib/
│ └── data/ # LittleFS assets (fonts, images)
├── ios/ # SwiftUI app (Xcode project)
│ └── Bixy/
├── protocol/ # Shared BLE GATT spec & on‑wire data formats (source of truth)
│ └── ble-protocol.md
└── docs/ # Architecture notes, hardware bring‑up, field‑test logs
- Firmware: C++ / Arduino framework, PlatformIO, LVGL for UI, NimBLE‑Arduino for BLE, LittleFS for storage, a GPS/NMEA parser (e.g. TinyGPS++).
- iOS: Swift / SwiftUI, SwiftData for persistence, Core Bluetooth for BLE, MapKit for route rendering. Target iOS 17+.
The repo is being bootstrapped — scaffolding lands in the M0 — Foundations tasks tracked in Linear. The commands below are the intended workflow once scaffolding exists.
# Install PlatformIO Core (or use the VS Code extension)
pip install platformio
cd firmware
pio run # build
pio run -t upload # flash the connected device
pio device monitor # serial logscd ios
xcodegen generate # generate Bixy.xcodeproj from project.yml (brew install xcodegen)
open Bixy.xcodeproj # build & run from Xcode on a device (BLE needs real hardware)Bluetooth does not work in the iOS Simulator — use a physical iPhone for BLE testing.
Work is tracked in the Bixy Linear project, organized into milestones:
- M0 — Foundations & Hardware Bring‑up — repo scaffold, display/GPS/battery bring‑up, BLE protocol spec, Xcode project.
- M1 — Device Core Tracking (offline) — activity state machine, GPS sampling, distance/speed, on‑device UI + storage, power mgmt.
- M2 — iOS Foundation & Dashboard — data models, dashboard, activity detail w/ map, settings, GPX export.
- M3 — BLE Connectivity & Sync — peripheral + central, pairing, activity transfer, dedup.
- M4 — Live Activity & Polish — live stat streaming, time sync, reconnection, low‑battery handling, field testing.
- M5 — Navigation (v2) — route selection in app, turn‑by‑turn directive protocol, on‑device directive display.
🚧 Early bootstrap. See the Linear project for current task status.