Skip to content

Instantly share code, notes, and snippets.

@switchabl
Last active May 5, 2023 17:02
Show Gist options
  • Save switchabl/75b2619e2e3381f49425479d59523ead to your computer and use it in GitHub Desktop.
Save switchabl/75b2619e2e3381f49425479d59523ead to your computer and use it in GitHub Desktop.
Tacx legacy ANT protocol description

Tacx legacy ANT protocol

Older Tacx wireless trainers are not ANT+ FE-C compatible and use a proprietary ANT-based protocol instead.

This summary is based on work done by @totalreverse, @fluxoid-org, @mikeymclellan, @m472 and @rjohn65 (see sources) along with own research.

This document is a work in progress and represents a best guess. Some of the information has not been verified with actual hardware.

All messages are sent as broadcast data (unless otherwise noted). All integer values are big-endian (MSB first).

Generic pages

The following pages are supported by all Tacx legacy ANT devices (unless otherwise noted).

Command pages (PC -> Device)

Page 0xac - Request information

Bytes Value Interpretation
0 0xac Page
1 0x01 Request serial
0x02 Request version
0x04 Request battery status
0x11 Request brake version (Bushido and Vortex head units only)
0x12 Request brake serial (Bushido and Vortex head units only)
2-7 0x00 Padding

Information pages (Device -> PC)

Page 0xad (0x01) Serial number

Bytes Values Interpretation
0 0xad Page
1 0x01 Sub page
2 0x00 Reserved
3 UInt8 Production year
4-7 Int32 Device number

The serial number is of the form XX-YY-ZZZZZ where

XX = 20 (Blacktrack)

XX = 21 (Genius)

XX = 22 (Genius head unit)

YY = Production year

ZZZZZ = Device number

Page 0xad (0x02) Version

Bytes Values Interpretation
0 0xad Page
1 0x02 Sub page
2 UInt8 Major version
3 UInt8 Minor version
4-5 UInt16 Build number
6-7 ? ?

Page 0xad (0x04) Battery status

Bytes Values Interpretation
0 0xad Page
1 0x02 Sub page
2 UInt8 Battery status
0 Reserved
1 New
2 Good
3 Ok
4 Low
5 Critical
6 Reserved
>=7 Invalid
3-7 ? ?

Battery status definition is the same as ANT+ common page 82 (D00001198_-_ANT+_Common_Data_Pages_Rev_3.1.pdf, 6.11.2).

Genius brake (T2021)/Bushido head unit (T1982)/Vortex head unit (T1962/T2172)

The Bushido and Vortex protocols are very similar to the Genius protocol (with some subtle differences) when pairing with the head unit. The protocol used between the head unit and the brake itself is also ANT-based but is quite different.

ANT channel configuration (PC)

Parameter Value
Channel type Slave (0x00)
Network key Public network
RF frequency channel 60 (2460 MHz) (Genius/Bushido head unit)
channel 78 (2478 MHz) (Vortex head unit)
Transmission type 0 (for pairing)
Device type 83 (0x53) (Genius)
82 (0x52) (Bushido head unit)
62 (0x3e) (Vortex head unit)
Device number 0 (for pairing)
Channel period 4096 (8 Hz) (Genius/Bushido head unit)
3840 (~8.5 Hz) (Vortex head unit)

Data pages (Brake -> PC)

The brake continuously sends sub pages 0x01, 0x02 and 0x03 during training.

Page 0xdd (0x01) - Speed/Power/Cadence

Bytes Value Interpretation
0 0xdd Page
1 0x01 Sub page
2-3 UInt16 Wheel speed (0.1 km/h)
4-5 UInt16 Power (W)
6 UInt8 Cadence (rpm)
7 UInt8 L/R Balance (%)

Page 0xdd (0x02) - Distance/HR

Bytes Value Interpretation
0 0xdd Page
1 0x02 Sub page
2-5 UInt32 Distance (m)
6 UInt8 Heart rate (bpm)
7 0x00 Padding

Page 0xdd (0x03) - Alarm/Temperature

Bytes Value Interpretation
0 0xdd Page
1 0x03 Sub page
2-3 UInt16 Alarm status (bitmask)
4 UInt8 Brake temperature (°C?)
5-6 UInt16 Power generated ("Powerback") (W)
(Genius only)
7 0x00 Padding

