一种异种网络Modbus软件网关的实现

2015-01-26 14:13杨国栋高云岭
物联网技术 2015年1期
关键词:吞吐量

杨国栋+高云岭

摘 要:针对Modbus网关大部分产品为硬件实现成本高,可扩展性差且功能单一的问题,提出了一种在基于软件实现Modbus网关的方法。该方法支持异种网络设备拓扑架构,支持多进程处理进一步提高Modbus协议的吞吐量。同时在嵌入式Linux和Arm硬件平台架构上对该方法的正确性进行了检测验证。

关键词:Modbus;软件网关;异种网络;吞吐量

中图分类号:TP273    文献标识码:A     文章编号:2095-1302(2015)01-00-04

0  引  言

Modbus协议作为一种在工业控制领域广泛使用的总线协议,其有着标准、开放,支持多种电气接口,以及帧格式简单、紧凑、通俗易懂等优点。据不完全统计,自Modbus协议1979年面世以来,截止2007年,其已被应用在了超过1 000万个设备节点中。

由于Modbus协议本身支持TCP和RTU两种链路连接方式。对于TCP,其基于以太网为物理连接链路。而对于RTU,一般基于RS 232或者RS 485作为物理链路连接。对于Modbus设备节点的组网,通常会基于同种物理链路,基于TCP方式的组网,可以使用以太网交换机来完成。而对于RTU方式的组网,RS 485通过双绞线直接串接在一起即可。

但由于实际应用场景中,通常会结合两种网络的优点。如以太网传输速度快,具有高吞吐率的特点,RS 485具有组网简单,传输距离长的特点。通常采用Modbus硬件网关来结合两种网络组成异种网络拓扑结构。但硬件网关具有接口数目固定,成本高,不便扩展等缺点。

本文针对这些实际应用和产品维护期间遇到的问题,设计实现了一种针对异种网络的,设置灵活,性能可靠,易扩展,低成本的软件网关实现方法。

1  总体架构设计

Modbus协议通常用在如油田、车间等有多设备需要进行组网且有复杂工况的环境下。多台上位机可以通过RJ45连接到以太网交换机,其通过1502端口发送标准的TCP数据包到以太网交换机。运行有Modbus网关的Modbus Server连接到以太网交换机,其接收Modbus TCP数据请求并分析目的地址后将该数据请求分发到对应的Modbus Server中。数据分发时,组件对应的RS 485数据包并通过485总线传递数据。具体结构如图1所示。

图1  Modbus异种网络组网拓扑图

一种在实际生产环境中经常会见到的用例是:在油田监控网络中,上位机运行于监控室监控各个油井抽油机的状态。而Modbus Server作为安装在每一个油井抽油机上的监控装置用向采集油井状态并向上位机汇报。运行有Modbus网关的Modbus Sever则可作为井场主监控装置起到一个数据转发的作用。由于油井之间的距离长度通常会超过100 m,因此采用485串行物理链路的方式会更便于油井采集器之间的组网。而各个油井设备的数据汇聚到了主采集器之后,其过大的数据量对于485串行链路而言负担较重,容易丢失数据。因此主采集器采用以太网物理链路与上位机连接。

1.1  网关结构

Modbus网关运行于Modbus Server中,可根据配置文件来配置为是否启动网关。启动了网关的Modbus Server本身和其它Modbus Server设备一样,也可以提供数据采集功能。

为了能接收多个上位机的数据请求,运行了Modbus网关的Modbus Server会启动一个支持多路输入的Socket服务器用于监听上位机的TCP数据请求。对于请求本机地址的数据,将直接返回相关数据。而对于其它Modbus Server地址的数据请求,将被网关中的数据分发器Dispatcher通过启动一个独立进程的方式分发到Sub-Modbus Server中。为保证数据多个数据请求之间不会在485总线网络中造成冲突,在数据分发器启动的多个数据处理进程和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网关中在向串行链路设备转发数据时的设备地址就保存在单元标识符中。TCP通信链路下,ADU组成为:

TCP MODBUS ADU = 249 B+ MBAP (7 B) = 256 B

对于串型链路通信来说,其地址域为一个字节长度。而差错校验部分存储的数据通过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个数据项,但实际而言,数据的大小规格限制和事务处理的功能码是相关联的。在本实现中,取工业控制领域常用的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服务器监听来自上位机的Modbus客户端的请求。由于会存在多台上位机,socket服务器在设计中需考虑可同时接受多个TCP请求。而对于TCP请求,在一条链路已经建立以后,来自同一台上位机的再次请求应不需要再次进行链路的建立。

首先对于一个未建立过连接的TCP请求,需要为该请求创建必要的工作环境并保存环境。考虑到网关的处理能力,对于允许的最大连接数将通过配置文件进行读取。

// 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 */

}   }   }

}

}

}

而对于一个已经建立好的连接,则需要调用转发函数将其转发到对应的子设备中去。对于目的地址为网关设备本身的,需要根据上位机的请求,将网关设备本身采集到的数据返回给上位机或者完成对应的写数据操作。在对于网关设备本身的操作中,由于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  转发模块设计

数据转发模块首先会启动一个独立的进程并在该进程中完成数据转发的全部过程。由于数据转发的过程中,可能会有其它上位机的数据请求再次到来并启动一个进程通过485总线向下位机传递数据,因此在任意一个进程通过485总线传输数据时,需对该总线进行上锁。同2.1节中设计一样,此处采用信号量完成该工作。

网关运行过程中,由于父进程可能会随时退出,在数据转发子进程中需监控父进程信息。如父进程退出,则数据转发子进程也应退出从而避免成为僵尸进程。核心代码如下:

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  数据转发流程

3  功能验证

以AT91RM9200为硬件平台,以Linux 3.8为内核以及基于Busybox 1.2.0组件的根文件系统为软件平台作为Modbus服务器的测试平台。上位机为普通PC,运行Ubutntu 12.04。基于本文中图一搭建测试网络结构。验证的主要过程如下:

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网关服务器发送Modbus数据请求。

3.3  验证结果

在Ubuntu 12.04 上位机开始执行Modbus,以TCP方式向Modbus网关服务器分别发送读、写数据请求。测试Modbus网关收到了信息并进行了数据转发,而对应的子Modbus服务器也收到了从Modbus网关服务器发送的485数据格式的数据请求。测试结果如图7所示。

图7  调试信息采集和集成测试

测试重点完成了两项验证,其一,上位机发送的数据被Modbus网关所收到并进行了转发;其二,子Modbus服务器收到了Modbus网关的数据请求。

4  结  语

本文主要描述了一种异种网络Modbus软件网关的设计与实现,考虑了多种实际工作中的应用场景。结合了485物理链路和以太网物理链路的优点,可以应用在多任务、多设备的复杂网络拓扑中。同比较目前常见的硬件网关而言,其低成本、易扩展的特点具有非常现实的积极意义。而在油田中部署的油井监控系统也充分验证了本系统的设计与实现。

参考文献

[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.

猜你喜欢
吞吐量
2019年6月长三角地区主要港口吞吐量
2018年6月长三角地区主要港口吞吐量
2017年12月长三角地区主要港口吞吐量
2018年10月长三角地区主要港口吞吐量
2017年11月长三角地区主要进港口吞吐量
2017年10月长三角地区主要港口吞吐量
2017年6月长三角地区主要港口吞吐量
2017年4月长三角地区主要港口吞吐量
2017年3月长三角地区主要港口吞吐量
2016年10月长三角地区主要港口吞吐量