Engineering Guides · Module 04
Connecting a sensor to the onboard computer
A link must survive noise and restarts: stable device names, framed messages with a checksum, and a parser that resynchronises.
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
A sensor that works once on a desk is not integrated. On the robot the device may enumerate under a different name after a reboot, bytes arrive corrupted, and packets can start in the middle. A reliable connection handles all three.
2. When is this needed?
- Writing or choosing the interface for a new sensor.
- When a USB serial device changes its name between boots.
- When corrupted frames produce wrong readings.
3. Selection and design decisions
Typical choices: USB or UART for simple sensors, Ethernet for high-rate sensors, CAN for distributed actuators. On Linux a USB serial device appears as /dev/ttyUSB* or /dev/ttyACM*, and stable names can be provided by /dev/serial/by-id/ links or by udev rules keyed to the device’s vendor and product IDs and serial number.
| Concern | Technique |
|---|---|
| Stable device name | Use /dev/serial/by-id/ paths or a udev rule with a symlink |
| Permissions | Add the user to the group that owns the device (commonly dialout) or set the group in the udev rule |
| Framing | Sync byte, length, payload and checksum so the receiver can find packet boundaries |
| Resynchronisation | On a bad checksum, skip one byte and search for the next sync byte |
| Timestamps | Stamp at arrival in the driver, and use the device clock if it provides one (see the timing guides) |
4. Advantages and disadvantages
- Binary framing is compact and needs a careful parser; text framing is easy to debug and costs bandwidth.
- Checksum vs CRC: a CRC detects more errors at a small compute cost.
- A longer maximum length allows bigger packets and makes false headers more costly.
5. Requirements and constraints
- A maximum payload length so a corrupt length byte cannot stall the parser.
- A checksum or CRC on every packet.
- The device name does not depend on enumeration order.
6. Architecture
sensor ──bytes──▶ OS serial driver ──▶ driver node: [find sync] [check length] [verify checksum] ──▶ ROS 2 message (stamped)7. Implementation
- Identify the device by vendor and product ID and create a stable name.
- Set the serial parameters from the datasheet.
- Implement framing with a sync byte, length and checksum.
- Implement the parser to resynchronise (below) and count the bad packets.
- Publish the standard ROS 2 message with a correct frame_id and timestamp, and verify with
ros2 topic hzandecho.
def parse(stream, max_len=16):
out, i = [], 0
while i + 3 <= len(stream):
if stream[i] != 0xAA:
i += 1
continue
n = stream[i + 1]
if n > max_len:
i += 1 # implausible length: not a real header
continue
if i + 3 + n > len(stream):
break
payload, chk = stream[i + 2:i + 2 + n], stream[i + 2 + n]
if (sum(payload) + n) & 0xFF == chk:
out.append(list(payload)); i += 3 + n
else:
i += 1 # bad checksum: resynchronise on the next byte
return out
good = [0xAA, 3, 1, 2, 3, 9]
noise = [0x00, 0xAA, 0x77]
bad = [0xAA, 2, 5, 5, 0x00]
print(parse(noise + good + bad + good))Printed (checked by the site’s tests):
[[1, 2, 3], [1, 2, 3]]Reading it: the stream starts with noise, then a good packet, a packet with a bad checksum, and another good packet. The parser recovers both good packets ([1, 2, 3] twice) and skips the corrupt one. Without the maximum-length check, the noise byte 0x77 after a stray 0xAA would be read as a length of 119 and the parser would wait for bytes that never come. The packet format here is invented for illustration.
8. Real examples
- GNSS receiver on USB: a udev symlink such as /dev/gnss0 and a driver that publishes
sensor_msgs/NavSatFix.
9. Failure scenarios
- The device appears as ttyUSB1 after a reboot and the driver opens ttyUSB0 (another device).
- A parser that blocks waiting for a long bogus packet.
- No permission to open the port after an update.
10. Troubleshooting
- Check
dmesgfor the device and its name. - Read raw bytes with a terminal tool at the configured baud and compare with the datasheet.
- Count checksum failures: many means noise or wrong settings.
11. Validation
- The parser example prints the lines shown (executed by the site tests).
- The device name is the same after 20 reboots and re-plugs.
- Message rate equals the configured rate with no gaps.
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).
- Linux kernel documentation and your distribution’s udev manual for device naming rules.
Related on FixTheRobot
- Robust Optimization and Outlier Handling SLAM · Lesson