王瀟 盧如意 李博
(第七一五研究所,杭州,310023)
姿態(tài)傳感器顯控軟件是連接計(jì)算機(jī)終端與傳感器的橋梁,其將控制指令發(fā)送給傳感器并使計(jì)算機(jī)終端接收到測(cè)量數(shù)據(jù),使整個(gè)測(cè)量系統(tǒng)構(gòu)成回路。以傳統(tǒng)的MFC(Microsoft Foundation Classes)方法開發(fā)復(fù)雜的圖形界面,需要程序員編寫大量的代碼,對(duì)控件的實(shí)現(xiàn)需要調(diào)用底層的作圖函數(shù)進(jìn)行繪制,開發(fā)時(shí)間長。而Qt具有跨平臺(tái)性能[1],可以一次編寫多處編譯,具有良好的封裝機(jī)制、友好的信號(hào)-槽連接事件驅(qū)動(dòng)機(jī)制,并提供Qt Designer圖形界面開發(fā)工具[2],可進(jìn)行拖拽式的界面控件排布,便于程序開發(fā)。本文介紹了一種使用 Qt的姿態(tài)傳感器顯控軟件設(shè)計(jì)方法,以較小的代碼量以及較短的開發(fā)周期實(shí)現(xiàn)了計(jì)算機(jī)終端與姿態(tài)傳感器的控制指令及測(cè)量信息的交互,以及測(cè)量數(shù)據(jù)實(shí)時(shí)顯示保存的功能需求。
本文所使用的姿態(tài)傳感器通過 RS485串口與外部設(shè)備通信,可同時(shí)上傳偏航角、俯仰角、橫滾角以及溫度數(shù)據(jù),將其封裝在一個(gè)15 Byte數(shù)據(jù)包中。測(cè)量數(shù)據(jù)通信協(xié)議如表1所示。
表1 姿態(tài)傳感器測(cè)量數(shù)據(jù)通信協(xié)議
若干個(gè)姿態(tài)傳感器由下位單片機(jī)串聯(lián)在RS485通信總線上,共用一個(gè)串口與顯控終端通信,通過姿態(tài)傳感器的通信地址尋址通信,即可同時(shí)測(cè)量一個(gè)陣列中各節(jié)點(diǎn)處的姿態(tài)數(shù)據(jù),上傳的測(cè)量數(shù)據(jù)即為若干個(gè)15 Byte數(shù)據(jù)包的拼接,非傳感器通信地址的命令幀將不予響應(yīng)。顯控軟件在打開串口建立串口通信后即發(fā)送開始測(cè)量指令,串聯(lián)在一起的若干個(gè)傳感器即可按照給定的頻率上傳測(cè)量結(jié)果數(shù)據(jù)。顯控軟件解析數(shù)據(jù)包,可得到連接的傳感器數(shù)量并顯示測(cè)量結(jié)果數(shù)據(jù)與圖線。
姿態(tài)傳感器顯控軟件根據(jù)功能組成劃分為串口通信模塊、圖形顯示模塊與數(shù)據(jù)存儲(chǔ)模塊,如圖1所示。
圖1 姿態(tài)傳感器顯控軟件架構(gòu)圖
串口通信模塊使控制指令及測(cè)量結(jié)果根據(jù)相關(guān)通信協(xié)議進(jìn)行封包或解析[3],并以數(shù)據(jù)幀的形式進(jìn)行上傳與下發(fā)。該模塊使用Qt封裝的QSerialPort串口控件[4],其提供主要接口函數(shù)如表2所示。
表2 QSerialPort控件接口函數(shù)
圖形顯示模塊將從串口獲取的測(cè)量數(shù)據(jù)顯示在界面中并繪制成圖線。該模塊使用 Qt提供的QGraphicsView 控件[5],其依靠 QGraphicsView-QGraphicsScene-QGraphicsItem的三級(jí)機(jī)制繪圖:View為“畫板”,Scene為“畫布”,Item即為繪制在“畫布”上的圖形。圖形顯示區(qū)域采用 QMdiWidget的多子窗口顯示機(jī)制,由測(cè)量數(shù)據(jù)包解析結(jié)果獲取傳感器數(shù)量并生成對(duì)應(yīng)數(shù)量的子窗口,可采用平鋪(tile)或?qū)盈B(cascade)的方式同時(shí)顯示所有子窗口,或者以選項(xiàng)卡的形式最大化某一子窗口。這部分內(nèi)容將在第3節(jié)介紹。
數(shù)據(jù)存儲(chǔ)模塊將測(cè)量數(shù)據(jù)實(shí)時(shí)存儲(chǔ)到本地的CSV 文件中[6]。該模塊封裝了 Qt的 QFile類與QTextStream類,以實(shí)現(xiàn)數(shù)據(jù)文件的存儲(chǔ)。
軟件的UML類圖如2所示。圖形顯示模塊由PaintArea類構(gòu)成,其為繼承自QGraphicsView的子類,嵌入在MesFigDisArea類中,它的類對(duì)象作為后者成員變量,一起構(gòu)成測(cè)量數(shù)據(jù)及圖線的顯示控件。DMCCom_Array類為主界面類,其包含了串口通信模塊與數(shù)據(jù)存儲(chǔ)模塊,由一個(gè)QList裝入若干MesFigDisArea類對(duì)象,可同時(shí)顯示多個(gè)傳感器的測(cè)量結(jié)果。
圖2 姿態(tài)傳感器顯控軟件UML類圖
軟件運(yùn)行流程如圖3所示。在以給定參數(shù)配置打開串口之后,與下位機(jī)建立通信并發(fā)送上數(shù)指令,在狀態(tài)欄顯示串口狀態(tài)。在接收到下位機(jī)第一次上傳的數(shù)據(jù)包之后進(jìn)行解析。首先,如果數(shù)據(jù)包長度為單個(gè)傳感器數(shù)據(jù)包長度整數(shù)倍,則判斷為正確數(shù)據(jù)包,不符合條件的直接剔除。對(duì)于正確數(shù)據(jù)包,遍歷數(shù)據(jù)包的每一個(gè)字節(jié)尋找0xAA、0x55的幀頭,檢測(cè)幀頭后第4個(gè)字節(jié)的指令位是否為0x31的反饋標(biāo)識(shí)判斷是否為有效數(shù)據(jù)包,剔除不符合反饋標(biāo)識(shí)的數(shù)據(jù)包;對(duì)于有效數(shù)據(jù)包,計(jì)算幀頭后續(xù)第4~13個(gè)字節(jié)的檢驗(yàn)和判斷是否為正確數(shù)據(jù)包。對(duì)于每個(gè)幀段都滿足以上條件的正確數(shù)據(jù)包,根據(jù)幀頭數(shù)量得到下位機(jī)所串聯(lián)的傳感器數(shù)量,據(jù)此初始化出相應(yīng)數(shù)量的子窗口,默認(rèn)以平鋪的方式顯示在主界面的多窗口顯示區(qū)域中,并更新傳感器列表及狀態(tài)欄中的傳感器數(shù)量。此后,根據(jù)通信協(xié)議給定的字節(jié)順序以及分辨率解析每個(gè)幀段的數(shù)據(jù)位,得到各項(xiàng)測(cè)量數(shù)據(jù)并在界面中顯示、保存。對(duì)于下位機(jī)后續(xù)上傳的數(shù)據(jù)包,同樣根據(jù)以上方法判斷數(shù)據(jù)包的正確性,剔除錯(cuò)誤數(shù)據(jù)包,解析出正確數(shù)據(jù)包的測(cè)量值,并在界面中更新顯示。軟件會(huì)記錄持續(xù)測(cè)量時(shí)間以及測(cè)量數(shù)據(jù)上傳次數(shù)并在界面中顯示。
圖3 姿態(tài)傳感器顯控軟件流程圖
軟件主圖形界面見圖 4,左側(cè)區(qū)域用作串口參數(shù)設(shè)置及操作、測(cè)量計(jì)數(shù)顯示、傳感器列表顯示以及測(cè)量結(jié)果存儲(chǔ)操作。其中,以一個(gè) QListWidget控件顯示由數(shù)據(jù)包解析到的傳感器列表,并與右側(cè)測(cè)量結(jié)果顯示區(qū)域聯(lián)動(dòng)。主界面右側(cè)以一個(gè)QMdiWidget控件顯示測(cè)量結(jié)果。主界面下方狀態(tài)欄可顯示當(dāng)前串口狀態(tài)以及檢測(cè)到的傳感器數(shù)量。
偏航角、俯仰角、橫滾角與溫度測(cè)量值顯示子窗口界面如圖5所示。界面上方顯示4個(gè)測(cè)量數(shù)值,右側(cè)以4個(gè)QGraphicsView小控件顯示曲線對(duì)應(yīng)的顏色圖例。下方的白色區(qū)域?yàn)轱@示曲線圖的QGraphicsView控件。每個(gè)傳感器均獨(dú)立地以一個(gè)子窗口顯示測(cè)量值及圖線。
圖4 姿態(tài)傳感器顯控軟件主界面
圖5 測(cè)量值顯示子窗口
建立串口通信后,顯控軟件向姿態(tài)傳感器發(fā)送“開始測(cè)量“指令,使之以應(yīng)答模式或者廣播模式工作。顯控軟件收到傳感器通過串口上傳的測(cè)量數(shù)據(jù)包,按照通信協(xié)議進(jìn)行解析,解算出偏航角、俯仰角、橫滾角與溫度,獲取當(dāng)前時(shí)間后在相應(yīng)控件中顯示并保存到本地文件。同時(shí),顯控軟件將偏航角、俯仰角、橫滾角與溫度換算為 QGraphicsView的場(chǎng)景中的坐標(biāo)值并繪制出曲線圖。
使用QSerialPort串口控件類,需要注意的是在調(diào)用 open()函數(shù)打開類對(duì)象的串口時(shí)須使用COMMTIMEOUTS結(jié)構(gòu)體對(duì)象來設(shè)置串口類對(duì)象的超時(shí)。在設(shè)置完串口波特率、數(shù)據(jù)位等參數(shù)并設(shè)置好超時(shí)后即在計(jì)算機(jī)與傳感器之間建立了串口通信。
控制指令同樣以數(shù)據(jù)幀的形式發(fā)送,使用一個(gè)QByteArray類對(duì)象,以 append()函數(shù)依次壓入 16進(jìn)制的指令字節(jié),然后將 QByteArray類對(duì)象作為串口類對(duì)象write()函數(shù)的實(shí)參調(diào)用即可發(fā)送控制指令給傳感器。
串口接收到數(shù)據(jù)后,將會(huì)觸發(fā)QSerialPort串口類對(duì)象的readyRead()信號(hào)函數(shù)?;赒t的信號(hào)-槽事件驅(qū)動(dòng)體制,將readyRead()信號(hào)與用于讀取數(shù)據(jù)的自定義槽函數(shù)通過connect()函數(shù)連接即可使顯控軟件做出讀取到串口數(shù)據(jù)后的響應(yīng)動(dòng)作。在自定義槽函數(shù)中,通過串口類對(duì)象的readAll()將從串口獲取的字節(jié)數(shù)組賦給QByteArray類對(duì)象,使用一個(gè)8位無符號(hào)整型數(shù)據(jù)作為元素的 QList容器存入QByteArray類對(duì)象中的各個(gè)字節(jié)以便進(jìn)行后續(xù)的解析工作[7]。
將反饋數(shù)據(jù)包存入 QList容器后,以容器的size()函數(shù)判斷數(shù)據(jù)包的長度,其值應(yīng)為單個(gè)傳感器反饋的測(cè)量結(jié)果數(shù)據(jù)包長度的整數(shù)倍,即 15 Byte的整數(shù)倍,若不滿足該條件則認(rèn)為數(shù)據(jù)錯(cuò)誤并剔除。反之,將QList容器作為實(shí)參傳入數(shù)據(jù)包解析函數(shù),查看每個(gè)15 Byte幀段的首兩個(gè)字節(jié)是否為0xAA 0x55的雙字節(jié)數(shù)據(jù)包幀頭、每個(gè)幀段的第 5 Byte是否為 0x31的反饋標(biāo)識(shí)、計(jì)算每個(gè)幀段第 4~13 Byte的檢驗(yàn)和與第14 Byte是否吻合來檢驗(yàn)數(shù)據(jù)包的正確性。同時(shí)滿足以上三個(gè)條件方為正確的測(cè)量結(jié)果幀段。剔除錯(cuò)誤數(shù)據(jù)包,對(duì)于正確結(jié)果將第6~13 Byte的偏航角、俯仰角、橫滾角與溫度數(shù)據(jù)以高字節(jié)在前、低字節(jié)在后的順序換算為 10進(jìn)制的整型數(shù)據(jù),再乘以給定的分辨率得到相應(yīng)的測(cè)量值。以一個(gè)QList
在收到測(cè)量數(shù)據(jù)包并解析之后,從QList
圖6 測(cè)量結(jié)果顯示
從下位機(jī)接收到正確數(shù)據(jù)包并解析數(shù)據(jù)后,以獨(dú)立子窗口顯示各傳感器測(cè)量結(jié)果如圖6所示。對(duì)于需要重點(diǎn)關(guān)注的傳感器,可將該子窗口以選項(xiàng)卡的形式最大化顯示。
在顯示并繪制測(cè)量值及圖線的同時(shí),數(shù)據(jù)存儲(chǔ)模塊將測(cè)量結(jié)果以CSV文件的格式保存在彈出對(duì)話框選定的路徑中。存儲(chǔ)模塊以QFile類對(duì)象建立CSV文件,以QTextStream類對(duì)象將測(cè)量結(jié)果以文本流的形式輸出到目標(biāo)文件中。CSV文件本質(zhì)上是以逗號(hào)分隔的TXT文本文件,在以文本流輸出一個(gè)測(cè)量值后跟著輸出一個(gè)逗號(hào),即可實(shí)現(xiàn)以表格形式存儲(chǔ)測(cè)量數(shù)據(jù)。在初次存儲(chǔ)數(shù)據(jù)時(shí),首先建立CSV文件,輸出包含上數(shù)時(shí)間以及各測(cè)量項(xiàng)的表頭,后續(xù)每次保存都按照給定順序輸出即可。軟件可以手動(dòng)保存或者設(shè)定時(shí)間間隔以定時(shí)器進(jìn)行自動(dòng)保存。測(cè)量結(jié)果文件見表3。
表3 測(cè)量結(jié)果CSV文件
本文提出的基于 Qt的姿態(tài)傳感器顯控軟件設(shè)計(jì)思路,靈活調(diào)用 Qt圖形界面庫中高度集成、成熟的串口通信控件與二維圖形繪制控件,在一定程度上減輕了軟件編制難度,以較小的代碼量以及較短的開發(fā)周期實(shí)現(xiàn)了計(jì)算機(jī)終端與姿態(tài)傳感器的控制指令及測(cè)量信息的交互以及測(cè)量數(shù)據(jù)實(shí)時(shí)顯示、保存的功能需求。