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

Experimental support for Keiser M3 #50

Closed chriselsen closed 3 years ago

chriselsen commented 3 years ago

To try this out:

chriselsen commented 3 years ago

Sorry, realized that I had a typo in the instructions for testing above. Could you try again? If everything works out fine, you should see a file ./src/bikes/keiser.js within the gymnasticon folder. That is the new bike driver.

If you only have a Bluetooth 4.0 dongle right now, this might indeed not work. Gymnasticon needs to receive and send, which is only possible with Bluetooth 4.1+ over the same dongle. Let me see if I can build you a simple test script, just to confirm the communication with your bike.

chriselsen commented 3 years ago

@nealjane I added a very simple test script, just to validate the communication with your bike.

var noble = require('@abandonware/noble');

noble.on('stateChange', function(state) {
  if (state === 'poweredOn') {
    noble.startScanning(null, true);
    console.log('Scanning...');
  } else {
    noble.stopScanning();
  }
});

noble.on('discover', function(peripheral) {
  if (peripheral.advertisement.localName == "M3") {
    console.log('Discovered Keiser M3: ', peripheral.address);
    try {
      console.log(peripheral.advertisement.manufacturerData);
      console.log('Power: ', peripheral.advertisement.manufacturerData.readUInt16LE(10));
      console.log('Cadence: ', Math.round(peripheral.advertisement.manufacturerData.readUInt16LE(6)/10));
    } catch (err) {
      console.log(`\tError parsing: ${err}`);
      console.log(`\t ${err.stack}`);
    }
  }
});

Just download it into the gymnasticon folder with

wget https://raw.githubusercontent.com/ptx2/gymnasticon/01f629418f6472a6ede127dedb253dcfc2e87efe/keiser.js

and then execute it with node keiser.js.

It should show you Power and Cadence values - along with some other debug data. Just validate that the Power and Cadence values displayed match what you see on the console. If it doesn't, paste the output of one "<Buffer ..." line with the subsequent Power / Cadence values.

nealjane commented 3 years ago

@chriselsen. Hi Chris, Ran script you wrote this am. watts and power are shown on screen = bike screen.-fab! (Can’t take pic from bike as I’m peddaling - but it’s definitely picking up correct rpm and power) image

nealjane commented 3 years ago

@chriselsen - just realised/reread the instruction on front page, I’m using pi zero W - so does that mean I don’t need the extra usb Bluetooth 4.1 dongle as it’s built in?!

chriselsen commented 3 years ago

@chriselsen. Hi Chris, Ran script you wrote this am. watts and power are shown on screen = bike screen.-fab! (Can’t take pic from bike as I’m peddaling - but it’s definitely picking up correct rpm and power)

That's great news! Than the experimental bike driver should work as expected.

As you're using a Raspberry Pi Zero W, you don't need any external Bluetooth dongle. Just follow above steps to get the experimental bike driver running and you should be good to go.

Let me know how it went.

nealjane commented 3 years ago

@chriselsen , unplugged my bt4.0 and restarted pi0w- it’s just hanging at ‘connecting to bike’ image ..anything to do with me installing gymnasticon with bt4.0 originally plugged in??

chriselsen commented 3 years ago

..anything to do with me installing gymnasticon with bt4.0 originally plugged in??

You'll have to follow the steps in post 1 to actually download and build the new driver. You can go into the gymnasticon folder and continue with the second block, the one that begins with git fetch...

Also the command line option should be --bike keiser. Without it, it will try to connect to the default Flywheel bike. That won't work.

Looks like you're rebooting your Pi. In that case you also want to stop the gymnasticon service with sudo service gymnasticon stop. Otherwise you'll end up with two instances running at the same time, which won't work either.

nealjane commented 3 years ago

@chriselsen Giving me an error as follows from typing - ‘git fetch origin pull/50/head:keiser-m3-experimental’

chriselsen commented 3 years ago

You have to be inside the gymnasticon folder when executing the command.

tompijls commented 3 years ago

Hey Chris,

started playing with this as well.

Once you stop pedalling on the keiser, it shows average cadence/power for about a minute before the device shuts down.

It's specified by the data type integer per keiser specs: https://dev.keiser.com/mseries/direct/#advertising-data-structure

So ideally you should only report data when it is realtime data. Don't think you make that distinction currently?

Cheers

chriselsen commented 3 years ago

