Skip to content

Latest commit

 

History

History
299 lines (204 loc) · 10.5 KB

hk310-info.md

File metadata and controls

299 lines (204 loc) · 10.5 KB

HobbyKing HK310 and Turnigy X-3S deep-dive

Author: laneboysrc@gmail.com

Introduction

This document describes the internal functionality of the HobbyKing HK310 transmitter. Most findings also apply to the Turnigy X-3S transmitter.

The HobbyKing HK300 uses the same hardware RF module as the HK310 and X-3S, but the module contains a different firmware and uses the pins of the module in an entirely different way. Therefore this document does not apply to the HK300.

The HK310 comprises of a microcontroller (MCU) of unknown origin, and a RF module using Nordic Semiconductor NRF24LE1 (refered to as "NRF module" in this document).

The MCU reads the sticks and switches, drives the display; it basically handles all user-facing functions of the transmitter.

The MCU connects to the NRF module using a serial port (UART). See Serial port protocol for details on the communication protocol. Because the MCU is operating at 5V and the NRF module at 3.3V, a simple resistor divider of 1k/2.4k is placed in the Tx (MCU) / Rx (NRF module) path. Note that the X-3S transmitter has a different MCU operating at 3.3V, so no level shifting hardware is present.

A 24C16A I2C EEPROM is connected to the NRF module. This EEPROM resides on the transmitter PCB, not the NRF module. The EEPROM contains random bytes used to differentiate between different transmitters and models. See EEPROM contents for more info.

Note that the transmitter PCB contains a second EEPROM that connects to the MCU. This EEPROM is likely to hold the model data etc. but has not been investigated yet.

NRF module pin-out

    +--------------------------------------------------------------------------+
    |   GND            Tx   GND                      O (Hole)                  |
    |   o    o    o    o    o    o                                             |
    |   GND  P0.2 PROG P0.3 NC   NC                                            |
    |                                                                          |
    |   3V3                                                                    |
    |   o    o    o    o    o    o                                             |
    |   VDD  P0.1 P0.0 P1.6 P1.5 NC                                            |
    |  +--------------------------------------------------------------------+  |
    |  |                                                                    |  |
    |  |                                                                    |  |
    |  |                                                                    |  |
    |  |                                                                    |  |
    |  |                                                                    |  |
    |  +--------------------------------------------------------------------+  |
    |   GND  3V3                                                               |
    |   o    o    o    o    o    o                                             |
    |   GND  VDD  P0.6 P1.1 P1.3 RESET                                         |
    |                                                                          |
    |   Rx             SCL  SDA  Tx-Off?                                       |
    |   o    o    o    o    o    o                                             |
    |   P0.4 P0.5 P0.7 P1.0 P1.2 P1.4                                          |
    | O (Hole)                                                                 |
    +--------------------------------------------------------------------------+

P1.4 (Tx-Off?) goes to the amplifier chip in the NRF module. It has short pulses that repeat with about 200Hz. Speculation: this may be a kind of enable signal to the amplifier, turning it on only when the NRF chip actually sends packets to preserve power.

Programming pins:

  • P0.7: FMOSI
  • P1.0: FMISO
  • P1.0: FCSN
  • PROG

The X-3S uses different pins to connect to the EEPROM:

  • P1.1 = SDA
  • P1.3 = SCL

Serial port protocol

The serial port runs at 19200,N,8,1.

Data is only sent to the NRF module. The Tx line of the NRF module is connected to the MCU in the transmitter, but there is no data being sent.

Data is sent to the NRF module in packets of 15 bytes. The first three bytes indicate the packet type. There are two packet types in use:

ff 55 aa: Stick data and Failsafe

ff aa 55: Model number

The Stick data and Failsafe packet structure is as follows:

Bytes 0..2: Header (ff 55 aa)

Bytes 3..8: Payload

Bytes 9, 10: CRC16-CCITT of Payload

Bytes 11, 12: Not used, seems to contain junk data. For stick data it is influenced by steering wheel only (not trim, etc!)

Left: 87 7c

Centre: e6 08

Right: 22 7c

For Failsafe the value changes depending on which buttons are pressed.

Bytes 13, 14: 16-bit sum of bytes 3 to 10, MSB first

The first payload byte is always aa. The high nibble of byte 4 is a for Stick data or b for Failsafe.

Packets that are of type Stick data and Failsafe are repeated every 13.28ms (75.3Hz). Note that this does not match the output rate of the receiver, which is 16ms (62.5Hz).

Checksum algorithms

Data is protected with two checksums.

The whole packet travelling over the serial port is protected with a simple 16-bit sum of the bytes 3 to 10. MSB is stored in byte 13, LSB in byte 14. Note that bytes 11 and 12 are not protected, they don't seem to be in use and seem to leak internal information of the MCU.

