UAV Interconnect Bus - iNavFlight/inav GitHub Wiki

INAV implements universal interconnect bus for various types of sensors and executable devices.

It's compatible with all existing controllers that have a spare UART and designed to be able to connect multiple sensors to one shared bus. Devices on the bus can be daisy-chained together for neater wiring.

Physical layer

Option 1: Differential signalling

This option is taken from automotive applications and uses CAN bus transceivers (MCP2551 or SN65HVD232) to convert between twisted pair and UART. A special converter is required between each device and a bus. While this option is more expensive it's also very reliable.

Advantages: high reliability, long wires possible.

Option 2: Shared wire

This option is designed for tight spaces or very cost-sensitive solutions. Wiring should follow Siemens Application Node AP2921: On-Board Communication via CAN without Transceiver (https://www.mikrocontroller.net/attachment/28831/siemens_AP2921.pdf)

Advantages: low price, low wire count

Data format on the wire

From data format point of view it's plain asynchronous serial with following parameters:

115200,8,n,1

**FIXME: Chose a baud rate that has high reliability across multiple MCUs **

Notes

Both differential signalling and shared wire connection options are verified to work.

Device addressing

Each slave device on a bus has a unique DevID which defines device functionality (GPS, Optical flow, RC receiver etc). DevID is one byte and also serves as a device priority - master controller will favor devices with lower DevID

During discovery phase on the bus each device is assigned a SlotID which it must use for communicating with the master. DevID is only used during discovery phase.

Device capabilities

During discovery each device must report capability flags (16-bit field, see IDENTIFY command).

Flag mask Name Description
0x01 HAS_READ Indicates that device supports READ command and should be polled periodically
0x02 HAS_WRITE Indicates that device supports WRITE command and can accept data

Transactions on a bus

Everything on a bus is coordinated by a master device (flight controller) and all transactions are organised in slots. There are at most 32 slots (active devices) possible on a single bus.

Master begins transaction with one byte. Highest 3 bits indicate a command, while lower 5 bits indicate a SlotID. The rest of transaction depends on which command is being executed.

A 2ms guard interval is mandatory between transactions and is used by all devices to reset internal state. First byte after guard interval is assumed to be a command from master device.

Data integrity

Each transaction on a bus ends with a 1-byte CRC calculated by CRC-8/DVB-S2 algorithm. CRC is calculated over all transaction bytes starting with command byte. CRC is calculated by the data originator and verified by the master.

Commands on a bus

Hex Binary Name Description
0x00 000xxxx IDENTIFY Performs device identification and slot assignment
0x20 001xxxx NOTIFY Notifies a device about assigned (or re-assigned) slot
0x40 010xxxx READ Performs a read transaction from a slot
0x60 011xxxx WRITE Performs a write transaction on the bus
0x80 100xxxx reserved Not used
0xA0 101xxxx reserved Not used
0xC0 110xxxx reserved Not used
0xE0 111xxxx reserved Not used

IDENTIFY (0x00)

Byte Originator Description
0 Master Value of (0x00 + SlotID)
1 Master DevID of requested device
2 Master UIB Protocol version (0x00)
3 Master CRC1 (over bytes 0-1)
4 Slave Poll interval (low byte)
5 Slave Poll interval (high byte)
6 Slave Device flags (low byte)
7 Slave Device flags (high byte)
8 Slave Device parameters [0]
9 Slave Device parameters [1]
10 Slave Device parameters [2]
11 Slave Device parameters [3]
12 Slave CRC2 (over bytes 0-10)

During discovery phase master sends IDENTIFY commands for each supported DevID. Device with corresponding DevID must respond with desired poll interval (in milliseconds) and flag field. Master will send it's protocol version in IDENTIFY request. Slave device should respond only if it's able to talk this protocol version. Also, device which has detected it's DevID must remember the SlotID of the transaction - this will be the SlotID assigned to the device; it should also remember the protocol version it should be using to communicate.

Device parameters field (4 bytes) is device-specific and may be used to pass extended capabilities or non-standard flags to the host driver.

NOTIFY (0x20)

Byte Originator Description
0 Master Value of (0x20 + SlotID)
1 Master DevID of requested device
2 Master UIB Protocol version (0x00)
3 Master CRC1 (over bytes 0-1)

Used to assign a slot to a device. Device shouldn't respond, but only keep record of assigned SlotID.

READ (0x40)

Byte Originator Description
0 Master Value of (0x40 + SlotID)
1 Master CRC1 (over byte 0)
2 Slave Data payload length (may be zero)
3... Slave Data packet (up to 32 bytes)
last Slave CRC2 (from start of packet)

Device with SlotID that was assigned to it during discovery phase must respond to this command with a variable-length data packet. If device has no new data available it should respond with zero payload length.

WRITE (0x60)

Byte Originator Description
0 Master Value of (0x80 + SlotID)
1 Slave Data payload length (may be zero)
2... Master Data packet (up to 32 bytes)
last Slave CRC2 (from start of packet)

Device with SlotID that was assigned to it during discovery phase must silently accept the data. No acknowledgement it done by the device. Together with NOTIFY this command brings a possibility to have several devices on the same DevID/SlotID.

Devices

It's recommended that each device use first byte of READ payload as flag field with following values:

Bit Mask Description
0 0x01 UIB_DATA_VALID - indicates data validity
1 0x02 Unused, must be zero
2 0x04 Unused, must be zero
3 0x08 Unused, must be zero
4 0x10 Unused, must be zero
5 0x20 Unused, must be zero
6 0x40 Unused, must be zero
7 0x80 Unused, must be zero

Device ID = 0x12 : Rangefinder

Flag UIB_DATA_VALID will indicate that reading is valid (surface is in range and measurement is correct)

Recommended payload format:

typedef struct __attribute__((packed)) {
    uint8_t flags;
    uint16_t distanceCm;
} rangefinderData_t;

Device ID = 0x13 : GPS sensor

Flag UIB_DATA_VALID will indicate that reading is valid, UIB_DATA_NEW - that data is fresh

Recommended payload format:

typedef struct __attribute__((packed)) {
    uint8_t fix_type;
    uint8_t sat_count
    uint8_t hdop;
    int32_t longitude;
    int32_t latitude;
    int32_t altitude_msl;
    int16_t vel_north;
    int16_t vel_east;
    int16_t vel_down;
    int16_t speed_2d;
    int16_t heading_2d;
} gpsDataPacket_t;

Device ID = 0x80 : RC Receiver

Flag UIB_DATA_VALID will indicate that receiver has a valid link to transmitter. This is an inverse of FAILSAFE flag in common digital receivers.

Recommended payload format:

typedef struct __attribute__((packed)) {
    uint8_t  flags;         // UIB_DATA_VALID (0x01) - link ok
    uint8_t  rssi;
    uint8_t  sticks[4];     // Values in range [0;255], center = 127
    uint8_t  aux[8];        // Analog AUX channels - values in range [0;255], center = 127
    uint16_t reserved;      // Reserved for future use
} rcReceiverData_t;

Values of sticks[] and aux[] array should be in range [0;255] and will correspond to [1000;2000] values.