@tompijls Thanks for the feedback and the pointer. I now added support for real-time vs. summary mode. At the end of a ride, once you stop pedaling, gymnasticon should now transmit a value of 0 for power and cadence.

Give it a try and let me know how it's working for you:

git branch -d keiser-m3-experimental
git fetch origin pull/50/head:keiser-m3-experimental
git checkout keiser-m3-experimental
npm install
npm run build
npm link
gymnasticon --bike keiser
tompijls commented 3 years ago

Yes, this seems to work partially ==> although after a little while it stops reporting and i get following noble warning.

[2021-02-15T21:41:46.291Z] pedal stroke [timestamp=1613425306291.1465 revolutions=10 power=11W] [2021-02-15T21:41:46.584Z] received stats from bike [power=11W cadence=74rpm] [2021-02-15T21:41:47.101Z] pedal stroke [timestamp=1613425307101.9573 revolutions=11 power=11W] [2021-02-15T21:41:47.234Z] received stats from bike [power=11W cadence=73rpm] [2021-02-15T21:41:47.548Z] received stats from bike [power=11W cadence=73rpm] [2021-02-15T21:41:47.875Z] received stats from bike [power=11W cadence=72rpm] [2021-02-15T21:41:47.935Z] pedal stroke [timestamp=1613425307935.2905 revolutions=12 power=11W] [2021-02-15T21:41:48.198Z] received stats from bike [power=11W cadence=72rpm] [2021-02-15T21:41:48.769Z] pedal stroke [timestamp=1613425308768.6238 revolutions=13 power=11W] [2021-02-15T21:41:49.601Z] pedal stroke [timestamp=1613425309601.957 revolutions=14 power=11W] [2021-02-15T21:41:50.436Z] pedal stroke [timestamp=1613425310435.2903 revolutions=15 power=11W] [2021-02-15T21:41:51.268Z] pedal stroke [timestamp=1613425311268.6235 revolutions=16 power=11W] [2021-02-15T21:41:52.102Z] pedal stroke [timestamp=1613425312101.9568 revolutions=17 power=11W] [2021-02-15T21:41:52.936Z] pedal stroke [timestamp=1613425312935.29 revolutions=18 power=11W] noble warning: unknown handle 66 disconnected!

chriselsen commented 3 years ago

will try fresh tomorrow.- 😞

  1. Create the SD card as described here: https://github.com/ptx2/gymnasticon
  2. Before disconnecting the card from your computer: Within the drive that is labeled "boot" create an empty file with the name ssh. This will enable SSH access on your Pi.
  3. Stick the SD card into the Pi and boot up.
  4. After a few minutes you should be able to connect via SSH and user "pi".
  5. At this point just copy and paste:
sudo apt-get install git
cd
git clone https://github.com/ptx2/gymnasticon.git
cd gymnasticon
sudo service gymnasticon stop
sudo setcap cap_net_raw+eip $(eval readlink -f $(which node))
git fetch origin pull/50/head:keiser-m3-experimental
git checkout keiser-m3-experimental
npm install
npm run build
npm link
gymnasticon --bike keiser

Now start pedaling and see what happens.

chriselsen commented 3 years ago

Yes, this seems to work partially ==> although after a little while it stops reporting and i get following noble warning.

I assume that's when you're still pedaling? Looks like gymnasticon stopped receiving data after 2021-02-15T21:41:48.198Z in that example.

Can you try running it with debugs enabled? NODE_DEBUG=gymnasticon:bike* gymnasticon --bike keiser

tompijls commented 3 years ago

seems to be unrelated to your keiser implementation, but rather when I try to add the cycling meter in the mPaceline app (which seems unsupported for now)

Trying to connect the sensor stops the capturing of data from the keiser (or the bot bike) Disconnecting it throws the noble warning.

Shall i raise the issue in the main issue section of this repository?

chriselsen commented 3 years ago

seems to be unrelated to your keiser implementation, but rather when I try to add the cycling meter in the mPaceline app (which seems unsupported for now)

Trying to connect the sensor stops the capturing of data from the keiser (or the bot bike) Disconnecting it throws the noble warning.

Shall i raise the issue in the main issue section of this repository?

Yes, please raise a separate issue for this. Especially if this also happens with the "bot" bike. If I understand you correctly, you are trying to add gymnasticon as a power/cadence source in the mPaceline app?

