WouterJD / FortiusANT

FortiusANT enables a pre-smart Tacx trainer (usb- or ANT-connected) to communicate with TrainerRoad, Rouvy or Zwift through ANT or Bluetooth LE.
GNU General Public License v3.0
143 stars 77 forks source link

Support for Genius T2021 Brake (~46, 117) #101

Open WouterJD opened 3 years ago

WouterJD commented 3 years ago

Hi Wouter, from Melbourne, Australia

FortiusANT is not registering the trainer yet though. Any tips to try and get it working?

Thanks

Originally posted by @Sigfreid74 in https://github.com/WouterJD/FortiusANT/issues/14#issuecomment-667527513

WouterJD commented 3 years ago

@m472 I see that cadence = 0 in the logfile. This may be due to lose contact/no magnet etc. Tacx Fortius does not work well when there is no cadence.

So current status for the i-Genius development is that it conceptually works, but is not yet stable for @m472 ? Correct?

@mikeymclellan the "old" tacx trainers are not very precise nor repeatable in the power-reporting. It's also quite dependant of the tire-temperature. My yesterday's training was tenths of Watts off (realized versus requested power) but after half an hour is stabilized. This has to do with the calibration, which obviously moves during the training. I already experimented with a dynamic calibration (realized power must be equal to requested power) but did not activate it in the software because it seemed superfluous; where yesterday I had differences again. Yesterday the room was colder than some time ago ==> colder tire ==> longer warming-up time.

WouterJD commented 3 years ago

@m472 @mikeymclellan could you share the current status of the code modifications you made, please?

m472 commented 3 years ago

@WouterJD Thank you for the hint with the cadence, I have not had any problems with the slope simulation if the cadence was measured correctly.

So current status for the i-Genius development is that it conceptually works, but is not yet stable for @m472 ? Correct?

Yes, I would agree. It works well if it works but I have the following issues with the code:

Should I create a pull request to try to integrate the code or continue testing and try to find out how to implement the head unit stuff correctly (probably implement according to reverse engineered Bushido protocol and see if it works with @mikeymclellan)?

WouterJD commented 3 years ago

hi @m472 for a starter I do not know how the Genius works, so it's difficult to answer questions on technical level. A quick reaction now to assist to forward, I would need more time for an in-depth verification.

Tacx-Mode == stop perhaps leave as is; merely needed for dongles that disconnect I think.

def TargetPower2Resistance(self):
    self.TargetResistance = self.TargetPower

If the Genius supports setting TargetPower or TargetGrade, that must be implemented From what I understand is that the Vortex supports setting TargetPower only (at least: that is what is implemented)

I do not have Genius specs, so cannot help you here

Pull request: It's most usefull that you submit the pull-request when the implementation is fine for you.

If you want me to do code-review in the meantime; yes submit it.

Success guys! Keep me posted.

WouterJD commented 3 years ago
  • As I don't have the head unit for the Genius, I am not quite sure what to do with the head unit code I copied from clsAntTacxVortexTrainer

The i-Vortex consists of two devices; the brake and the headunit. Your system works without the headunit, so the thing is "only" to provide buttons and manual control.

You could choose:

In clsTacxAntGeniusTrainer

In FortiusAntBody.py I would also leave the headunit code present

I do not know how you implemented the Genius channel info; did you add new variables or simply change the Vortex variables?

m472 commented 3 years ago

You could choose:

  • implement brake-only
  • implement brake and head-unit , but leave head-unit untested.

Decided to go for the second. Actually the button protocol of the Bushido and the Vortex is the same, so I guess its probably the same for the Genius as well.

In clsTacxAntGeniusTrainer

  • (pairing can take a minute) will remain visible since you do not have a head-unit, which is not nice. I think I would add a flag to ignore absense of head-unit and leave code complete (to be prepared for later extension).

I added a flag to the __init__ method and the --no-headunit flag to the command line arguments.

I do not know how you implemented the Genius channel info; did you add new variables or simply change the Vortex variables?

I guess you mean the variables DeviceTypeID_VTX, RfFrequency_2466Mhz etc. I did create new variables for these in order not to affect the Vortex functionality

