Giter Club home page Giter Club logo

kbikeble's Introduction

KBikeBLE

Arduino-based replacement computer for a Keiser M3 spin bike with Bluetooth services and display Photo

What it does

Replaces the computer on a Keiser M3 spin bike and adds Bluetooth Low Energy (BLE) Cycling Power Service (CPS) and Fitness Machine Service (FTMS). Since it replaces rather than augments the original computer, a simple display is provided as well.

Capabilities

  • Displays cadence (RPM), gear or % resistance per the user's preference, and estimated power. Power estimates replicate those from Keiser's V4.06 computer.
  • Battery level, with low battery indicator
  • Bluetooth services
    • CPS (typical for power meters) - power and cadence
    • FTMS (typical for ergometers and trainers) - power, resistance setting, and cadence (though no apps I have tried to date read the resistance, and all I have tried want to set the resistance (resistance servo on the "some day" list!))
    • Battery level
  • Command line "console," accessible via USB or Bluetooth, used mostly for one-time calibration but also providing some debugging functions.
  • Calibration to an individual bike using a procedure similar the Keiser's, using the Keiser calibration tool.
  • If used about an hour per day, runs for a month or two on an 1800 mAHr LiPo battery

NOTES:

  • Important changes starting with v1.0: Default pin assignments in bike_interface.h have changed, and the default ADC reference is now Vdd. See Calibration_change.md for details.
  • Use Released v1.1 if intending to enable the FTMS service, to avoid an issue at startup with FTMS.
  • Note to Apple watch users: Once paired, your Apple watch may connect whenever KBikeBLE is started up with the watch within its Bluetooth range, preventing individual apps from connecting. Unless and until the apps you use acquire data via the watch, you may need to forget KBikeBLE in your Apple watch Bluetooth settings.

Computer hardware

This code is for an Adafruit nrf52840 Express microcontroller and a generic 128x64 OLED display (SH1106 driver in the development system). Modestly experienced programmers should be able to adapt the code pretty readily to any board with a Nordic nrf52840. The U8G2 display library will accommodate other 128x64 displays, with a change in just one line in the code.

Bike hardware

Connection to the bike is through the RJ9 (phone handset) connector used for the stock Keiser computer. The sensor board has a 10K pot that's linked to the magnet assembly, and a magnetic reed switch (not a Hall sensor) that closes once per crank revolution. Using the standard RJ9 lead colors, the leads are

  • Green - The crank switch. This is pulled to ground when a magnet on the crank assembly passes by.
  • Black - "Top" of the resistance magnet position sense pot
  • Red - Wiper of the pot
  • Yellow - Ground - other end of the pot, and of the crank switch

Any replacement RJ9 cord provides access, or you connect to the stock Keiser connector at the handlebar end. Connectors to mate with the stock cable are easily obtained.

Dependencies

Calibration

The software provides for calibration using Keiser's calibration tool. Calibration is reatined in flash memory, so this is a one-time process when the computer is installed on a new bike or the bike's magnetic brake assembly is serviced.

Calibrations were obtained by comparison with a Keiser computer, V4.06 software. A published Keiser chart showing power vs. resistance magnet position, along with data from a Keiser computer on power vs. speed at fixed resistance, are used to provide the power estimates.

See https://user-images.githubusercontent.com/68538658/113517760-e75ac880-9579-11eb-968e-854193421594.jpeg for info from Keiser on gear number vs. magnet assembly position, as well as power vs. magnet position at 90 RPM. Calibration replicates the scale on that figure, with 0 to 100% representing the full extent of the X axis. The Gear display can be the unevenly spaced gears shown on the figure, or a more uniform but very similar set. Users may prefer one over the other, or prefer the simple 0-100% display that's provided as well.

See the comments in the code for details.

Inspiration and thanks

https://github.com/Tschucker/ArduinoBLE-Cycle-Power-Service

https://github.com/turbodonkey/bike_power_meter

The very nice people over at https://github.com/ptx2/gymnasticon

kbikeble's People

Contributors

ajs123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kbikeble's Issues

Stuck on log screen when FTMS enabled

I would like to try BitGym which I believe requires FTMS. When I enable FTMS by uncommenting #define PROVIDE_FTMS in options.h, it freezes on the log screen during startup.
IMG_5676