It's interesting that you seeing a noble error. Noble is used for communication between gymnasticon and the source bike, not between gymnasticon and any receiving devices (Zwift, apps, sports watches, ...).

Please do let me know if there is anything not working with the "Keiser" bike driver though.

tompijls commented 3 years ago

Ok,

I used the gymnasticon image (yesterday did manual install) with a clean install.

Bot now works correctly, noble warning still shows up

Keiser bike reports data correctly until the moment i connect the sensor in the app, than it somehow stops getting data.

[2021-02-16T07:28:02.871Z] pedal stroke [timestamp=1613460482871.7336 revolutions=52 power=16W] [2021-02-16T07:28:03.504Z] received stats from bike [power=15W cadence=49rpm] [2021-02-16T07:28:03.823Z] received stats from bike [power=15W cadence=49rpm] [2021-02-16T07:28:04.096Z] pedal stroke [timestamp=1613460484096.2234 revolutions=53 power=15W] [2021-02-16T07:28:04.149Z] received stats from bike [power=15W cadence=49rpm] [2021-02-16T07:28:04.470Z] received stats from bike [power=14W cadence=48rpm] [2021-02-16T07:28:05.348Z] pedal stroke [timestamp=1613460485346.2234 revolutions=54 power=14W] [2021-02-16T07:28:06.596Z] pedal stroke [timestamp=1613460486596.2234 revolutions=55 power=14W] [2021-02-16T07:28:07.846Z] pedal stroke [timestamp=1613460487846.2234 revolutions=56 power=14W] [2021-02-16T07:28:09.097Z] pedal stroke [timestamp=1613460489096.2234 revolutions=57 power=14W] [2021-02-16T07:28:10.347Z] pedal stroke [timestamp=1613460490346.2234 revolutions=58 power=14W] [2021-02-16T07:28:11.597Z] pedal stroke [timestamp=1613460491596.2234 revolutions=59 power=14W] [2021-02-16T07:28:12.846Z] pedal stroke [timestamp=1613460492846.2234 revolutions=60 power=14W] [2021-02-16T07:28:14.096Z] pedal stroke [timestamp=1613460494096.2234 revolutions=61 power=14W] [2021-02-16T07:28:15.347Z] pedal stroke [timestamp=1613460495346.2234 revolutions=62 power=14W] [2021-02-16T07:28:16.596Z] pedal stroke [timestamp=1613460496596.2234 revolutions=63 power=14W] noble warning: unknown handle 64 disconnected!

nealjane commented 3 years ago

Morning Chris- managed to get it all working this am on a new sd card. Text shown on screen matches the keiser bike - so its working. 😀👍🏻- Your hard work on this is very much appreciated. (used your most recent update)

connecting to Zwift/peloton cadence makes it go haywire pi stating fixed power and cadence which then doesn’t stop even when you stop. (cadence was at approx 100 on bike before i started to connect to Zwift, after that cadence and power were stuck on the last recoded figures. I disconnected from zwift bluetooth where the buffer finishes..)

