Wahoo Kickr Bike - External Gear Display

Wow, a lot of activity on this thread since I last checked. Seems like there are actually several topics going now - the PC software to sniff out bluetooth info like gears, programming the ESP32 hardware in general, and the software for the Kickr/Shift - I guess even that could be split in two, since the Shift crowd have no need for the grade info.

Anyhoo… I’ve updated my git page for the Wahoo Kickr Display Dingus:


This update brings in the following:

  • if no bluetooth connection is made within 20 seconds, the dingus will reboot itself and try again. No need to repower or press the boot button.
  • adds a power distribution graph to the “coasting” screen
  • add a power distribution graph to the main screen that alternates with the max/avg power info every three seconds
  • fixed a bug in the eeprom save/restore code so it can tell whether it is reading “noise” on the first usage of the software
  • added cadence (thanks to Nikolaus Kirchseige for figuring out how to get crank revolutions out of the power update callback) - tinkered with this for a week or so, and my current averaging logic seems to get with a rev or two of how Zwift/Rouvy calculate RPMs
  • added a front crank animation to my gear display, animation responds to the actual cadence

Oversaturated video showing new crank animation here:


As with all links, you’ll need to fix the link since this forum doesn’t allow working links…

1 Like

@Jay_Wheeler - Is there any reason it can’t simply continue trying to connect, rather than rebooting?
I still have to power cycle mine based on your code a few times before it will connect, and I was thinking of trying to make it loop the connection attempt until it does connect.

Hi Dan - I don’t know if a loop would work - I didn’t write the doConnect() code, but it looks like it is intended to return true or false, but I"ve never seen it return false - it just seems to hang when it doesn’t work.

Note that the main loop is already, um, looping, as my approach to reset the hardware after 20 seconds wouldn’t kick in otherwise. But, if you figure out a more elegant way, please do post it. In the meantime, my brute force approach seems to work. Generally by the time I"m done picking a course in Zwift or Rouvy, it has managed to connect without me having to pay attention to it.

Thanks, Jay.
I’ll dig into the connect portion a bit more in a few days.

@Jay_Wheeler @Dan_Kothlow You can take a look at the code I’m using as it does the retry.

Hi, Do you mind telling me where you got the platform attached to the handle bars from? Looks very neat! Thanks

Hi can you please tell me where you got the table attached to the bars from?

This is really just some cheap DIY containing of:

  • Garmin aero mount (there are really cheap aftermarket products out there): h**ps://amzn.to/49uyJwL

  • adhesive Garmin adapter: h**ps://amzn.to/4bz83wH

  • small aluminum mousepad: h**ps://amzn.to/4bqeVwi

I‘m quite happy as it holds easily the ESP, my phone and other small stuff I want to keep nearby.

Thanks for the info.

Doesn’t look cheap at all!

Have you already published it on github? Like to have a look at it!

I bet this chainring/sprocket information is not published via BT, als the original Kickr Bike Display also is showing only the gear numbers.

The current configuration of the gears (tooth count) is available… along with the “shift type” (Di2, sram, mechanical, campy)

You mean these info is aired out via BT?

There’s a Sauce mod now to show Kickr gears, just install that as much easier in the long run.

Yes it is available. A bit of reverse engineering the communication between iOS wahoo app and bike I was able to figure it out.


This is my creation, before it was on the handlebar, but too close to the wahoo bike shift bt unit causing interference. Now i use a separate iphone stand. Works well, no issues
Next step is to read the unused left buttons on the handlebar

Really great projects on this thread!

Maybe some of my github pages will be interesting to you - I have been documenting all the BLE functionality of the KICKR bike.

I am slowly building up a python test script that calls all the BLE functions. I am testing the Python script with a Raspberry PI and also on Windows. It’s my first Python code (this project is really an excuse to try out the python language), so the code may not be the best. I haven’t had a chance to test with a Pi Pico or other embedded device yet. These ESP32 modules you are using look very impressive!

I’ve also worked out how to add custom shifters for TT bars for example. There’s instructions and photos on how to build them.

It’s still a work in progress. Let me know what you think and if there are any bits I can improve. I am currently documenting the cycling power service extension, so that bit’s not finished yet. After that I aim to cover off the FTMS service.


Wahoo KICKR Indoor Bike Bluetooth Projects

Wahoo KICKR Indoor Bike Shifter Projects

Hi Stephen,
thanks for the detailed information on the services and charateristics provided by the bike.
Iḿ working on an init choose where you can choose between the different gearoption and save them in eeprom. The chararteritics is the a026e039-0a7d-4ab3-97fa-f1500f9feb8b but there is only write and notify possible. So i have to write the grooupset confguration at every start to the bike. Maybe you or sameone else has an idear how to get this information, because on startup the Kickr bike knows this information so it must be stored somewhere!
Thanks best regards Matthias

Hi Matthias,
Are you asking how to read (get) the groupset configuration, rather than write (set) it?

Hi Steve,
thanks for the reply.
Yes i´d like to get/read the stored groupset configuration form the bike.