摘要 運動底盤是移動機器人的重要組成部分,不像激光雷達、IMU、麥克風、音響、攝像頭這些通用部件可以直接買到,很難買到通用的底盤。一方面是因為底盤的尺寸結構和參數是要與具體機器人匹配的;另一方面是因為底盤包含軟硬體整套解決方案,是很多機器人公司的核心技術,一般不會隨便公開。出於強烈的求知欲與學習熱情 ...
摘要
運動底盤是移動機器人的重要組成部分,不像激光雷達、IMU、麥克風、音響、攝像頭這些通用部件可以直接買到,很難買到通用的底盤。一方面是因為底盤的尺寸結構和參數是要與具體機器人匹配的;另一方面是因為底盤包含軟硬體整套解決方案,是很多機器人公司的核心技術,一般不會隨便公開。出於強烈的求知欲與學習熱情,我想自己DIY一整套兩輪差分底盤,並且將完整的設計過程公開出去供大家學習。說乾就乾,本章節主要內容:
2.stm32主控軟體設計
上一節搭建好了底盤的stm32主控硬體,現在就來說說怎麼開發配套的stm32軟體。關於建立stm32工程、使用stm32開發庫、stm32軟體調試方法等基礎知識就不多說了,有需要的可以查閱相關資料學習,我覺得http://www.openedv.com《正點原子》的開發資料寫的還可以。我就直接從底盤控制的項目入手,直接進行項目中各個功能需求開始分析講解,如圖11,是我的底盤控制stm32工程項目。
(圖11)底盤控制stm32工程項目
2.1.電機控制
電機控制分為兩個部分(電機轉向控制、電機轉速控制),這些都集成在了電機驅動晶元TB6612FNG裡面,所以只需要用單片機的IO口產生控制轉向的高低電平和控制轉速的PWM波就能實現。
首先,初始化IO口作為輸出腳,用於產生高低電平輸出來控制轉向,實例代碼如圖12。
(圖12)電機轉向控制IO口初始化
然後,用通用定時器TIM4的通道CH1和CH2分別產生兩路PWM輸出用於兩個電機的轉速控制,定時器預設引腳分配如圖13。
(圖13)stm32定時器通道預設引腳分配
初始化通用定時器TIM4的通道CH1和CH2為PWM輸出,實例代碼如14。
(圖14)電機轉速控制IO口初始化
最後,將電機轉向和速度控制的操作封裝在一個函數中,便於其它地方調用,實例代碼如圖15。
(圖15)電機轉向和速度控制封裝
2.2.編碼器數據讀取
編碼器對底盤來說至關重要,一方面底盤通過編碼器的反饋進行PID閉環速度控制,另一方面底盤通過編碼器進行航跡推演得到里程計用於後續的定位與導航等高級演算法中。這裡用到的編碼器是正交編碼器,所以直接使用通用定時器的輸入捕獲中的編碼器模式來讀取編碼器。採用通用定時器TIM2的通道CH1和CH2捕獲encoder1的A相和B相脈衝,採用通用定時器TIM3的通道CH1和CH2捕獲encoder2的A相和B相脈衝。
先初始化TIM2作為編碼器encoder1的捕獲,實例代碼如圖16。
(圖16)初始化TIM2作為編碼器encoder1的捕獲
然後,將讀取編碼器計數值的操作封裝在一個函數中,便於其它地方調用,實例代碼如圖17。
(圖17)讀取編碼器encoder1計數值封裝
最後,編寫TIM2計數溢出時的中斷處理函數,實例代碼如圖18。
(圖18)TIM2計數溢出中斷處理函數
同理可得TIM3捕獲encoder2的代碼實現,這裡就不在贅述了。
2.3.串口數據收發
串口2是數據介面,負責接收上位機發送過來的控制指令,同時將編碼器值返回給上位機;串口1是debug介面,負責接收上位機發送過來的版本信息請求、PIDm預設值恢復、PID值設定等調試指令,同時將程式中的debug列印信息返回給上位機。但是在底盤正常工作時,只需要連接串口2;串口1是預留出來給有需要自己動手修改PID參數使用的。
首先,配置串口1,先對串口1的輸出進行printf函數列印支持,實例代碼如圖19。
(圖19)串口1的輸出進行printf函數列印支持
然後,初始化串口1,實例代碼如圖20。
(圖20)初始化串口1
最後,編寫串口1接收中斷處理函數,此函數主要進行對上位機發過來的數據進行協議解析,實例代碼如圖21。
(圖21)串口1接收中斷處理函數
接下來,介紹串口2,初始化串口2,實例代碼如圖22。
(圖22)初始化串口2
然後,將串口2發送數據的操作封裝到函數中,便於其它地方調用,實例代碼如圖23。
(圖23)串口2發送數據封裝
最後,編寫串口2接收中斷處理函數,此函數主要進行對上位機發過來的數據進行協議解析,實例代碼如圖24。
(圖24)串口2接收中斷處理函數
到這裡,串口有1和串口2的數據發送與接收都編寫好了,依據我們定義的usart2數據通信協議和usart1調試通信協議,上位機就可以編寫對應的程式來跟底盤的串口2和串口1進行通信了。關於通信協議的具體內容,將在後續做展開。
2.4.電機速度PID控制
我在底盤中採用的是增量型PID演算法,編程涉及到的數學表達式有3個,分別是:
e(k) = target_value - current_value
delta_u(k) = Kp*[e(k)-e(k-1)] + Ki*e(k) + Kd*[e(k)-2*e(k-1)+e(k-2)]
u(k) = u(k-1) + delta_u(k)
將這3個數學表達式封裝到函數中,便於其它地方調用,實例代碼如圖25。
(圖25)串口2接收中斷處理函數
電機1與電機2採用同樣的PID演算法,所以電機2的PID演算法代碼實現就不贅述了。關於PID參數的整定方法,將在後續做展開。
2.5.周期性控制
通過上面的講解,各個模塊的驅動代碼都準備就緒了,現在需要產生一個周期性的過程,在裡面實現編碼器計數值採樣、PID控制等具體實現。這裡採用定時器TIM1產生一個周期性的中斷,在中斷處理函數中實現各模塊的具體操作。
首先,配置定時器TIM1,實例代碼如圖26。
(圖26)配置定時器TIM1
然後,編寫中斷處理函數,實例代碼如圖27。
(圖27)TIM1中斷處理函數
2.6.stm32主控軟體整體框圖
通過上面的講解,對底盤控制的stm32程式實現有了一定的瞭解,接下來就來做一個總結。
先來看看main()函數實現,如圖28。
(圖28)main()函數實現
結合上面TIM1中斷處理函數,不難發現,整個stm32程式的執行過程:
a.在main()函數中初始化各個模塊;
b.TIM1中斷處理函數周期性的讀取編碼器值、反饋獲取的編碼值、PID控制;
c.剩下的就是串口1和串口2的通信交互。
具體stm32主控軟體整體框圖如圖29。
(圖29)stm32主控軟體整體框圖
需要說明的是,在周期性迴圈體中,要首先讀取編碼器的值,來保證嚴格的等間隔採樣。
後記
如果大家對博文的相關類容感興趣,或有什麼技術疑問,歡迎加入下麵的《SLAM+語音機器人DIY》QQ技術交流群,一起討論學習^_^