.setName for Bluetooth service seems picky

In main routine, if I have the following, Zwift works fine: Bluefruit.setName("K");

However, if I put Bluefruit.setName("KbikeBLE"); in there, the cadence part seems to work fine and lists the service as KbikeBLE, however, the Power Source connection in Zwift show the service as K36. It does connect, but immediately I get a No Signal alert on that service. Speed shows up but Power does not. I didn't pick up the latest release that allow FTMS to be disabled but I believe I have FTMS disabled on my own.
I guess I must have something messed up as I sense that other folks have this working without a problem.

FTMS support

This software is awesome. I am quite new to programming. In order to get this software to work with the RGT Cycling app, I disabled Advertising of the ftms service. Apparently RGT software didn't like that? Before I disabled it, my board would never connect. After disabling, it connects every time. If I decide to pay for Zwift, maybe I will have to re-enable? Not sure.

Thanks

Bluetooth Function only

Hello,

I love your work, unfortunately seems a bit complicated for me.

  1. Is it possible to create a version for us that only add the bluetooth function to the Keiser M3, while keeping the original display please!!?
  2. Does the heart beat sensor work here?

Cheers,
York

Connecting the M3 computer and the Feather at once

Hi - Not sure if you considered this or not. Do you think it's possible to simultaneously connect both the M3 computer and the KBikeBLE? I split the cable to each device. When I do that, everything seems to work except there is no voltage on the resistance pin. I've tried several combinations of pullup and pulldown resisors, with no luck. (very, very newbie here).

Any ideas?

This software and build is really cool! Thank you for sharing it!

Parts List

I'm a fellow M3 bike user and have been looking for this exact solution for my bike to be able to connect via bluetooth with fitness apps.

I'm new to coding and these kind of DIY projects in general and I thought this was a good real world project to dive into but I'm struggling a little to know which components are necessary and compatible for this project.

I was wondering if you could post a list of the exact Arduino board, display, and other parts for this project that you are using?

Sorry if this isn't the correct forum to ask this, I'm new to Github as well.

I think what you have done is pretty awesome and appreciate you sharing it.

Featherwing OLED boot loop

Hi,

Thanks for this awesome project!

I went ahead and purchased the Adafruit feather and featherwing OLED 128X64 as mentioned in HOWTO.md. There is very little information available regarding using the 128X64 SH1107 OLED with U8G2 and I am struggling.

I have altered the U8G2 constructor from:
U8G2_SH1106_128X64_NONAME_F_HW_I2C display(U8G2_R1, /* reset=*/U8X8_PIN_NONE);
to:
U8G2_SH1107_64X128_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE);

Without the display plugged in, it works as expected BLE etc. When I plug the display in, as soon as the display shows "KBikeBLE" followed by the version, the feather reboots? in a loop: Boot with USB

I am not really sure where to start debugging. I tested the display using the code on this page and it works fine so no issues with the hardware.

Any help much appreciated.

UPDATE: I was just packing up for the night when I unplugged the USB cable so it was just on battery, now it almost works as expected: Boot on battery

  • Interesting that it boot loops when connected to USB
  • Also interesting that there are those faint horizontal lines

SEEED STUDIO XIAO NRF52840 compatible

Just an FYI....
I got KBikeBLE's software to work with a SEEED STUDIO XIAO NRF52840 processor, which is quite a bit smaller and less expensive. A few changes I had to make:
Added “static const uint8_t VBAT = PIN_VBAT ;” to Variant.h file so I could use this in bike_interface.h.
In Bike_interface.h, instead of #define BATTERY_PIN A6, changed to #define BATTERY_PIN VBAT
In Arduino IDE, in board manager, added “Seeed nRF52 by Seeed Studio.

I used 1.0.0 of this board library as I believe newer versions don't support the BLE libraries in this project.

The perfect couple KBikeBLE & SmartSpin2k

Hello. I just wanted to comment that after mounting this fantastic screen and enjoying such a good Bluetooth connection and watt measurement, I wanted to do something to use a motor map to change gears without using the lever. Searching I found another great project that did just what I wanted and also had ERG and SIM mode for Zwift.
It is a project for other types of bicycles but I have adapted it for the "Keiser M3".
I'm still testing and calibrating but I'm already enjoying it and I think it may be of interest to anyone who already has this screen. I have modified the files and have the STL for the "Keizer M3" that I will share shortly when I finish making all the changes.