Alarm status (Genius)

Bitmask Interpretation Severity Message
0x0001 Overtemperature Warning Temperature too Hot! Slow Down!
0x0004 Overvoltage Error Overvoltage! Stop!
0x0008 Generic error
0x0020 Overcurrent Warning Overcurrent! Brake Limited!
0x0080 Speed too high Warning Speed is too high.
0x0100 Undervoltage Warning Undervoltage! Speed Up!
0x0200 Virtual power
0x4000 Downhill speed limited
0x8000 Communication error Error No communication with the brake

Alarm status (Bushido)

Bitmask Interpretation Severity Message
0x0001 Temperature level 1
0x0002 Temperature level 2
0x0003 Temperature level 3 Warning Temperature too Hot! Slow Down!
0x0004 Temperature level 4 Warning Temperature too Hot! Brake Limited!
0x0005 Temperature level 5 Error Temperature too Hot! Stop!
0x0008 Overvoltage Error Overvoltage! Stop!
0x0010 Overcurrent level 1 Warning Overcurrent! Brake Limited!
0x0020 Overcurrent level 2 Error Overcurrent! Stop!
0x0080 Speed too high Warning Speed is too high.
0x0100 Undervoltage Warning Undervoltage! Speed Up!
0x2000 Virtual power
0x4000 Virtual speed
0x8000 Communication error Error No communication with the brake

Alarm status (Vortex)

Bitmask Interpretation Severity Message
0x0001 Wrong mains voltage Error Problems with mains voltage Brake Limited!
0x0002 Temperature high Warning Temperature too Hot! Slow Down!
0x0004 No brake coils Error Brake coils not connected with electric circuits. Stop!
0x1000 Virtual power
0x2000 Virtual speed
0x4000 Brake not paired Error Vortex connected to a brake but they are not paired. It's not possible to alter the brake power. Stop!
0x8000 Communication error Error No communication with the brake

Page 0xdd (0x04) - Calibration status (Genius)

Bytes Value Interpretation
0 0xdd Page
1 0x04 Sub page
2 UInt8 Calibration state
0x00 Stopped
0x01 Started
0x02 Running
0x03 Calibrated
0x04 Uncalibrated
0x81 Value error
0x82 Cadence error
0x83 Speed error
0x84 Timeout
0x85 Torque error
3-4 UInt16 Calibration value
5-7 ? ?

Calibration value is informational only. It is applied automatically on successful calibration. Power-cycling the brake resets status to uncalibrated, but calibration value is persisted. The recommended range for the is calibration value is 60-90 ("green" range in TTS).

Page 0xdd (0x10) - Buttons (Bushido/Vortex) This page is sent as acknowledged, not broadcast data.

Bytes Value Interpretation
0 0xdd Page
1 0x10 Sub page
2 0xXY X: Key flag
Y: Key code
3-6 0x00 Padding
7 UInt8 Button event count
(Vortex only)

Key flag

Byte Interpretation
0x0 Normal press
0x8 Long press (>0.5s)
0xc Very long press (>2.5s)

Key code

Byte Interpretation
0x0 None
0x1 Left
0x2 Up
0x3 OK
0x4 Down
0x5 Right

Control pages (PC -> Brake)

The PC regularly sends 0x01 and 0x02, alternating between the two.

Page 0xdc (0x01) - Target

Bytes Value Interpretation
0 0xdc Page
1 0x01 Sub page
2 0x00 Slope mode
0x01 Power mode
0x02 Heart rate mode (?)
3-4 Int16 Target slope (0.1%)/power (W)/heart rate (bpm)
5 UInt8 Rider + bike weight (kg)
6 0x00
0xee Reset distance (Genius and Bushido only)
7 0x00 Padding

The rider/bike weight is used for both gravity simulation (in slope mode) and to adjust the inertia of the virtual flywheel. The virtual flywheel is active even in power mode. Power mode is very slow to adjust to changes in cadence/power target unless the rider/bike weight is lowered (e.g. ~10kg).

Page 0xdc (0x02) - Wind/Track resistance

