孫學華 錢思宇
(南京工業大學電子信息與工程學院,江蘇 南京 210009)
隨著某化工倉儲企業生產經營規模的不斷擴大,不同時期所采用的現場儀表不同往往使得儀表種類越來越多,需要處理的數據量也越來越大。這些數據有的通過PLC控制系統采集,有的甚至還需要人工抄表和手動錄入數據,這不僅造成了工作效率低下,而且還容易導致各個生產區之間的信息彼此孤立,形成一個個信息孤島。信息孤島使得企業的生產管理人員無法及時獲知準確有效的數據并及時做出決策,這在一定程度上影響了企業的生產運營。在工業信息化的大背景下,有必要將各孤立系統的數據進行集成整合,建立實時數據庫系統,從而為上層ERP系統及應用軟件提供準確實時的數據。
由于該企業的大部分儀表還能正常使用,如直接淘汰、更換系統將會造成很大的資源浪費。本文結合該企業的數據采集改造項目,設計實現了一套對全廠生產數據進行集成處理的軟件系統。
罐區實時生產數據主要有儲罐液位、溫度和壓力等,這些原始數據由現場的液位計、多點溫度測量儀、壓力表等獲取。該化工倉儲企業現有一套西門子S7-300 PLC控制系統、2臺AWG-ⅡA型巡檢儀、若干AWG-IB型光電智能液位儀、若干科隆BM100雷達液位計、若干帶通信接口的罐旁指示儀和其他一些溫度、壓力、液位傳感器。這些現場測量儀表有的通過4~20 mA的模擬信號或通信線接入到PLC控制系統中,有的通過帶有通信接口的罐旁指示儀或直接接入到巡檢儀(二次表),其他的則未接入任何系統。
根據現有系統設備的特點,數據采集軟件需實現以下3個功能:與PLC控制系統通信并采集數據、從巡檢儀中采集數據、直接與現場表通信并采集數據。
整個數據采集系統以數據采集為中心,在一臺工控機上運行數據采集程序;從底層采集各部分原始數據,根據相應的計算標準計算體積、儲量等;并通過網絡通信協議將數據轉存到數據服務器。這些數據作為歷史數據存入關系數據庫,為上層的應用提供數據。系統結構圖如圖1所示。

圖1 系統結構圖Fig.1 Structure of the system
由于系統中的設備類型各不相同,它們各自具有不同的通信協議,因此,數據采集程序必須遵循相應的通信規范才能從各種設備中讀到數據。
本系統數據通信解決方案如下。
①與PLC控制系統的通信采用OPC協議。OPC是過程控制數據采集的標準,為目前主流的組態軟件所遵循[1]。西門子的上位機軟件支持OPC標準,并提供OPC Server服務,即只要在客戶端開發OPC Client,就可請求到存放在OPC Server中的過程數據[2]。
②由于OPC標準被大多數自動化廠家所采用,所以部分底層數據采集設備也支持OPC。在通信軟件中開發OPC Server程序,將硬件設備作為OPC的數據源,可直接從底層采集設備中獲取過程數據值。
③與巡檢儀及部分現場儀表的通信采用Modbus協議。巡檢儀及大部分現場設備都支持目前工業領域最流行的通信協議之一的Modbus。通過工控機串口與它們提供的接口相連,即可進行主從方式通信。
④部分不支持通信的采集設備,可將數值轉換為4~20 mA模擬信號,接入到PLC控制系統中,再通過OPC方式采集。
⑤由于OPC服務器很難穿過防火墻進行數據傳輸,所以采集程序與數據服務器及上層應用軟件之間通過UDP協議交換數據[3]。
通過該解決方案,所有的數據都能接入到采集系統,并進行實時準確測量。
主程序分為Modbus通信模塊、OPC通信模塊、UDP通信模塊和數據計算模塊。程序采用多線程技術,將各種數據的接收和發送放在優先級較高的線程中。在數據收發期間,數據的計算處理并不影響主程序的運行。此外,在程序中采用全局內存存放實時采集的數據,以便于數據的快速存取交換。系統主要程序基于VC++實現。
Modbus協議包括ASCII、RTU(遠程終端單元)、TCP等工作模式,本系統采用較高數據傳送密度的RTU通信模式。在該模式下,數據通信一般采用主從方式,主機向從設備發出請求消息;從設備接收到正確消息后就可以發送數據到主機,以響應請求[4]。Modbus RTU消息幀結構如圖2所示,其中,T1-T2-T3-T4為不小于3.5個字符時間的停頓間隔。

