Skip to content

Instantly share code, notes, and snippets.

@eonist
Created March 9, 2026 04:16
Show Gist options
  • Select an option

  • Save eonist/2d421d16c873bf5caae1c71fe8f698e8 to your computer and use it in GitHub Desktop.

Select an option

Save eonist/2d421d16c873bf5caae1c71fe8f698e8 to your computer and use it in GitHub Desktop.
Stem bike brain.md

DIY Bike Tracker — Build Guide

Overview

A compact, GPS-enabled bike tracker with Bluetooth (BLE), built to fit inside a seat tube. It tracks speed and position, sends data to a phone app, and includes an integrated brake light system using LEDs and an accelerometer.

Estimated cost: ~435 NOK (AliExpress) / ~1,330 NOK (local hobby shops)


Parts List

Main Electronics

Component Model Qty Purpose Price (CN) Price (NO)
Microcontroller ESP32-C3 SuperMini 1 Brain, Bluetooth 5.0, PWM control 35 kr 120 kr
GPS Module Beitian BN-180 or ATGM336H 1 Speed & location tracking 90 kr 250 kr
GPS Antenna 15×15mm Active Ceramic (u.FL/IPEX) 1 Signal reception through seat tube hole incl. incl.
Accelerometer LIS3DH (breakout board) 1 Brake detection & deep sleep wake 25 kr 90 kr

Brake Light System

Component Model Qty Purpose Price (CN) Price (NO)
LEDs 3W Red Power LEDs 5 Brake light (15–50 lumen) 20 kr 100 kr
Lenses 13mm Mini TIR LED Lenses (60°) 5 Focus & prism effect 15 kr 80 kr
LED Driver IRLB8721 Logic Level MOSFET 1 Lets ESP32 drive high-power LEDs 10 kr 40 kr
Resistors Appropriate values for LEDs 5 Current limiting incl. incl.

Power System

Component Model Qty Purpose Price (CN) Price (NO)
Battery 18650 Li-ion 3500mAh (Samsung 35E / LG MJ1) 3 10,500 mAh total capacity 180 kr 450 kr
Charge Module TP4056 USB-C (with protection) 1 Charging & battery safety 10 kr 50 kr
USB-C Breakout Female USB-C breakout board (optional) 1 Mount charge port in seat tube hole incl. incl.

Mounting & Protection

Component Purpose Price (CN) Price (NO)
30AWG Silicone Wire (stranded, multi-color) Vibration-resistant wiring 50 kr 150 kr
Heat Shrink Tubing (30mm & 40mm) Moisture sealing incl. incl.
Conformal Coating (e.g. MG Chemicals 419D) PCB corrosion protection incl. incl.
Clear UV Resin or 2-part Epoxy Waterproof lens sealing (IP67) incl. incl.
Self-adhesive Foam Tape / Neoprene Vibration dampening in tube incl. incl.
Thermal Glue Heat transfer from LEDs to metal tube incl. incl.

Tools Required

  • Soldering iron + solder (rosin core flux)
  • Multimeter (check for shorts before connecting battery)
  • Heat gun or lighter (for heat shrink)
  • UV lamp (if using UV resin)

Assembly — Physical Layout

Where Everything Goes (Seat Tube Stack)

The components are stacked vertically inside the seat tube in a "sandwich" formation:

  ┌─────────────────────┐  ← Seat tube opening / hole
  │  GPS Antenna         │  ← Topmost: sits at or just below the hole
  │  (faces skyward)     │
  ├─────────────────────┤
  │  USB-C Breakout      │  ← Optional: mounted in the hole for charging
  ├─────────────────────┤
  │  GPS Module (BN-180) │
  │  ───────────────────│
  │  ESP32-C3 SuperMini  │  ← Glued back-to-back with GPS, insulation between
  │  ───────────────────│
  │  LIS3DH Accelerometer│
  ├─────────────────────┤
  │  MOSFET + Resistors  │  ← LED driver circuit
  ├─────────────────────┤
  │  18650 Battery #1    │
  │  18650 Battery #2    │  ← 3 cells in parallel (same voltage!)
  │  18650 Battery #3    │
  └─────────────────────┘  ← Bottom of seat tube