Bytes Value Interpretation
0 0xdc Page
1 0x02 Sub page
2-3 Int16 0.5 * wind resistance coefficient (0.001 kg/m)
4-5 Int16 Genius: Wind speed (0.004 m/s, tail wind +/head wind -)
Bushido: Wind speed (1 m/s, tail wind -/head wind +) (?)
UInt16 Vortex: Wind speed (1 m/s, head wind only) (?)
6-7 UInt16 Rolling resistance (0.01 N) (Vortex only)

TTS4 apparently assumes units of 0.01 m/s for the Genius, but seems to be closer to 0.004 m/s in reality.

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

TTS4 default values

air density = 1.226 kg/m^3

surface area = 0.5m^2

drag coefficient = 0.5

0.5 * wind resistance coefficient = 0.15325 kg/m (0x0099)

rolling resistance = (user weight + bike weight) * 9.81 m/s^2 * rolling resistance coefficient

There is no setting for rolling resistance on the Genius and Bushido. Presumably a default rolling resistance coefficient of 0.004 is used (smooth asphalt).

Page 0xdc (0x04) - Calibration (Genius)

Bytes Value Interpretation
0 0xdc Page
1 0x04 Sub page
2 UInt8 Calibration action
0x00 Stop
0x01 Start
0x02 Request calibration info
0xff Trigger production calibration
3-7 0x00 Padding

Check that speed is 0, then send Start (0x01) to start calibration, request calibration information (0x04) to monitor for errors/completion at ~1s intervals. Send Stop (0x00) on user request only to interrupt calibration.

Command pages (PC -> Brake)

Page 0x00 - Keep-alive (Bushido/Vortex)

Regularly send to keep the head unit from turning off (every ~10s).

Bytes Value Interpretation
0 0x00 Keep-alive
1-7 0x00 Padding

Broadcast data may be lost, so the following commands should be re-sent until a response (0xad) is received.

Page 0xac (0x03) - Set mode (Bushido/Vortex)

Bytes Value Interpretation
0 0xac Page
1 0x03 Set mode command
2 UInt8 Mode
0x00 Stand-alone
0x01 Reset distance
0x02 Training
0x03 Paused ("Start cycling")
0x04 PC control
3-7 0x00 Padding

Keep requesting the new mode until confirmation is received with page 0xad (0x01). Need to switch to mode 0x04 when connecting, optionally clear the distance counter with 0x01, then switch to 0x03 (can maybe be omitted?), then start with 0x02. During training, if state 0x03 is received, request 0x02 to continue.

Information pages (Brake -> PC)

Page 0xad (0x01) Serial number/mode (Bushido)

Bytes Values Interpretation
0 0xad Page
1 0x01 Sub page
2 UInt8 Mode
0x00 Stand-alone
0x01 Reset distance
0x02 Training
0x03 Paused ("Start cycling")
0x04 PC control
3 UInt8 Production year
4-7 Int32 Device number

The serial number is of the form XX-YY-ZZZZZ where

XX = Device type (Bushido head unit: 82)

YY = Production year

ZZZZZ = Device number

Page 0xad (0x01) Serial number (Vortex)

Bytes Values Interpretation
0 0xad Page
1 0x01 Sub page
2 UInt8 Mode
0x00 Stand-alone
0x01 Reset distance
0x02 Training
0x03 Paused ("Start cycling")
0x04 PC control
3 UInt8 Production year
4 UInt8 Device type
5-7 UInt32 Device number
(MSB=0x00)

XX = Device type

YY = Production year

ZZZZZ = Device number

Page 0xad (0x11) Brake serial number (Bushido)

Bytes Values Interpretation
0 0xad Page
1 0x11 Sub page
2 ? ?
3 UInt8 Production year
4-7 Int32 Device number

The serial number is of the form XX-YY-ZZZZZ where

XX = Device type (Bushido brake: 81)

YY = Production year

ZZZZZ = Device number

Page 0xad (0x11) Brake serial number (Vortex)

Bytes Values Interpretation
0 0xad Page
1 0x11 Sub page
2 ? ?
3 UInt8 Production year
4 UInt8 Device type (?)
5-7 UInt32 Device number
(MSB=0x00)

The serial number is of the form XX-YY-ZZZZZ where

