ROS 2 - micro-ROS - Using STM32 USB serial port to communicate with a Linux host via WSL 2

Connecting a microcontroller to a modern robotics ecosystem can be a daunting task, especially when working across different operating systems.

In this tutorial, we will explore how to transform an STM32F3 Discovery board into a fully functional ROS 2 node with the help of micro-ROS library.

More specifically, we’ll use the STM32 native USB serial port to establish real-time communication with a Linux host running inside WSL 2.

Shopping list

Github of this tutorial :

To successfully follow this tutorial, you will need a specific set of hardware and software tools.

This setup is designed for developers working on Windows using WSL2.

Hardware Requirements

  • STM32F3 Discovery Board.
  • Two Mini-USB Cables:
    • Cable 1 (ST-LINK): To flash the firmware and power the board.
    • Cable 2 (USER): Connected to the USB User port for native serial communication.
  • A Windows PC: Running Windows 10 or 11.

Software Stack

  • WSL2 (Ubuntu 24.04): The host Linux distribution on Windows.
  • Docker & Dev Containers: Used to run a ROS 2 Humble environment (based on Ubuntu 22.04).
  • Visual Studio Code: With the PlatformIO extension installed for STM32 firmware development.
  • usbipd-win: A crucial tool to "attach" your physical USB devices from Windows to your WSL2 instance (a bridge from Windows to Linux via /dev/ttyACM0 port).

An interesting thing is the use of Ubuntu 24.04 as host for WSL and Ubuntu 22.04 as Docker environment for ROS 2 Humble (inside the host).

Hierarchically we have:

Windows 10 (or 11) > Ubuntu 24.04 via WSL 2 > Ubuntu 22.04 as dev container > ROS 2 Humble + micro-ROS.

And more generally we can resume our stack as follows:

Data Flow: From silicon to ROS 2:

  1. STM32 hardware: The microcontroller sends raw data packets over the USB User port (using the USB CDC protocol).
  2. Windows host: Windows detects the device. Since it's "bound" via usbipd, it doesn't try to use it locally.
  3. The Bridge (usbipd): usbipd captures the USB traffic and redirects it to the WSL 2 kernel.
  4. Ubuntu 24.04 (virtual host): The Linux kernel recognizes the device and creates a virtual file at /dev/ttyACM0.
  5. Dev container mapping: Docker maps this device from the host into the Ubuntu 22.04 container.
  6. micro-ROS Agent: Inside the container, the Agent opens /dev/ttyACM0, reads the packets, and translates them into ROS 2 messages.
  7. ROS 2 ecosystem: The data is finally published as a ROS 2 Topic (e.g., /sensor_data), making it available to any other node (Rviz, navigation, etc.).

Let’s get started

Plugging the device

The first thing is to follow to plug your STM32F3Discovery board to your PC.

Then follow this tutorial explaining how to set your Windows environment in order to use WSL with your board:

The above tutorial was for a basic interaction with the board.

For our new current tutorial we are going to use the second USB connector of the STM32F3 board.

Connect the USB ST-LINK with a cable to a first USB PC port and the USB USER with another cable to a second USB port.

Then from your Powershell type the following commands (if not already done):

usbipd list

It's generate the following output:

Connected:

BUSID  VID:PID    DEVICE                                                        STATE

2-1    0483:3748  STM32 STLink                                                  Shared

2-2    0483:5740  Serial device USB (COM5)                                      Shared

If you don't see the Serial device USB (COM5), don't worry, it means that you have to firstly flash your board with the firmware compiled further in this tutorial.

If you see the both USB devices, then let's continue.

Start your WSL 2 instance.

From Powershell, for the ST-LINK USB, use this command:

usbipd attach --wsl --busid 2-1

For the USER USB use this one :

usbipd attach --wsl --busid 2-2 --auto-attach

You can note the last option: « --auto-attach ».

This last option is really important because even a micro second can make the device lose the connection with the USB port.

So the connection with the serial port can be lost by micro-ROS if there no auto attach mode.

Let’s assume you have your source files in your Ubuntu (24.04) WSL folder, such as :

  • /home/mika/p/ros2

Then from VSCode, let’s rebuild the project as a dev container:

  • CTRL + SHIFT + P > Dev Containers: Rebuild Container

Select the .devcontainer/devcontainer.json file from the list if many files or from the directory taken from the Github project.

Let the container build.

Create now a project directory in your dev container as the following :

  • /workspaces/ros2/badprog-ros-2-micro-ros-using-stm32-usb-serial-port-to-communicate-with-a-linux-host-via-wsl-2

Go inside this directory :

cd badprog-ros-2-micro-ros-using-stm32-usb-serial-port-to-communicate-with-a-linux-host-via-wsl-2

Copy the platformio.ini file (from the Github link up above) and add it at the root of your project.

  • /workspaces/ros2/badprog-ros-2-micro-ros-using-stm32-usb-serial-port-to-communicate-with-a-linux-host-via-wsl-2/
    • platformio.ini

So globally this is so far the only file of your project.

Enabling Native USB Serial (CDC)

To make the STM32 "User USB" port visible as a COM port on Windows, we must force the microcontroller to behave as a USB Communication Device Class (CDC).

In your platformio.ini, these two flags are the "magic" that triggers the hardware:

  • -D USBD_USE_CDC: Instructs the chip to use the USB Serial protocol.
  • -D USBCON: Enables the native USB stack within the Arduino framework.

Note: Without these flags, the STM32 will not be detected by usbipd on the second cable, as the USB User port remains inactive by default.

 

In the main.cpp, we use the function with the SerialUSB parameter instead of just Serial:

set_microros_serial_transports(SerialUSB);

This tells micro-ROS to bypass the standard UART pins (TX/RX) and send data directly through the USB User connector.

This allows for a much cleaner setup with higher bandwidth and no need for an external FTDI adapter.

Let’s now build the microros library from the dev container instance:

pio run

This command will download everything needed to build the micro-ROS library for our STM32F3Discovery board.

It’s a cross compilation, from our container on Ubuntu 22.04 for the STM32F303VC microcontroller.

If you see the following line appear and blocking in the terminal it's a good sign:

Building micro-ROS library

The first time it could take several minutes (between 5 to 10 minutes) to build.

The next compilation of your program will be shorter of course (don’t need anymore to build the micro-ROS library).

If everything went OK then we can upload our program on the STM32F3Discovery board:

pio run --target upload

If you see the following output then your firmware has been flashed on the microcontroller:

...

Uploading .pio/build/disco_f303vc/firmware.elf

xPack Open On-Chip Debugger 0.12.0-01004-g9ea7f3d64-dirty (2023-01-30-15:03)

Licensed under GNU GPL v2

For bug reports, read

        http://openocd.org/doc/doxygen/bugs.html

debug_level: 1


srst_only separate srst_nogate srst_open_drain connect_deassert_srst


[stm32f3x.cpu] halted due to debug-request, current mode: Thread

xPSR: 0x01000000 pc: 0x0800638c msp: 0x2000a000

** Programming Started **

Warn : Adding extra erase range, 0x08015d6c .. 0x08015fff

** Programming Finished **

** Verify Started **

** Verified OK **

** Resetting Target **

shutdown command invoked

=========== [SUCCESS] Took 12.38 seconds =========

The ttyACM0 serial port

This is not the end.

Indeed, at this point you shouldn’t see your green LED blinking.

To see it blink, we have to come back to our host (Ubuntu 24.04 as WSL) and first check if the  /dev/ttyACM0 serial port is available:

ls /dev/tty*

Every device should appear and hopefully the ttyACM0 one as well.

If it’s the case, then run the following Docker command from the host (Ubuntu 24.04):

docker run -it --rm --privileged -v /dev:/dev microros/micro-ros-agent:humble serial --dev /dev/ttyACM0

You should see the output saying that the session has been established, a participant, topic and publisher created.

At this time, the green LED should blink on your board.

To finish the demonstration, come back to the dev container (Ubuntu 22.04 where ROS 2 is installed) then type this command:

ros2 topic echo /badprog_topic_counter

The counter should increment each second like this :

data: 0
---
data: 1
---
data: 2

…

Well done, you did it cool

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.