Bike Display Replacement

As part of our recent moves toward better fitness, my partner & I picked up a secondhand exercise bike in the fall. Nice enough bike, but batteries were left in the display module when it went into storage, so it was dead when we got it. Enter the Arduino nerd; I set out to build a replacement module.

The assembled device, mounted on the bike

First task was to figure out the cadence sensor. On this bike it’s connected via a 3.5mm TS plug. I overthought this one an awful lot; I was thinking some sort of magnetic-sensing coil or 1-wire hall-effect sensor or something; so I did a bunch of awkward trial and error with my multimeter before I found mention of bikes using a magnetic reed switch. So simple! Magnet on the flywheel and a reed switch in the housing; at a certain point in the rotation the switch closes. Dead simple.

In firmware, I set the cadence pin mode to INPUT_PULLUP and attach an interrupt handler on the falling edge. The handler sets a global variable to the current timestamp and starts the rotation timer. In the main loop, we check that global flag; if it’s set then we copy the value to a local variable and clear the global, then do our “on rotation” stuff: increment the distance, calculate the time for a rotation and invert that to get the rpm, and we EMA the new rpm into our moving average.

The original Uno + breadboard prototype

The first prototype hardware was a little over complicated; I used an external pull-down resistor for the cadence sensor; in the current revision I use the Arduino’s internal pull-up.

The perfboard design in Fritzing

I used Fritzing to design the perfboard layout. There are some differences between the Fritzing and real-life layouts; the real board only allows one wire per hole, so there are some nasty big solder bridges in real life, where the design shows nicely-tidy joints like the nest of ground connections near the middle.

Early stages of soldering

Perfboard is kind of nasty to work with – you end up making a lot of solder busses, and if you use both sides you can end up with surface-mount sadness mixed in.

Solder busses! Solder busses everywhere!

Because of space constraints, it wasn’t practical to mount the Arduino right on the board. What I settled on was a wiring harness to a pair of 8-pin Dupont headers. I had some trouble with the headers for the input wires, and currently they are bare socket headers shoved onto the pins, while the lower header still has its 8-pin shroud. If this proves unstable and wiggles loose, my next plan is to take the headers off the wires and the nano, and solder the harness in directly.

All wired up and mounted in the case

Currently, the display shows all available information (current rpm & speed, riding time, and distance) at once, but I’m thinking to make separate screens with larger (and more readable) text, using the front panel button to toggle through like the original unit did. I’m also planning a kmh/mph toggle (long-press the button to switch).

I’ve published the and Fritzing files On GitLab; I welcome any feedback, suggestions, or questions. If you build your own, let me know!

Author: Eddie Roosenmaallen

By day I'm the Release Manager at Distributive; I help build the Distributed Compute Protocol at In my off time I explore Linux, JavaScript and the web, and I try to share some of my knowledge and some of my humour online.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.