XX = Device type

YY = Production year

ZZZZZ = Device number

Page 0xad (0x12) Brake version (Bushido/Vortex)

Bytes Values Interpretation
0 0xad Page
1 0x12 Sub page
2 UInt8 Major version
3 UInt8 Minor version
4-5 UInt16 Build number
6-7 ? ?

Bushido brake-unit (T1981)

ANT channel configuration (PC)

Parameter Value
Channel type Slave (0x00)
Network key Public network
RF frequency channel 60 (2460 MHz)
Transmission type 0 (for pairing)
Device type 81 (0x51)
Device number 0 (for pairing)
Channel period 4096 (8 Hz)

Data pages (Brake -> PC)

Page 0x01 - Force/Power

Bytes Value Interpretation
0 0x01 Page
1-2 ? ?
3-4 UInt16 Power (W)
5-6 ? ?
7 0x00 Padding

Page 0x02 - Speed/Cadence/Balance

Bytes Value Interpretation
0 0x02 Page
1-2 UInt16 Wheel speed (0.1 km/h)
3 UInt8 Cadence (rpm)
4 UInt8 L/R Balance (%)
5-7 0x00 Padding

Page 0x04 - Motor Voltage/Current

Bytes Value Interpretation
0 0x04 Page
1-7 ? ?

Page 0x08 - Distance

Bytes Value Interpretation
0 0x08 Page
1-4 UInt32 Distance (m)
3-7 0x00 Padding

Page 0x10 - Alarm

Bytes Value Interpretation
0 0x10 Page
1-2 UInt16 Alarm status (bit mask)
3 UInt8 Brake temperture (?)
4-7 0x00 Padding

Alarm status

Bitmask Interpretation Severity Message
0x0001 Temperature level 1
0x0002 Temperature level 2
0x0003 Temperature level 3 Warning Temperature too Hot! Slow Down!
0x0004 Temperature level 4 Warning Temperature too Hot! Brake Limited!
0x0005 Temperature level 5 Error Temperature too Hot! Stop!
0x0008 Overvoltage Error Overvoltage! Stop!
0x0010 Overcurrent level 1 Warning Overcurrent! Brake Limited!
0x0020 Overcurrent level 2 Error Overcurrent! Stop!
0x0080 Speed too high Warning Speed is too high.
0x0100 Undervoltage Warning Undervoltage! Speed Up!

Page 0x22 - Calibration data

Bytes Value Interpretation
0 0x22 Page
1-2 ? ?
3 UInt8 Calibration status
0x00 Off
0x01 Start Cycling
0x02 Speed up (to 40 km/h)
0x03 Stop Cycling
0x04 Wait for spin down
0x05 Spin down
0x06 Processing
0x0a Show data
0x0b End calibration
0x0c Finished
0x0d Error
0x42 Calibration successful
0x4d Request calibration value
4-5 UInt16 Rolling resistance (0.1N?)
(HU value × 10)
(for status 0x42 only)
0x0000 (otherwise)
6-7 0x00 Padding
"green" range: 130-190

Command pages (PC -> Brake)

Page 0x01 - Target force

Bytes Value Interpretation
0 0x01 Page
1-2 UInt16 Force (0.1N)
3-7 0x00 Padding

Page 0x23 - Calibration mode

Bytes Value Interpretation
0 0x23 Page
1 UInt8 Command
0x4d Start calibration
0x58 Request calibration result
0x63 Request rolling resistance
2-7 0x00 Padding

Vortex brake-unit (T1961/T1968/T2071)

ANT channel configuration (PC)

Parameter Value
Channel type Slave (0x00)
Network key Public network
RF frequency channel 66 (2466 MHz)
Transmission type 0 (for pairing)
Device type 61 (0x3d)
Device number 0 (for pairing)
Channel period 8192 (4 Hz)

Data pages (Brake -> PC)

Page 0x00 - Power/Speed/Cadence

Bytes Value Interpretation
0 0x00 Page
1 (bit 7) bool Virtual speed
1 (bit 5-6) UInt8 Calibration status
1 (bits 0:2)-2 UInt16 Power (W)
3 (bits 1:2)-4 UInt16 Speed (0.1 km/h)
5-6 ? ?
7 UInt8 Cadence