Sigfreid74 commented 3 years ago

This is amazing work people! I have now been testing the new additions made by m472 and by gosh it works! I have successfully been using my non-smart Genius with Golden Cheetah.

I have a head unit; is there a way I can help you test the code out for that? So far it is not seeming to recognise the head unit.

Also is there a calibration routine Genius users can use reliably now that we are free of TTS4? Ideally the wheel should be spun up to 30km/h for about 6-7 minutes in my experience with TTS4. I think the heating of the tyre changes the resistance or something.

WouterJD commented 3 years ago

The title is changed to be consistent with the other developments Related issues: #46 = Vortex, #101 = Genius, #117=Bushido

WouterJD commented 3 years ago

I have a head unit; is there a way I can help you test the code out for that? So far it is not seeming to recognise the head unit.

Yes you sure could. First question: are you able to program in python?

Sigfreid74 commented 3 years ago

Sorry Wouter, I am not able to program in Python (or anything else properly - I am very limited to just trying to change a few numbers here and there!). I just have the hardware ready to test it out and provide some logs.

WouterJD commented 3 years ago

@Sigfreid74 as I read in @m472 response, disabling the headunit is a command-line option. So it appears ready to test

WouterJD commented 3 years ago

@m472 great work and I also see @Sigfreid74 's confirmation!

Now we can proceed with details and integration!

I added a flag to the __init__ method and the --no-headunit flag to the command line arguments.

Would it be an idea to define -t Genius or -t Genius- in stead of a separate command-line parameter?

A similar option could be usefull for the Vortex (Vortex- for no headunit). It will be obvious that such configurations exist.

I will look into the Genius code in detail lateron (now busy with bluetooth, then genius). What is you opinion on the Vortex / Genius classes; integrate or keep separate?

WouterJD commented 3 years ago

As permissible values for -t we will have Vortex, Genius, Bushido (i-Vortex as an compatibility option) with optional - for no-headunit.

I see you make a remark on Bushido headunit protocol; do you have a Bushido as well? Is your solution an answer for #117 also? Sorry for messing around with the issue-titles, but I try to keep track of them all.

switchabl commented 3 years ago

I had the opportunity to buy a Genius T2020 (with T2022 head unit and T2420 steering frame) for cheap and couldn't resist. So I may have something to contribute soon.

Curious to see if it is a meaningful improvement over the Fortius (apart from getting rid of the cables and the cadence sensor).

m472 commented 3 years ago

@WouterJD no, I do not have a Bushido brake. My remarks on #117 are only based on the reverse engineered bushido protocol mentioned here: https://github.com/fluxoid-org/CyclismoProject/wiki/Tacx-Bushido-Headunit-protocol. My pull request could work with the Bushido as well as the protocol seems to be identical.

However I realized yesterday, that the device ID for the Bushido is different. Therefore some adjustments are necessary in order to support the Bushido.

switchabl commented 3 years ago

From my (still limited) research on the Tacx ANT protocol, a big difference between the Genius and the Bushido protocol is that on the Genius you specify a target slope or power and the trainer basically does the rest. The Bushido is more like the Fortius in that you specify a target force instead, where you have to calculate slope, rolling resistance and wind resistance yourself. So without figuring that out, it's unlikely to work properly.

m472 commented 3 years ago

@switchabl okey, I just had another look at the protocol description at Cyclismo Project and it seems the head unit can do this conversion between power and resistance because the head unit protocol is almost identical to the genius brake protocol.

I think this means the Bushido brake unit needs some more work than just changing an ID and will be its own project.

@WouterJD I like your suggested solution to replace the --no-headunit flag by changing the --TacxType argument. I will change the implementation.

What is you opinion on the Vortex / Genius classes; integrate or keep separate? I think for the moment keeping the Vortex / Genius classes separate is the better solution. If someone gets the Bushido to work it might be useful to do some refactoring to reduce code duplication but for the moment I would not combine the two classes.

switchabl commented 3 years ago

My apologies, I think you are right. If you connect through the head unit it looks almost exactly like a Genius. It is only when you connect to the brake directly that things get messy (and there is probably little reason to do that?).

