Skip to content

Tacx Bushido Headunit protocol

Will edited this page Dec 6, 2017 · 47 revisions

Key:

Tx = Transmitted from PC, message seems to start with 0xXC i.e. 0xAC, 0xDC
Rx = Received from Bushido head unit, message seems to start with 0xXD i.e. 0xAD, 0xDD
Sent prior to PC connection in sequence not required for data acquisition
Tx: 0xAC02000000000000 Request version no.?
Rx: 0xAD02000500040102 Version number of the headunit 0xAD02MMmmbbbbxx (in this case 0.5.4) xx=?
Tx: 0xAC12000000000000 Doesn't seem to do anything??
Rx: 00AD12000000000000 In response to above
Tx: 0xAC11000000000000 Doesn't seem to do anything?
Initialise PC connection:
Tx: 0xAC03040000000000 Initialise PC connection / display PC connection screen after ride finishes (mode 4). (Questionable) keep sending until you recieve 0xad0104 ?
Tx: 0xAC03010000000000 Paused on data screen with no message? This also resets the odometer on the headunit (as sent in 0xDD02) - If you don't "reset" the odometer will continue to count from the last session (if batteries are not removed)
Tx: 0xAC03020000000000 Switch from pause to acquisition (mode 2)
Tx: 0xAC03030000000000 Pause and display "start cycling" on the head unit (mode 3)
Terminate PC connection:
Tx: 0xAC03000000000000 Terminate PC connection (mode 0)
Initialise cycling session:
Tx: 0xDC01050700500000 Sent in slope / distance, slope / time, distance / watts and distance / heart rate modes but not required?
Tx: 0xDC02009900000000
Slope / time, slope distance mode:
Tx: 0xDC0A000000000000 Start slope / time course? (Seen only once)
Tx: 0xDC01000000WW0000 Set no slope on the brake
Tx: 0xDC0100ZZXXWW0000 Set slope on the brake
NOTE: Brake is unaware of distance / time limit which is controlled in the PC software.

Slope settings:
ZZXX = signed 16bit [msb-lsb]. If ZZ = 00 then: SLOPE = XX/10
If ZZ = FF then: SLOPE = (XX-256)/10 (Not 255!)
WW = User weight = 0x50 = 80kg
Distance / power, distance / heart rate mode:
Tx: 0xDC0101PPPPWW0000
PPPP = Target power (10-990W)
WW = User weight = 0x50 = 80kg

NOTE: Constant heart rate mode sends the same packets as constant power mode. Calculation to achieve a constant heart rate must be done in the PC software, even though the head unit can also do it.
During cycling session:
Tx: 0xDC02009900000000 Appears when monitoring...always the same
Mode data sent from the head unit:
Rx: 0xAD01000a00000a02 Computer Idle, not connected to PC (mode 0x00)
Rx: 0xAD01040a00000a02 Connected to PC (mode 4)
Rx: 0xAD01010a00000a02 Pre cycling? (mode 1)
Rx: 0xAD01020a00000a02 Data acquisition (mode 2)
Rx: 0xAD01030a00000a02 Paused (mode 3)
NOTE: It has also been reported from a different head unit that the following is sent:

Rx: 0xad01030c000001e9 Paused
Rx: 0xad01000c000001e9 Computer idle
Rx: 0xad01040c000001e9 Connected to PC
The meaning of bytes 4-6 appear is currently unknown but could be related to the serial number. Bytes 7 and 8 are the last two (least signifcant) bytes of the headunit's serial number. The a0 (10) could be the 10 in in 2010 (the production date), a ten that appears in the serial number (unlikely? do all serials start with 82100?), part of a larger number (although no obvious matches as 2/3 byte number), something else device specific?

Data sent when in mode 0x20:
Rx: 0xDD01SSSSPPPPCCUU S = Speed (kmph) * 10, Power (W), C = Cadence (RPM)
Rx: 0xDD02DDDDDDDDHHUU D = Distance (m), H = Heart Rate (bpm)
Rx: 0xDD030000TT000000 T = Brake temperature (degrees C)?
Data sent in response to button presses:
Rx: 0xDD10010000000000 Left
Rx: 0xDD10020000000000 Up
Rx: 0xDD10030000000000 OK
Rx: 0xDD10040000000000 Right
Rx: 0xDD10050000000000 Down
Rx: 0xDD10840000000000 84= medium long press + button 4 (0.5 second hold)
Rx: 0xDD10c40000000000 c4= long press + button 4 (2.5 second hold)

Note: It will send the intermediate button press states multiple times (~ every 0.5 seconds), a short press is only sent once. This seems to vary based on: button being pressed? state of device (start cycling flag etc)?
Tests for the above (repeats colon separated, non consistent values comma separated):

left button : 0.5s : 0.5s
ok button: 0.125s, 0.5s, 0.25s : 0.5s
pause state: no buttons presses transmitted
start cycling state: no button presses transmitted
mid cycle state : button presses are transmitted
Conclusion: Think the inconsistency arises from the button briefly losing contact. When contact is remade it still tramsits last duration flag.

Psuedocode

// messages sent
init_pc_connection = ant.broadcastMessage([0xac,0x03,0x04,...])
start_cycling = ant.broadcastMessage([0xac, 0x03, 0x03,...])
resume = ant.broadcastMessage([0xac, 0x03, 0x02, ...])
datatx1 = ant.broadcastMessage([0xdc, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00]) // insert slope bytes in here
datatx2 = ant.broadcastMessage([0xdc, 0x02, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00]) // always the same
terminate_connection = ant.broadcastMessage([0xac, 0x03,...])


// messages received
headunit_paused = ant.broadcastMessage([0xad , 0x01 , 0x03 , 0x0a , 0x00 , 0x00, 0x0a, 0x02])
datarx1 = ant.broadcastMessage([0xdd,0x01,...])
datarx2 = ant.broadcastMessage([0xdd,0x02,...])
request_data = ant.broadcastMessage([[0xad , 0x01 , 0x02,..])
up_button_pressed = ant.AcknowldegedMessage([0xdd, 0x10, 0x02,...])
down_button_pressed = ant.AcknowldegedMessage([0xdd, 0x10, 0x04,...])


transmit init_pc_connection until TX SUCCESS channel event

transmit start_cycling until TX SUCCESS channel event 

slope = 0

while(course not completed) {
    if (ant message recieved) {
        if message == headunit_paused then transmit resume until TX SUCCESS
            elseif (message == datarx1 or message == datarx2) then decode_and_log_data()
            elseif message == request_data {
            insert_slope_into_datatx1()
            transmit datatx1 until TX SUCCESS
            transmit datatx2 until TX SUCCESS
            }
            //button presses                
            elseif message == up_button_pressed then slope += 1
            elseif message == down_button_pressed then slope-=1
            
    }
} 

// send headunit back to pc connection screen
transmit init_pc_connection until TX SUCCESS channel event

// terminate connection - you may want to keep connection open until user requests disconnect or program closed
transmit terminate_connection until TX SUCCESS channel event
Clone this wiki locally