Use a serial link
Needs first: Run a talker
Use a serial link when a board has a UART but no network, or when a point-to-point cable to one host is all the network you want. It is the link the board starters use first, because it needs no IP stack, no address and no switch.
The image’s locator makes the link. A locator that starts with serial/
tells the build to leave the IP stack out, and tells zenoh-pico to send its
frames over that UART. On the host, rmw_zenohd listens on the serial
device and connects the board to every other node. For XRCE-DDS over a UART,
see Use XRCE-DDS; WiFi is not covered yet.
Before you start
- The board provisioned for zenoh, for example
nros setup mps2-an385-baremetal --rmw zenoh. - ROS 2 Humble with
ros-humble-rmw-zenoh-cpp, sourced in each terminal. It provides the router.
Steps
-
Scaffold a project. A board that brings a UART out to the host gets a serial image from
nros new:nros new serial_ws --board mps2-an385-baremetal --template talker cd serial_wsThe image block in
src/serial_node_bringup/system.tomlnames the board’s UART and its rate:[image.baremetal] board = "mps2-an385-baremetal" locator = "serial/UART_0#baudrate=115200" -
Run it in the emulator.
nros runboots QEMU with the UART on a terminal device of your host, then starts the router on that device:nros run serial_node --expect 'Publishing:'nros run: starting the zenoh router on serial//dev/pts/4#baudrate=115200 Publishing: 'Hello World: 1' nros run: matched afterThe device number differs from run to run. The router also listens on
tcp/127.0.0.1:7447, so ROS 2 nodes on this host can reach the board. -
Hear it from ROS 2. Leave
nros run serial_noderunning in one terminal, and in another:export RMW_IMPLEMENTATION=rmw_zenoh_cpp ros2 topic echo /chatter std_msgs/msg/String --qos-reliability best_effortdata: 'Hello World: 2' -
Change the rate, for a board on a real cable. Edit the
baudratein the locator;nros rungives the router the same options. QEMU ignores the rate, so it matters only on hardware:locator = "serial/UART_0#baudrate=921600"115200 works on any adapter. Many USB serial adapters take 460800, and 921600 is the top rate of many MCU UARTs. A long or noisy cable gives framing errors at high rates.
-
Run the router yourself for a real board. Flash the board as its starter shows. Its UART then appears as a USB serial device,
/dev/ttyACM0for example.rmw_zenohdreads no command-line arguments, so give it the endpoints inZENOH_CONFIG_OVERRIDE: the serial device for the board, and a TCP port for ROS 2 nodes on this host:source /opt/ros/humble/setup.bash ZENOH_CONFIG_OVERRIDE='listen/endpoints=["serial//dev/ttyACM0#baudrate=115200","tcp/127.0.0.1:7447"]' \ ros2 run rmw_zenoh_cpp rmw_zenohdThe router listens and the board dials it. Reset the board, then run the
ros2 topic echoof step 3. -
On a Zephyr board, set the main thread below the zenoh read task. With Zephyr’s default main priority, 0, the main thread outranks the read task while it creates entities, the UART receive ring overflows, and a board joining a busy domain misses the router’s replies. Put this in the image’s Zephyr fragment, the file its
os_confignames:CONFIG_MAIN_THREAD_PRIORITY=5nros buildrefuses a serial image whose main thread is not below the read task, and its message names the value to use. If joins into a busy domain still fail, raiseCONFIG_NROS_ZENOH_SERIAL_RX_RING_BYTESfrom its default of 1024; the ring is static RAM.
Example
The scaffold’s whole bringup, which runs as is in QEMU:
# src/serial_node_bringup/system.toml
[system]
name = "serial_node"
rmw = "zenoh"
ros_edition = "humble"
domain_id = 0
[[component]]
pkg = "serial_node"
class = "serial_node::Talker"
name = "serial_node"
[image.baremetal]
board = "mps2-an385-baremetal"
locator = "serial/UART_0#baudrate=115200"
source /opt/ros/humble/setup.bash
nros run serial_node
If it doesn’t work
- The session never opens, or times out. The router listens on a
different device than the board’s UART, or the two use different rates.
Check the device in the router’s endpoint and the
baudrateon both sides. - The board runs but ROS 2 hears nothing. The router has no TCP endpoint
for host nodes (add
tcp/127.0.0.1:7447as in step 5), the two sides use differentdomain_idvalues, orros2 topic echois missing--qos-reliability best_effort. - Nothing arrives on hardware, but QEMU works. The UART may also carry the board’s debug console. Give zenoh a UART of its own, or turn the console off.
nros runstops and names the router. It could not findrmw_zenohd. Source ROS 2, or setNROS_RMW_ZENOHDto the binary.
See also
- Configure zenoh: network locators, a router on another host, and the session file.
- Tune throughput and latency: the buffers a serial image gets and how to change them.
- Environment variables:
the locator forms
NROS_LOCATORtakes. - Troubleshoot: failures that are not specific to serial.