ptx2 / gymnasticon

Make obsolete and/or proprietary exercise bikes work with popular cycling training apps like Zwift, TrainerRoad, Rouvy and more.
https://ptx2.net/posts/unbricking-a-bike-with-a-raspberry-pi
MIT License
299 stars 39 forks source link

Cadence incongruity when bike goes from zero cadence to non-zero #17

Closed jeremydk closed 4 years ago

jeremydk commented 4 years ago

After a period of time sitting at zero cadence, the first non-zero cadence update will generate a bunch of pedal events:

Oct 04 22:01:07 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:07.171Z] pinging app since no pedal strokes for 6s
Oct 04 22:01:07 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:07.262Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:07 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:07.858Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:08 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:08.163Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:08 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:08.768Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:09 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:09.374Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:09 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:09.678Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:10 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:10.284Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:10 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:10.890Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.201Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.808Z] received stats from bike [power=1W cadence=15rpm]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.815Z] pedal stroke [timestamp=1601863043002.3733 revolutions=210 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.821Z] pedal stroke [timestamp=1601863047002.3733 revolutions=211 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.828Z] pedal stroke [timestamp=1601863051002.3733 revolutions=212 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.834Z] pedal stroke [timestamp=1601863055002.3733 revolutions=213 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.839Z] pedal stroke [timestamp=1601863059002.3733 revolutions=214 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.845Z] pedal stroke [timestamp=1601863063002.3733 revolutions=215 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.851Z] pedal stroke [timestamp=1601863067002.3733 revolutions=216 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.857Z] pedal stroke [timestamp=1601863071002.3733 revolutions=217 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.863Z] pedal stroke [timestamp=1601863075002.3733 revolutions=218 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.868Z] pedal stroke [timestamp=1601863079002.3733 revolutions=219 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.873Z] pedal stroke [timestamp=1601863083002.3733 revolutions=220 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.879Z] pedal stroke [timestamp=1601863087002.3733 revolutions=221 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.885Z] pedal stroke [timestamp=1601863091002.3733 revolutions=222 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.893Z] pedal stroke [timestamp=1601863095002.3733 revolutions=223 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.901Z] pedal stroke [timestamp=1601863099002.3733 revolutions=224 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.906Z] pedal stroke [timestamp=1601863103002.3733 revolutions=225 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.912Z] pedal stroke [timestamp=1601863107002.3733 revolutions=226 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.918Z] pedal stroke [timestamp=1601863111002.3733 revolutions=227 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.921Z] pedal stroke [timestamp=1601863115002.3733 revolutions=228 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.926Z] pedal stroke [timestamp=1601863119002.3733 revolutions=229 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.931Z] pedal stroke [timestamp=1601863123002.3733 revolutions=230 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.935Z] pedal stroke [timestamp=1601863127002.3733 revolutions=231 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.939Z] pedal stroke [timestamp=1601863131002.3733 revolutions=232 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.943Z] pedal stroke [timestamp=1601863135002.3733 revolutions=233 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.947Z] pedal stroke [timestamp=1601863139002.3733 revolutions=234 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.951Z] pedal stroke [timestamp=1601863143002.3733 revolutions=235 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.955Z] pedal stroke [timestamp=1601863147002.3733 revolutions=236 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.959Z] pedal stroke [timestamp=1601863151002.3733 revolutions=237 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.963Z] pedal stroke [timestamp=1601863155002.3733 revolutions=238 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.967Z] pedal stroke [timestamp=1601863159002.3733 revolutions=239 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.971Z] pedal stroke [timestamp=1601863163002.3733 revolutions=240 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.975Z] pedal stroke [timestamp=1601863167002.3733 revolutions=241 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.979Z] pedal stroke [timestamp=1601863171002.3733 revolutions=242 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.983Z] pedal stroke [timestamp=1601863175002.3733 revolutions=243 power=1W]
Oct 04 22:01:11 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:11.987Z] pedal stroke [timestamp=1601863179002.3733 revolutions=244 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.001Z] pedal stroke [timestamp=1601863183002.3733 revolutions=245 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.006Z] pedal stroke [timestamp=1601863187002.3733 revolutions=246 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.011Z] pedal stroke [timestamp=1601863191002.3733 revolutions=247 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.015Z] pedal stroke [timestamp=1601863195002.3733 revolutions=248 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.022Z] pedal stroke [timestamp=1601863199002.3733 revolutions=249 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.032Z] pedal stroke [timestamp=1601863203002.3733 revolutions=250 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.036Z] pedal stroke [timestamp=1601863207002.3733 revolutions=251 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.039Z] pedal stroke [timestamp=1601863211002.3733 revolutions=252 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.054Z] pedal stroke [timestamp=1601863215002.3733 revolutions=253 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.057Z] pedal stroke [timestamp=1601863219002.3733 revolutions=254 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.061Z] pedal stroke [timestamp=1601863223002.3733 revolutions=255 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.086Z] pedal stroke [timestamp=1601863227002.3733 revolutions=256 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.092Z] pedal stroke [timestamp=1601863231002.3733 revolutions=257 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.106Z] pedal stroke [timestamp=1601863235002.3733 revolutions=258 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.114Z] pedal stroke [timestamp=1601863239002.3733 revolutions=259 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.159Z] pedal stroke [timestamp=1601863243002.3733 revolutions=260 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.177Z] pedal stroke [timestamp=1601863247002.3733 revolutions=261 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.189Z] pedal stroke [timestamp=1601863251002.3733 revolutions=262 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.219Z] pedal stroke [timestamp=1601863255002.3733 revolutions=263 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.227Z] pedal stroke [timestamp=1601863259002.3733 revolutions=264 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.231Z] pedal stroke [timestamp=1601863263002.3733 revolutions=265 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.249Z] pedal stroke [timestamp=1601863267002.3733 revolutions=266 power=1W]
Oct 04 22:01:12 gymnasticon gymnasticon[1805]: [2020-10-05T02:01:12.262Z] pedal stroke [timestamp=1601863271002.3733 revolutions=267 power=1W]

