王巖,褚澤帆,符偉杰,唐躍平
(水利部南京水利水文自動(dòng)化研究所水利部水文水資源監(jiān)控工程技術(shù)研究中心,江蘇南京 210012)
移動(dòng)機(jī)器人的控制軟件作為系統(tǒng)的管理主體,承擔(dān)機(jī)器運(yùn)動(dòng)的精準(zhǔn)控制、數(shù)據(jù)的實(shí)時(shí)采集和傳輸、用戶指令的有效執(zhí)行等任務(wù),軟件平臺(tái)的優(yōu)劣直接關(guān)系到整個(gè)機(jī)器人系統(tǒng)能否正常工作[1]。市面上現(xiàn)有的RTOS 雖然在實(shí)時(shí)性要求上有所突破,但是由于其任務(wù)調(diào)度、內(nèi)存管理等模塊本身需要占用一定的內(nèi)存、定時(shí)器等資源,且線程通信復(fù)雜不好掌控,使得在設(shè)計(jì)任務(wù)、分配資源時(shí)要充分小心,尤其在硬件資源緊張的平臺(tái)上如何把握實(shí)時(shí)性和效率平衡的問題更加突出[2]。
針對(duì)以上所提出的設(shè)計(jì)問題,文中設(shè)計(jì)完成了一套通用的軟件控制平臺(tái)[3]URSP(Universal Robort Software Platform)。URSP 以STM32 小型化移動(dòng)機(jī)器人為載體,充分利用軟件分層設(shè)計(jì)思想,各層將所管理的軟硬件內(nèi)容以模塊化方式并列,各模塊之間互不交叉,只由最上層應(yīng)用調(diào)配各層模塊協(xié)同工作。此外,文中提出一套簡化、高效的協(xié)議方案,最終由用戶下達(dá)的用戶幀指令調(diào)度完成各項(xiàng)工作,達(dá)到運(yùn)動(dòng)的可靠、數(shù)據(jù)傳輸?shù)挠行蛞约跋到y(tǒng)管理的便捷。
URSP 采用分層化管理,從上到下依次劃分為協(xié)議解析層、功能控制層和硬件驅(qū)動(dòng)層,如圖1 所示。每層的主要功能明確,層與層之間通過特定的數(shù)據(jù)協(xié)議進(jìn)行通信,減少了應(yīng)用和硬件驅(qū)動(dòng)間的交互冗余。各層的模塊采用通用的數(shù)據(jù)結(jié)構(gòu)進(jìn)行設(shè)計(jì),即使內(nèi)部的模塊有所變化,也不會(huì)對(duì)其他層造成影響,極大地保證了軟件的可擴(kuò)展性。用戶端以無線方式下達(dá)用戶幀命令,系統(tǒng)調(diào)配根據(jù)用戶端下達(dá)的用戶協(xié)議幀逐層解析執(zhí)行,實(shí)現(xiàn)機(jī)器的各項(xiàng)功能控制。
圖1 URSP總體結(jié)構(gòu)
協(xié)議解析層位于URSP 的最上層,是URSP 系統(tǒng)的調(diào)度和控制中心,向上連接用戶,向下控制機(jī)器人各功能硬件[4]。協(xié)議解析層的主要功能包括:
1)系統(tǒng)初始化及各種軟件資源的創(chuàng)建;
2)接收用戶發(fā)送的協(xié)議數(shù)據(jù)包并存儲(chǔ),檢測(cè)功能控制層的各模塊是否已準(zhǔn)備好,如果是則開始解析協(xié)議數(shù)據(jù)包;
3)將用戶協(xié)議數(shù)據(jù)包解析并轉(zhuǎn)換為協(xié)議層和功能控制層的接口數(shù)據(jù),按照接口數(shù)據(jù)的類型向功能控制層的各模塊分發(fā)命令;
4)收集傳感器、GPS 等數(shù)據(jù)并打包,上傳給用戶程序。
協(xié)議解析層從結(jié)構(gòu)上主要由接收/發(fā)送循環(huán)緩沖區(qū)、接收/發(fā)送fifo、命令流分發(fā)器和傳感數(shù)據(jù)收集器構(gòu)成[5],如圖2 所示。
圖2 協(xié)議解析層功能模塊圖
協(xié)議解析層包含了接收環(huán)形緩沖區(qū)和發(fā)送環(huán)形緩沖區(qū),原始的用戶協(xié)議數(shù)據(jù)包被緩存在接收環(huán)形緩沖區(qū),協(xié)議解析器根據(jù)數(shù)據(jù)包的頭部信息分析用戶命令的類型,數(shù)據(jù)包長度、校驗(yàn)碼等,提取相關(guān)數(shù)據(jù)并轉(zhuǎn)換為所需的內(nèi)部協(xié)議數(shù)據(jù)[6],并添加內(nèi)部控制域的字段,然后通知分發(fā)器提取內(nèi)部接口。用戶協(xié)議解析示意圖如圖3 所示。
圖3 用戶協(xié)議解析示意圖
分發(fā)器在得到已解析轉(zhuǎn)換過的同部接口數(shù)據(jù)后,直接通過幾個(gè)控制字段向功能控制層的對(duì)應(yīng)模塊分發(fā);接收隊(duì)列則存儲(chǔ)由功能控制層上傳的內(nèi)部協(xié)議幀,收集器檢測(cè)并解析內(nèi)部幀,將數(shù)據(jù)重新打包成用戶幀后推送入發(fā)送環(huán)形緩沖區(qū)。
功能控制層由機(jī)器人的各功能硬件組成,功能硬件采用模塊化方式管理,以本URSP 的物理載體輪式救援機(jī)器人為例,功能硬件包括電機(jī)模塊、機(jī)械臂舵機(jī)模塊、云臺(tái)舵機(jī)模塊、各類傳感器模塊、GPS 模塊、探照燈模塊、報(bào)警器模塊等,每個(gè)模塊以統(tǒng)一的結(jié)構(gòu)CFuncModule表示,模塊對(duì)象定義示意圖如圖4所示。
圖4 模塊對(duì)象定義示意圖
所有的功能模塊都使用統(tǒng)一的形式定義[7],不僅使功能控制層與協(xié)議解析層或硬件驅(qū)動(dòng)有了統(tǒng)一的交流接口,而且有利于模塊的增減,一定程度上提高了軟件的復(fù)用性。除上面所述的通用的數(shù)據(jù)和接口外,功能模塊可根據(jù)自身的需要?jiǎng)?chuàng)建控制算法數(shù)據(jù)和接口,采用PrivateData 訪問這一區(qū)域。功能算法控制是各功能模塊的核心任務(wù),對(duì)各功能硬件進(jìn)行調(diào)配和管理,URSP實(shí)現(xiàn)的功能算法控制示意圖如圖5所示。
圖5 功能控制示意圖
硬件驅(qū)動(dòng)層直接和MCU 交互,具有硬件平臺(tái)依賴性,文中實(shí)驗(yàn)平臺(tái)選用STM32F103 單片機(jī),以官方固件庫為基礎(chǔ)[8],將硬件驅(qū)動(dòng)層組織起來。為簡化硬件配置,屏蔽底層硬件驅(qū)動(dòng)細(xì)節(jié),將各片內(nèi)外設(shè)的驅(qū)動(dòng)參數(shù)以宏定義形式集中在一個(gè)文件中,可快速有效地完成MCU 硬件配置。主要的硬件驅(qū)動(dòng)配置參數(shù)如表1 所示。
表1 硬件驅(qū)動(dòng)配置參數(shù)
硬件驅(qū)動(dòng)各功能模塊以統(tǒng)一接口與功能控制層交互,如1.2 節(jié)描述,功能控制層通過將read/write 綁定到硬件驅(qū)動(dòng)的外部接口實(shí)現(xiàn)控制硬件的目的[9]。
用戶協(xié)議分為上行協(xié)議和下行協(xié)議[10],用戶協(xié)議的設(shè)計(jì)原則是在滿足控制功能的基礎(chǔ)上盡可能簡化以達(dá)到節(jié)省內(nèi)存、優(yōu)化控制的目的,上、下行協(xié)議各字段的定義如表2 所示。
表2 用戶上、下行協(xié)議
協(xié)議各字段定義如下:
1)幀頭:用于用戶和機(jī)器人的同步,以3 字節(jié)的0xFF 表示;
2)目的地址:當(dāng)協(xié)議下行時(shí),目的地址即為機(jī)器人地址;當(dāng)協(xié)議上行時(shí),為用戶端地址;
3)數(shù)據(jù)域長度低字節(jié)和高字節(jié):用于表示數(shù)據(jù)域的字節(jié)長度,以此數(shù)據(jù)長度可直接從數(shù)據(jù)域中取出所需數(shù)據(jù);
4)命令位/數(shù)據(jù)類型:在下行協(xié)議中,命令位表示機(jī)器所要進(jìn)行的運(yùn)行控制(例如前進(jìn)、后退、云臺(tái)左轉(zhuǎn)等);在上行協(xié)議中,數(shù)據(jù)類型表示機(jī)器人所上傳的數(shù)據(jù)類型,包括溫度、距離、GPS 位置等;
5)數(shù)據(jù)域:在下行協(xié)議中,數(shù)據(jù)域中的數(shù)據(jù)表示運(yùn)動(dòng)控制的具體參數(shù),如前進(jìn)的速度、機(jī)械臂上抬的角度等;在上行協(xié)議中,數(shù)據(jù)類型表示機(jī)器人上傳的具體有效數(shù)據(jù);
6)Crc 高低字節(jié):是通過Crc 校驗(yàn)算法從幀頭開始到數(shù)據(jù)域最后一個(gè)字節(jié)結(jié)束所計(jì)算出的Crc 碼,分兩個(gè)字節(jié)存放,用于機(jī)器人或用戶校驗(yàn)。
內(nèi)部協(xié)議主要為協(xié)議解析層數(shù)據(jù)封裝以及協(xié)議解析層和功能控制層的信息交互[11],如表3 所示。
表3 內(nèi)部協(xié)議
內(nèi)部協(xié)議同樣分為上下行數(shù)據(jù),上行數(shù)據(jù)為各傳感器模塊、GPS 模塊等的采集信息,下行數(shù)據(jù)則為用戶協(xié)議的命令解析[12],內(nèi)部協(xié)議各字段定義如下:
1)BlockId:用于標(biāo)識(shí)功能控制層的各模塊,每個(gè)功能模塊有唯一的BlockId 標(biāo)識(shí);
2)方向:0 表示從協(xié)議解析層到功能控制層;1 表示從功能控制層到協(xié)議解析層;
3)命令:解析用戶協(xié)議的命令位,配合內(nèi)部協(xié)議的硬件索引下達(dá)正確的命令;
4)硬件索引:用于表示硬件模塊的標(biāo)識(shí),例如電機(jī)模塊有4 個(gè),則索引為0~3;
5)控制參數(shù):解析用戶協(xié)議的數(shù)據(jù)域,將其轉(zhuǎn)換為硬件索引所標(biāo)識(shí)的硬件參數(shù),例如電機(jī)轉(zhuǎn)速、云臺(tái)轉(zhuǎn)動(dòng)角度等;
6)數(shù)據(jù)域:是一個(gè)8 bits 的指針,指向要上傳數(shù)據(jù)Buffer 的首地址,只在數(shù)據(jù)上傳時(shí)會(huì)用到。
考慮到MCU 硬件平臺(tái)的差異性,在功能控制層并未定義協(xié)議,只定義了對(duì)應(yīng)的接口指針去訪問各硬件驅(qū)動(dòng),以便快速移植驅(qū)動(dòng)庫[13]。
一個(gè)完整的數(shù)據(jù)流處理周期包括下行數(shù)據(jù)流處理和上行數(shù)據(jù)流處理。下行數(shù)據(jù)流處理由用戶根據(jù)控制需求發(fā)送,無線數(shù)據(jù)經(jīng)過WIFI 模塊轉(zhuǎn)發(fā),通過UART送入到STM32單片機(jī)[14]。單片機(jī)以中斷方式接收數(shù)據(jù),根據(jù)用戶協(xié)議的幀頭和Crc 校驗(yàn)碼斷定協(xié)議幀的開始和結(jié)束,然后將數(shù)據(jù)幀推入到協(xié)議解析層的環(huán)形緩沖區(qū),并更新環(huán)形緩沖區(qū)的相關(guān)標(biāo)志信息。一旦協(xié)議解析層檢測(cè)到環(huán)形緩沖區(qū)中有新的協(xié)議幀數(shù)據(jù),就立即從中取出,根據(jù)各字段解析用戶協(xié)議幀所表示的意義[15]。之后將解析出的數(shù)據(jù)轉(zhuǎn)換為內(nèi)部協(xié)議數(shù)據(jù),添加入BlockId、硬件索引等字段后,將內(nèi)部幀數(shù)據(jù)推入到內(nèi)部幀接收隊(duì)列中,并通知分發(fā)器工作,然后解析器可立即投入到下一次的解析。分發(fā)器接收到解析器的通知后,從隊(duì)列頭取出一個(gè)數(shù)據(jù)幀,只需要根據(jù)其BlockId 就可以將內(nèi)部數(shù)據(jù)幀分發(fā)到相應(yīng)的功能模塊進(jìn)行處理。功能模塊得到已經(jīng)解析完的內(nèi)部協(xié)議幀,直接調(diào)用自身的算法處理接口進(jìn)行底層控制參數(shù)計(jì)算,完成后即可將相關(guān)參數(shù)write到對(duì)應(yīng)的片內(nèi)外設(shè),由此完成一次協(xié)議幀的下發(fā)處理,工作流程如圖6所示。
圖6 下行數(shù)據(jù)流處理
上行數(shù)據(jù)流處理針對(duì)傳感器數(shù)據(jù)和GPS 信息,上行數(shù)據(jù)流的開啟仍由用戶啟動(dòng),相關(guān)的硬件模塊在用戶請(qǐng)求獲取數(shù)據(jù)后才開始工作,在用戶通知數(shù)據(jù)獲取完成后結(jié)束工作,最大程度地降低系統(tǒng)功耗。硬件驅(qū)動(dòng)在獲取傳感器數(shù)據(jù)后會(huì)將數(shù)據(jù)信息地址和數(shù)據(jù)長度打包成一個(gè)DataEntry,并將其加入到一個(gè)全局鏈表中,由于GPS 數(shù)據(jù)長度達(dá)數(shù)百字節(jié),系統(tǒng)設(shè)定全局鏈表的長度在一定范圍內(nèi)[16]。而各類數(shù)據(jù)的生成速度可能快于功能控制層的讀取速度,當(dāng)DataEntry 的數(shù)量超過鏈表規(guī)定的長度時(shí),需要將最舊的DataEntry 釋放,這樣保證用戶端拿到的數(shù)據(jù)相對(duì)是比較新的。功能控制模塊read 讀取DataEntry,然后打包成內(nèi)部協(xié)議,推送到發(fā)送隊(duì)列[17]。收集器在檢測(cè)到發(fā)送隊(duì)列中有協(xié)議幀后,從中取一幀解析并再封裝成用戶幀,推送到發(fā)送環(huán)形緩沖區(qū),然后啟動(dòng)UART向用戶端發(fā)送,用戶隨時(shí)可以下達(dá)命令,中止傳感器數(shù)據(jù)的上傳,上行數(shù)據(jù)流處理流程如圖7所示[18-19]。
圖7 上行數(shù)據(jù)流處理流程
文中以STM32為硬件平臺(tái),介紹了通用軟件控制平臺(tái)(URSP)的設(shè)計(jì)主體,該軟件平臺(tái)規(guī)避了傳統(tǒng)RTOS 運(yùn)行所需的資源耗費(fèi),以分層化模塊化構(gòu)建了協(xié)議解析層、功能控制層和硬件驅(qū)動(dòng)層,給出分層協(xié)議的方案,簡化數(shù)據(jù)流的處理細(xì)節(jié),并成功應(yīng)用在水利信息采集機(jī)器人平臺(tái)上,取得了良好的技術(shù)經(jīng)濟(jì)效益。