FixTheRobot Explore Robotics / Systems Engineering / Design & Selection / Module 04

Design & Selection · Module 04

Choosing a communication interface

Pick the interface from data rate, distance, number of nodes and noise, then confirm the payload rate leaves margin.

  • Intermediate
  • Module 04: Embedded Systems & Hardware Interfaces
  • Written for ROS 2 Jazzy where ROS 2 is used
  • Sources checked 2026-11-06

Assumptions: Numbers in the examples are illustrative and the code is executed by the site’s tests. Facts taken from a cited source are marked; other statements are general engineering knowledge and must be confirmed on the datasheet of the part you use.

1. Engineering problem

Every sensor and actuator needs a link to the controller. The wrong choice shows up as lost data, noise sensitivity or a bus that cannot be extended. A quick payload-rate calculation removes most wrong choices before any hardware is bought.

2. When is this needed?

  • When selecting a new sensor, motor driver or controller board.
  • When adding a device to an existing bus.
  • When a link drops data and you need to know whether it is overloaded or noisy.

3. Selection and design decisions

General characteristics (the facts marked as sourced come from Wikipedia: classic CAN carries 8 bytes per frame and CAN FD up to 64; CAN uses a twisted pair terminated with 120 Ω at each end; common I²C speeds are 100 and 400 kbit/s with a 7-bit address and pull-up resistors; SPI is full-duplex with an active-low select line per device). The rest is general engineering knowledge; confirm on the datasheets.

Overview
InterfaceTopologyTypical useWatch for
UARTPoint to pointGNSS receivers, simple modules, debugNo addressing; baud-rate error; no built-in error recovery
SPIOne controller, one select line per deviceIMUs, ADCs, flash at high rateShort wires; extra select line per device; mode must match
I²CShared two-wire bus with 7-bit addressesSlow sensors, EEPROMsPull-up value and bus capacitance; address clashes; clock stretching
CAN / CAN FDMulti-drop twisted pair, 120 Ω at both endsMotor drivers, battery, actuators over metresTermination, bit timing, bus load
EthernetSwitched, point to pointLiDAR, cameras, computersSwitch bandwidth, PTP support, connectors
USBHost with hubsCameras, adaptersHub power, cable length, host controller sharing

4. Advantages and disadvantages

  • Simplicity vs robustness: UART is trivial to wire and weak at noise and errors; CAN is differential with error detection but needs termination and configuration.
  • Rate vs distance: faster signalling shortens the usable cable length.
  • Shared vs dedicated links: a shared bus saves wiring and couples devices (one faulty node can disturb all).

5. Requirements and constraints

  • Required payload rate ≤ 70 % of the link’s usable payload rate (a design margin, not a standard).
  • Cable length and environment match the signalling (differential for noisy, long runs).
  • The controller has the peripheral and the driver support for the interface.

6. Architecture

sensor/actuator ──link (UART | SPI | I²C | CAN | Ethernet | USB)──▶ controller or computer ──▶ ROS 2 driver node

7. Implementation

  1. List each device with its required data rate in bit/s.
  2. Compute the usable payload rate of each candidate link (below).
  3. Keep only links where the need is ≤ 70 % of the payload rate.
  4. Filter by distance, noise, number of nodes and driver support.
  5. Write the choice and the numbers in the interface control document.
def uart_payload_bps(baud, data_bits=8, parity=0, stop=1):
    frame = 1 + data_bits + parity + stop          # start + data + parity + stop bits
    return baud * data_bits / frame
def i2c_payload_bps(clock_hz):
    return clock_hz * 8 / 9                         # 8 data bits + 1 ACK bit per byte; addressing overhead ignored
need = {"imu": 0.2e6, "gps": 0.04e6, "lidar": 90e6}   # required bit/s
links = {"UART 115200": uart_payload_bps(115200), "UART 921600": uart_payload_bps(921600), "I2C 400k": i2c_payload_bps(400e3)}
for name, rate in need.items():
    ok = [l for l, c in links.items() if rate <= 0.7 * c]
    print(name, "fits:", ok or "none of these links")

Printed (checked by the site’s tests):

imu fits: ['UART 921600', 'I2C 400k']
gps fits: ['UART 115200', 'UART 921600', 'I2C 400k']
lidar fits: none of these links

Reading it: a UART frame of 8 data bits with one start and one stop bit carries 8 payload bits per 10 line bits, so 115200 baud gives about 92 kbit/s of payload; I²C sends 9 clock cycles per byte (8 data bits and an acknowledge bit), so 400 kHz gives about 356 kbit/s before addressing overhead. A 0.2 Mbit/s IMU stream does not fit 115200 baud with margin, a 90 Mbit/s LiDAR fits none of these links (it needs Ethernet). Rates are illustrative.

8. Real examples

  • Mobile robot: IMU over SPI to a microcontroller, motor drivers on CAN, LiDAR on Ethernet, GNSS on UART.

9. Failure scenarios

  • An IMU configured at a data rate that exceeds a 115200 baud UART, so samples are silently dropped.
  • Two I²C devices with the same address.
  • A CAN bus without termination.

10. Troubleshooting

  1. If data is lost, compare the measured rate with the payload rate and the 70 % limit.
  2. If errors appear only when motors run, suspect noise and look at the cabling guide.
  3. If a device does not answer, check address, mode, voltage level and pull-ups.

11. Validation

  • The fit check above prints the lines shown (executed by the site tests).
  • Measured message rate equals the configured rate with no gaps over the longest mission.

12. Engineering checklist

13. Further references

  • Wikipedia, UART, SPI and I²C, read 2026-11-06 (secondary sources; the I²C specification itself was not read).
  • Wikipedia, CAN bus and CAN FD, read 2026-11-06 (secondary source; the standards are ISO 11898, which was not read).

Related on FixTheRobot