An initial readthrough of src/app/simulation.js leads me to believe this has to do with the early return in schedulePedal(), but I'd need to tease through this logic a bit more directly.

jeremydk commented 4 years ago

Added some logging -- we're passing a nextPedalTime that ends up being in the past, which causes these to rapid-fire through.

Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.185Z] received stats from bike [power=0W cadence=0rpm]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.490Z] received stats from bike [power=0W cadence=25rpm]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173497 timeSinceLast: 43374.333251953125 nextPedalTime: 1601864132522.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.504Z] pedal stroke [timestamp=1601864132522.6667 revolutions=3 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173509 timeSinceLast: 40986.333251953125 nextPedalTime: 1601864134922.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.515Z] pedal stroke [timestamp=1601864134922.6667 revolutions=4 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173520 timeSinceLast: 38597.333251953125 nextPedalTime: 1601864137322.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.526Z] pedal stroke [timestamp=1601864137322.6667 revolutions=5 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173530 timeSinceLast: 36207.333251953125 nextPedalTime: 1601864139722.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.537Z] pedal stroke [timestamp=1601864139722.6667 revolutions=6 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173542 timeSinceLast: 33819.333251953125 nextPedalTime: 1601864142122.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.548Z] pedal stroke [timestamp=1601864142122.6667 revolutions=7 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173553 timeSinceLast: 31430.333251953125 nextPedalTime: 1601864144522.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.559Z] pedal stroke [timestamp=1601864144522.6667 revolutions=8 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173563 timeSinceLast: 29040.333251953125 nextPedalTime: 1601864146922.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.570Z] pedal stroke [timestamp=1601864146922.6667 revolutions=9 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173575 timeSinceLast: 26652.333251953125 nextPedalTime: 1601864149322.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.580Z] pedal stroke [timestamp=1601864149322.6667 revolutions=10 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173586 timeSinceLast: 24263.333251953125 nextPedalTime: 1601864151722.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.593Z] pedal stroke [timestamp=1601864151722.6667 revolutions=11 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173596 timeSinceLast: 21873.333251953125 nextPedalTime: 1601864154122.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.602Z] pedal stroke [timestamp=1601864154122.6667 revolutions=12 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173605 timeSinceLast: 19482.333251953125 nextPedalTime: 1601864156522.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.610Z] pedal stroke [timestamp=1601864156522.6667 revolutions=13 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173613 timeSinceLast: 17090.333251953125 nextPedalTime: 1601864158922.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.618Z] pedal stroke [timestamp=1601864158922.6667 revolutions=14 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173621 timeSinceLast: 14698.333251953125 nextPedalTime: 1601864161322.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.626Z] pedal stroke [timestamp=1601864161322.6667 revolutions=15 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173629 timeSinceLast: 12306.333251953125 nextPedalTime: 1601864163722.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.633Z] pedal stroke [timestamp=1601864163722.6667 revolutions=16 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173636 timeSinceLast: 9913.333251953125 nextPedalTime: 1601864166122.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.641Z] pedal stroke [timestamp=1601864166122.6667 revolutions=17 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173644 timeSinceLast: 7521.333251953125 nextPedalTime: 1601864168522.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.649Z] pedal stroke [timestamp=1601864168522.6667 revolutions=18 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173652 timeSinceLast: 5129.333251953125 nextPedalTime: 1601864170922.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.656Z] pedal stroke [timestamp=1601864170922.6667 revolutions=19 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173659 timeSinceLast: 2736.333251953125 nextPedalTime: 1601864173322.6667
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:13.664Z] pedal stroke [timestamp=1601864173322.6667 revolutions=20 power=0W]
Oct 04 22:16:13 gymnasticon gymnasticon[1946]: now: 1601864173667 timeSinceLast: 344.333251953125 nextPedalTime: 1601864175722.6667
Oct 04 22:16:14 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:14.098Z] received stats from bike [power=3W cadence=24rpm]
Oct 04 22:16:14 gymnasticon gymnasticon[1946]: now: 1601864174102 timeSinceLast: 779.333251953125 nextPedalTime: 1601864175822.6667
Oct 04 22:16:14 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:14.700Z] received stats from bike [power=3W cadence=24rpm]
Oct 04 22:16:14 gymnasticon gymnasticon[1946]: now: 1601864174705 timeSinceLast: 1382.333251953125 nextPedalTime: 1601864175822.6667
Oct 04 22:16:15 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:15.003Z] received stats from bike [power=3W cadence=24rpm]
Oct 04 22:16:15 gymnasticon gymnasticon[1946]: now: 1601864175009 timeSinceLast: 1686.333251953125 nextPedalTime: 1601864175822.6667
Oct 04 22:16:15 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:15.609Z] received stats from bike [power=3W cadence=23rpm]
Oct 04 22:16:15 gymnasticon gymnasticon[1946]: now: 1601864175620 timeSinceLast: 2297.333251953125 nextPedalTime: 1601864175931.3623
Oct 04 22:16:15 gymnasticon gymnasticon[1946]: [2020-10-05T02:16:15.936Z] pedal stroke [timestamp=1601864175931.3623 revolutions=21 power=3W]
jeremydk commented 4 years ago

Initial testing of clamping nextPedalTime looks like a good call for now - only did one test ride to confirm for now, need to think through how we can add some tests around this behavior.

src/app/simulation.js

62:     let nextPedalTime = Math.max(now, (now - timeSinceLast + this._interval));
ptx2 commented 4 years ago

Thanks for reporting this! I agree it would be good to add some tests here. I'll have a look at pushing out this fix tomorrow morning.

ptx2 commented 4 years ago

I just pushed up #18 but can't actually test it with a bike right now. I think it should fix this issue, hopefully also the Garmin issue you mentioned earlier, and also adds some tests around pedal timestamps and cadence changes. As soon as I have a chance to test it properly I'll push out a fix -- if you have a chance in the meantime, let me know how it goes!

jeremydk commented 4 years ago

Initial test last night looked good.

ptx2 commented 4 years ago

Nice, just tested here too and looks good.