The Stick data and Failsafe packets include a checksum using the CRC16-CCITT algorithm, 0x1021 polynominal. This checksum is most likely sent to the receiver.

The checksum is calculated over the payload bytes 3..8, and is stored in bytes 9 (MSB) and 10 (LSB).

Unfortunately neither checksum are verified at the receiving end. Sending bogus values has no impact on the operation of the system :(

Stick data

Each channel is a 12 bit number. The highest nibbles are packed in bytes 4 and 5, the low bytes are in bytes 6..8.

Channel values 0x000 to 0x9ff generate a valid output pulse. Values above 0x9ff create a very long pulse that does not change with the value.

The forumla of how to determine the resulting pulse based on a given channel value is as follows::

    rx_pulse = (tx_value - 2560) * 17 / 16

And to calculate a channel value for a desired pulse length::

    tx_value = (2720 - rx_pulse) * 16 / 17

The generated pulses are unfortunately not very precise. There is a jitter of about +/-2us. Furthermore, every now and then there are glitches making the pulses longer. In reality it means that the lower 5 bits are not usable for reliable transmission of binary data.

                 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14
                -------------------------------------------- 
    CH3 pos 0   ff 55 aa aa a4 42 94 7a 8a 34 15 e6 08 03 71
    CH3 pos 1   ff 55 aa aa a4 46 94 7a 72 90 f3 e6 08 04 97
    TH  fwd     ff 55 aa aa a4 22 94 71 8a b1 3d e6 08 03 ed
    TH  back    ff 55 aa aa a4 52 94 dc 8a 98 6a e6 08 04 9c
    ST  left    ff 55 aa aa a3 42 53 7a 8a f0 a6 87 7c 04 7c
    ST  right   ff 55 aa aa a5 42 dc 7a 8a 2a 48 22 7c 03 e3
    --------------------------------------------------------
                             s t3 ss tt 33 cc cc XX XX kk kk
                         yy yy yy yy yy yy                   checksum bytes: CRC16 = cc cc
                         xx xx xx xx xx xx xx xx             checksum bytes: sum = kk kk

Failsafe

Failsafe packets are only sent if the failsafe function is enabled for the current model.

Failsafe packets are transmitted after every 14 stick data transmissions.

     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14
    -------------------------------------------- 
    ff 55 aa aa bb cc 78 78 06 c9 e2 a5 09 04 d2
    --------------------------------------------
                      ss tt mm cc cc XX XX kk kk
             yy yy yy yy yy yy                   checksum bytes: CRC16 = cc cc
             xx xx xx xx xx xx xx xx             checksum bytes: sum = kk kk

ss, tt:

Steering, throttle in percent.

0x78 means 0%, 0x00 means -120%, 0xf0 means +120%

mm:

bit mask whether which channel is enabled for failsafe:

bit 0: steering

bit 1: throttle

bit 2: always 1 (CH3?)

The percentage value translates into the following pulse timings on the respective servo output:

    +120%   +100%       0%    -100%    -120%
     784us   904us   1540us   2120us   2240us

Model number

This packet is sent after power on and every time a model is changed.

It is repeated three times every 46.4ms, and often disrupts an ongoing transmission, causing CRC errors -- which is most likely the reason for repeating it three times.

Changing a model takes 197.3ms, then 3 model number commands are sent, and then the first Stick data (or Failsafe) packet after 168.1ms.

     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14
    -------------------------------------------- 
    ff aa 55 00 02 07 00 00 21 10 42 20 63 30 84 
    ff aa 55 00 02 07 00 00 21 10 42 20 63 30 84 
    ff aa 55 00 02 07 00 00 21 10 42 20 63 30 84 
                mm

mm:

model code. mod0 = 0x02, mod15 = 0x11

rest:

unknown, but constant data independent of the model number

The model code serves as index into the code data stored in the EEPROM that is connected to the NRF module.

EEPROM contents

The EEPROM connected to P0.7 (SCL) and P1.0 (SDA) contains binding data. Note: the EEPROM is connected to different pins on the X-3S: P0.6 = SDA, P1.1 = SCL

There is a 25 byte code for each model, starting at address 0. These 25 bytes correspond with the data we read from the EEPROM in the receiver.

Note that only the first 6 bytes contain random values, the rest are padding (value increments from the last random byte value onwards. Note sure if only the first 6 bytes are transmitted over the air, or all 25 bytes. The NRF chip supports 5 bytes of address, so it could well be that only the first 5 bytes are significant and the rest is just padding. The data found in the receiver EEPROM matches all 25 bytes, but that could just be done as a kind of checksum.

Furthermore, address 0x19a and 0x19b contain the value 0xaa. It is not known whether this information is used, but it is present in both HK310 and X-3S.