LED Placement

  • Drill 4–5 small holes in the seat post, facing rearward
  • Mount each 3W LED behind a TIR lens in each hole
  • Seal with clear UV resin or epoxy for waterproofing (IP67)
  • Glue LED backs to the metal tube wall with thermal glue (acts as heatsink)

Antenna Placement

The GPS antenna must have "sky view" — metal blocks GPS signals (Faraday cage effect).

  • Route a thin u.FL cable from the GPS module up through the seat tube hole
  • Place the 15×15mm ceramic antenna at the opening, just under the seat
  • If the frame is carbon, signal may partially pass through without external antenna

Wiring Diagram

Power Circuit

USB-C ──→ TP4056 Charge Module
                │
          B+ ───┤──→ 3x 18650 in Parallel (connect + to + , − to −)
          B− ───┘
                │
         OUT+ ──┤──→ ESP32 VIN (3.3V regulated onboard)
         OUT− ──┘──→ ESP32 GND

⚠️ Before connecting batteries in parallel, charge each cell individually to the same voltage first.

GPS Module → ESP32

BN-180 TX  ──→  ESP32 RX (GPIO20 or any UART-capable pin)
BN-180 RX  ──→  ESP32 TX (GPIO21 or any UART-capable pin)
BN-180 VCC ──→  3.3V
BN-180 GND ──→  GND
u.FL port  ──→  External GPS antenna (via cable through tube)

Accelerometer → ESP32 (I2C)

LIS3DH SDA ──→  ESP32 SDA (GPIO8)
LIS3DH SCL ──→  ESP32 SCL (GPIO9)
LIS3DH VCC ──→  3.3V
LIS3DH GND ──→  GND
LIS3DH INT ──→  ESP32 GPIO (for wake-from-sleep interrupt)

LED Brake Light Circuit

Battery+ ──→ MOSFET Drain ──→ LED+ (via resistor per LED)
                                LED− ──→ GND
ESP32 GPIO (PWM) ──→ MOSFET Gate (with pull-down resistor)
MOSFET Source ──→ GND

Software Logic

Libraries

  • TinyGPS++ — Parses GPS data; use .speed.kmph() for speed
  • ESP32 BLE Arduino — Bluetooth Low Energy communication with phone app

Core Behavior

  1. Boot → Initialize GPS, BLE, accelerometer
  2. Active Mode (cycling):
    • GPS reads position & speed at 1–10 Hz
    • ESP32 sends speed via BLE to phone app
    • Accelerometer detects braking (negative G-force) → trigger LEDs at 50 lumen
    • Normal riding → LEDs at ~15 lumen (tail light mode)
  3. Deep Sleep Mode (parked):
    • No motion for 2 min → turn off GPS & BLE
    • Power draw drops to ~1–2 mA (accelerometer stays awake)
    • Motion detected → instant wake-up, resume tracking
  4. BLE timeout:
    • No phone connected for 5 min → stop BLE advertising to save power

Speed Smoothing

GPS speed can jump under trees or between buildings. Apply a simple moving average filter (last 3 readings) for stable display in the app.


Battery Life Estimates

Mode Current Draw Duration (10,500 mAh)
Active (GPS + BLE + tail light) ~100–150 mA ~35+ hours continuous
Braking (LEDs at 50 lumen) ~300–500 mA Burst only
Deep Sleep (parked) ~1–2 mA ~200+ days
Real-world (1 hr/day commute) 2–4 months between charges

Battery Tips

  • Cold weather (−5°C to −10°C) reduces effective capacity by 20–30%
  • Poor GPS signal = higher power draw (module works harder)
  • 10 Hz updates use more power than 1 Hz — tune to your needs

Weatherproofing Checklist

  • Heat shrink (with adhesive lining) around all electronics except antenna
  • Conformal coating on all PCBs to prevent condensation corrosion
  • UV resin or epoxy seal on each LED lens hole (flush with seat post)
  • Foam/neoprene wrap around the module stack to prevent rattling
  • Use stranded silicone wire (not solid core) — handles vibration

Mounting Options

Location Pros Cons
Inside seat tube (recommended) Invisible, theft-proof, protected Requires external GPS antenna, metal blocks BLE signal
Under the seat Easy access, good GPS signal Visible, vulnerable to theft/weather
Bottle cage mount Flat box, easy to remove for charging Takes up bottle cage spot