pi@gymnasticon:~/gymnasticon $ NODE_DEBUG=gymnasticon:bike* gymnasticon --bike keiser [2021-02-16T14:42:32.778Z] connecting to bike... [2021-02-16T14:42:33.513Z] bike connected eb:9b:9e:70:01:12 [2021-02-16T14:42:33.552Z] no ANT+ stick found GYMNASTICON:BIKES:KEISER 513: Found Keiser M3: M3 Address: eb:9b:9e:70:01:12 Data: <Buffer 02 01 06 31 00 00 db 05 00 00 23 00 00 00 00 00 00 00 01> Power: 35 Cadence: 150 [2021-02-16T14:42:33.933Z] received stats from bike [power=35W cadence=150rpm] [2021-02-16T14:42:33.951Z] pedal stroke [timestamp=1613486553938 revolutions=1 po.......

.......242.6929 revolutions=37 power=66W] [2021-02-16T14:43:09.849Z] pedal stroke [timestamp=1613486589848.7534 revolutions=38 power=66W] [2021-02-16T14:43:10.456Z] pedal stroke [timestamp=1613486590454.814 revolutions=39 power=66W] [2021-02-16T14:43:11.062Z] pedal stroke [timestamp=1613486591060.8745 revolutions=40 power=66W] [2021-02-16T14:43:11.667Z] pedal stroke [timestamp=1613486591666.935 revolutions=41 power=66W] [2021-02-16T14:43:12.274Z] pedal stroke [timestamp=1613486592272.9956 revolutions=42 power=66W] [2021-02-16T14:43:12.881Z] pedal stroke [timestamp=1613486592879.0562 revolutions=43 power=66W] [2021-02-16T14:43:13.486Z] pedal stroke [timestamp=1613486593485.1167 revolutions=44 power=66W] [2021-02-16T14:43:14.093Z] pedal stroke [timestamp=1613486594091.1772 revolutions=45 power=66W] [2021-02-16T14:43:14.699Z] pedal stroke [timestamp=1613486594697.2378 revolutions=46 power=66W] [2021-02-16T14:43:15.305Z] pedal stroke [timestamp=1613486595303.2983 revolutions=47 power=66W] [2021-02-16T14:43:15.910Z] pedal stroke [timestamp=1613486595909.359 revolutions=48 power=66W] [2021-02-16T14:43:16.517Z] pedal stroke [timestamp=1613486596515.4194 revolutions=49 power=66W] [2021-02-16T14:43:17.123Z] pedal stroke [timestamp=1613486597121.48 revolutions=50 power=66W] [2021-02-16T14:43:17.729Z] pedal stroke [timestamp=1613486597727.5405 revolutions=51 power=66W] [2021-02-16T14:43:18.334Z] pedal stroke [timestamp=1613486598333.601 revolutions=52 power=66W] [2021-02-16T14:43:18.940Z] pedal stroke [timestamp=1613486598939.6616 revolutions=53 power=66W]

chriselsen commented 3 years ago

connecting to Zwift/peloton cadence makes it go haywire pi stating fixed power and cadence which then doesn’t stop even when you stop. (cadence was at approx 100 on bike before i started to connect to Zwift, after that cadence and power were stuck on the last recoded figures. I disconnected from zwift bluetooth where the buffer finishes..)

Let me look into that and see what is causing it. Seems like noble (which talks to the Keiser bike) and bleno (which talks to Zwift) are getting into each other's hairs.

tompijls commented 3 years ago

I wonder if this has to do with using only 1 bluetooth device.

This projects tries to achieve something similar using 2 bluetooth devices

https://github.com/hypermoose/Keiser2Zwift

tompijls commented 3 years ago

Is it weird though I also get the noble warning when using the bot bike

chriselsen commented 3 years ago

@tompijls Yes, it probably does. And if you e.g. use a 2nd Bluetooth adapter and bind the bike part to it via --bike-adapter hci1, I expect things to work. There is also certain Bluetooth hardware than cannot connect (necessary for Zwift) while scanning (necessary for Keiser). So I need to see if that's the issue here.

tompijls commented 3 years ago

unfortunately i can't get it to work with this step.gymnasticon stops getting data from the keiser when i connect the sensor.

just checking, when I run gymnasticon --version after downloading this pull request, it shows 1.2.0, while clean install shows 1.3.0. Are you using the latest version? Cause bot doesn't work properly either after pull request

chriselsen commented 3 years ago

@tompijls @nealjane Looks like we were hitting this bug in noble. I created a workaround and pushed it. You can you give it a try with:

cd gymnasticon
git branch -d keiser-m3-experimental
git fetch origin pull/50/head:keiser-m3-experimental
git checkout keiser-m3-experimental
npm run build
gymnasticon --bike keiser

While I don't have an actual Keiser bike, it does work for me while running a simulator for the bike. Let me know how it works for you.

tompijls commented 3 years ago

We're getting somewhere Chris - really cool you do this without having a bike yourself

Your build didn't work. However I made following change and now it is working fine