Some relevant differences:

In summary, it looks similar enough to give it a go even if you can't test it. But it definitely needs a separate implementation (with maybe a common base class later on).

switchabl commented 3 years ago

I've looked at it a bit more closely and can maybe fill in a few blanks.

The target (sub-)page is pretty much already complete on the Cyclismo page: Bytes Value Interpretation
0 0xdc Page
1 0x01 Sub page
2 0x00 Slope mode
0x01 Power mode
0x02 Heart rate mode (not sure that actually works)
3-4 Int16 Target slope (0.1%)/power (W)/heart rate (bpm)
5 UInt8 Rider + bike weight (kg)
6 0x00
0xee Reset distance
7 0x00 Padding
There is also a wind resistance sub-page: Bytes Value Interpretation
0 0xdc Page
1 0x02 Sub page
2-3 UInt16 0.5 * wind resistance coefficient (0.001 kg/m)
4-5 Int16 Genius: Wind speed (0.01 m/s, tail wind +/head wind -)
Bushido: Wind speed (1 m/s, tail wind -/head wind +)
6-7 0x00 Padding

wind resistance coefficient = air density surface area drag coefficient * drafting factor

At least that is my best guess at the moment, I hope I have worked the units and signs out correctly. There is no page for rolling resistance, but I guess we can absorb any deviations from the internal default (probably 0.004) into the slope.

All integer values are big-endian (MSB first).

switchabl commented 3 years ago

I wrote up a summary of the Genius/Bushido protocol here: https://gist.github.com/switchabl/61f051700b1b91dccbbdea14d9aac70b See next post for current version.

There are still some small gaps and probably some errors.

switchabl commented 3 years ago

It looks like the Vortex protocol is really similar too if you control it through the head unit instead of pairing the brake directly (like FortiusANT currently does). So we might share most of the implementation between Genius/Bushido/Vortex.

I added my best guesses for the Vortex protocol, although this is of course completely untested: https://gist.github.com/switchabl/75b2619e2e3381f49425479d59523ead

Sigfreid74 commented 3 years ago

Amazing work Switchabl! We might be able to get some sort of auto-calibration routine happening with all that information.

switchabl commented 3 years ago

Yes, I think so. I still don't have my Genius, but once I get it I will try to get calibration and head unit to work.

So far, this is mostly based on playing around with TTS without the actual hardware and some experimentation/testing will of course be necessary. But I think it is a good starting point.

m472 commented 3 years ago

Great work @switchabl!

I will try to implement the Genius-specific parts and test them.

switchabl commented 3 years ago

My Genius finally arrived and I can do some tests of my own now. I also fixed a few typos in the protocol specification (most importantly page 0xdc is used for the calibration command, not 0xac).

I have verified the protocol for the Genius head unit, but I would suggest that we don't implement the head unit in clsTacxAntGeniusTrainer, since it is technically completely independent from the Genius brake (you could use it without the brake or vice versa). I think it makes more sense to add support for the head unit as a general remote control along with #121.

m472 commented 3 years ago

@switchabl the suggestion to implement the head unit as a separate device seems reasonable for the Genius brake. It would also reduce the line count of the Genius class by 99 lines from 296 to 197.

For the Bushido brake I am not sure if it would not sense as the head unit makes the communication a lot easier. But one may also argue that there is not even a Bushido proof of concept yet so we should not spend too much thought about it.

switchabl commented 3 years ago

Yes, I agree, for the Bushido it makes sense to go through the head unit. If we eventually want to support the Bushido brake solo, I can dig a little deeper into the brake protocol as well. But I think the Bushido was always sold with the head unit, so if that is the case that should be low priority.

When I finally get around to finishing the ANT+ remote (I got side-tracked with the Genius), I will implement the Genius remote there. I now have one to test, so that should be easy enough.