Scaling to Production

Volume Estimated Unit Cost
1 (prototype) ~435 kr (CN) / ~1,330 kr (NO)
100 units ~300 kr (custom PCB)
1,000+ units ~200–250 kr (PCBA + bulk batteries)

Suggested retail price: ~990 kr (healthy margin for an advanced product).

Note: 25% MVA (VOEC) applies on shipments from abroad over 350 kr. Always use reputable battery brands (Samsung, Panasonic, LG) — avoid cheap cells with fake capacity ratings.

@eonist
Copy link
Author

eonist commented Mar 9, 2026

Revision for find my support:

DIY Bike Tracker — Build Guide

Overview

A compact, GPS-enabled bike tracker with Bluetooth (BLE), built to fit inside a seat tube. It tracks speed and position, sends data to a phone app, and includes an integrated brake light system using LEDs and an accelerometer. Supports both Apple Find My and Google Find My Device networks via the official MFi / FMDN certification path.

Estimated cost: ~480 NOK (AliExpress) / ~1,400 NOK (local hobby shops)


Parts List

Main Electronics

Component Model Qty Purpose Price (CN) Price (NO)
Microcontroller Seeed XIAO nRF52840 Sense 1 Brain, Bluetooth 5.0, NFC, PWM control, built-in IMU + mic 160 kr 220 kr
GPS Module Beitian BN-180 or ATGM336H 1 Speed & location tracking 90 kr 250 kr
GPS Antenna 15×15mm Active Ceramic (u.FL/IPEX) 1 Signal reception through seat tube hole incl. incl.
Piezo Buzzer 9mm Passive Piezo Buzzer (3.3V) 1 Apple Find My "play sound" (required for MFi) 5 kr 30 kr

Why the Sense variant? The XIAO nRF52840 Sense has a built-in 6-axis IMU (LSM6DS3TR-C) that replaces the separate LIS3DH accelerometer, and a PDM microphone — saving a component and wiring. The nRF52840 chip also has built-in NFC required by Apple Find My for lost-mode tap-to-identify.

Brake Light System

Component Model Qty Purpose Price (CN) Price (NO)
LEDs 3W Red Power LEDs 5 Brake light (15–50 lumen) 20 kr 100 kr
Lenses 13mm Mini TIR LED Lenses (60°) 5 Focus & prism effect 15 kr 80 kr
LED Driver IRLB8721 Logic Level MOSFET 1 Lets nRF52840 drive high-power LEDs 10 kr 40 kr
Resistors Appropriate values for LEDs 5 Current limiting incl. incl.

Power System

Component Model Qty Purpose Price (CN) Price (NO)
Battery 18650 Li-ion 3500mAh (Samsung 35E / LG MJ1) 3 10,500 mAh total capacity 180 kr 450 kr
Charge Module TP4056 USB-C (with protection) 1 Charging & battery safety 10 kr 50 kr
USB-C Breakout Female USB-C breakout board (optional) 1 Mount charge port in seat tube hole incl. incl.

Mounting & Protection

Component Purpose Price (CN) Price (NO)
30AWG Silicone Wire (stranded, multi-color) Vibration-resistant wiring 50 kr 150 kr
Heat Shrink Tubing (30mm & 40mm) Moisture sealing incl. incl.
Conformal Coating (e.g. MG Chemicals 419D) PCB corrosion protection incl. incl.
Clear UV Resin or 2-part Epoxy Waterproof lens sealing (IP67) incl. incl.
Self-adhesive Foam Tape / Neoprene Vibration dampening in tube incl. incl.
Thermal Glue Heat transfer from LEDs to metal tube incl. incl.

Find My Network Compatibility

The nRF52840 is one of the only chips officially supported by both Apple and Google for their Find My networks.

Feature Support
Apple Find My (MFi) ✅ via Nordic nRF Connect SDK
Google Find My Device (FMDN) ✅ via Nordic nRF Connect SDK
NFC (Apple lost mode tap) ✅ Built into nRF52840
Play Sound (anti-stalking) ✅ Via piezo buzzer
DULT (unwanted tracker detection) ✅ Required by both Apple & Google
UWB Precision Finding (optional) ❌ Requires additional Qorvo DW3xxx chip

