Open WouterJD opened 4 years ago
Hi @iepuzaur
I have created this separate issue for you.
Some questions:
If yes, there is a fair chance that FortiusANT may work and I will assist. Just let me know!
By the way, where are you from? I like to know who I talk with :-)
https://tacx.com/product/i-vortex/
Is this the machine?
Hi, Thanks for creating the topic, indeed the i-vortex is the one from the link you sent, except i have it on light green color. Now with spending time at home a lot, I wanted to use it again and discovered Tacx sold to Garmin, support is inexistent and if you lost your previous installation of TTS4, than it's rather useless. It is the version before Vortex Smart and has only Ant+, without fe-c. the trainer works fine with TTS 4, connection is not made by usb cable, but through an Ant+ usb dongle. I'll have a look at the repo and see if I manage anything, would be glad to test this. Greets from Bucharest, Romania
Head unit is 1962 though.
So your i-Vortex is from the time that Tacx wanted to keep software and hardware bundled and proprietary. What would be needed is to (1) understand how the i-Vortex communicates through ANT and (2) convert that tp "ANT+ FE-C". (1) is the challenge.
As said above: please try ExplorANT.py and check what it finds; that's the first step. To do this you need a computer (windos, linux, mac) and (for a starter) with one USB ANT-dongle? If you want to start Zwift... from the same computer a second dongle is required.
I have been searching for an "i-Vortex ANT definition" and found the folllowing article: https://www.dcrainmaker.com/2015/06/trainer-profile-zwifttrainerroadkinomap.html (June 2015)
So how do you upgrade your trainer? Via a simple app. Tacx today released a new utility app called ‘Tacx Utility’, this app connects to your Smart series trainer and updates the trainer’s firmware. Once upgraded, then 3rd party apps that support the ANT+ Trainer Profile can control it as they see fit.
Zwift: ... As long as you upgrade your trainers firmware first, you can then scan for the trainer using the usual Zwift option, which will in turn find the trainer and allow you to control it. Super simple.
It's interesting to give it a try.
It looks like Goldencheetah has support for the proprietary i-Vortex ANT protocol. Check the src/ANT/ANTMessage.cpp file.
Thanks, man, you're a great help. Will check
ANT parameters are (unconfirmed)
ANT Device-Type = 0x3d Channel 66 = 0x42 Period = 0x2000 No network key (= the default key after resetting the ANT dongle)
You're doing a great job, btw.
Just being lazy and asking; does this mean if I would simply bridge the i-vortex as a FE-C it would be enough?
I guessed that would be the easy way to make a proprietary trainer
Just being lazy and asking; does this mean if I would simply bridge the i-vortex as a FE-C it would be enough?
Answer: Unfortunately No
GoldenCheetah ANTMessage.cpp Line ~ 660 ++
case ANTChannel::CHANNEL_TYPE_TACX_VORTEX:
{
const uint8_t* const payload = message + 4;
vortexPage = payload[0];
switch (vortexPage)
{
case TACX_VORTEX_DATA_SPEED:
vortexUsingVirtualSpeed = (payload[1] >> 7) == 1;
vortexPower = payload[2] | ((payload[1] & 7) << 8); // watts
vortexSpeed = payload[4] | ((payload[3] & 3) << 8); // cm/s
// 0, 1, 2, 3 = none, running, new, failed
vortexCalibrationState = (payload[1] >> 5) & 3;
// unclear if this is set to anything
vortexCadence = payload[7];
break;
case TACX_VORTEX_DATA_SERIAL:
// unk0 .. unk2 make up the serial number of the trainer
//uint8_t unk0 = payload[1];
//uint8_t unk1 = payload[2];
//uint32_t unk2 = payload[3] << 16 | payload[4] << 8 || payload[5];
// various flags, only known one is for virtual speed used
//uint8_t alarmStatus = payload[6] << 8 | payload[7];
break;
case TACX_VORTEX_DATA_VERSION:
{
//uint8_t major = payload[4];
//uint8_t minor = payload[5];
//uint8_t build = payload[6] << 8 | payload[7];
break;
}
case TACX_VORTEX_DATA_CALIBRATION:
// one byte for calibration, tacx treats this as signed
vortexCalibration = payload[5];
// duplicate of ANT deviceId, I think, necessary for issuing commands
vortexId = payload[6] << 8 | payload[7];
break;
}
break;
}
ANTMessage.cpp Line about 955 ++
ANTMessage ANTMessage::tacxVortexSetFCSerial(const uint8_t channel, const uint16_t setVortexId)
{
return ANTMessage(9, ANT_BROADCAST_DATA, channel, 0x10, setVortexId >> 8, setVortexId & 0xFF,
0x55, // coupling request
0x7F, 0, 0, 0);
}
ANTMessage ANTMessage::tacxVortexStartCalibration(const uint8_t channel, const uint16_t vortexId)
{
return ANTMessage(9, ANT_BROADCAST_DATA, channel, 0x10, vortexId >> 8, vortexId & 0xFF,
0, 0xFF /* signals calibration start */, 0, 0, 0);
}
ANTMessage ANTMessage::tacxVortexStopCalibration(const uint8_t channel, const uint16_t vortexId)
{
return ANTMessage(9, ANT_BROADCAST_DATA, channel, 0x10, vortexId >> 8, vortexId & 0xFF,
0, 0x7F /* signals calibration stop */, 0, 0, 0);
}
ANTMessage ANTMessage::tacxVortexSetCalibrationValue(const uint8_t channel, const uint16_t vortexId, const uint8_t calibrationValue)
{
return ANTMessage(9, ANT_BROADCAST_DATA, channel, 0x10, vortexId >> 8, vortexId & 0xFF,
0, 0x7F, calibrationValue, 0, 0);
}
ANTMessage ANTMessage::tacxVortexSetPower(const uint8_t channel, const uint16_t vortexId, const uint16_t power)
{
return ANTMessage(9, ANT_BROADCAST_DATA, channel, 0x10, vortexId >> 8, vortexId & 0xFF,
0xAA, // power request
0, 0, // no calibration related data
power >> 8, power & 0xFF);
}
Thanks again; let's seet what @iepuzaur will provide. New challenge to port the software at distance, not having the device at hand.
Hi WouterJD I have the same trainer Tacx Vortex with the T1962 head unit, Happy to help if you just let me know what you need!
Great guys; it will not be an easy job - but worth while trying. It will take some testing....
Currently busy to get the software running on MacOS: #45 :-)
As probably stated above, the first step is to install the software - and you do not need to a python expert, check the wiki - and run ExplorANT, a small tool that shows what's going on on the ANT+ network.
Command: ExplorANT -d127
which will create a logfile, please post.
In the meantime, say hallo on Strava: https://www.strava.com/athletes/2885978
I am on windows 10 as well.
În mie., 15 apr. 2020 la 17:43, WouterJD notifications@github.com a scris:
By the way:
- What systems do you use? I work with windows
- Please download the newest software which has been improved the last days to debug the MacOS environment
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/46#issuecomment-614081599, or unsubscribe https://github.com/notifications/unsubscribe-auth/APEJOVRATFKEMRK5YKPHMODRMXBXLANCNFSM4MGACCGA .
Windows 10 for me as well
Hi,
I also have an i-vortex. I'll probably be able to do the test at the end of the day (in 8 hours) if nobody had the time to do it before.
For this first test, do I need to reinstall the trainer as a libusb-win32 device or it doesn't matter for now ?
Anyway, thanks for the time spent on this.
Welcome! Yes it's a libusb device; please check https://github.com/WouterJD/FortiusANT/wiki#windows
Yes, sorry about that. the log attached. ExplorANT.2020-04-16 09-12-38.log
It seems that ExplorANT is running and does not "see" any ANT+ devices. The idea is that you start Tacx iVortex and then start ExplorANT.
Can that be the case? I hope that the iVortex acts like a master ANT+ device and should be visible...
To avoid misunderstanding:
ExplorAnt.py -d127
Thanks
In case of any help, I did the manip. Started i-vortex trainer and head unit. Started TTS4, both units are seen. Started ExplorANT.
As a side note, at the very beginning of the trainer, tacx tts4 needed to have head unit started in order to control the trainer. Then, at some point they did an update and it was not needed anymore. Tacx TTS4 was able to control the trainer without the head unit
so I have checked as per your indications, then I get this:
16:05:15,811: ExplorANT started
16:05:15,812: -d 127 (0b1111111)
16:05:15,813: -D -1 (-0x1)
16:05:15,816: -H -1 (-0x1)
16:05:15,816: -F -1 (-0x1)
16:05:15,817: --------------------
16:05:15,817: Dongles in the system:
16:05:15,859: manufacturer=Dynastream Innovations, product= ANT USBStick2, vendor= 0xfcf, product=0x1008(4104)
16:05:15,860: --------------------
16:05:15,861: GetDongle - Check for dongle 4100 Older
16:05:15,871: GetDongle - Check for dongle 4104 Suunto
16:05:15,889: GetDongle - Try dongle: manufacturer=Dynastream Innovations, product= ANT USBStick2, vendor= 0xfcf, product=0x1008(4104)
DEVICE ID 0fcf:1008 on Bus 000 Address 001 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x20 (32 bytes)
idVendor : 0x0fcf
idProduct : 0x1008
bcdDevice : 0x100 Device 1.0
iManufacturer : 0x1 Dynastream Innovations
iProduct : 0x2 ANT USBStick2
iSerialNumber : 0x3 123 ¡¢£¤ ÀÁÂà DSI
bNumConfigurations : 0x1
CONFIGURATION 1: 100 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x20 (32 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x2 ANT USBStick2
bmAttributes : 0x80 Bus Powered
bMaxPower : 0x32 (100 mA)
INTERFACE 0: Vendor Specific ===========================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x2
bInterfaceClass : 0xff Vendor Specific
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x2 ANT USBStick2
ENDPOINT 0x81: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x1
ENDPOINT 0x1: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x1 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x1
16:05:15,914: GetDongle - Set configuration
16:05:15,914: GetDongle - Send reset string to dongle
16:05:15,915: GetDongle - Exception: [Errno None] b'libusb0-dll:err [claim_interface] could not claim interface 0, win error: The requested resource is in use.\r\n'
16:05:15,918: GetDongle - Check for dongle 4105 Garmin
16:05:15,927: GetDongle() returns: No (free) ANT-dongle found
16:05:15,928: No (free) ANT-dongle found
16:05:15,928: We're done
Of course this is because the other app is using the Ant+ usb device. But what I have sent earlier is for sure with the units (brake and headunit connected to the ant+ usb stick).
PS. If worth knowing, my Ant+ USB device is T2018 of Tacx.
stop tts4 before starting explorANT and redo test
In case of any help, I did the manip. Started i-vortex trainer and head unit. Started TTS4, both units are seen. Started ExplorANT.
Good next step. I have modified ExplorANT to separate the logging from the console + some minor improvements. Important change -done for MacOS support- is that dongle error handling is improved, messages MAY got lost, hence a rerun is useful. Thanks.
Please download software, rerun and let me see output.
Hi, here is the log with the latest version ExplorANT.2020-04-17 07-00-01.log
This logfile looks as if there is no device "in the air". I have reviewed the device pairing-process and learned from it and updated the software.
Please download antDongle and ExplorANT and retry.
I assume that you have the iVortex "ready to use" when running ExplorANT, true?
Yes, everything is "ready to use". If I launch Tacx TTS4, it discovers immediately both devices (head unit and trainer). Of course when I do your test, Tacx TTS4 is not launched. New log is attached ExplorANT.2020-04-17 11-37-13.log
So, the "normal" open pairing mechanism does not work. It will require an extended version of ExplorANT to support more pairing options. I will come back on it
ANT Device-Type = 0x3d Channel 66 = 0x42 Period = 0x2000
I have extended the device pairing for the Tacx i-Vortex for pairing with masters with the pairing-bit set; which does not make a lot of difference it seems.
Also, I always open a channel for VTX (i-Vortex) and listen to messages.
So ready for next test.
Test done ExplorANT.2020-04-18 06-41-34.log
One device is recognized
06:41:42,638: ExplorANT: ? discovered on channel=0, number= 5866 typeID=122 TrType=122
06:41:42,638: ExplorANT: added to list
Will continue later-on, other things to be done now!
PS. 122?? DeviceTypeID_bike_cadence =122
do you have an active bike-cadence sensor on your bike?
Q: while doing the test, did you cycle on the bike & trainer?
Well yesterday I did the test in a room with no bike. Today I did it where I store usually the trainer and the bike. So indeed there might have been other ant devices like speed sensor, cadence sensor and power sensor. I removed everything from the room and did the test again. Sorry about that.
And no, I did not cycle. This time I did.
No worries. Well. I think I listen on channel 7 to the Tacx i-Vortex but do not receive any messages. The setup is now OK; I will have to study the material as provided above by @totalreverse to check what I should do, using the investigations Golden Cheetah evidently have done.
Not sure if it helps, but if you need a team viewer access to test directly next time when you have time to look on this matter, I could grant it to my laptop which runs the trainer.
Thanks a lot for the effort!
În sâm., 18 apr. 2020 la 13:01 WouterJD notifications@github.com a scris:
No worries. Well. I think I listen on channel 7 to the Tacx i-Vortex but do not receive an messages. The setup is now OK; I will have to study the material as provided above by @totalreverse https://github.com/totalreverse to check what I should do, using the investigations Golden Cheetah evidently have done.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WouterJD/FortiusANT/issues/46#issuecomment-615835131, or unsubscribe https://github.com/notifications/unsubscribe-auth/APEJOVUH5TKRGU3QKYREQADRNF253ANCNFSM4MGACCGA .
sure @iepuzaur please do the test as above and communicate logfile. ci!
Here attached my log. ExplorANT.2020-04-18 12-08-25.log
same result. I will study GoldenCheetah code where the solution should be and come back on it.
Great to have two testers!
BTW @iepuzaur and @darkpotpot do you have Strava accounts? We could meet there to exchange our Tacx results in near future👍
Honestly I haven't use it and nevertheless I am just a humble amateur :)) so I will definitely be the last :-)) but I will see if I can (re)connect it to Tacx (my Tacx was dusty for some years and only this terrible situation put it back on track, also noticing that much changed in the field since I have lost interest in it i.e. smart trainers). Again, your help is very appreciated!
Quick scan over GoldenCheetah source, and recording here what is where.
I'll do what I can
BTW @iepuzaur and @darkpotpot do you have Strava accounts? We could meet there to exchange our Tacx results in near future👍
Yes I have one. If a French Guy is asking to follow you, then it's me ;) Thank you for your work on this.
@WouterJD it looks to me, that you set the right devicetype and the right period but not the right channel (0x39 instead of 0x42 for vortex) and you're using a network with the ANT+ key. The vortex use the default key. After resetting the dongle just omit the key-setting or if you set a key on network #0 you can use i.e. network #1 (without a key).
Thanks for thinking with us!
PS. I do not understand the channel 0x39/0x42 paragraph; 0x42 is the msgID_AssignChannel or do I misunderstand?
Summarized, two changes:
Action for next test, action @iepuzaur, @darkpotpot, @plundberg75:
Ah yes - using the word "Channel" for the Frequency is not a good idea. Frequency = 66 is what I wanted to say. Are you sure you checked in the right antDongle.py file? The current file looks like an old version.
@totalreverse & @mattipee thanks for references to code samples!
GoldenCheetah ANTMessage.cpp Line ~ 660 ++ case ANTChannel::CHANNEL_TYPE_TACX_VORTEX: { const uint8_t* const payload = message + 4; vortexPage = payload[0];
switch (vortexPage) { case TACX_VORTEX_DATA_SPEED: vortexUsingVirtualSpeed = (payload[1] >> 7) == 1; vortexPower = payload[2] | ((payload[1] & 7) << 8); // watts vortexSpeed = payload[4] | ((payload[3] & 3) << 8); // cm/s // 0, 1, 2, 3 = none, running, new, failed vortexCalibrationState = (payload[1] >> 5) & 3; // unclear if this is set to anything vortexCadence = payload[7];
Sorry for asking, but I'm a little bit stuck here how to read this I expect the payload to be 7 bytes (it's always seven) where pageNr is the first.
0=Datapage number 1=Power1 2=Power2 3=Speed1 4=Speed2 5=not used 6=not used 7=Cadence, but this would be the eighth byte...
The first bit of Power1 is vortexUsingVirtualSpeed; I'm fine with that The second and third bit of Power1 are vortexCalibrationState but also calculated in Power1; isn't that strange? Power is calculated as Power1 << 8 | Power2 but I would expect Power2 << 8 | Power1 (little endian) And if the payload would be seven bytes; payload[7] would be out of range?
I do not have a logfile of received packages (yet) so cannot check...
Got some hints?
Ah yes - using the word "Channel" for the Frequency is not a good idea. Frequency = 66 is what I wanted to say. Are you sure you checked in the right antDongle.py file? The current file looks like an old version.
Sorry... now it's the good one.
"vortex power" is an 11 bit value with the lower 8 bits from payload[2] and bit 0,1,2 from payload[1] as bit 8,9,10 in the power value (when I say bit 0 I mean "bit 0" = 2^0=1 and bit 7 is 2^7=128). So bit 7 of payload[1] is "vortexUsingVirtualSpeed" and bit 5,6 is vortexCalibrationState. Bit 3,4 of payload[1] is not decoded.
And yes: looks like the vortex trainer talks a big endian protocol.
Btw: The ANT+ payload is also 8 bytes long and the page number is the first byte (byte 0)
OK, Big endian and 8 bytes (Tacx indeed tried to make things difficult). The waiting is for a logfile.
But if Power uses payload[1] & 7
and vortexCalibrationState = (payload[1] >> 5) & 3
;
then the CalibrationState bits are calculated into Power, or am I getting tired?
bit # 7 6 5 4 3 2 1 0
values: a b c d e f g h
payload[1] & 7 results in "0 0 0 0 0 f g h" and
(payload[1] >> 5) & 3 results in "0 0 0 0 0 0 b c"
hi, I own a Tacx i-vortex (the non-smart one). Would this work with it? I might give it a try :)
Originally posted by @iepuzaur in https://github.com/WouterJD/FortiusANT/issues/14#issuecomment-612229158