ideas.
August 15, 2026 3 min read hardwareconsumerdata

Pothole logger for your bike

A seatpost sensor and companion app that scores how rough every street you ride is, then draws it on a map you can act on.

The idea

A matchbox-sized device clamps to your seatpost and records vertical acceleration while you ride. When you get home, a phone app pulls the ride over Bluetooth, snaps the track to the street network, and scores each 10-metre segment for roughness. The result is a personal map of your city coloured by how bad the pavement actually is — not how bad someone remembers it being.

Why build this

Every regular cyclist has a mental list of streets that will rattle their fillings out, and no way to share it. Route planners optimise for distance, elevation, or the presence of a painted bike lane; none of them know that the "protected" lane on Third has a seam every four metres. Riders pick routes badly, and city public works departments run on complaint volume, which correlates with who has time to file complaints rather than where the road is worst.

The reason this is buildable now and wasn't five years ago: a Seeed XIAO ESP32-C3 with an ICM-42688-P IMU costs under fifteen dollars, BLE 5 on both phone platforms is finally boring, and open map-matching (Valhalla, OSRM) against OpenStreetMap will snap a noisy GPS trace to a way ID for free. The hard parts are commodity. What's left is the signal processing and the map.

Stack sketch

  • Device: Seeed XIAO ESP32-C3, ICM-42688-P IMU sampled at 200 Hz, 500 mAh LiPo, USB-C charging, 3D-printed clamp enclosure.
  • Firmware: Arduino core with NimBLE-Arduino. Buffer to LittleFS on the onboard flash as packed binary frames (timestamp delta, three axes, int16) — roughly 1.5 MB per hour, so a week of commuting fits without sync.
  • Position: phone GPS, not a GPS module. The phone is already logging the ride; correlating on wall-clock time is enough at 10-metre resolution and it saves you a NEO-M9N, an antenna, and a fix-acquisition problem.
  • App: Flutter with flutter_blue_plus for sync and geolocator for the track. MapLibre GL for rendering.
  • Roughness metric: band-pass the vertical axis to 0.5–30 Hz to strip out gravity and pedalling cadence, then take RMS per 10-metre bin normalised by speed. This is an IRI proxy, not IRI — call it that honestly.
  • Backend: FastAPI, Postgres with PostGIS, Valhalla for map matching. Segment scores keyed by OSM way ID plus offset.

Scope for v1

In:

  • One device, one rider, one phone. No accounts beyond a magic-link email.
  • Manual sync — open the app, tap sync, watch a progress bar.
  • A map with segments coloured on a five-step scale, and a ride list you can tap into.
  • A calibration ride: sixty seconds on pavement you declare smooth, used to set the per-device baseline.

Deliberately out: real-time streaming during the ride, crowd aggregation, photo capture at impact events, iOS background sync, and any attempt at absolute road-quality units.

Where it could go

Aggregation is the obvious second act, and it changes the product. Once twenty riders have covered the same street, you can weight by device, tyre width, and rider mass, throw out the outliers, and produce a segment score that means something to someone who wasn't on the bike. That's the version a city can use — and the export format matters more than the map at that point: a CSV or GeoJSON that drops into a 311 backlog or a pavement-management system is what gets a street resurfaced.

The other direction is routing. A "smoothest route" option layered on top of an existing bike router is a genuinely new feature, not a reskin, and it's the thing riders will actually open the app for daily. From there, e-scooter and bike-share fleets are a plausible B2B path: they already care about component wear, and vehicle-mounted units on a fleet cover a city faster than volunteers ever will.

Watch out for

Absolute roughness is a fiction — mounting stiffness, tyre pressure, and rider weight move the numbers more than the road does, so everything must be relative to a calibrated per-device baseline, and cross-rider comparison only works after aggregation. Also trim the first and last hundred metres of every ride before upload, or you are shipping a database of where your users live.