async restartScan() { // Restart BLE scanning while in connected state if (this.state == 'connected') { debuglog('Restarting BLE Scan'); this.startScanningAsync(null, true); }

async restartScan() { // Restart BLE scanning while in connected state if (this.state == 'poweredOn') { debuglog('Restarting BLE Scan'); this.startScanningAsync(null, true); } }

tompijls commented 3 years ago

Now i need to do some debugging, as I had some 0 values in cadence, while i never stopped pedalling

will advise when i identified where it comes from IMG_19DA69EE6742-1

nealjane commented 3 years ago

Chris - didn't work for me either - sorry - just same as previously.

(haven't managed to get Tom changes working - but, thats more likely down to me and my editing skills - src/bike/keiser.js clearly more to it than that.)

chriselsen commented 3 years ago

Now i need to do some debugging, as I had some 0 values in cadence, while i never stopped pedalling

These issues are unfortunately rather common with these kind of bikes. The sensor probably has dropouts. The vendors then "fix" this with a filter in software. I can create that filter later today. Just takes a bit longer to implement the same issue in the simulator for testing.

I also see what I did wrong with the connected part. Will fix that as well.

tompijls commented 3 years ago

The weird thing is that the 0 values seamingly didn't show up in the console output

Will do another ride tomorrow and push output to a text file so we can compare

On the other side, I noticed the bike's output (on the display) becomes unreliable at low cadence/low power (no impact during workout)


From: Christian Elsen notifications@github.com Sent: Wednesday, February 17, 2021 3:41 PM To: ptx2/gymnasticon gymnasticon@noreply.github.com Cc: tompijls tompijls@hotmail.com; Mention mention@noreply.github.com Subject: Re: [ptx2/gymnasticon] Experimental support for Keiser M3 (#50)

Now i need to do some debugging, as I had some 0 values in cadence, while i never stopped pedalling

These issues are unfortunately rather common with these kind of bikes. The sensor probably has dropouts. The vendors then "fix" this with a filter in software. I can create that filter later today. Just takes a bit longer to implement the same issue in the simulator for testing.

I also see what I did wrong with the connected part. Will fix that as well.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/ptx2/gymnasticon/pull/50#issuecomment-780601825, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAGK6CBYITJ2MHAIHI6AIMDS7PIS5ANCNFSM4XSVKZWQ.

chriselsen commented 3 years ago

@tompijls @nealjane Added two more things:

I also fixed the previous mistake on restarting the scanning.

Give it a try and let me know how it works.

cd gymnasticon
git branch -d keiser-m3-experimental
git fetch origin pull/50/head:keiser-m3-experimental
git checkout keiser-m3-experimental
npm run build
gymnasticon --bike keiser
nealjane commented 3 years ago

@chriselsen its like Christmas everyday of the week with all this work you’re doing on our behalf! 🥇

tompijls commented 3 years ago

Thanks Chris, will advise in the morning after my ride.

Tom

nealjane commented 3 years ago

@chriselsen Its working!! Tried zwift and peloton quickly and both worked- cadence was spot on in both, power was a bit off in zwift (10% out- but only sometimes (low power like tom mentioned i think)-but I’m sure Tom will be able to give it a better try in the morning) - stayed connected for the few minutes I tried on each app - fabulous!!!👏🚴👏

chriselsen commented 3 years ago

That's great news!

power was a bit off in zwift (10% out- but only sometimes

Keep in mind that Zwift by default shows the 3s power average, while your bike's console most likely shows the instant (current) power values. That could explain the difference. At least from a gymnasticon side, we are passing through whatever is received from the bike to the receiving apps (Zwift, Peloton, ...).

Now, if you want to make these changes permanent, you want to do the following:

It should now connect to your bike and start broadcasting to Zwift / Peloton automatically.

tompijls commented 3 years ago

worked smoothly - no drops in connectivity - will you integrate it in the main build? Thanks a lot for building this.

chriselsen commented 3 years ago

will you integrate it in the main build?

Yes, now that you and nealjane have confirmed that this works for you, I'll update the documentation and ask ptx2 to include it into mainline.

djwasser commented 3 years ago

I was pointed to this thread by @nealjane -- really great that this is all working! However, after looking at the code, I am baffled as to why the cadence is working. The Bluetooth specifications for Cycling Power Service and Cycling Speed and Cadence Service both specify that a crank revolution count and a time stamp are both required to be present, and that the client (in this case Zwift) is responsible for calculating the instantaneous cadence. Also, @ptx2 states the same thing in his developement blog.

However the code for the keiser appears to just grab the raw instantaneous cadence supplied by the keiser m3i boadcast (which is instantaneous rpms x 10) and passes it along. I am wondering if someone can enlighten me.... thanks!

chriselsen commented 3 years ago

However the code for the keiser appears to just grab the raw instantaneous cadence supplied by the keiser m3i boadcast (which is instantaneous rpms x 10) and passes it along. I am wondering if someone can enlighten me.... thanks!

There are basically two parts to Gymnasticon:

This implementation here in this pull request is solely the bike driver for the Keiser bike. Therefore you are right that all it does it pickup the raw values for power and cadence that is sent according to the Keiser spec. Gymmasticon then passes these raw power / cadence values to the sensor simulation piece. That piece of the code, which simulates a cadence sensor, will then generate the revolution count and time stamps based on the raw cadence value last received.

This approach allows you to connect various bikes (currently 4 different families are supported) and broadcast the data from these different bikes, both over BLE and ANT+ to various apps.

robcalm commented 3 years ago

Thanks to @nealjane for pointing me here and to all of you who have worked to get this running. I have been using keiser2zwift on an RP3 B+ with ZEXMTE BT4.0 dongle up until this point, but the broken BT connection with K2Z to PC is stopping me from improving my setup from ipad -> PC / 4k video / large screen.

The readme for gymnasticon doesn't mention RP3 B+ as a compatible device. Can any of you clarify what special considerations are needed when using an RP3 B+? Can I get away with just using the integrated wifi/BT combo adapter (having removed the ZEXMTE dongle), or do I need to replace that dongle with a BT5.0 type? If so, any suggestions on which to purchase?

Thanks again.

tompijls commented 3 years ago

Rob, my understanding is it needs bluetooth 4.1 minimum to read from the keiser and expose the BLE Cycling Power Service at same time. if you have a 2nd bluetooth dongle, you may try following parameter which chris advised higher up in this thread: -bike-adapter hci1

nealjane commented 3 years ago

@robcalm finding a compatible cheap bt5.0 isn’t easy. I’d suggest it’s easier and cheaper to just by a rpi0w- it just then works..

ptx2 commented 3 years ago

Really excited to add support for the Keiser bikes. And to now have a reference for any other bikes that broadcast their stats in advertisement packets. Nice work @chriselsen, thanks for contributing this!

ptx2 commented 3 years ago

@robcalm A BT 4.1+ adapter that supports multi-role is needed if you want to connect to a BLE bike and also rebroadcast over BLE using a single BLE adapter. Multi-role is a feature that enables the adapter to act as a Central (client) and Peripheral (server) at the same time. It was introduced in BT 4.1 but it is optional so not all BT 4.1 adapters will have this.

It looks like your RPi3B+ claims BT 4.2 (multi-role is still optional in 4.2) so it's worth a try. If it works, let us know and we'll update the README.

You could also just use two BT 4.0+ adapters: one for the central (to connect to bike) and one for the peripheral (to accept connections from Zwift).

robcalm commented 3 years ago

Thanks everyone for the info. I'll give it a go this weekend a with both the internal adapter, and using both adapters, and let you know how it works out.

robcalm commented 3 years ago

Hi folks, I can confirm that this works using the built in BT adapter in an RP 3B+ ! I've used it with fulgaz on an ipad and a windows 10 PC.

Some observations:

--Noble errors and disconnection

Sometimes when my bike was idle for a while it would generate noble warnings noble warning: unknown handle 64 disconnected! noble warning: unknown handle 12 disconnected!

Other times it wouldn't generate this, but timed out "normally" [2021-02-21T03:45:06.749Z] bike disconnected e8:43:12:e4:2d:e9

However, once disconnected the only way to get things running again was to manually reconnect the bike gymnasticon --bike keiser Is this the expected behaviour? Shouldn't gymnasticon be able to automatically pick up the connection again for another session? Otherwise you'd always have to SSH in and fire it up immediately before a workout.

--Data dropouts

The is really noticeable for me. Gymnasticon frequently receives and transmits 0W and 0RPM stats. The RP is within maybe 5 or 6 meters of the bike so I don't think it is signal strength. I suppose the wifi and BT on single chip may be clashing, but this also seems a little unlikely.

Zero data pops up more often with significant changes in rpm or power, like if I drop from cadence of 60 down to 20 quickly it will almost always throw some zeros. But it also seems to just throw them sometimes with no trigger. I've increased the power smoothing function in fulgaz from 3 seconds to 6s, and this helps even things out. But it's not ideal.

I think that in the keiser2zwift tool the spurious generation of zero data by the bike might have been handled by transmitting the last-received non-zero data when zero data was received out of the blue. But I could be wrong. I don't remember ever seeing random zero data appear in the transmission logs there.

--Connecting to PC

This was still a challenge. Neither the Win10 BT config app nor fulgaz could see gymnasticon at first, even with repeated searching. I manged to get it working by using bluetoothctl; scan on; from the RP command line to search for the mac address of the PC BT adapter and then using the; pair; function to request a pair. Once the passkey was confirmed on each side gymnasticon appeared on the windows BT app and could be picked up by fulgaz. Fulgaz sees multiple copies of the power and cadence devices, which is strange, but selecting one of each worked fine.

Gymnasticon is great. I'm not a coder but I'll help however I can to improve it. Let me know.

robcalm commented 3 years ago

I see that since I did my build you've been looking to address the disconnect / reconnect situation: " Is the idea here to remove our restartScan handler? Good call! I think we may just be adding an extra empty handler and not removing the restartScan one. Should we use this.noble.off('scanStop', this.restartScan); instead? "

tompijls commented 3 years ago

Will you turn it into a new release including image?

Cheers

Tom


From: ptx2 notifications@github.com Sent: Sunday, February 21, 2021 1:41 AM To: ptx2/gymnasticon gymnasticon@noreply.github.com Cc: tompijls tompijls@hotmail.com; Mention mention@noreply.github.com Subject: Re: [ptx2/gymnasticon] Experimental support for Keiser M3 (#50)

Merged #50https://github.com/ptx2/gymnasticon/pull/50 into master.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/ptx2/gymnasticon/pull/50#event-4355843743, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAGK6CCLLAVDO5CRP4GRX33TABJE5ANCNFSM4XSVKZWQ.

tompijls commented 3 years ago

This is what the output shows when at the end of my run - bike disconnect after 5 minutes although the keiser switched of way faster

[2021-02-21T12:14:22.686Z] received stats from bike [power=50W cadence=63rpm] [2021-02-21T12:14:23.335Z] received stats from bike [power=49W cadence=63rpm] [2021-02-21T12:14:23.394Z] pedal stroke [timestamp=1613909663395.9834 revolutions=2471 power=49W] [2021-02-21T12:14:24.349Z] pedal stroke [timestamp=1613909664348.3643 revolutions=2472 power=49W] [2021-02-21T12:14:24.968Z] received stats from bike [power=52W cadence=65rpm] [2021-02-21T12:14:25.271Z] pedal stroke [timestamp=1613909665271.4412 revolutions=2473 power=52W] [2021-02-21T12:14:25.296Z] received stats from bike [power=52W cadence=65rpm] [2021-02-21T12:14:26.195Z] pedal stroke [timestamp=1613909666194.518 revolutions=2474 power=52W] [2021-02-21T12:14:26.273Z] received stats from bike [power=51W cadence=64rpm] [2021-02-21T12:14:26.919Z] received stats from bike [power=51W cadence=62rpm] [2021-02-21T12:14:27.163Z] pedal stroke [timestamp=1613909667162.26 revolutions=2475 power=51W] [2021-02-21T12:14:27.246Z] received stats from bike [power=51W cadence=62rpm] [2021-02-21T12:14:27.897Z] received stats from bike [power=51W cadence=62rpm] [2021-02-21T12:14:28.130Z] pedal stroke [timestamp=1613909668130.002 revolutions=2476 power=51W] [2021-02-21T12:14:28.221Z] received stats from bike [power=49W cadence=62rpm] [2021-02-21T12:14:28.543Z] received stats from bike [power=48W cadence=62rpm] [2021-02-21T12:14:28.864Z] received stats from bike [power=48W cadence=62rpm] [2021-02-21T12:14:29.096Z] pedal stroke [timestamp=1613909669097.744 revolutions=2477 power=48W] [2021-02-21T12:14:29.193Z] received stats from bike [power=48W cadence=62rpm] [2021-02-21T12:14:29.517Z] received stats from bike [power=50W cadence=63rpm] [2021-02-21T12:14:29.839Z] received stats from bike [power=50W cadence=63rpm] [2021-02-21T12:14:30.049Z] pedal stroke [timestamp=1613909670050.1248 revolutions=2478 power=50W] [2021-02-21T12:14:30.162Z] received stats from bike [power=50W cadence=63rpm] [2021-02-21T12:14:30.482Z] received stats from bike [power=52W cadence=65rpm] [2021-02-21T12:14:30.810Z] received stats from bike [power=52W cadence=65rpm] [2021-02-21T12:14:30.973Z] pedal stroke [timestamp=1613909670973.2017 revolutions=2479 power=52W] [2021-02-21T12:14:31.128Z] received stats from bike [power=52W cadence=65rpm] [2021-02-21T12:14:31.446Z] received stats from bike [power=53W cadence=65rpm] [2021-02-21T12:14:31.772Z] received stats from bike [power=53W cadence=65rpm] [2021-02-21T12:14:31.897Z] pedal stroke [timestamp=1613909671896.2786 revolutions=2480 power=53W] [2021-02-21T12:14:32.098Z] received stats from bike [power=53W cadence=65rpm] [2021-02-21T12:14:32.422Z] received stats from bike [power=52W cadence=65rpm] [2021-02-21T12:14:32.820Z] pedal stroke [timestamp=1613909672819.3555 revolutions=2481 power=52W] [2021-02-21T12:14:33.065Z] received stats from bike [power=52W cadence=65rpm] [2021-02-21T12:14:33.387Z] received stats from bike [power=49W cadence=62rpm] [2021-02-21T12:14:33.705Z] received stats from bike [power=49W cadence=62rpm] [2021-02-21T12:14:33.787Z] pedal stroke [timestamp=1613909673787.0974 revolutions=2482 power=49W] [2021-02-21T12:14:34.033Z] received stats from bike [power=49W cadence=62rpm] [2021-02-21T12:14:34.359Z] received stats from bike [power=43W cadence=58rpm] [2021-02-21T12:14:34.681Z] received stats from bike [power=43W cadence=58rpm] [2021-02-21T12:14:34.822Z] pedal stroke [timestamp=1613909674821.58 revolutions=2483 power=43W] [2021-02-21T12:14:35.334Z] received stats from bike [power=43W cadence=50rpm] [2021-02-21T12:14:35.658Z] received stats from bike [power=43W cadence=50rpm] [2021-02-21T12:14:35.976Z] received stats from bike [power=43W cadence=50rpm] [2021-02-21T12:14:36.021Z] pedal stroke [timestamp=1613909676021.58 revolutions=2484 power=43W] [2021-02-21T12:14:36.303Z] received stats from bike [power=34W cadence=50rpm] [2021-02-21T12:14:36.630Z] received stats from bike [power=34W cadence=50rpm] [2021-02-21T12:14:36.953Z] received stats from bike [power=34W cadence=50rpm] [2021-02-21T12:14:37.221Z] pedal stroke [timestamp=1613909677221.58 revolutions=2485 power=34W] [2021-02-21T12:14:37.594Z] received stats from bike [power=34W cadence=50rpm] [2021-02-21T12:14:37.919Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:38.245Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:38.563Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:38.892Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:40.508Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:40.829Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:41.157Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:41.479Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:41.800Z] received stats from bike [power=4W cadence=9rpm] [2021-02-21T12:14:42.443Z] received stats from bike [power=4W cadence=9rpm] [2021-02-21T12:14:43.084Z] received stats from bike [power=4W cadence=9rpm] [2021-02-21T12:14:43.407Z] received stats from bike [power=4W cadence=9rpm] [2021-02-21T12:14:43.732Z] received stats from bike [power=4W cadence=9rpm] [2021-02-21T12:14:43.889Z] pedal stroke [timestamp=1613909683888.2468 revolutions=2486 power=4W] [2021-02-21T12:14:44.379Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:45.024Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:45.674Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:46.972Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:47.289Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:47.933Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:48.254Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:48.902Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:49.228Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:14:49.556Z] received stats from bike [power=0W cadence=0rpm] Stats timeout: Restarting BLE Scan [2021-02-21T12:14:51.560Z] received stats from bike [power=0W cadence=0rpm] [2021-02-21T12:19:49.557Z] bike disconnected c7:bc:77:bb:1f:8a

ptx2 commented 3 years ago

@robcalm Great to know about the RPi3B+! Thanks for reporting that. I've added it to the README.

Can you confirm that you had the latest code when you did your last test? If not, hopefully your issues go away after grabbing the latest code. From your current gymnasticon directory, you can get the latest code by:

git checkout master
git pull
npm run build
gymnasticon --bike keiser
ptx2 commented 3 years ago

@tompijls Chris did mention somewhere above that timeout is probably too long and I agree. However in practice, had you started riding again during that 5 minutes, I believe it would have started to pick up stats again, as it should still be scanning. Let us know if you think that's not the case.

Looking at that log I actually don't think we need to restart the BLE scan there either, as it should still be scanning, just not finding anything. But in practice I don't think it matters.

Can you confirm your last ride was with the latest code? Besides the 5 minute timeout, does everything else still look good?