MFi Certification Path

  1. Enroll in Apple's MFi Program at mfi.apple.com
  2. Submit a Product Plan for approval
  3. Develop firmware using Nordic's nRF Connect SDK (Find My integration)
  4. Test with Apple's "Find My Certification Asst." app
  5. Pass Apple factory audit
  6. Timeline: ~45+ working days

Google FMDN Certification

  1. Implement Fast Pair + FMDN spec on nRF Connect SDK
  2. Register product with Google
  3. Implement DULT anti-stalking compliance
  4. Requires Android 9+ on user's phone

Tools Required

  • Soldering iron + solder (rosin core flux)
  • Multimeter (check for shorts before connecting battery)
  • Heat gun or lighter (for heat shrink)
  • UV lamp (if using UV resin)
  • nRF Connect SDK + VS Code (firmware development)
  • J-Link or XIAO's built-in USB bootloader (flashing)

Assembly — Physical Layout

Where Everything Goes (Seat Tube Stack)

The components are stacked vertically inside the seat tube in a "sandwich" formation:

  ┌─────────────────────┐  ← Seat tube opening / hole
  │  GPS Antenna         │  ← Topmost: sits at or just below the hole
  │  (faces skyward)     │
  ├─────────────────────┤
  │  USB-C Breakout      │  ← Optional: mounted in the hole for charging
  ├─────────────────────┤
  │  GPS Module (BN-180) │
  │  ─────────────────── │
  │  XIAO nRF52840 Sense │  ← Glued back-to-back with GPS, insulation between
  │  (21 x 17.5 mm)      │     Built-in: IMU, mic, NFC, BLE antenna
  │  ─────────────────── │
  │  Piezo Buzzer         │  ← Apple Find My "play sound"
  ├─────────────────────┤
  │  MOSFET + Resistors  │  ← LED driver circuit
  ├─────────────────────┤
  │  18650 Battery #1    │
  │  18650 Battery #2    │  ← 3 cells in parallel (same voltage!)
  │  18650 Battery #3    │
  └─────────────────────┘  ← Bottom of seat tube

Note: The XIAO nRF52840 Sense is only 21 × 17.5 mm — smaller than the ESP32-C3 SuperMini — and fits easily in any standard seat tube (27.2mm+).

LED Placement

  • Drill 4–5 small holes in the seat post, facing rearward
  • Mount each 3W LED behind a TIR lens in each hole
  • Seal with clear UV resin or epoxy for waterproofing (IP67)
  • Glue LED backs to the metal tube wall with thermal glue (acts as heatsink)

Antenna Placement

The GPS antenna must have "sky view" — metal blocks GPS signals (Faraday cage effect).

  • Route a thin u.FL cable from the GPS module up through the seat tube hole
  • Place the 15×15mm ceramic antenna at the opening, just under the seat
  • If the frame is carbon, signal may partially pass through without external antenna
  • The nRF52840's onboard BLE antenna should be positioned near the tube opening for best range
  • NFC antenna is built into the XIAO board — position the board near the top so NFC tap works through the opening

Wiring Diagram

Power Circuit

USB-C ──→ TP4056 Charge Module
                │
          B+ ───┤──→ 3x 18650 in Parallel (connect + to + , − to −)
          B− ───┘
                │
         OUT+ ──┤──→ XIAO VIN / 5V pad (3.3V regulated onboard)
         OUT− ──┘──→ XIAO GND

⚠️ Before connecting batteries in parallel, charge each cell individually to the same voltage first.

GPS Module → XIAO nRF52840

BN-180 TX  ──→  XIAO D7 / RX (P0.22)
BN-180 RX  ──→  XIAO D6 / TX (P0.24)
BN-180 VCC ──→  3.3V
BN-180 GND ──→  GND
u.FL port  ──→  External GPS antenna (via cable through tube)

Accelerometer (Built-in IMU)

No external wiring needed — the LSM6DS3TR-C is soldered onto the XIAO Sense board and communicates via internal I2C. Access it in firmware directly.

Piezo Buzzer

Buzzer +   ──→  XIAO D0 (or any PWM-capable pin)
Buzzer −   ──→  GND

