The thirty-second problem.
What the sensors were trying to tell me.

The gear detector I built last week works beautifully — in simulation. There's just one catch: to make it commit to a gear, you'd have to hold that gear, steadily, for the better part of thirty seconds. Nobody rides a bike like that. Chasing down why led somewhere I didn't expect — to a small truth about what a bicycle sensor is actually telling you, and to the uncomfortable discovery that the simulator I'd been trusting was quietly lying to me.

24
crank revolutions the old detector needed to commit a gear
~30s
how long that is at a normal cadence
1–2
samples the new approach needs instead
1/1024 s
the timestamp resolution that makes it possible

A detector that needs you to sit still

The detector from the last devlog watches the gear ratio and, once it has held steady inside a band for a minimum number of samples, commits it as a gear. In the data viewer, we fed a ride where each gear was held for a good long while, it drew a lovely clean staircase. When we fed it a ride with realistic shifting — a gear held for ten or fifteen seconds before the next change — it fell apart: spurious rungs, ratios committed mid-transition, a ladder that climbed in the wrong order.

The binding number turned out to be the averaging window. To beat the sensor noise the detector leans on roughly sixteen crank revolutions, plus a handful more to confirm — call it twenty-four crank revolutions before it'll trust a gear. At a normal 75 rpm that's about twenty seconds, and I'd padded it to thirty for margin. Wonderful for a bench test. Useless as a thing you ask a human to do at a traffic light.

why a counting window is slow
ratio precision ≈ 1 / N_revs
With integer revolution counts, a window of N crank revs pins the ratio to about ±1/N. To tell 2nd gear (2.00) from 3rd (2.18) — a gap of just 0.18 — you need N greater than about twelve. That floor is baked into counting. You cannot average your way out of it quickly.

What the sensor was actually saying

Here is the thing I had been walking straight past. A Bluetooth speed or cadence sensor doesn't just hand you a count. The standard Cycling Speed and Cadence profile gives you a cumulative revolution count and the time of the most recent revolution — stamped on the sensor's own clock, to one part in 1024 of a second. That second number is the whole gift.

Because the time is measured at the actual revolution — not at some arbitrary sampling boundary — you can compute a frequency from a single revolution and have it be accurate. Wheel frequency is revolutions divided by the precisely measured time those revolutions took. Do the same for the crank. The gear is just their ratio.

the whole detector, really
gear ratio = wheel_hz / crank_hz
Each frequency comes straight from that sensor's own event timestamps, so the ratio is accurate per sample — it resolves a gear in one or two notifications, not thirty seconds. The precision lives in the timestamp, not in counting lots of revs.

The simulator was lying

So why had I needed the window at all? Because the bench simulator I had been testing against was generating its fake sensor data the easy way — integer revolution counts ticked off a single shared clock.  A close look at the output and we found the wheel frequency was always exactly one-times, two-times, three-times the crank. Never the 1.41× of first gear. It had thrown away the one piece of information the real approach depends on: that the wheel and the crank are timed independently, by two separate clocks, to sub-revolution precision.

The thirty-second window was never a property of the problem. It was a property of my test rig. I had built a simulator that was easier to write than reality, and it had lied to me in precisely the place I most needed the truth.

The lesson A simulator that's cheaper to build than the thing it stands in for will cut the corner you can't see — and it'll be the corner that matters. If the model can't reproduce the signal your method relies on, you aren't testing your method. You're testing the model.

So: a bench that doesn't lie

The fix isn't a cleverer detector. It's an honest bench. Three rules fell out of the post-mortem.

"I'd built a simulator that was easier to write than reality. It lied to me in exactly the place I most needed the truth."

What comes next

The plan that fell out of this is a four-board bench: a pulse-driven "rider", two independent sensor radios, and the GearSense head unit watching over Bluetooth — built to behave like the real hardware, right down to the two clocks.

  1. Build the Ride Generator: a scriptable drivetrain emitting two gear-coupled pulse trains
  2. Two identical sensor boards, role-strapped as speed or cadence, timestamping pulses on their own clocks
  3. The Central: connect to both, fuse wheel and crank, classify the gear by frequency ratio
  4. Prove a gear resolves in a sample or two, not a window
  5. Then stress it — coasting, rapid shifts, the lot

Comments

Loading…

Leave a comment