遲 穎,何 杰,耿 斌,周 剛,張 楊
(1.中國環境監測總站,北京 100012;2.光大城鄉再生能源(淮安)有限公司,江蘇 淮安 223001;3.南京柯普士儀器科技有限公司,江蘇 南京 210012)
隨著網絡技術的不斷發展,移動應用端越來越多地被人們認可,Android平臺所開發的APP應用軟件更是被應用到了各個場合。由于工業控制領域具有特殊性,考慮到其穩定性、安全性、復雜性,一直少有相關方面的應用。積極開展移動設備在工業控制方面的應用,在未來5G平臺下,將有非常廣闊的前景[1]。
連續排放氣態污染物監測系統(Continuous Emission Monitoring System,CEMS),應用于垃圾發電企業的煙氣監測,為核對該系統的數據準確性,企業需要接受各級主管部門比對檢查。受委托的檢測機構持便攜式檢測儀進行采樣比對,會涉及兩套系統數據的對比,對比工作的流程如下:(1)同步。同步兩套系統的時間;(2)采集。在線實時采集數據;(3)比對。比對兩套系統同一時間段內的各項數據。由于兩套系統的輸出設備(數據顯示終端)距離較遠,一方在0 m層的分析小屋內,另一方在煙囪約35 m處的采樣口,數據的實時核對必須兩地要有人員通過通信工具進行有效溝通。探討拉近一端數據,實現單人單地即時比對,提高工作效率,減少人員數量,具有顯著的效果。
Modbus是一種通信協議,廣泛應用于工業控制領域各個系統間,其協議版本較常見的有串口和以太網兩大類,是一個主站master/從站slave架構的協議?;谠搮f議的設備之間進行互連互通,首先,要確定主站與從站。根據協議約定,Modbus協議中主從站的關系為一對多型,即主站只能有一臺,而從站可以擁有地址范圍在0~247(其中0為廣播地址)的多臺設備(通信點),主站發出數據請求消息(查詢代碼),從站對主站發送的命令做出響應。主站接收從站響應過來的數據,完成一次數據通信。
Modbus RTU與Modbus TCP同屬于Modbus通信協議,但RTU通信更多地在傳輸介質上采用雙絞線、光纖,同時,以二進制數據方式直接傳送數據,而TCP通信采用的傳輸介質更多的是常見的網線,也可以通過無線傳輸,將每字節二進制數據轉換為固定兩位16進制字符串,再依次串聯在一起,以TCP碼形式進行數據傳送?,F場的工業應用中,常見于RTU轉TCP的應用,以便于搭載網絡通信[2]。
OSI開放系統互連參考模型,定位于應用層與TCP/IP協議族通信的中間軟件抽象層就是Socket通信接口,將復雜的TCP/IP協議族隱藏在Socket接口后面。Socket的服務端(Server)建立服務傾聽socket,同時,等待并接收請求,Socket的客戶端(Client)創建連接socket向服務端發送請求,此時,服務端接收到客戶端的請求創建連接socket。通信時,客戶端OutputStrean輸出流到服務端輸入InputStream,服務端OutputStream輸出流到客戶端的輸入流InputStream。結束通信只需要關閉雙方的socket即可。依靠該協議,Modbus的通信可以搭建完成一個數據交互的鏈接,完成雙方的通信過程。
Android平臺的通信基于無線網絡技術,通信網絡可以是基于路由器的互聯網,可以借助于互聯網實現數據的超遠距離訪問;也可以是基于AP熱點的點對點的網絡(或者藍牙方式),可以在有限定的條件下確保數據安全的訪問。
系統分為三大模塊:(1)系統配置模塊,用于配置和存儲通信用IP地址、端口號、數據地址、數據長度、數據內容等信息,并保存在本地數據庫中,以備下次應用時直接使用。(2)柱狀圖顯示模塊,清晰、直觀地顯示可以實時比對各組分在同一時間內的差異。(3)折線圖顯示模塊,根據實際現場的比對需求,可以定義折線圖的采集時間間隔和采集數據量,折線圖針對單一組分的總體趨勢具有很好的顯示效果,增加了計算平均值、最大值和最小值的功能,完全貼合現場所要參比的數據。
系統的硬件搭配:現場數據的采集,需要通過CEMS系統自帶的modbus協議端口進行二次打包轉發,一般為PLC通信口。為實現無線組網通信,還必須將雙方置于該網絡環境中,本研究采用西門子S7-200 SMART SR40 CPU模塊卡,485通信端口直接連接了一款串口轉無線WiFi的工業通信設備,在配置時采用默認的AP模式,設置好串口協議、AP熱點狀態下所需要的通信IP和端口,完成硬件配置[3]。
數據庫以原始DB數據庫為基礎,單獨一個配置界面(見圖1),用以存儲、更改、調用通信所涉及的各項參數。為適配現場的無線通信設備,增加了通信方式的選擇,在選擇Serial串口方式通信時,只是代表該通信查詢代碼是以RTU方式發送的16進制字符串,該字符串查詢代碼以及返回的數據代碼不同于TCP/IP格式,需要注意的是該方式并不表示要去接一個真正的串口。

