現在學術界最實用的STM32和ROS機器人的串口通信方案,一般人我不告訴他
全網最實用的STM32和ROS機器人的串口通信方案(大量網友調用成功)
具體協議大致如下,易讀、易調用、易拓展、易更改。
源碼文件:進入下面公眾號:小白學移動機器人,發送:串口通信升級。即可獲得。
本方案解決的問題:解決以STM32做ROS機器人底層驅動的串口通信問題。
為什麼要寫篇文章?:
最近發現越來越多的小夥伴走入ROS機器人的領域,而ROS機器人與底層驅動的串口通信問題,是大家學習路上的一個難題。很多小夥伴對STM32單片機並不熟悉,對串口通信的理解並不透徹,自己去解決這個問題,費時費力,最後也可能沒有好的結果,並且這又不是大多數學習ROS機器人的重點。最後發現網上也沒有很好的教程(也可能是我沒找到),所以,這裡根據本人的開發經歷,給大家提供一種高效、穩定、易用的ROS機器人與STM32串口通信的常用方案。
如果不想了解細節的朋友,可以只看下面方案介紹和方案快速使用部分,關於方案的原理就不用花時間思考了,但是還是希望大家對細節有敬畏之心。
本方案提供的API:(最基礎的ROS機器人需要的協議)
STM32向ROS發送左輪實時輪速、右輪實時輪速、實時角度、預留控制位。
ROS向STM32發送左輪設定速度、右輪設定速度、預留控制位
本方案優勢:
經測試,長期穩定運行
保證數據準確率極高
頻率50HZ左右,可更高,根據自己發送頻率設置
易用,引入相關頭文件即可,低耦合
------------------------------------------------華麗麗的分界線--------------------------------------------
方案介紹:
本方案將數據開頭加入數據頭,數據尾部加入數據循環冗餘校驗和數據尾,將數據打包發送,確保數據的正確性,避免出現一些無法察覺的問題。同樣根據STM32和Linux系統配備相應的數據解析協議。
本方案STM32下位機依托USART1編寫的收發協議,ROS上位機依托boost::asio編寫的收發協議。串口並不一定是串口1,可以更改,但是需要程序變更一些內容(很容易,程序中有標記共三處)。
本方案巧妙的使用共用體的特性,進行數據解析,(也就是無需使用數據分離技術解析數據)。關於共用體,你只需要知道以下幾點:
.C語言的一種機制,結構體內不同成員共享內存的機制,(即內存地址一致)
.同一時刻,只能訪問其中的一個成員
.不同成員,按照成員類型的性質進行內存訪問
不理解的小夥伴,可以看下圖,有直觀的理解即可。有圖有真相
溫馨提示:從左向右讀圖。
-----------------------------------------------華麗麗的分界線--------------------------------------------
方案快速使用:
硬體環境準備:(必須)
STM32串口+TTL轉USB模塊(CH340)+Linux硬體設備
線路連接:(有圖有真相)
STM32下位機軟體使用介紹:
首先是STM32串口參數的配置:(這裡配置代碼和相關例程都一致)
·波特率=115200
·數據長度=8位
·停止位=1個
·奇偶校驗位=無
·硬體數據流控制=無
其次是函數使用說明,封裝函數如下圖:
這裡做簡單說明:
函數usartReceiveOneData(int *p_leftSpeedSet,int *p_rightSpeedSet,unsigned char *p_crtlFlag),填入地址參數作數據獲取,使用時放在相應串口的中斷服務函數中即可。如這裡使用的串口1,如下圖所示:
函數usartSendData(short leftVel, short rightVel,short angle,unsigned char ctrlFlag),填入需要發送的數據變量作發送,使用時放入指定頻率的循環里使用,每次發送一次數據,最好延時10-15ms,下位機發送和上位機接收都需要時間(時間和串口波特率有關)。我使用的如下圖所示:
其餘的兩個函數是被上面兩個函數調用的,這裡就不多說了。
注意:
在外部引用函數時,注意引用頭文件#include "mbotLinuxUsart.h"
小夥伴在編譯時,可能出現#include "mbotLinuxUsart.h"文件下 sys.h不存在,原因是使用的不是正點原子的例程,此時將#include 替換為各自版本的配置頭文件,如果不清楚,就在其他.h文件中複製粘貼已有的頭文件,關於stm32的
ROS上位機軟體使用介紹:(PC)
看圖說話,下面共有四個函數,看函數名和參數就可以理解用途。
首先是調用頭文件#include "mbot_linux_serial.h",然後進行初始化串口
在程序初始化的時候調用serialInit()函數,內置串口參數和下位機串口參數一致。
然後就是在調用writeSpeed(double RobotV, double YawRate,unsigned char ctrlFlag)函數,參數是機器人線速度和角速度,也就是/cmd_vel的數據。將機器人的需要設定的速度下發到下位機。
最後就是調用readSpeed(double &vx,double &vth,double &th,unsigned char &ctrlFlag)函數,這裡使用的引用,輸入存放機器人線速度、角速度、角度的變量即可。為了發布機器人里程計用的。
注意:
這裡需要兩個參數根據自己的機器人進行更改,ROBOT_LENGTH機器人真實輪間距(從左側輪子中心到右側輪子中心的距離),ROBOT_RADIUS機器人輪間距的一半。
文中boost::asio::serial_port sp(iosev, "/dev/mbot");的設備名字是我的串口的設備名字,小夥伴可以根據自己的進行更改,例如,/dev/ttyUSB0。
到這裡大家肯定都可以愉悅的使用了。如果想知道細節,請往下看。
-------------------------------------------華麗麗的分界線-----------------------------------------------
方案的原理解釋:
此方案用的是共用體的思路,上面小夥伴們也都對共用有個大致的了解。這是一種按照共用體內成員的數據類型進行內存訪問的特性,不同數據類型按照自己的類型訪問內存。上位機和下位機的原理是一致的。都定義了數據頭、數據尾的常量,和收發共用體。
下位機發送的數據協議:上位機發送的數據協議:
STM32的串口接收原理:每接收到一個位元組就會觸發一次中斷,我這裡採用在串口的中斷服務函數中進行數據接收的解析,具體函數體現在receiveTo103()
根據上位機發送的協議進行判斷解析,詳見代碼,注釋清晰。
Linux上位機采用ASIO,ASIO不僅支持網絡通信,還能支持串口通信。
這裡采用boost::asio::write(sp, boost::asio::buffer(buf));發送數據
使用boost::asio::read_until(sp, response, "\r\n",err);
copy(istream_iterator(istream(&response)>>noskipws),
istream_iterator(),buf);
獲取數據,再具體的細節需要見源碼解釋了。腦子裡的思想就是把相應的數據放到相應的位置,沒有數據解析概念,對應的字符數據存好後,就可以通過另外一個成員訪問了。
我自己在今年年初錄製了一套還比較系統的入門單片機教程,想要的同學找我拿就行了免費的,私信我就可以哦~點我頭像黑色字體加蚣重呺也能領取哦。