Calibration status

Value Interpretation
0x0 None
0x1 Running
0x2 New
0x3 Failed

Page 0x01 - Serial number/Alarm

Bytes Value Interpretation
0 0x01 Page
1 UInt8 Device type
2 UInt8 Production year
3-5 UInt32 Device number (MSB=0)
6-7 UInt16 Alarm status (bit mask)

The serial number is of the form XX-YY-ZZZZZ where

XX = Device type

YY = Production year

ZZZZZ = Device number

Alarm status

Bitmask Interpretation Severity Message
0x0001 Wrong mains voltage Error Problems with mains voltage Brake Limited!
0x0002 Temperature high Warning Temperature too Hot! Slow Down!
0x0004 No brake coils Error Brake coils not connected with electric circuits. Stop!

Page 0x02 - Version

Bytes Value Interpretation
0 0x02 Page
1-2 UInt16 Total distance (0.1 km)
4 UInt8 Major version
5 UInt8 Minor version
6-7 UInt16 Build number

Page 0x03 - Calibration

Bytes Value Interpretation
0 0x03 Page
1-4 0xffffffff Reserved
5 Int8 Calibration value
(HU value × 10)
6-7 UInt16 device number of paired HU

Command pages (PC -> Brake)

Page 0x10/0x55 - Coupling

Bytes Value Interpretation
0 0x10 Page
1-2 UInt16 HU device number
3 0x55 Command
4 0x7F ?
5-7 0x00 Padding

Page 0x10/0xaa - Target power/calibration

Bytes Value Interpretation
0 0x10 Page
1-2 UInt16 device number of paired HU
3 0xaa Command
4 UInt8 Calibration request
5 Int8 Calibration value
6-7 UInt16 Target power (W)

Genius head unit (T2022)

The Genius head unit is an optional handlebar controller with five buttons and analog heart rate receiver (non-coded 5.3kHz).

ANT channel configuration (PC)

Parameter Value
Channel type Slave (0x00)
Network key Public network
RF frequency channel 60 (2460 MHz)
Transmission type 0 (for pairing)
Device type 85 (0x55)
Device number 0 (for pairing)
Channel period 4096 (8 Hz)

Page 0x00 - Button/HR data (head unit -> PC)

Bytes Value Interpretation
0 0x00 Page
1-2 UInt16 Key code (bitmask)
3 UInt8 Heart rate (bpm)
4-7 0x00 Padding

Key codes

Bitmask Interpretation
0x0000 None
0x0001 Left
0x0002 Up
0x0004 Right
0x0008 Down
0x0010 OK

Page 0x01 - Keep alive (PC -> head unit)

Regularly send to keep the head unit from turning off (every ~10s).

Bytes Value Interpretation
0 0x01 Page
1-7 0x00 Padding

Page 0x02 - Request data (?) (PC -> head unit)

Sent continuously by TTS, but doesn't seem necessary normally. Maybe only if heart rate is used. Changes the blinking pattern of the LEDs.

Bytes Value Interpretation
0 0x02 Page
1-7 0x00 Padding

BlackTrack steering frame (T2420/T2430)

ANT channel configuration (PC)

Parameter Value
Channel type Slave (0x00)
Network key Public network
RF frequency channel 60 (2460 MHz)
Transmission type 0 (for pairing)
Device type 84 (0x54)
Device number 0 (for pairing)
Channel period 2048 (16 Hz)

The Blacktrack continuously sends page 0x00 with the current steering angle.

Page 0x00 - Steering data (Blacktrack -> PC)

Bytes Value Interpretation
0 0x00 Page
1-2 Int16 Steering angle
3 0xff ?
4-7 0x00 Padding

Three point calibration (full left, full right and center) of the steering angle is required.

Page 0x01 - Keep alive (PC -> Blacktrack)

Regularly send to keep the steering unit from turning off (every ~10s).

Bytes Value Interpretation
0 0x01 Page
1-7 0x00 Padding

License

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.

Sources

@slaclau
Copy link

slaclau commented May 5, 2023

Hi, just wondering if you have any more detail on the request pages - I can’t seem to get a battery status page out of the Bushido head unit - have you been able to do this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment