使用cubemx+HAL库将rosserial移植到STM32
-
- rosserial的作用
- 需要实现的功能
- 移植步骤
- 我创建的工程
- 没有积分的可以到github下载
rosserial的作用
使用过ros的话都会了解过ros特殊的通信机制,通过话题的发布和订阅来进行通信。
有时候我们需要从PC端的串口与单片机进行通信,我曾试着直接调用串口与STM32进行数据传输,但是数据非常不好处理,自己定协议也是一个非常麻烦的事情,还经常出现一些奇怪的乱码,如果能在STM32上模仿ros直接发布或订阅话题并能够使用ros的数据类型就好了。
我曾在ros的官网上看到有将rosserial移植到arduino的教程,当移植成功后可以将arduino当成一个节点直接订阅ros通信网络上的话题,也可以直接往ros的通信网络发布话题,但是坑爹的是ros官网没给STM32的移植教程。
网上也有一些大佬用标准库移植过,但写的不明不白,我花了大量精力将大佬的代码看懂并强行移植到HAL库,最后确实能用,但代码看起来非常恶心。直到今天我发现了一种非常简单的移植方法,可以将代码搞得非常漂亮,为了让大家少踩坑,我将移植过程写出来供大家参考。
需要实现的功能
我们从PC端发布一个话题为pc_to_stm32的std_msgs::String类型数据,单片机订阅该话题,并将该数据通过话题stm32_to_pc发布出来。
移植步骤
- 首先我们建一个CUBEMX工程
- 选好你的芯片的型号,我的单片机是F103ZET6
- 分别配RCC ,SYS,TIM2,USART
- 配时钟树,这里我配64MHZ
- 配USART波特率,这里我配57600,因为这是serial_node的默认参数,方便,你要是改别的也行,但是serial_node也要改对应了
- 配串口DMA
- 串口中断开启
- 配置工程路径与参数
- 点击OK后CUBEMX将生成32的工程,但先别急着打开,先关掉
- 我们将RosLibs文件夹复制粘贴到我们的工程文件夹下,这个文件夹是arduino移植过程生成的,里面储存的是ROS的各种消息类型,方便我们以后调用的,我们这次移植的目的就是为了能直接调用这些数据类型。这个文件夹可以从我分享的文件获得,或者参考官网的arduino教程获取。
- 我们在MDK-ARM目录建立三个文件
- 将刚才加进来的文件添加进32的工程
- 如果成功添加那我们就能从工程看到所添加的文件
- 由于ros数据类型是以类的方式写好的,属于C++的特性,所以我们的32工程需要进行C与C++的混编,同时我们添加数据类型文件的路径
- 在mainpp.cpp文件创建订阅节点和发布节点,与ros在PC的方式完全一样,mainpp.h文件需要注意添加使用C编译规则编译
- 然后我们在main.c文件调用mainpp.cpp的函数,记住要添加mainpp.cpp的头文件
- 编译后我们可以看到编译是通过的,但是有15个警告,不要慌,这是由于keil对C++的支持不太好,但是不影响我们使用。我们需要将警告屏蔽掉,因为不能让别人以为是由于我们代码写的不好而出现的警告
- 忽略警告后重新编译,又是一段 0 Error(s), 0 Warning(s)的完美代码
- 我们将代码烧录到单片机并将串口怼到PC测试,看能不能出现我们想要的效果,首先不要忘了提高串口权限,然后运行rosserial节点
sudo chmod 777 /dev/ttyUSB0
rosrun rosserial_python serial_node.py
- 监听话题 /stm32_to_pc(此时/stm32_to_pc没有任何数据)
rostopic echo /stm32_to_pc
- 发布话题 /pc_to_stm32 ,同时我们可以看到STM32通过话题/stm32_to_pc将数据转反回来,到这里就说明我们移植成功了。
rostopic pub -r 1 pc_to_stm32 std_msgs/String hello
- 通过rqt查看节点我们可以这样理解,节点serial_node作为STM32与ros的桥梁,主要负责数据的转化。
- 如果移植到STM32别的系列主要改动下面几个地方(以F407ZGT6为例)
24.BUG解决
由于我用来讲解的单片机是F103ZET6,受限于硬件问题,就是tim2用于计数那个寄存器是16位的,最大值只能到65535,我们用了它的数据作为rosserial协议的时间戳的数据源,当计数超出65535时候就会溢出,这导致了我们的时间戳匹配不上,从而会重新连接,并报出Unable to sync with device; possible link problem or link software version mismatch such as hydro rosserial_python with groovy Arduino这个错误,你们会发现没10秒左右就出重新连接一次就是这个原因,但是这并不影响实际的通信效果,只是非常恶心罢了,如果你用了别的型号的单片机,你可以检查一下这个寄存器的容量,有的是32位的,比如F407ZGT6就是32位的,根据下图修改就可以修复这个小bug了
我创建的工程
rosserial
没有积分的可以到github下载
github下载地址