圖1 配置界面
Android平臺下,以手機為適配機,需要做Modbus主機的響應機制。根據協議規定,以傳送8個有效浮點數據為例,發送16進制的查詢代碼:00 01 00 00 00 06 02 03 00 00 00 10,其中,02表示為從站號是2,03表示modbus功能碼03,即讀取保持寄存器地址,10表示是查詢的數據長度為十進制的16。將其定義為一個byte字節數組發送出去,客戶端響應該查詢得到的也是一個16進制的字符串:00 01 00 00 00 23 02 03 20 00 00 40 00 00 00 40 40 00 00 40 A0 00 00 40 E0 00 00 41 00 00 00 41 40 00 00 40 40 00 00 42 84,其中,20表示是后面的數據長度為10進制的32個,是實際的數據內容。
在獲取返回的數據串后,需要進行數據的轉換,將其轉換為浮點數。Modbus浮點數的存儲格式為SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM,S是符號位,1表示負值;EEE EEEE E表示為指數冪;MMM MMMM MMMM MMMM MMMM MMMM表示為數據位,該數據位缺省了1.需要補上。此時,小數位可以按指數調整:得到一個負的指數就向左移動小數點,得到一個正的指數向右移動小數點。算出小數點左邊和小數點右邊的數,最后得到該浮點數。
核心代碼:
StringbinStr = hex2Bin(hexstr);
Stringsign = binStr.substring(0, 1);
Stringex = binStr.substring(1, 9);
int exint = Integer.parseInt(ex, 2);
Stringmdatastr = binStr.substring(9);
int movebit = exint - 127;
StringBuffersb = new StringBuffer();
for (int i = 0; i < 23; i++) {
if (i == movebit)
sb.append(".");
char b = mdatastr.charAt(i);
sb.append(b);
}
Stringaddstr = "1" + sb.toString();
int sint = addstr.indexOf(".") - 1;
Doubledoublevalue = 0.0d;
for (int i = 0; i < addstr.length(); i++) {
if (addstr.charAt(i) == '.')
continue;
Doubledtmp = Math.pow(2, sint);
int itmp = Integer.valueOf(addstr.charAt(i) + "");
dtmp = dtmp * itmp;
sint = sint - 1;
doublevalue = doublevalue + dtmp;
}
if (sign.equals("1")) {
doublevalue = 0 - doublevalue;
}
}
以上轉換如果得不到實際對應的數值,那就應該考慮浮點數據的翻轉。按照數據存儲的約定:字節順序模式分為大端數據模式和小端數據模式,是根據數據在內存中的存儲方式來區分的。小端字節順序的數據存儲模式是按內存增大的方向存儲的,即低位在前高位在后;大端字節順序的數據存儲方向恰恰相反,即高位在前,低位在后。據此,只需要重新排列一下一個浮點數所占用兩個寄存器地址位的前后順序,就可以完成數據翻轉。
柱狀圖表的顯示比文字更具有簡潔性,也更加直觀,具體如圖2所示。將讀取到的遠端數據以圖表的形式呈現出來,應用MPAndroidChart的柱狀圖顯示功能,引入該控件的com.github.mikephil.charting.charts.BarChart包,對其X軸Y軸進行自定義,同時,增加一個以時間為刷新內容的描述項。核心代碼如下:
x軸的定義
xAxis.setValueFormatter (new ValueFormatter () {
private String[] xStrs = new String[]{"CO", "HCL", "NO", "NO2", "SO2", "H2O", "Temp", "FlOW"};
@Override
public String getFormattedValue(float value) {
int position = (int) value;
if (position >= 8) {
position = 0;
}
return xStrs[position];
}
});
時間描述
Description description = new Description ();
description.setEnabled (true);
t = new SimpleDateFormat ("yyyy年MM月dd日 HH:mm:ss");
description.setText (t.format (new Date ()));
chart.setDescription (description);

圖2 柱狀圖表的顯示
相較于柱狀圖,折線圖可以突出一組數據的變化趨勢,將各組數據以不同的顏色標注出,既可以單組數據顯示,又可以多組數據比對顯示,實際第三方比對數據時常常會取一個時間段內的數據,以下拉框選擇的方式將所需時間段以及數據量展現出來,減少人工輸入錯誤,具體如圖3所示。應用引入控件的com.github.mikephil.charting.charts.LineChart包,對其X軸Y軸進行自定義,同時,增加一個數據點位的標記,用以記錄該條數據的詳細信息:當前組分名稱、當前數值、總采集數、當前條數、平均值、最大值、最小值。核心代碼如下:
java.util.Set
String valName = entry.getKey ().trim ();
switch (valName) {
case "co":
coMax = (Double) Collections.max ((List) entry.getValue ());
coMin = (Double) Collections.min ((List) entry.getValue ());
coAverage = getAverage ((List) entry.getValue (), xCount);
break;
case "hcl":
……
}
}
采用java.util.Set

圖3 折線圖顯示
該客戶端應用APP主要基于無線通信,網絡質量好壞直接影響數據的傳輸,實際使用過程中,采用了點對點的通信方式,數據刷新周期為每30 s一次,完全可以滿足現場通信監控比對的需求。工業現場端Modbus通信是常規通信協議,無論是集控室DCS端,還是現場儀表端,都有此類接口,在確保數據安全的情況下,充分利用此類接口與移動端對接,提高了整體的工作質量和效率,具有極大的實用價值。