圖2 Modbus RTU消息幀結構Fig.2 Structure of the message frame of Modbus RTU
Modbus協議需要對數據進行校驗。串行協議中除有奇偶校驗外,RTU模式還采用16位CRC(循環冗長檢測)校驗。CRC的生成流程具體如下。
① 預置一個16位寄存器為0FFFFH(全1),即為CRC寄存器。
②把數據幀中的第一個字節的8位與CRC寄存器中的低字節進行異或運算,結果存入CRC寄存器。
③將CRC寄存器向右移一位,最高位填以0,最低位移出并檢測其值。
④如果最低位為0,則進行下一次移位;如果最低位為1,將CRC寄存器與一個0A001H進行異或運算。
⑤重復步驟③~步驟④,直到8次移位,這樣就處理完了一個完整的8位數據。
⑥處理下一個8位數據,直到所有的字節處理結束,最終CRC寄存器的值就是CRC的值。
OPC服務器由服務器、組和數據項這3類對象組成[5]。服務器對象具有服務器的所有信息,同時也是組對象的容器。組對象具有本組的所有信息,同時包容數據項。項對象是讀寫數據的最小邏輯單位,項與具體的位號相連[6]。OPC服務器支持自動化接口和定制接口兩種訪問接口。
OPC Client的具體開發流程如下。
①初始化COM庫,當需要調用COM庫時,需使用CoInitializeEx()來為當前線程初始化 COM庫[7]。CoInitializeEx()提供了一個讓用戶可以選擇多線程模式還是單線程模式的參數。

②通過OPC服務器的ProgID查詢CLSID,通過給定的ProgID,采用CLSIDFromProgID()函數從注冊表中查找出對應的類標符。

③創建OPC服務器對象,并查詢OPC服務器對象的IOPCServer接口。通過調用CoCreateInstanceEx()函數,不僅可以在本機中創建COM對象并得到一個接口指針,還可以實現遠程訪問。將MULTI_QI結構體數組中指向IOPCServer接口的元素賦值給變量m_pIServer,以獲取IOPCServer接口,進而可以使用該接口完成對組對象進行創建、刪除、枚舉和獲取當前狀態等操作。

④添加OPC組對象,并查詢IOPCItemMgt接口,通過IOPCServer接口的AddGroup()方法添加組對象,它將返回一個指向OPC組對象IUnknown的指針。通過IUnknown的QueryInterface方法可獲得OPC組對象的IOPCItemMgt接口指針,進而可以使用該接口完成對各項進行添加、刪除和設置參數等操作。

⑤添加項:為保存項的相關屬性值的結構體數組進行賦值。以該結構體數組為參數,用IOPCItemMgt接口的AddItem()方法添加項。

⑥同步讀寫:通過IUnknown的QueryInterface方法,獲得OPC組對象的IOPCSyncIO接口指針。

采用IOPCSyncIO接口的Read()方法,完成同步讀操作。
采用IOPCSyncIO接口的Write()方法,完成同步寫操作。
⑦ 釋放:在程序關閉之前,需要刪除已創建的OPC對象并釋放內存。
首先刪除以下項:

