1. 环境准备与工具安装

在开始MicroRos与STM32的集成之前,我们需要确保开发环境正确配置。我实测过多个Ubuntu版本,最终发现Ubuntu 24.04配合ROS2 Jazzy是最稳定的组合。这个组合的Cmake版本是3.28,正好满足MicroRos编译的要求。如果你用的是其他Ubuntu版本,可能需要手动调整Cmake版本,我之前在Galactic版本上就踩过坑,Cmake 3.16会导致编译失败,升级到3.28才解决。

安装ROS2 Jazzy推荐用鱼香ROS的一键安装脚本,省时省力。打开终端,运行以下命令:

wget http://fishros.com/install -O fishros && . fishros

选择ROS2 Jazzy版本,一路确认就行。安装完成后,别忘了装Colcon构建工具:

sudo apt-get install python3-colcon-common-extensions

Cmake版本检查很重要,运行cmake --version确认版本是3.28。如果不是,可以通过源码编译升级:

wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3.tar.gz
tar -xzf cmake-3.28.3.tar.gz
cd cmake-3.28.3
./bootstrap && make && sudo make install

STM32CubeMX的安装需要Java环境,先检查java -version,如果没有安装,运行:

sudo apt install default-jre

然后去ST官网下载Linux版的STM32CubeMX,解压后直接运行SetupSTM32CubeMX即可。安装过程中如果遇到权限问题,记得用chmod +x给执行文件添加权限。

2. STM32CubeMX工程配置

芯片选择是关键,MicroRos对资源要求较高,尤其是RAM。我最初用STM32F103C8T6测试,结果编译时报错显示资源溢出30KB,因为F103只有20KB RAM。后来换用STM32F407ZGT6(有128KB RAM),问题就解决了。所以建议选择F4或更高系列的芯片,确保RAM至少50KB以上。

在CubeMX中,先配置SYS为Serial Wire(用于调试),RCC选择外部晶振,然后配置时钟树。STM32F407的最高频率是168MHz,但为了稳定性,我通常设置为144MHz。接下来配置串口,我用的USART3,模式为Asynchronous,并开启全局中断。DMA配置中,RX设置为Circular模式,优先级Very High;TX为Normal模式,同样Very High优先级。

FreeRTOS配置里,任务堆栈大小设置为3000字节(静态分配),任务名称可以自定义,比如MicroRosTask。生成代码时,工具链选择Makefile,这样更方便在Linux下编译。生成工程后,建议先编译一次测试基础配置是否正确:

make -j8

如果编译通过,说明工程配置没问题。

3. MicroRos构建系统安装

MicroRos的构建依赖于micro_ros_setup功能包,官方推荐用Docker,但我在非Docker环境下实测更稳定。首先创建一个工作空间并下载源码:

mkdir microros_ws
cd microros_ws
git clone -b jazzy https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup

然后用rosdep安装依赖:

sudo apt update && rosdep update
rosdep install --from-paths src --ignore-src -y

安装pip并编译:

sudo apt-get install python3-pip
colcon build
source install/local_setup.bash

这一步可能会遇到网络问题,如果rosdep失败,可以手动安装缺失的包,比如python3-rosdistro

4. 静态库构建与集成

克隆micro_ros_stm32cubemx_utils到STM32工程目录:

git clone https://github.com/micro-ROS/micro_ros_stm32cubemx_utils.git

官方教程用Docker构建静态库,但我们可以手动实现。先安装交叉编译工具链:

sudo apt install gcc-arm-none-eabi

然后修改library_generation.sh脚本,重点是设置环境变量和路径。以下是我的自定义脚本my_library_generation.sh内容:

#!/bin/bash
set -e
export ROS_DISTRO=jazzy
export PROJECT=~/STM32Project/MicroRos_STM32F4
export BASE_PATH=$PROJECT/micro_ros_stm32cubemx_utils/microros_static_library

source /opt/ros/$ROS_DISTRO/setup.bash
source install/local_setup.bash

ros2 run micro_ros_setup create_firmware_ws.sh generate_lib

pushd firmware/mcu_ws > /dev/null
# 添加额外包(如果有)
mkdir extra_packages
pushd extra_packages > /dev/null
# 这里可以放入自定义ROS2包
popd > /dev/null
popd > /dev/null

pushd $PROJECT > /dev/null
export RET_CFLAGS=$(make print_cflags)
RET_CODE=$?
if [ $RET_CODE != "0" ]; then
    echo "Error reading CFLAGS"
    exit 1
fi
popd > /dev/null

export TOOLCHAIN_PREFIX=/usr/bin/arm-none-eabi-
ros2 run micro_ros_setup build_firmware.sh $BASE_PATH/library_generation/toolchain.cmake $BASE_PATH/library_generation/colcon.meta

# 复制生成的库文件
rm -rf $BASE_PATH/libmicroros
mkdir -p $BASE_PATH/libmicroros/microros_include
cp -R firmware/build/include/* $BASE_PATH/libmicroros/microros_include/
cp -R firmware/build/libmicroros.a $BASE_PATH/libmicroros/libmicroros.a

运行脚本构建静态库:

bash my_library_generation.sh

如果之前构建过firmware,可以用if false;then ... fi跳过创建步骤节省时间。

修改工程的Makefile,在build the application前添加:

LDFLAGS += micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a
C_INCLUDES += -Imicro_ros_stm32cubemx_utils/microros_static_library/libmicroros/microros_include
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/custom_memory_manager.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_allocators.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_time.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_transports/dma_transport.c

print_cflags:
	@echo $(CFLAGS)

注意@echo前必须是Tab缩进,否则Makefile会报错。

5. MicroRos任务实现

freertos.c中,首先包含必要的头文件:

#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <uxr/client/transport.h>
#include <rmw_microxrcedds_c/config.h>
#include <rmw_microros/rmw_microros.h>
#include <std_msgs/msg/int32.h>
#include <stdbool.h>
#include "usart.h"

然后复制传输函数声明和实现到合适的位置。在MicroRos任务中,初始化传输和发布者:

void MicroRosTask(void *argument) {
    rmw_uros_set_custom_transport(true, (void *) &huart3, 
        cubemx_transport_open, 
        cubemx_transport_close, 
        cubemx_transport_write, 
        cubemx_transport_read);

    rcl_allocator_t freeRTOS_allocator = rcutils_get_zero_initialized_allocator();
    freeRTOS_allocator.allocate = microros_allocate;
    freeRTOS_allocator.deallocate = microros_deallocate;
    freeRTOS_allocator.reallocate = microros_reallocate;
    freeRTOS_allocator.zero_allocate = microros_zero_allocate;
    rcutils_set_default_allocator(&freeRTOS_allocator);

    rcl_publisher_t publisher;
    std_msgs__msg__Int32 msg;
    rclc_support_t support;
    rcl_node_t node;
    rcl_allocator_t allocator = rcl_get_default_allocator();

    rclc_support_init(&support, 0, NULL, &allocator);
    rclc_node_init_default(&node, "stm32_node", "", &support);
    rclc_publisher_init_default(&publisher, &node, 
        ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), 
        "stm32_publisher");

    msg.data = 0;
    for(;;) {
        rcl_publish(&publisher, &msg, NULL);
        msg.data++;
        osDelay(100);
    }
}

这段代码创建了一个发布者,每100ms发送一个递增的整数。如果你的串口不是USART3,记得修改huart3为对应的句柄。

6. 编译与烧录

编译工程使用make -j8,如果一切顺利,会生成build/firmware.bin文件。烧录可以用ST-Link,先安装ST-Link工具:

git clone https://github.com/stlink-org/stlink
cd stlink
make release
sudo make install

连接ST-Link到STM32,运行:

st-flash write build/firmware.bin 0x8000000

烧录完成后,用USB线连接STM32和电脑,检查串口设备:

ls /dev/ttyACM*

如果看到/dev/ttyACM0或类似设备,说明连接成功。

7. MicroRos代理配置

最后启动MicroRos代理,将STM32的数据转换为ROS2格式。在microros_ws中运行:

source install/local_setup.sh
ros2 run micro_ros_setup create_agent_ws.sh
ros2 run micro_ros_setup build_agent.sh
source install/local_setup.sh

给串口设备权限并启动代理:

sudo chmod 777 /dev/ttyACM0
ros2 run micro_ros_agent micro_ros_agent serial -b 115200 --dev /dev/ttyACM0

现在打开另一个终端,就可以看到STM32发布的话题了:

ros2 topic list
ros2 topic echo /stm32_publisher

如果一切正常,你会看到不断递增的整数数据,说明MicroRos已经成功在STM32上运行。

更多推荐