Run Micro-ROS on almost any stm32

 Run Micro-ROS on almost any stm32 - Tech blog (guillaumebeuzeboc.github.io)

Run Micro-ROS on almost any stm32

19 Sep 2021 » c, cmake, stm32, micro-ros, clion

如果用的不是STM32F4,需要自己去生成micro_ros_stm32cubemx_utils库

Micro-ROS brings the ability to integrate microcontrollers into the ROS ecosystem. Having microcontrollers publishing topic directly into your ROS2 host could facilitate a lot of the integration. So far, Micro-ROS is only officially supporting a small amount of boards. Unfortunately, I didn’t have any stm32 board officially supported by Micro-ROS, so I decided to have a look at how to run Micro-ROS on the stm32 board I had at home. So I have a Nucleo-L476RG which is an ultra low power board. It has a lot of pins and configuration possibility, a Flash size of 1 MB and two RAMs (96 KB and 32 KB). In my case, I am going to use the UART to transmit my data (using the debugger UART to avoid additional wiring). Basically what we are going to do is that we are going to create a project with CUBEMX, configure it and adapt the CMakeLists in order to link with the static Micro-ROS library. In my case I will use Clion as an IDE but most of the CMake-compatible IDE should work (Clion has a nice stm32 plugins that facilitates a lot of things like uploading, debugging, etc.). Micro-ROS is not already expecting you to use CMake, it’s rather using plain Makefiles. But with just a few changes we will be able to use Cmake.


Install all you need

In this post, I am using Ubuntu 20.04 with ROS2 foxy already installed.

Micro ROS setup

Clone this repo GitHub - micro-ROS/micro_ros_setup at foxy and follow the instruction in order to build the Micro-ROS agent (interface between the UART and ROS2).

Micro_ros_stm32cubemx_utils

In order to generate the static library, we are going to need another repo micro_ros_stm32cubemx_utils GitHub - micro-ROS/micro_ros_stm32cubemx_utils at foxy. For this example, this repo as well as the CubeMX project are going to be located in one directory.

.
├── l476rg_test   # The CubeMX project explained right after
└── micro_ros_stm32cubemx_utils # the repo

Generate your project with CubeMX

UART

Within CubeMX I generated a project for my board: Nucleo-476RG. I activate the USART2 (the one connected to the debugger). Configure it for asynchronous and disable hardware control.

UART2 setup

I left the default basic setup of it (115200 Bits/s, 8 Bits, None, 1). Check the “Global interrupt” checkbox under the NVIC Settings.

NVIC settings

Make sure to enable to DMA for the corresponding UART. Both priorities must be set to very hight and RX direction must be set to Peripheral To Memory and TX one to Memory to Peripheral. Please also make sure that RX DMA Request settings Mode is set to Circular (Keep the Normal on for TX).

DMA setup

FreeRTOS

For our example, we will need FreeRTOS. We will simply need to configure a task (the default) for Micro-ROS. Activate FreeRTOS in CubeMX (I used CMSIS v2). Micro-ros will need at least 12 kB for its task, hence we need to increase the default TOTAL_HEAP_SIZE of FreeRTOS. I picked 20000 bytes for my test (but you can of course use 12000).

FreeRTOS setup

You must also create a task for your Micro-ROS. We are simply going to use the default one. And set a size of 3000 words (3000 words of 4 bytes is 12 kB).

FreeRTOS task setup

Generate the project

Here I want to use Clion with Cmake hence I am going to generate my project for the SW4STM32 toolchain : Project Manage -> Project -> Toolchain / IDE; and select SW4STM32. Generate code in order to have the source files as well as the CMakeLists.txt.


Generate the Micro-ROS static library

Here we are going to use the micro_ros_stm32cubemx_utils repo that we downloaded before. This repository is using the Makefiles to extract the compilation flags in order to build the Micro-ROS static library. Unfortunately, so far it’s only extracting from files with .mk extension and in our case the file containing the flags (generated by Cmake) is called flags.make. Thus, we will have to make a little change to the repo. We will change the file microros_static_library_ide/library_generation/library_generation.sh by adding [a] and [e] line 13:

@@ -10,7 +10,7 @@ if [ -f "$BASE_PATH/libmicroros/libmicroros.a" ]; thenexit 0fi######## Trying to retrieve CFLAGS ########
-export RET_CFLAGS=$(find /project -type f -name *.mk -exec cat {} \; | python3 $BASE_PATH/library_generation/extract_flags.py)
+export RET_CFLAGS=$(find /project -type f -name *.m[a]k[e] -exec cat {} \; | python3 $BASE_PATH/library_generation/extract_flags.py)RET_CODE=$?if [ $RET_CODE = "0" ]; then

Once it’s done, from the directory containing the CubeMX project and the micro_ros_stm32cubemx_utils repo, launch

 docker pull microros/micro_ros_static_library_builder:foxy &&\docker run --rm -v ${PWD}:/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:foxy`

You should see the list of CFLAGS detected. In my case:

 Found CFLAGS:
-------------
-ffunction-sections -fdata-sections -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Og
-------------

Make sure the options are the same that are on for your target, otherwise you could face some undefined var/functions or linking issues. This will take some time and after in the subfolder “libmicroros” containing an “include” folder and the library. In my case, I copied the libmicroros folder in my stm32 project root. I also included in it the extra_sources available in the “micro_ros_stm32cubemx_utils” repo.


Use the library

CMakeLists.txt

In order to use the library, we must add it and the headers in our CMakeLists.txt. We must first add the includes from Micro-ROS:

include_directories(Core/IncDrivers/STM32L4xx_HAL_Driver/IncDrivers/STM32L4xx_HAL_Driver/Inc/LegacyMiddlewares/Third_Party/FreeRTOS/Source/includeMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4FDrivers/CMSIS/Device/ST/STM32L4xx/Include Drivers/CMSIS/Includelibmicroros/include)

We also need to add the Micro-ROS extra_sources to the source file glob:

file(GLOB_RECURSE SOURCES "startup/*.*" "Middlewares/*.*" "Drivers/*.*" "Core/*.*" "libmicroros/extra_sources/*.*")

And finally we need to link the Micro-ROS static library to our target

target_link_libraries(${PROJECT_NAME}.elf ${CMAKE_SOURCE_DIR}/libmicroros/libmicroros.a)
Updating the main.c

Now that the CMakeLists.txt is ready, we can modify the main in order to publish our topic. We are basically going to use what is defined in https://github.com/micro-ROS/micro_ros_stm32cubemx_utils/blob/foxy/sample_main.c which is a full example of topic publishing. We will only have to modify the main.c (core/src) in our case.

First, we must include the necessary Micro-ROS layer includes, and our message type.

/* USER CODE BEGIN Includes */
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <uxr/client/transport.h>
#include <rmw_microros/rmw_microros.h>
#include <rcutils/stdatomic_helper/gcc/stdatomic.h>#include <std_msgs/msg/int32.h>
/* USER CODE END Includes */

We need to declare a bunch of methods that are actually defined in the extra_sources files (in our case in dma_transport.c and in microros_allocators.c)

/* USER CODE BEGIN 4 */
bool cubemx_transport_open(struct uxrCustomTransport * transport);
bool cubemx_transport_close(struct uxrCustomTransport * transport);
size_t cubemx_transport_write(struct uxrCustomTransport* transport, const uint8_t * buf, size_t len, uint8_t * err);
size_t cubemx_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err);void * microros_allocate(size_t size, void * state);
void microros_deallocate(void * pointer, void * state);
void * microros_reallocate(void * pointer, size_t size, void * state);
void * microros_zero_allocate(size_t number_of_elements, size_t size_of_element, void * state);
/* USER CODE END 4 */

Then we are going to change the code directly in our StartDefaultTask.

void StartDefaultTask(void *argument)
{/* USER CODE BEGIN 5 *//* Here we give our huart2 interface, and the 4 * transport functions*/rmw_uros_set_custom_transport(true,(void *) &huart2,cubemx_transport_open,cubemx_transport_close,cubemx_transport_write,cubemx_transport_read);/* Here you also give to the allocator the functions* that are going to be used in order to allocate memory etc.*/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;if (!rcutils_set_default_allocator(&freeRTOS_allocator)) {printf("Error on default allocators (line %d)\n", __LINE__);}// Micro-ROS apprcl_publisher_t publisher;std_msgs__msg__Int32 msg;/* The support is the structure that is going to carry all* the information about your Micro-ROS instance * (context, allocator, clock , options)*/rclc_support_t support;// The allocator that we defined earlierrcl_allocator_t allocator;rcl_node_t node;allocator = rcl_get_default_allocator();//create init_optionsrclc_support_init(&support, 0, NULL, &allocator);// create noderclc_node_init_default(&node, "cubemx_node", "", &support);// create publisherrclc_publisher_init_default(&publisher,&node,ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),"cubemx_publisher");msg.data = 0;for(;;){rcl_ret_t ret = rcl_publish(&publisher, &msg, NULL);if (ret != RCL_RET_OK){printf("Error publishing (line %d)\n", __LINE__);NVIC_SystemReset(); // If we cannot publish we restart}msg.data++;osDelay(10);}/* USER CODE END 5 */
}

From this point, your code is ready to compile and ready to upload on the MCU. On my MCU compiled with debug mode, the publisher takes one to two second to start publishing. Once your MCU is running and connected to your computer, you will need the Micro-ROS agent. Make sure to source your Micro-ROS ws source microros_ws/install/local_setup.zsh and run the agent ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 (To identify your serial port, you can simply list your /dev/ and check which one appears when you connect your MCU). Your agent should display something like:

[1632668621.125343] info     | TermiosAgentLinux.cpp | init                     | running...             | fd: 3
[1632668621.125450] info     | Root.cpp           | set_verbose_level        | logger setup           | verbose_level: 4
[1632668621.126870] info     | Root.cpp           | create_client            | create                 | client_key: 0x5851F42D, session_id: 0x81
[1632668621.126911] info     | SessionManager.hpp | establish_session        | session established    | client_key: 0x5851F42D, address: 0
[1632668621.142403] info     | ProxyClient.cpp    | create_participant       | participant created    | client_key: 0x5851F42D, participant_id: 0x000(1)
[1632668621.157779] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x5851F42D, topic_id: 0x000(2), participant_id: 0x000(1)
[1632668621.166655] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x5851F42D, publisher_id: 0x000(3), participant_id: 0x000(1)
[1632668621.176929] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x5851F42D, datawriter_id: 0x000(5), publisher_id: 0x000(3)

Here we see that a node connects and that it create a publisher. Now your MCU topic is available in your ROS2 and you can simply echo it.

:: ~ » ros2 topic echo /cubemx_publisher
data: 123
---
data: 124
---
.
.
.

You can find the complete example here: GitHub - Guillaumebeuzeboc/Micro-ROS-stm32-basic-pub

If you have any suggestion/question/remark please don’t hesitate to leave a comment.

Share this on →  Tweet 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/204171.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UNIX 文件权限设置的相关函数

函数 umask umask 函数为进程设置文件模式创建屏蔽字&#xff0c;并返回之前的值。这个函数没有出错返回&#xff0c;它不会出错. #include <sys/stat.h> mode_t umask(mode_t cmask); // 返回值&#xff1a;为文件模式创建屏蔽字 其中&#xff0c;参数 cmask 是由 文…

qt 5.15.2 主窗体菜单工具栏树控件功能

qt 5.15.2 主窗体菜单工具栏树控件功能 显示主窗体效果&#xff1a; mainwindow.h文件内容&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QFileDialog> #include <QString> #include <QMessageBox>#inc…

m1通过源码编译xgboost4j的jar

1、下载源码 git clone --recursive https://github.com/dmlc/xgboost cd xgboost 编译xgboost的动态链接库dylib&#xff0c;m1源码编译xgboost的动态链接库dylib文件 2、编译XGBoost的jar文件&#xff1a; A、如果没有安装maven可以通过以下命令进行安装&#xff0c;如果安…

【开发技能】-解决visio交叉线(跨线)交叉点弯曲问题

问题 平时工作中使用visio作图时&#xff0c;经常会遇到交叉线在相交时会形成一个弯曲弓形&#xff0c;这十分影响视图效果。可以采用下面的方法消除弓形。 方法 第一步&#xff1a;菜单栏--设计---连接线 第二步&#xff1a;选中这条交叉线---点击显示跨线 最终问题得到解决…

基于ssm学校运动会信息管理系统论文

摘 要 在当今社会上&#xff0c;体育运动越来越普及&#xff0c;参与运动会的人越来越多&#xff0c;但是目前对运动会信息管理还是处于手工记录的时代&#xff0c;这远远满足不了现在用户需求&#xff0c;因此建立一个运动会信息管理系统已经变的非常重要。 本文重点阐述了学…

16个UI设计小规则,但是却能产生巨大影响

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 文章目录 1.使用空间对相关元素进行分组2.保持一致3.确保外观相似的元素功能相似4.创建清晰的视觉层次5.删除不必要的样式6.有目的地使用颜色7.确保界面元素的对比…

漫步者开放式耳机怎么样?南卡、漫步者开放式耳机哪个好?

现在开放式耳机的市场越来越混杂&#xff0c;我们作为消费者在挑选的时候&#xff0c;一定要找准需求点才能把踩坑几率降到最低。实在不会挑选的也不要紧&#xff0c;我最近入了2款目前市面最畅销的百元款开放式耳机&#xff1a;南卡OE CC和漫步者comfo fit&#xff0c;亲身上耳…

resnet 图像分类的项目

1. 项目文件 文件下载资源&#xff1a;resnet 图像分类的项目代码 本章利用reset34 作图像分类&#xff0c;包括计算训练集和测试集的loss、accuracy曲线&#xff0c;对训练好的网络在训练集测试集上求混淆矩阵 data 文件为训练集测试集&#xff0c;图像按照文件夹摆放inferenc…

55.MQ高级特性

目录 一、RabbitMQ部署指南。 1&#xff09;单机部署。 1.1.下载镜像 1.2.安装MQ 2&#xff09;安装DelayExchange插件。 2.1.下载插件 2.2.上传插件 2.3.安装插件 2.4.使用插件。 3&#xff09;集群部署。 3.1.集群分类 3.2.获取cookie 3.3.准备集群配置 3.4.启…

MATLAB将动画演示以及将过程保存为gif动态图片

平时想要做一个动画图片来演示&#xff0c;本人一般有两种方法&#xff1a; 一种是截很多张图之后&#xff0c;将这些图片合成为一张gif动画&#xff1b; 另一种就是录屏再制作成gif&#xff0c;我一般是录下视频之后&#xff0c;使用QQ影音&#xff0c;里面的影音工具箱有一个…

2021年度大题:灰太狼的密码

分析&#xff1a;本题主要使用的是素数进行输出&#xff0c;然后难点是如何按照题目要求格式输出。 思路&#xff1a; 第一&#xff1a;我们可以先让素数存给一个一维数组&#xff0c;至于存多少个素数&#xff0c;是矩阵n*n个&#xff0c;控制数量用计数器count即可&#xf…

汽车电子 -- CAN文件格式ASC

Vector提供了两种记录数据格式的格式规范&#xff1a;BLF和ASC。 先讲讲ASC。 参看&#xff1a;图文详解CAN Log文件 - ASC文件格式 一、ASC文件格式 在Vector提供的 CAN_LOG_TRIGGER_ASC_Format.pdf 提取码&#xff1a;ltjv 文件中&#xff0c;规定了CANoe/CANalyzer ASC记…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之linux存储管理(3)》(19)

《Linux操作系统原理分析之linux存储管理&#xff08;3&#xff09;》&#xff08;19&#xff09; 6 Linux存储管理6.4 Linux 的分段和分页结构6.4.1Linux 的分段结构6.4.2 Linux 的三级分页结构6.4.3 内核页表和进程页表 6 Linux存储管理 6.4 Linux 的分段和分页结构 本节主…

微服务实战系列之Redis

前言 云淡天高&#xff0c;落木萧萧&#xff0c;一阵西北风掠过&#xff0c;似寒刀。冬天渐渐变得更名副其实了&#xff0c;“暖冬”的说法有点言过其实了。——碎碎念 微服务实战系列之Cache微服务实战系列之Nginx&#xff08;技巧篇&#xff09;微服务实战系列之Nginx微服务实…

多屏模式输入法可以正确切换屏幕展示原理剖析

背景 hi&#xff0c;粉丝朋友们&#xff1a; 近期有个学员问到了一个输入法相关问题。刚好梳理了一下输入法相关的在多屏模式的一个展示流程&#xff0c;这里做个记录&#xff0c;也相当于深入理解窗口相关的一篇干货blog。 如上面两幅图展示&#xff0c;输入法可以自由自在显…

谁登榜? 2023数据安全平台神兽企业

在数字经济的浪潮中&#xff0c;数据安全已成为企业发展的关键支撑。2023年8月&#xff0c;CSA大中华区启动数据安全平台神兽企业调研&#xff0c;得到了众多网络安全综合厂商、数据安全专业厂商、云服务提供商、用户单位的广泛关注和积极参与。 历时4个月&#xff0c;CSA大中…

Java 线程池到底是如何复用线程的

原理概述 其实 Java 线程池的实现原理很简单&#xff0c;说白了就是一个线程集合 workerSet 和一个阻塞队列 workQueue。 当用户向线程池提交一个任务时&#xff0c;线程池会先将任务放入 workQueue 中。workerSet 中的线程会不断的从 workQueue 中获取线程然后执行。当 work…

多人聊天Java

服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{ public static ServerSocket server_socket; public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []ar…

性能调优入门

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、性能定律和数理基础 1.三个定律法则 (1)帕累托法则 我它也被称为 80/20 法则、关键少数法则&#xff0c;或者八二法则。人们在生活中发现很多…

Ubuntur编译ROS报错:error PCL requires C++14 or above

ubuntu20.04 编译ROS包 报错&#xff1a; error&#xff1a; PCL requires C14 or above&#xff1a; 修改Cmakelists.txt文件&#xff1a; set&#xff08;CMAKE_CXX_STANDARD 14&#xff09; 再次编译成功.