I haven't been able to train yet due to illness but this week I will start and check how it works with long training sessions.

My impressions have been very good so far and I am very impressed with the result.

Any help here we can comment.

In this link I comment on the adaptation.

All the best.

Buying you a coffee

Hello Alan,

How can we buy you a coffee to thank you for developing this.

My grain of sand. 3D print

I am very grateful for the work on this project. I have assembled everything and it is going very well. Better than the original screen.
I have designed a quick box to house all the electronics and have mentioned this project.
I don't know if I'm breaking any rules. If so, let me know.
And if a larger screen with more information is added in the future, I would design another box.
Thank you so much.
Link to box:
Box 3D

Photos of hardware connection

Thanks for this awesome project. It would be awesome if you could include or link to photos and instructions for the hardware connection on the M3. I don't have an M3 yet so I want to know what's involved with this before I make the purchase.

Pinout not consistent across M3 builds

I got my Keiser M3 working with this code, modified slightly for my display and changes to the I/O. It appears my bike's I/O is different from the pinout identified by KBikeBLE. Below is what I am using for my bike and it is working with RGT Cycling app. Thanks so much for this development.

My Keiser M3 Serial No: 080118 (which means built 2008 - Jan 18)
Keiser M3 interface through the RJ9 4p4c jack:

  Red     - CRANK_PIN - crank switch to ground (dry switch, not Hall effect)
           To a digital input. Transient protection is recommended.
  Yellow  - RESISTANCE_TOP - 10K magnetic brake position sense pot high side
           Use a digital output so it can be turned off to save power
  Green   - RESISTANCE_PIN - magnet brake position sense pot wiper
           To an analog input channel
  Black   - GROUND - magnetic brake position sense pot low / crank switch low side

28Dec2022
Just a note, The Digikey Part Number 1175-2286-ND with description CABLE MOD 4P4C PLUG TO PLUG 7' is the cable I used for this project. It reverses the conductors order from one end to the other. This caused me problems until I figured it out :( The above coloring is referenced at the original cable by the crank.

Transient suppression on Crank Pin

I have failed a couple Crank Pin inputs on my processors. I do not have any suppression, despite your recommendation. I looked at the signal with a scope and it looks very clean, no voltage spikes. Did you have problems with this input before you added surge suppression? My project has run for hours before actually failing the input previously. Today, it failed after only 5 minutes so trying to find a solution that I can be confident with. Wondering if your suggestion for suppression was based on experience on this project or experience with reed switches in general or just good practice.

Thanks again for the awesome project. I actually have this running on a Seeed XIAO NRF52840 as it is much smaller and cheaper than the Adafruit Feather you used.

No RPM Data is shared with Zwift or Apple Watch

I've gone through how to setups and Brought my M3 KBikeBLE up and running. Calibration is completed.

The screen shows all values, RPM, Gear and Watts but when I connect my KBikeBLE to Apple Watch or Zwift, Only power value is transferred. Cadence or Speed/Distance values are not shared. I am not %100 sure I get the power values from KBikeBLE.

I enabled CPC / FTMS and both of them at the same time in different builds but still can't get the cadence and speed/distance data via bluetooth.

related section of the options.h

/* Bluetooth services. --------------------------------------------------------------------------------
   We can provide Cycling Power Service (CPS) and/or FiTness Machine Service (FTMS).
   CPS has been more thoroughly tested. In addition, apps that use FTMS may expect to be able to set
   the resistance (as with a full trainer). FTMS must include speed (Km/hr) and may include distance (Km), 
   but these are just estimates. Keiser's speed estimate, for example (like Peloton's)
   is just a fixed functions of power. It seems better to let training/riding apps like Zwift calculate
   speed from power, rider weight, and incline.

   Considering all of the above, the current default is to provide CPS only.
*/
#define PROVIDE_CPS
//#define PROVIDE_FTMS

#if (!defined(PROVIDE_CPS) & !defined(PROVIDE_FTMS))
#define PROVIDE_CPS
#endif

This is my first time working with microcontrollers and I have no idea where I am making mistakes. I do appreciate any help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.