楊國棟+高云嶺
摘 要:針對Modbus網關大部分產品為硬件實現成本高,可擴展性差且功能單一的問題,提出了一種在基于軟件實現Modbus網關的方法。該方法支持異種網絡設備拓撲架構,支持多進程處理進一步提高Modbus協議的吞吐量。同時在嵌入式Linux和Arm硬件平臺架構上對該方法的正確性進行了檢測驗證。
關鍵詞:Modbus;軟件網關;異種網絡;吞吐量
中圖分類號:TP273 ? ?文獻標識碼:A ? ? 文章編號:2095-1302(2015)01-00-04
0 ?引 ?言
Modbus協議作為一種在工業(yè)控制領域廣泛使用的總線協議,其有著標準、開放,支持多種電氣接口,以及幀格式簡單、緊湊、通俗易懂等優(yōu)點。據不完全統(tǒng)計,自Modbus協議1979年面世以來,截止2007年,其已被應用在了超過1 000萬個設備節(jié)點中。
由于Modbus協議本身支持TCP和RTU兩種鏈路連接方式。對于TCP,其基于以太網為物理連接鏈路。而對于RTU,一般基于RS 232或者RS 485作為物理鏈路連接。對于Modbus設備節(jié)點的組網,通常會基于同種物理鏈路,基于TCP方式的組網,可以使用以太網交換機來完成。而對于RTU方式的組網,RS 485通過雙絞線直接串接在一起即可。
但由于實際應用場景中,通常會結合兩種網絡的優(yōu)點。如以太網傳輸速度快,具有高吞吐率的特點,RS 485具有組網簡單,傳輸距離長的特點。通常采用Modbus硬件網關來結合兩種網絡組成異種網絡拓撲結構。但硬件網關具有接口數目固定,成本高,不便擴展等缺點。
本文針對這些實際應用和產品維護期間遇到的問題,設計實現了一種針對異種網絡的,設置靈活,性能可靠,易擴展,低成本的軟件網關實現方法。
1 ?總體架構設計
Modbus協議通常用在如油田、車間等有多設備需要進行組網且有復雜工況的環(huán)境下。多臺上位機可以通過RJ45連接到以太網交換機,其通過1502端口發(fā)送標準的TCP數據包到以太網交換機。運行有Modbus網關的Modbus Server連接到以太網交換機,其接收Modbus TCP數據請求并分析目的地址后將該數據請求分發(fā)到對應的Modbus Server中。數據分發(fā)時,組件對應的RS 485數據包并通過485總線傳遞數據。具體結構如圖1所示。
圖1 ?Modbus異種網絡組網拓撲圖
一種在實際生產環(huán)境中經常會見到的用例是:在油田監(jiān)控網絡中,上位機運行于監(jiān)控室監(jiān)控各個油井抽油機的狀態(tài)。而Modbus Server作為安裝在每一個油井抽油機上的監(jiān)控裝置用向采集油井狀態(tài)并向上位機匯報。運行有Modbus網關的Modbus Sever則可作為井場主監(jiān)控裝置起到一個數據轉發(fā)的作用。由于油井之間的距離長度通常會超過100 m,因此采用485串行物理鏈路的方式會更便于油井采集器之間的組網。而各個油井設備的數據匯聚到了主采集器之后,其過大的數據量對于485串行鏈路而言負擔較重,容易丟失數據。因此主采集器采用以太網物理鏈路與上位機連接。
1.1 ?網關結構
Modbus網關運行于Modbus Server中,可根據配置文件來配置為是否啟動網關。啟動了網關的Modbus Server本身和其它Modbus Server設備一樣,也可以提供數據采集功能。
為了能接收多個上位機的數據請求,運行了Modbus網關的Modbus Server會啟動一個支持多路輸入的Socket服務器用于監(jiān)聽上位機的TCP數據請求。對于請求本機地址的數據,將直接返回相關數據。而對于其它Modbus Server地址的數據請求,將被網關中的數據分發(fā)器Dispatcher通過啟動一個獨立進程的方式分發(fā)到Sub-Modbus Server中。為保證數據多個數據請求之間不會在485總線網絡中造成沖突,在數據分發(fā)器啟動的多個數據處理進程和Sub-Modbus Servers之間,會存在一個總線鎖。Modbus網關結構如圖2所示。
圖2 ?Modbus網關結構
1.2 ?目的地址傳遞
Modbus協議定義了一個與基礎通信層無關的簡單協議數據單元(PDU)。特定總線或者網絡上的Modbus協議映射能夠在應用數據單元(ADU)上引入一些附加域,如地址域或差錯校驗域。Modbus通用數據幀如圖三所示。
圖3 ?Modbus通用數據幀
一個ADU最大長度為256 B。對于TCP通信鏈路,通常其ADU不包含差錯校驗部分,而會包含一個7 B的Modbus報文頭(MBAP)。MBAP的組成為2 B的事務元標識符,2 B的協議標識符以及2 B的數據包長度和1 B的單元標識符。通常情況下,Modbus網關中在向串行鏈路設備轉發(fā)數據時的設備地址就保存在單元標識符中。TCP通信鏈路下,ADU組成為:
TCP MODBUS ADU = 249 B+ MBAP (7 B) = 256 B
對于串型鏈路通信來說,其地址域為一個字節(jié)長度。而差錯校驗部分存儲的數據通過CRC16算法所得,其數據長度為2 B。因此最大PDU長度為253 B。一個最大長度的ADU組成為:
RS 232 / RS 485 ADU = 253 B + 服務器地址(1 B) + CRC (2 B) = 256 B。
1.3 ?數據包解析
Modbus定義了4種具有不同特征的數據模型,分別是:
(1)離散量輸入,為只讀的單個比特位;
(2)線圈變量,為可讀寫的單個比特位;
(3)輸入寄存器,為只讀的2 B;
(4)輸出寄存器,為可讀寫的2 B。
對于這4種數據,Modbus協議都允許單個選擇65 536個數據項,但實際而言,數據的大小規(guī)格限制和事務處理的功能碼是相關聯的。在本實現中,取工業(yè)控制領域常用的8個功能碼來作為數據網關中處理的數據請求,如下:
0x01 讀線圈
0x02 讀輸入離散量
0x03 讀多個輸出寄存器
0x04 讀多個輸入寄存器
0x05 寫單個線圈
0x06 寫單個寄存器
0x0F 寫多個線圈
0x10寫多個寄存器
以讀多個輸出寄存器為例。讀數據時,請求PDU中需指定輸出寄存器的起始地址和讀取數量。一個讀取輸出寄存器第108到110的3個寄存器的數據如表1所示。
表1 ?讀輸出寄存器
請求 響應
名稱 數值(十
六進制) 名稱 數值(十
六進制)
功能碼 03 功能碼 03
起始地址(高) 00 數據長度 06
起始地址(低) 6B 寄存器值(高)- 108 02
讀取寄存器個(高) 00 寄存器值(低)- 108 2B
讀取寄存器個(低) 03 寄存器值(高)- 109 00
寄存器值(低)- 109 00
寄存器值(高)- 110 00
寄存器值(低)- 110 64
在網關中對數據解析時,對于不同的功能碼,應根據Modbus協議中的數據格式定義來對數據包進行解析。
2 ?模塊功能詳細設計
2.1 ?Socket服務器模塊設計
軟件網關與上位機之間通過TCP進行連接,網關將啟動一個socket服務器監(jiān)聽來自上位機的Modbus客戶端的請求。由于會存在多臺上位機,socket服務器在設計中需考慮可同時接受多個TCP請求。而對于TCP請求,在一條鏈路已經建立以后,來自同一臺上位機的再次請求應不需要再次進行鏈路的建立。
首先對于一個未建立過連接的TCP請求,需要為該請求創(chuàng)建必要的工作環(huán)境并保存環(huán)境??紤]到網關的處理能力,對于允許的最大連接數將通過配置文件進行讀取。
// Clear the reference set of socket
FD_ZERO(&refset);
// Add the server socket
FD_SET(server_socket, &refset);
// Keep track of the max file descriptor
fdmax = server_socket;
for (;;) {
rdset = refset;
select(fdmax+1, &rdset, NULL, NULL, NULL);
// Run through the existing connections looking for data to be read
for (master_socket = 0; master_socket <= fdmax; master_socket++) {
if (FD_ISSET(master_socket, &rdset)) {
if (master_socket == server_socket) {
/* A client is asking a new connection */
memset(&clientaddr, 0, sizeof(clientaddr));
newfd = accept(server_socket, (struct sockaddr *)&clientaddr, &addrlen);
if (newfd == -1) { perror(“Server accept() error”); ?}
else { FD_SET(newfd, &refset);
if (newfd > fdmax) {
fdmax = newfd; ?/* Keep track of the maximum */
} ? } ? }
}
}
}
而對于一個已經建立好的連接,則需要調用轉發(fā)函數將其轉發(fā)到對應的子設備中去。對于目的地址為網關設備本身的,需要根據上位機的請求,將網關設備本身采集到的數據返回給上位機或者完成對應的寫數據操作。在對于網關設備本身的操作中,由于modbus數據通常為由一個獨立的進程采集并存放到共享內存中,因此在操作共享內存時,需使用信號量來保證數據的正確性。
/* An already connected master has sent a new query */
modbus_set_socket(ctx, master_socket);
rc = modbus_receive(ctx, query);
if (rc > 0) {if (query[header_length -1] != config->server_id) {
device_write_hook (query, header_length, config, (share_mm_data *)share_mm);
sem_wait(&sem);
copy_mem_from_sharing (share_mm, mb_mapping); ?// copy memory form sharing mem into modbus mapping area.
sem_post(&sem);
} else {modbus_dispatch (ctx, query, config); } ?// For gateway mode switch
modbus_reply(ctx, query, rc, mb_mapping);}
2.2 ?組包模塊設計
在組建Modbus數據包時, 由于不同的Modbus請求命令其數據包組成結構不相同,因此需根據Modbus請求命令的不同來進行判斷。
組包模塊主要提供2個函數,其定義如下:
int package_read_data (char *data_485, char *data_tcp, int direction);
int package_write_data (char *data_485, char *data_tcp, int direction);
package_read_data函數用于將Modbus的讀數據請求進行TCP數據包和485數據包之間的轉換,根據direction參數的變化來決定轉換的方向。而package_write_data函數則用于將Modbus的寫數據請求進行TCP數據包和485數據包之間的轉換。
對于讀數據,收到的數據包中相關的Modbus功能碼為0x01、0x02、0x03、0x04,其數據復制組包的過程如圖4所示:
圖4 ?讀數據時數據復制包過程
對于寫數據,收到的數據包中相關的Modbus功能碼為0x05、0x06、0x0F、0x10,其數據復制組包的過程如圖5所示:
圖5 ?寫數據時數據復制包過程
2.3 ?轉發(fā)模塊設計
數據轉發(fā)模塊首先會啟動一個獨立的進程并在該進程中完成數據轉發(fā)的全部過程。由于數據轉發(fā)的過程中,可能會有其它上位機的數據請求再次到來并啟動一個進程通過485總線向下位機傳遞數據,因此在任意一個進程通過485總線傳輸數據時,需對該總線進行上鎖。同2.1節(jié)中設計一樣,此處采用信號量完成該工作。
網關運行過程中,由于父進程可能會隨時退出,在數據轉發(fā)子進程中需監(jiān)控父進程信息。如父進程退出,則數據轉發(fā)子進程也應退出從而避免成為僵尸進程。核心代碼如下:
pid=fork();
if (pid == -1) { exit(1); ?}
else if (pid == 0) {
// Child
share_mm= shmat (shmid, 0, 0);
ctx = modbus_new_rtu(config->dev, config->baudrate, config->parity, config->data_bit, config->stop_bit);
package_485_data (query, output);
sem_wait(&sem_485);
send_485_data (output);
sem_post(&sem_485);
while (1) { ? ?// 判斷父進程是否已退出
if (getppid() == 1) { exit(0); ?}
// Wait response
modbus_receive_confirmation(ctx, response);
if (response != -1) { ?break; ?}
}
package_tcp_data (response, output);
send_tcp_data (output);
}
其流程如圖6所示:
圖6 ?數據轉發(fā)流程
3 ?功能驗證
以AT91RM9200為硬件平臺,以Linux 3.8為內核以及基于Busybox 1.2.0組件的根文件系統(tǒng)為軟件平臺作為Modbus服務器的測試平臺。上位機為普通PC,運行Ubutntu 12.04?;诒疚闹袌D一搭建測試網絡結構。驗證的主要過程如下:
3.1 ?客戶端配置
(1)配置服務器IP及Modbus網關IP。假設服務器端IP地址信息為192.168.1.110,運行網關的Modbus網關服務器的IP地址信息為:192.168.1.111。需更改Modbus網關服務器應用程序配置文件/etc/modbus/config.ini文件如下:
[GLOBAL]
type=route
mode=tcp
server_id=1
[NETWORK]
ip_addr=192.168.1.111
(2)將子Modbus服務器通過485線纜連接到Modbus網關服務器。
(3)啟動Modbus網關應用程序。
(4)各子Modbus服務器啟動Modbus服務應用。
3.2 ?服務器端配置
服務器端運行一個封裝了標準Modbus請求的客戶端應用程序即可。通過TCP方式向Modbus網關服務器發(fā)送Modbus數據請求。
3.3 ?驗證結果
在Ubuntu 12.04 上位機開始執(zhí)行Modbus,以TCP方式向Modbus網關服務器分別發(fā)送讀、寫數據請求。測試Modbus網關收到了信息并進行了數據轉發(fā),而對應的子Modbus服務器也收到了從Modbus網關服務器發(fā)送的485數據格式的數據請求。測試結果如圖7所示。
圖7 ?調試信息采集和集成測試
測試重點完成了兩項驗證,其一,上位機發(fā)送的數據被Modbus網關所收到并進行了轉發(fā);其二,子Modbus服務器收到了Modbus網關的數據請求。
4 ?結 ?語
本文主要描述了一種異種網絡Modbus軟件網關的設計與實現,考慮了多種實際工作中的應用場景。結合了485物理鏈路和以太網物理鏈路的優(yōu)點,可以應用在多任務、多設備的復雜網絡拓撲中。同比較目前常見的硬件網關而言,其低成本、易擴展的特點具有非?,F實的積極意義。而在油田中部署的油井監(jiān)控系統(tǒng)也充分驗證了本系統(tǒng)的設計與實現。
參考文獻
[1]李英奇,吳桂初.Modbus-ModbusTCP/IP的網關設計[J]. 微型機與應用, 2013(10):48-50.
[2]翁建年,張浩,彭道剛,等. 基于嵌入式ARM的Modbus/TCP協議的研究與實現[J].計算機應用與軟件,2009,26(10):36-39.
[3] Wikipedia.Modbus[EB/OL]. http://en.wikipedia.org/wiki/Modbus,2013.