接著釋放OPC組對象的IOPCItemMgt接口和IOPCSyncIO接口,然后刪除OPC組對象:調用服務器對象m_pIServer的RemoveGroup()方法,刪除OPC組對象,再調用Release()釋放服務器資源,最后關閉COM庫。
用戶數據報協議(user data protocol,UDP)是一個簡單的面向數據包的傳輸層協議[8],它所提供的是非面向連接的、不可靠的數據流傳輸。UDP不提供報文到達確認、排序、可靠以及流量控制等功能;它只是將應用程序傳遞給IP層的數據報發送出去,但是并不能保證它們能到達目的地[9]。由于UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,因此,其傳輸速度更快。UDP數據通信格式和數據結構定義如下。
UDP請求數據報格式如圖3所示。

圖3 UDP請求數據報格式Fig.3 Request datagram format of UDP
其中,起始符為字符“#”,ASCII碼為 35(十進制);結束符為回車符,ASCII碼為13;請求位號長度為10 B,為固定長度,位號不足10 B的用空格符補充。定義一個UDP請求數據報可同時打包不超過30個位號。
UDP應答數據報格式如圖4所示。

圖4 UDP應答數據報格式Fig.4 Response datagram format of UDP
其中,起始符為字符“!”,ASCII碼為33(十進制);結束符為回車符,ASCII碼為13;應答位號長度為10 B,為固定長度,位號不足10 B的用空格符補充;返回值長度為20 B,為固定長度,數據不足20 B的用空格符補充;連接符、位號與數據之間用“=”號連接,ASCII碼為61。定義一個UDP應答數據報可同時打包不超過30個位號的數據,數據報總長度不超過990 B。
本系統在MFC中使用CSocket類實現UDP通信。CSocket是對WinSock API的封裝,用于管理通信,使得用戶可以直接避免調用API函數,數據的收發也因此變得簡單。
程序實現時,系統分別構造服務器和客戶端套接字對象,調用套接字對象的Creat()成員函數初始化套接字。調用CSocket類的重載函數OnReceive()響應接收事件;調用 ReceiveFrom(lpBuf,bufLen,RemoteIP,RemotePort,0)接收數據報,并按照協議格式將數據從數據報中取出。按照通信協議將需要發送的數據打包,并調用SendTo(lpBuf,SendStrLen,RemotePort,RemoteIP,0)發送數據報。
該套數據采集軟件的設計與實現,實際上為企業構建了一個實時數據庫系統。程序中采用全局內存共享技術對實時數據進行存取,并采用內存、文件管理、關系數據庫相結合的數據存儲策略,使系統在響應速度、實時數據的共享性和時間一致性方面初步滿足了實時數據庫系統的定義要求[10]。
系統自投用以來運行正常,效果良好,不僅解決了在生產數據管理過程中存在的問題,而且節省了購買SCADA硬件、軟件系統的大筆費用。同時,避免了大量仍能使用的儀表設備的淘汰棄置,具有一定的經濟效益。
[1]蔣近,段斌.基于OPC技術的監控主站實時數據傳輸[J].電力自動化設備,2008,28(9):97-100.
[2]西門子(中國)有限公司自動化與驅動集團.深入淺出西門子S7-300 PLC[M].北京:北京航空航天大學出版社,2004.
[3]牛丹丹,孫學華.貯油罐存量管理系統的研究與實現[J].計算機應用與軟件,2009,26(7):165-167.
[4]邊凌燕.基于CP341模塊的MODBUS協議免驅動應用[J].電氣傳動,2009,39(2):72-75.
[5]李世學,王小進,余光洪.OPC技術及其在SCADA系統中的應用[J].船電技術,2010,30(3):27-29.
[6]徐思成,李增權,郭國選.基于OPC技術和以太網的異構網絡集成[J].儀表技術與傳感器,2011(1):109-110.
[7]陳群.石化企業CIMS基礎數據集成平臺的設計與實現[J].工業控制計算機,2009,22(9):70-74.
[8]李一鳴,任勇毛,李俊.基于UDP的傳輸協議性能比較與分析[J].計算機應用研究,2010,27(10):3906-3910.
[9]周麗娟.基于UDP協議的Socket網絡編程[J].電腦知識與技術,2008,4(7):1867-1868.
[10]楊立保,許忠仁.組態軟件實時數據庫的研究與設計[J].自動化儀表,2009,30(8):19-21.