The Blacktrack steering thing was also included with my Genius. For now that is maybe not so interesting, but once Bluetooth is available, we could emulate an Elite Sterzo Smart to get steering on Zwift (https://github.com/kwakeham/zwift-steerer/).

switchabl commented 3 years ago

Btw here are the FCC application documents for the Genius (+ head unit + steering frame): https://fccid.io/2AAAZ

Maybe not that much interesting stuff in there, but there are some nice photos of the internals. Also a screenshot of their internal test software: https://fccid.io/img.php?id=2089359&img=bg7.png

So apparently the "trigger" calibration command (0xff) triggers the "production calibration". That explains why it is never sent by TTS and there is a risk sending it messes something up. Apart from that nothing surprising.

There are debug commands "contest", "calsrt" (driving the motor in some way) and "antcw", "antrnd" (for radio testing). I already know that there is a debug command "align" that needs to be run after firmware update. But none of that sounds particularly useful.

I couldn't find the non-smart Bushido. Maybe it was never officially sold in the US? The newer Tacx ("Smart") trainers are here: https://fccid.io/2AAMI

tjerkh commented 3 years ago

I did try my bushido last week with the branch from m472 https://github.com/m472/FortiusANT/tree/c02e8d356fc74b7417cdaaf3dea37b596c5511c2 by just changing the DeviceTypeID to 82, unfortunately that didn't work. I don't have any experience with Python or Ant+, but I tried to study the code and https://github.com/fluxoid-org/CyclismoProject/wiki/Tacx-Bushido-Headunit-protocol. I think the initialisation to the PC connection needs to be done, but I will need to have a better look to see if I can implement this.

switchabl commented 3 years ago

Yes, also take a look at my write-up if you haven't already: https://gist.github.com/switchabl/75b2619e2e3381f49425479d59523ead

I think the main thing is to set it to PC control mode (0x04) at the start (by sending 0xac03040000000000). If you set to 0x03 afterwards, apparently the "Start cycling" message comes up, but I think that is optional. Technically, you should keep sending the command until you get confirmation (0xad03040000000000), in case the transmission gets lost. But for a first test you can probably skip that.

We should probably also send a keep-alive page (0x0000000000000000) every ~10s, to prevent it from turning off. Not sure if this is strictly necessary if we are sending other commands continuously anyway.

Maybe you can copy some of the code for the Vortex head unit. It should be very similar in that respect.

There are a couple of other little differences, but for a first proof-of-concept this should be fine. We can worry about the details later.

Sigfreid74 commented 3 years ago

Maybe not that much interesting stuff in there, but there are some nice photos of the internals. Also a screenshot of their internal test software: https://fccid.io/img.php?id=2089359&img=bg7.png

I happen to have the Genius Test Application - sent to me by Tacx many years ago when I had a hardware problem. Does not seem to run on Windows 10 though. https://drive.google.com/file/d/1WTZMx2FX-tHLR9BjvY4X3AFJOaYP6ux2/view?usp=sharing May be of some use? It also came with some DLL's - I don't know if these are necessary to run this file.

switchabl commented 3 years ago

Interesting, thanks! Yes, having a minimal interface for testing could definitely be useful. And yes, the DLLs are unfortunately necessary to run it.

Sigfreid74 commented 3 years ago

Here's all the files they sent me: https://drive.google.com/file/d/1yuWhBjTc-qMsXde8dE9C5cx2K-UkcwRO/view?usp=sharing

Hope it helps in the reverse engineering.

simonperneel commented 3 years ago

Hi Wouter & co

First let me introduce myself. I am Simon Perneel, and i'm from Belgium. I recently discovered this amazing piece of software and i wanted to revive my old Tacx i-Genius (T2021, headunit) as Tacx doesn't support it anymore. I was hoping to get it working with Zwift. Today i received my second ant+ dongle and i tried the adapted code of @m472 with support for the Genius. I started FortiusAnt with following commands: python FortiusAnt.py -t Genius- However, i always get this error in the console:

16:01:54,808: Tacx   - Pair with Tacx i-Genius
Traceback (most recent call last):
  File "FortiusAnt.py", line 538, in <module>
    Console.Autostart()
  File "FortiusAnt.py", line 169, in Autostart
    Tacx2Dongle(self)
  File "FortiusAnt.py", line 118, in Tacx2Dongle
    rtn = FortiusAntBody.Tacx2Dongle(self)
  File "C:\Program Files\FortiusANT-Genius-Support\FortiusANT-Genius-Support\pythoncode\FortiusAntBody.py", line 483, in Tacx2Dongle
    rtn = Tacx2DongleSub(self, Restart)
  File "C:\Program Files\FortiusANT-Genius-Support\FortiusANT-Genius-Support\pythoncode\FortiusAntBody.py", line 779, in Tacx2DongleSub
    TacxTrainer.Refresh(QuarterSecond, usbTrainer.modeResistance)
  File "C:\Program Files\FortiusANT-Genius-Support\FortiusANT-Genius-Support\pythoncode\usbTrainer.py", line 667, in Refresh
    self.SendToTrainer(QuarterSecond, TacxMode)
  File "C:\Program Files\FortiusANT-Genius-Support\FortiusANT-Genius-Support\pythoncode\usbTrainer.py", line 1381, in SendToTrainer
    info = ant.msgPageDC_TacxGeniusSetPower (ant.channel_GNS_s, \
AttributeError: module 'antDongle' has no attribute 'channel_GNS_s 

What am i doing wrong? I use the Tacx T2028 antenna and a second Cyclplus dongle ( i know there are bad experiences about this dongle, but i already ordered it when i read about this).

EDIT: I am running both FortiusAnt and Zwift on the same Windows 10 computer.

This is what i get in Zwift: Schermafbeelding 2020-11-28 171053

I'm happy to help testing the headunit if I manage to get FortiusAnt working. Anyway, thank you for all the work you put into this project!

Simon

switchabl commented 3 years ago

@Sigfreid74 Thank you again! It looks like it supports Bushido and Vortex as well. It kind of works on Windows 10 for me and exchanges some data, but doesn't pair properly for some reason. Have to look into it more carefully, but it might be quite useful.

@simonperneel Yes, it is a work in progress and the current commit seems to be broken. I ran into the same problem when I wanted to test it yesterday, here is my quick-fix: https://github.com/switchabl/FortiusANT/tree/genius. I rode an hour or so on Zwift without issues. Calibration is not yet implemented. If you have a working TTS4, you can use that to run the calibration before you start FortiusANT. If not, power may be a bit off.

WouterJD commented 3 years ago

Hi guys, thanks for all three work. I was busy with the magnetic trainer.

What is the best branch today for genius and bushido? I will start from there to integrate into the base branch of FortiusANT.

simonperneel commented 3 years ago

Thank you @switchabl! I will give a try with your fork of the code. What command are you using to start FortiusAnt for the Genius?

switchabl commented 3 years ago

@simonperneel I am using python FortiusAnt.py -g -a -t Genius. The Genius- option will very likely go away (and is gone already in my branch). Let us know if it works for you!

@WouterJD Well, the code is really all by @m472. I've really only done some minor clean-up in my branch for my testing. So I would really defer to him on how to proceed as well.

But in any case, I will try to give a quick status report:

simonperneel commented 3 years ago

I did a quick test and it appears to be working well for me on Zwift 😃 ! I will do some more workouts in the coming days, and will share my experiences with the Genius ( right now i'm using the branch of @switchabl)

switchabl commented 3 years ago

I tried the Genius in power mode for the first time today and it mostly works, but it reacts very slowly. Maybe we need to set a lower flywheel weight in power mode like on the Fortius. Or maybe this is normal and a limitation of the brake. I will investigate tomorrow.

The cadence also reads slightly high on mine (by ~4 rpm). But this definitely not our fault, it is just the number that the brake sends.

switchabl commented 3 years ago

So, more on ERG mode:

Tl;dr ERG mode should be much better now with https://github.com/switchabl/FortiusANT/commit/232410a42f0ac7331cb6d30aacdde6adcca4e3ef

simonperneel commented 3 years ago

I did a few workouts on Zwift the past days with the Genius. It appears to work well and it responds to my trainer. However, i have some issues with it and don't know if these are limitations of FortiusAnt, or just because the Genius is not fully implemented yet. I start FortiusAnt with python FortiusAnt.py -g -a -t Genius. This is the grade mode I suppose?

Is it just a limitation of the current implementation or am I doing something wrong? Can anyone clarify this? Thanks in advance!

switchabl commented 3 years ago

@simonperneel Thank you for testing and for your feedback! No, this definitely not the expected behaviour. The mode, either power or slope is requested by Zwift. So when you start Zwift the target should switch to something like "1%, 143W" (unless you load an ERG-mode workout in Zwift). If this doesn't happen, it sounds like Zwift is not talking to FortiusANT. The only Zwift-related feature that is currently missing is track resistance, so at the moment riding on a dirt road doesn't feel harder than on asphalt. But slope is definitely supported (and has so far worked fine for me) and should feel quite realistic on the Genius up until 10-12%.

You should first check that the simulated trainer is paired as a "Controllable" (and not just a "Power source"). If that doesn't help, run FortiusANT with the -d 127 option to generate a log file and upload that here so that we can see what is going wrong.

simonperneel commented 3 years ago

Thanks for the fast response! Indeed, there must be something wrong between the communication from Zwift to the Genius. My trainer is paired as a 'Controllable' (see first image). I don't think FortiusAnt is running in grade mode, as I don't see the grade displayed in the GUI in FortiusAnt (see second image).

\ Schermafbeelding 2020-12-05 092751 \ Schermafbeelding 2020-12-05 092705 \ I did a quick ride in Zwift and generated this log file: FortiusANT.2020-12-05 12-00-20.log Maybe the problem is that I use a cheap ANT+ dongle from Aliexpress next to my original Tacx ant+ dongle? Thanks for having a look.

WouterJD commented 3 years ago

AliExpress / price is not the issue; as long as it's not the cycplus dongle giving issues. Take care that the dongles communicate with each other; no electronics between them. See manual for explanation.

switchabl commented 3 years ago

@simonperneel I don't have as much experience with the log files as @WouterJD , but to me it looks normal, except that we never receive any commands from Zwift. In any case, it doesn't look Genius-related.

It seems that FortiusANT is currently using the Tacx/Dynastream dongle and Zwift is using the Cycplus. It may be worth a try to switch that (don't plug in the Tacx dongle until after FortiusANT is running). Zwift doesn't seem to like the Cycplus dongle either. This sounds familiar: https://forums.zwift.com/t/cycplus-ant-issue/514339

The Zwift logs may or may not be helpful: https://support.zwift.com/locating-log-files-BykKO63fr

WouterJD commented 3 years ago

Enter cycplus and start FortiusANT + search for hw and start Then enter 2nd dongle and start zwift

Cycplus dongle remains a problem

switchabl commented 3 years ago

Minor update: https://github.com/switchabl/FortiusANT/tree/genius

Status:

switchabl commented 3 years ago

New version now adjusts wind resistance if supported by the CTP (Zwift does not). I am still confused about the units of the wind speed. TTS seems to assume 100 * wind speed (m/s), but reality seems closer to 250 * wind speed (m/s). Still, seems to be working fine now using the latter value.

Maybe more importantly, the default wind resistance is now more in line with the other trainers (and the FE-C specification). So doesn't feel like riding a TT bike anymore.

Sometimes the wheel keeps spinning slowly in ERG mode after you stop pedaling. Haven't really found a way to fix that yet.

switchabl commented 3 years ago

Calibration is now supported

Head-unit is not supported yet (will do this separately) and the virtual gearbox is not supported right now (and it is not clear if it ever will be, needs more experimenting). I find that higher gradients are not super smooth, but compared to the Fortius quite ridable, so I don't miss it much. On Zwift, maybe set a "Trainer difficulty" a bit lower than 100%, on Rouvy try the new -G option (for example -G 75/50) to reduce the simulated gradient a bit if you have problems.

@Sigfreid74 @m472 @trygvelu @mikeymclellan @simonperneel (and anyone else with a Genius) Let me know if you are missing anything or are running into any issues with the current version (https://github.com/switchabl/FortiusANT/tree/genius)

@m472 I hope you are okay with me taking this over, most of the credit for the implementation is yours. I assume you have been (relatably) busy with other things.

@WouterJD If the feedback is good, I will make a new pull-request later this week for inclusion in the main branch.