LED Brake Light Circuit

Battery+ ──→ MOSFET Drain ──→ LED+ (via resistor per LED)
                                LED− ──→ GND
XIAO D1 (PWM) ──→ MOSFET Gate (with 10kΩ pull-down resistor)
MOSFET Source ──→ GND

Software Logic

SDK & Toolchain

  • Nordic nRF Connect SDK (based on Zephyr RTOS) — required for official Find My / FMDN
  • NMEA parser (Zephyr-compatible) — parses GPS data for speed and position
  • Find My SDK — accessed via MFi license through nRF Connect SDK
  • FMDN SDK — Google's Find My Device Network spec, also via nRF Connect SDK

Core Behavior

  1. Boot → Initialize GPS (UART), BLE, NFC, IMU, Find My services
  2. Active Mode (cycling):
    • GPS reads position & speed at 1–10 Hz
    • nRF52840 sends speed via BLE to phone app (custom GATT service)
    • IMU detects braking (negative G-force) → trigger LEDs at 50 lumen
    • Normal riding → LEDs at ~15 lumen (tail light mode)
    • Find My beacons broadcast in background (both Apple & Google)
  3. Deep Sleep Mode (parked):
    • No motion for 2 min → turn off GPS and custom BLE service
    • Find My BLE advertising continues (ultra-low power, ~5 μA)
    • Power draw drops to ~5–10 μA (IMU wake-on-motion interrupt active)
    • Motion detected → instant wake-up, resume full tracking
  4. Find My Features:
    • Play sound via piezo buzzer when triggered from Find My app
    • NFC tap in lost mode shows owner contact info
    • DULT: respond to unwanted tracker detection scans
  5. BLE timeout:
    • No phone connected for 5 min → stop custom BLE service advertising
    • Find My advertising always stays on (negligible power)

Speed Smoothing

GPS speed can jump under trees or between buildings. Apply a simple moving average filter (last 3 readings) for stable display in the app.


Battery Life Estimates

Mode Current Draw Duration (10,500 mAh)
Active (GPS + BLE + tail light) ~70–100 mA ~50+ hours continuous
Braking (LEDs at 50 lumen) ~300–500 mA Burst only
Deep Sleep + Find My beacon ~5–10 μA 2+ years standby
Real-world (1 hr/day commute) 3–5 months between charges

The nRF52840 draws significantly less current than the ESP32-C3 (~15–20 mA active BLE vs ~40–50 mA), and its deep sleep is ~5 μA vs ~1–2 mA. This means Find My tracking continues for months even when parked, without draining the battery.

Battery Tips

  • Cold weather (−5°C to −10°C) reduces effective capacity by 20–30%
  • Poor GPS signal = higher power draw (module works harder)
  • 10 Hz updates use more power than 1 Hz — tune to your needs
  • Find My beacons are extremely low power and can stay on indefinitely

Weatherproofing Checklist

  • Heat shrink (with adhesive lining) around all electronics except antenna
  • Conformal coating on all PCBs to prevent condensation corrosion
  • UV resin or epoxy seal on each LED lens hole (flush with seat post)
  • Foam/neoprene wrap around the module stack to prevent rattling
  • Use stranded silicone wire (not solid core) — handles vibration
  • Ensure buzzer sound can escape (small vent hole or thin membrane)

Mounting Options

Location Pros Cons
Inside seat tube (recommended) Invisible, theft-proof, protected Requires external GPS antenna, metal may weaken BLE/NFC
Under the seat Easy access, good GPS + BLE signal Visible, vulnerable to theft/weather
Bottle cage mount Flat box, easy to remove for charging Takes up bottle cage spot

Scaling to Production

Volume Estimated Unit Cost
1 (prototype) ~480 kr (CN) / ~1,400 kr (NO)
100 units ~350 kr (custom PCB + MFi fees)
1,000+ units ~200–250 kr (PCBA + bulk batteries)

Suggested retail price: ~990–1,290 kr (premium justified by dual Find My support).

Note: 25% MVA (VOEC) applies on shipments from abroad over 350 kr. Always use reputable battery brands (Samsung, Panasonic, LG) — avoid cheap cells with fake capacity ratings. MFi enrollment and factory audit costs are separate from per-unit costs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment