Support for Tacx older smart trainers

(John Taylor) #21

The USB protocol for the fortius T1932 head unit has already been reverse engineered:

device ID 3561:1932


When measuring data and sending commands-
sends payloadcount 12, 12 bytes output USB request block
sends(?) payloadcount 12, 0 bytes
waits about 100ms
receives payload count 64, no bytes input USB request block
then receives payload count 64, 64 bytes

never receive 24 or 48 byte count

sent to T1932:
The first 4 bytes are always 01 08 01 00
Bytes 11 and 12 are always 10 04.
bytes 4,5 are resistance - hexdec(byte5.byte4)/650.2 gives % slope

received from T1932:
bytes 1-12 never change
byte 13 is heart rate
byte 14 buttons 01 ENTER, 02 DOWN, 04 UP, 08 cancel.
bytes 15-32 never change
bytes 35,36,44,47 never change
byte 34 is speed in whole kmh
byte 39,40 is resistance (19=5,15=4,30=8,38=10,42=11,46=12,50=13)
byte 43 turns from 0 to 1 when pedal passes cadence- can repeat on same revolution so needs debounce of 300ms
byte 45 is cadence
bytes 48-64 never change
unknown but change: 33,37,38,41,42,46 (byte 33 appears to change with speed)


All based on the work done by Michael Dagenais: (text below is from the driver file he produced)


Michel Dagenais, michel.dagenais at
February 20, 2010


Linux driver for the Tacx Fortius 1942 bicycle trainer

This driver acts as an input device. It produces events for buttons and for the
various parameters, distance, speed, cadence, power, steering. It accepts
input through the friction force feedback API for the wheel resistance, -5% to 20%
of slope, and for the cyclist weight, 50 to 120Kg. A simple test program is
provided to demonstrate the driver use.



This driver was tested with a Tacx Fortius 1942 bicycle trainer.


Driver usage

The driver reports the information as follows
(bike trainer -> linux input events):

Buttons (up or down):
  Enter -> BTN_RIGHT
  Down -> BTN_BACK
  Cancel -> BTN_LEFT
  Pedal sensor -> BTN_0
  Active (pedal signal active, cyclist on duty) -> BTN_1

Axis (value):

  Steering -> ABS_WHEEL
  Distance -> ABS_DISTANCE
  Speed -> ABS_GAS
  Power output of cyclist -> ABS_VOLUME
  Pedaling cadence -> ABS_MISC

Finally, the brake resistance to exert on the wheel is specified as
a FRICTION force feedback. The road slope (-5% to 20%) and
cyclist weight (50Kg to 120Kg) are specified as
effect->u.condition[0].right_coeff and
effect->u.condition[0].right_saturation respectively.

It should be noted that the input device event framework
(input_report_key, input_report_abs…) does not report all the data
it receives. For instance, it only reports changes for input keys
(i.e. when several consecutive input_report_key calls report the
same status for a key, only the first will be delivered to the application).
Similarly, when different input_report_abs calls report the same value
in consecutive calls, only the first value, which just changed, is
reported to the application.


Limitations and things to do

The driver works on the tested configuration but has not been widely tested on
other configurations. Any contact with Tacx in order to get access to technical
documentation, or to a technical person, would be most useful in order to
make Tacx trainers better working and more appealing to Linux users. Similarly,
getting the permission from Tacx to distribute the firmware along with the driver,
again simplifying the life of Linux using Tacx customers, would be most appreciated.
Finally, the driver should be submitted for inclusion to the Linux kernel mainline,
thus avoiding the need for separate download and installation.

The driver currently does nothing special upon suspend and resume, it could be
relevant to reinitialize the bicycle trainer upon suspend. The udev rules,
driver module and firmware installation makefile rules could be improved upon
by experienced kernel developers.

The driver produces data in raw form. The test_fortius program uses empirically
determined coefficients to obtain proper units such as kilometers. The distance
and speed values are fairly well calibrated and can be checked with a cyclometer.
The cadence looks fairly good as well but varies a lot and should probably be
averaged over a few readings. The power output looks OK but has not been calibrated
with proper instruments; getting the correct equation to compute the power from
Tacx or experimenting with a power meter would be highly desirable.

On windows, the driver gets a new set of values from the USB device every
about 67ms. In most cases, all 48 bytes are received; once in a while, a shorter 24
bytes message is received. In the Linux driver, the same strategy is now used,
a timer delays sending the input USB request block 70ms after sending the
output USB request block. This way, the full 48 bytes are received at input
almost every time. With a smaller 50 ms delay, 25% of input blocks were only
24 bytes. With no delay, a 10ms period was obtained but over 95% of the input
blocks were only 24 bytes. Even the steering value, which is received as part of
the short 24 bytes messages and can be read with no delay, every 10ms,
does not change faster than about once per 40ms.


The Tacx Fortius trainer

The Tacx Fortius is a bicycle trainer. With the front wheel removed,
the bicycle fork is attached to the front of the trainer to monitor
steering. The bicycle rear wheel axle is held in the back.
A small wheel connected to a brake/motor is then pressed
onto the rear wheel. Finally, a controller with buttons
is attached to the bicycle handlebar. A cadence sensor
monitors when the left pedal passes in front of it. There is an
optional heart rate sensor (not tested).

The controller on the handlebar connects to the host computer with USB,
to the brake/motor controller with a serial link cable with RJ-11
connectors, and to the steering sensor holding the bicycle fork with
a 8 pins mini DIN proprietary connector.

The circuit board in the handlebar controller contains a 44 pins Cypress
EZ-USB, 8051 compatible controller, number AN2131SC (0543 ESJ0115),
a 8 pins 24C01WP ST8535W, ST Microelectronics serial I2C EEPROM 128*8,
for storing the product/vendor ID, a 8 pins TI 58M RC4558 CJ14C4,
Texas Instruments dual operational amplifier, a 5 pins LORA, and a 2 pins
NEOSID T7 39K Fixed value inductor 39K micro Henry.

The EZ-USB controller first appears as USB device 3561:e6be. Firmware
then needs to be downloaded. This device driver was tested with firmware
file FortiusSWPID1942Renum.hex, 19888 bytes, version reported by the Tacx
Test program for the interface: The firmware can be uploaded with
program fxload.

The typical communication (on Windows) between the host and the
handlebar controller is that the host writes the desired
brake force and cyclist weight, waits about 70 ms, reads the input data
(buttons pressed, wheel speed, wheel distance, power, steering position…)
and immediately repeats with a write. New values are thus read about every 70ms.

The initial write to the controller, or after restarting the training
program, is only 4 bytes:

02 00 00 00

At other times, 12 bytes are sent out.

The first 4 bytes are always 01 08 01 00.

Then, bytes 5 and 6, little endian, two’s complement, are the force from
-5% (0xf34d or -0x0cb3 or -3251) to -2.5% (0xf9a7 or -0x659 or -1625),
0 (0), 2.5% (0x0659 or 1625), 5% (0x0cb3 or 3251), 7.5% (0x130c or 4876),
10% (0x1966 or 6502), 12.5% (0x1fbf or 8127), 15% (0x2618 or 9752),
17.5% (0x2c72 or 11378) and 20% (0x32cb or 13003).

Byte 7 is the echo of the pedal sensor. While it normally is 00, each time
the pedal sensor is active (byte 43 in input is read as 01)
the software outputs this byte as 01. Presumably this tells the
Fortius controller that the software is running properly and
seeing its pedal sensor signal.

Byte 8 is always 0.

Byte 9 is 0 at initialization time and set to 2 when the training starts and
the software is ready to change the force.

Byte 10 is the cyclist weight in kilos, from 0x32 (50kg) to 0x4b (75kg),
0x64 (100kg) and 78 (120kg).

Bytes 11 and 12 are always 10 04.

Some examples

01 08 01 00 00 00 00 00 00 52 10 04 (initially)
01 08 01 00 00 00 00 00 02 52 10 04 (brake force is 0)
01 08 01 00 14 05 00 00 02 32 10 04 (brake force is 0x0514 or 2%, weight 50kg)
01 08 01 00 4d 13 01 00 02 64 10 04 (brake force 0x134d/7.6%, pedal echo, 100kg)
01 08 01 00 d8 02 00 00 02 78 10 04 (weight 120kg)
01 08 01 00 00 00 00 00 02 0a 10 04 (set brake force to 0 at the end)
01 08 01 00 00 00 00 00 00 50 10 04 (set brake force to 0 at the end)

The input data is always 24 or 48 bytes. When the brake/motor is
disconnected, or once in a while (no new data from the brake/motor)
only 24 bytes are received.

The first 13 bytes are almost always identical, with byte 11 being
exceptionally 40 instead of 50:

20 9f 00 00 08 01 00 00 07 00 50 bd 00

It looks like the heart sensor may report its information in
bytes 12, 13 and 14? I do not have the heart sensor.

Byte 14 is the handlebar controller buttons:
01 ENTER, 02 DOWN, 04 UP, 08 cancel.

Bytes 15 and 16 are usually 00 00, once seen as 00 01.
Bytes 17 and 18 remain around 6d 02.

Bytes 19, 20 (little endian) are the steering and vary from 0x02–
to 0x04-- from one extreme to the other.

Bytes 21 to 28 are constant at d0 07 d0 07 03 13 02 00

Bytes 29, 30 (and possibly 31, 32) is the distance (little endian),
possibly the number of turns of the brake wheel.

Bytes 33, 34 is the speed (little endian), 0x0800 : 5km/h,
0x0c00 : 10km/h, 0x1300 : 15km/h, 0x1600 : 20km/h, 0x1c00 : 25 km/h,
0x2200 : 30 km/h.

Byte 35, varies around 2c.
Byte 36, jumps mostly between 02 and 0e.
Bytes 37 and 38 vary with the speed but go to 0 more quickly than the
speed or power.

Bytes 39, 40 is the force on the wheel to compute the power
(little endian, two’s complement) When pedalling fast and letting go suddenly,
the force may be negative. The force multiplied by the speed gives the power.

Bytes 41, 42 also vary somewhat with speed

Byte 43, pedal sensor, normally 0, 1 when the pedal passes near the sensor.

Bytes 45, 46 cadence (little endian)

Byte 47, 0x02 when active, 0x00 at the end

Byte 48, varies even when the system is idle

When the system is idle, bytes 17, 19, 35 and 48 vary. Byte 19
is probably noise in the low order byte of the steering.

(* Minyana*NEO [ZESP]) #22

Phew !!! I have not heard anything too technical for me


I also think it would be a good idea to use the usb tacx the swift. I have a speed sensor / cadence and heart rate monitor garmin ant + and although it works, is not the same, yours would zwift control the resistance trainer.

(Jo-) #24

… This is probably a worn out thread, but I have suggested to Tacx through other forums that its understandable they dont want to make their older “Interactives” compatible with Zwift, I get it, sales of new devices. I have proposed this: Tacx determines a fee they want to open up their older devices, they have something - we want it, simple business. So say its $30,000, whatever I’m pulling a number out of thin air, a crowd sourcing model is used. Tacx has a mailing list, send out the proposition. If we as a group of older Tacx owners make their dollar number, good - We don’t, well there was not enough interest. I think as a EU Company this would be a responsible alternative to many perfectly good trainers, plus the associated hardware and electronics being tossed aside simply because Tacx wants to preserve ongoing sales. . . . AS a workaround, I do this. Wahoo Speed/Cadence ANT, set Zwift to Tacx Blue Twist. Open TTS4 software, set to “Free Cycling” - set grade to . .8% to 1% … Tacx TTS4 power numbers match Zwift very closely at wattages over 200 …

(. KeithD [WKG](c) Final Front EAR) #25

 Please see my new post on getting older Tacx trainers to work by piggy backing TTS software. I have not tried it as I have a Genius Smart, but I know lots of people with the older trainers who could use them manually adjusting grade, but it would be better if the two systems could be run to get an accurate speed and distance on Zwift matching the TTS software. The problem would be sorted. 

(paha SBG [ZHU]) #26

Joe Giovenco your idea is good.  Have you got any response from TACX?

(paha SBG [ZHU]) #27

John Taylor: if the protocol already has been reverse engineered, isn’t it possible to create a device which communicates with the trainer through USB and acts like an ANT+ device on the other end?

(Dave Rossow (Las Vegas)) #28

Peter, interesting idea. I’m sure it could be done using a simple Raspberry Pi with an Ant+ dongle for under $50.

(paha SBG [ZHU]) #29

@Dave: yes the hardware costs are low but we need someone who knows USB programming on Linux, knows the ANT+ protocol, is a bike fanatic and has an old Tacx trainer. :slight_smile:

(Jo-) #30

#Tacx has of course not responded … Sure it would be nice if the older Tacx’s were smart and not dumb. But they are not that dumb, they can report wattage. that would be good enough. I can understand why Tacx wont let the older models be Interactive - so here is the compromise - Just let the watts and maybe speed be reported - How about that Tacx - Thats not asking too much is it ??

(Dave Rossow (Las Vegas)) #31

@Peter, I’m going to take a stab at it.  I have a Fortius trainer I haven’t used in a few years, and I have several raspi’s sitting on my workbench already waiting for a good project.  I think I may also have an Ant+ dongle already too.

(paha SBG [ZHU]) #32

Glad to hear that. If you don’t find the dongle I can support your project by buying one for you. Or tell me if I can support it somehow. Thank you.

(Jo-) #33

Peter (I noted in another thread - Hey Tacx just let the old stuff report watts!!) … Yes its absolutely true that in Tacx Software Versions previous to TTS3 … Netathlon was a usable 2nd party app. And it worked well. Tacx can open the older trainers, they have in the past, it’s not new ground - They just dont want to, 

(Stian Maurstad) #34

Hi all,


Just wanted to let you know I see all these posts, and it´s sad & poor customer service from Tacx (please show your good side).


The fact that they don´t help out their existing customers with power data from the old trainers. It would be perfect for a secondary

setup for kids, wife or at a cabin place or similar. If they understood the great benefit and credit this would give to existing customer (much better to keep existing vs. getting bad rep. and finding new ones), they would understand that the likelyhood of staying with Tacx would greatly increase (if they listened & collaborated). Instead people now start buying Wahoo (like my self and many others) + other brands, where they care more for their customers. I think it is sad to see old trainers laying around a potentially just being thrown away. I would love to support any efforts & development. I am not rich nor developer my self, but would definetly pay to support a solution for my old Tacx Fortius multiplayer trainer to work with Ant+ & hopefully Zwift.


All the best, Stian

(Stian Maurstad) #35

But on second thought, the best thing to do I guess is to just switch indoor trainer brand, and show them what happens when they don´t care for their existing customers. I guess you could always use the old trainer for TTS4 etc… of course boring compared to Zwift, but it´s at least a case where the hardware can be used.



(Jo-) #36

Ok – Will someone tell me what a raspi is . .and if this works I’ll stop gazing at NEOs …Oh and about switching brands … Tacs cant make Flux’s and NEOs fast enough … Delivery date for NEOs has been pushed back at least twice and maybe 3 times . Ya know - In the early days of TTS3 and TTS4, it was constant updates, then fix what the update broke. Fitness was a possible gain, patience was the probable gain - And not to mention - The hardware would just break - - I have gone on and on in the Tacx Forum in a way that some thought was entertaining (Bowfluv there) taking stabs at Tacx - Hey! They owe us early users for all the nights we would kit up - Get up & something was Screwed up…Right now the Tacx free Virtual is really good, the thing is, absolutely no one uses it. 


(Dave Rossow (Las Vegas)) #37

@Joe, “raspi” is just shorthand for Raspberry Pi, which is a miniature single-board Linux computer that is highly extensible and smaller than a bar of soap.

(paha SBG [ZHU]) #38

Thank you @Dave.  Just let me know if I can help somehow.  Testing, whatever.  I have also a Fortius trainer.  You find me @paha77 on Twitter, FB, Gmail, everywhere. :slight_smile:

(Robert Klinkhammer[TriFury]) #39

Well, this is my new project.   I am glad the USB protocol has been reverse engineered.  It should be a simple matter of utilizing a small micro controller (I have several), have one USB connection to the trainer, and another USB for an ANT+ dongle.  All that would be required is to translate the TACX data to look like some other supported trainer.   I assume that the ANT+ interfaces for trainers has some documentation somewhere.  

This really shouldn’t be that hard.  Once I am done, I will post the code on GITLAB.

(Robert Klinkhammer[TriFury]) #40