首页 > 基础资料 博客日记
Java服务开发者眼中的Modbus及设备接入
2024-06-22 12:00:08基础资料围观397次
1、简介
ModBus是一种免费的、易于维护的总线通信协议,广泛应用于工业电子化设备通信中,我们日常接触较为频繁的是RS485协议与ModBus-RTU协议,RS-485为硬件层,ModBus为软件层协议。
各种设备只要遵循该协议,我们就可以按照该协议制定设备数据接入方案。本文主要从一个Java应用开发者初次接入Modbus协议的角度来基本阐述该协议的基本特征,以便在应用中接入该类设备,并从中读取相应的数据,提供相应的开发思路(数据网关)。
本文只提供相应的开发思路,面向有一定基础的开发人员,具体的代码实现可GPT。
2、特点
从使用角度来说,Modbus具有免费、简单轻便、易于开发等特征。而从技术角度来看,Modbus在通信模式上主要为主从模式(master/slave),或者理解为半双工模式(双方在一条总线上进行数据交互,同一时刻只允许一个方向的信息流),同时ModBus是面向寄存器进行数据交互的,在信息帧上有特定的规则。
3、常见的名词及解释
1)主站从站:也有叫主机从机的,由一台主站及多个从站组成,主站可进行单播或广播模式通信,从站有自己特定的设备标识1-255,主站通过特定的标识由特定的信道向从站发送请求,从站在接收到请求后,由该信道向主站发送请求结果,地址码为0时为广播,从站不作答,并且从站不向主站主动发送请求。
2)信息帧:也叫数据帧,由特定规则组成的数据帧,包括地址码、功能码、数据区、CRC冗余循环码等,具体规则见下文
3)波特率:串口通信频率,指每秒传输的Bit数量,比如,波特率9600,指每秒可以传输9600个字节,双方通信要指定相同的波特率,否则无法正常的通信
4、信息帧规则
Modbus与RS485一样,都拥有自己的信息帧规则,具体的如下
4.1、地址位
从站的设备标识,0-255的范围,其中0表示该通信为主站广播,从站不回应;若为1-255,则表示主站向指定的从站发送通信,从站也需要携带自己的地址位向主站回复
4.2、功能码
协议规定的部分功能代码,最常用的有03、06
03:查询某些寄存器的数据
06:修改某些寄存器的数据
4.3、数据区
通信过程中的主要数据,根据不同的功能码,有相应的格式要求,比如03的查询,会要求指定寄存器及寄存器数量
4.4、校验位
CRC冗余循环校验,信息接收方通过该校验位与信息帧中某些区段数据进行计算,来判定该通信数据的准确性,采用除法+余数的方式来进行计算(本文不具体阐述)。具体场景中,可根据对应厂商的采取的CRC算法,直接在线搜索计算工具即可。
使用注意,在线工具计算结果一般以高位低位排序,但主从站发送数据帧则一般以低位高位排序,注意顺序。
4.5、场景举例说明
目前有一个温湿度传感器,地址为1,其中温度数据在第5、6寄存器内,湿度在第7、8寄存器内,请求与响应数据表现为,其中CRC校验算法采用CRC-16(根据实际场景具体应用):
读取温度:
主站问询帧:01030501336C(16进制描述)
0X01:从站地址
0X03:查询功能码
0X05:从第5个寄存器开始读
0X01:读一个,读到06,为双闭合,体现为要读取的寄存器个数-1
0X33:CRC冗余校验低位
0X6C:CRC冗余校验高位
从站应答帧:010302090BDBD3(16进制描述)
0X01:从站地址
0X03:查询功能码
0X02:数据长度
090B:温度数据,转10进制为2315/100=23.15度(具体参考厂商说明)
0XDB:CRC冗余校验低位
0XD3:CRC冗余校验高位
读取温湿度(多寄存器读取):
与单指标数据读取类似,即读取多个寄存器数据,分别处理应答帧数据区数据。
主站问询帧:01030503B2AD(16进制描述),即从第5个寄存器开始读3个(共四个)
从站应答帧:010304090B1203DFCC
0103:从站地址+查询功能码
0X04:数据长度
090B:温度数据
1203:湿度数据,转十进制4611/100=46.11%(具体参考厂商说明)
DFCC:CRC用于校验低高位
5、开发思路
整体上使用开发机(充当主站)利用串口与从站设备进行数据交互,将信息帧点对点或广播到从站,并从主站获取到各从站的应答帧,解析应答数据并进行应用,主要分为设备映射、信息帧发送与应答帧监听、数据解析三个主要模块。
实际应用中,厂商一般会提供数据网关,服务平台接入数据网关API,即可快速获取各从站设备数据(一般要额外购买设备,不在本文讨论范围,本文主要讲如何直接接入设备,类似自己开发数据网关)。
5.1、设备映射
通过设计平台设备(逻辑设备)与IOT设备(物理设备)的映射关系,例如,可将通过设备组中MD(主设备MasterDevice)与SD(子设备SlaveDevice)概念关系与物理设备中主站从站概念结合,将从站设备地址与子设备DeviceID进行绑定,从而得到相应的设备数据。如下图:
5.2、信息帧发送与应答帧监听
开发机作为主站时通过串口(com口)与各从站进行通信,而串口无法直接与从站进行通信(协议不一致),上文已经说明,一般来说ModBus设备使用RS-485物理层协议进行通信,所以这时需要一个串口转RS-485的转换模块(USB转RS-485模块)来进行协议转换。
Java开发上使用RXTX包进行通信开发,该包不在openJDK内,需要自己准备,并将其引入到工程中。
注意:
1)ModBus协议是半双工模式,点对点模式一定是先发送询问帧,然后等待应答帧,以间隔时间为完成标识(波特率,相当于对讲机的over机制),RXTX中有相应的配置,在应答帧未完全接收完成时,继续发送询问帧,一定报错。广播模式从站不应答,即无需等待。
2)串口,在windows中叫com口,在设置-硬件管理-串口中可以看到相应的串口名称,在RXTX包中直接写com口名称即可(例如com3),而linux/mac中以串口文件/dev/ttys*为名称。
3)建议将问询帧作为配置项封装到相应子设备中,便于调试维护
4)建议线程与设备组进行绑定,以便进行后续的数据解析
5.3、数据解析
该模块主要负责解析应答帧中的数据区数据,根据厂商提供的规则,将应答帧的16进制数据转换为相应可读数据。
同时建议将应答帧规则作为配置封装到相应子设备中,使用script脚本运行,便于调试维护。
以伪代码的形式描述如下:
// 运行代码
public void run(){
// 线程池
ThreadPool pool;
// 遍历设备组
for(DeviceGroup group: groups){
// 构建运行规则
Rule rule = new Rule();
rule.build(group);
// 获取运行线程
Thread thread = pool.getThread();
rule.setThread(thread);
// 运行
rule.run();
}
}
// 运行规则定义
public class Rule{
// 绑定线程
Thread bindThread;
// 设备组
DeviceGroup group;
// 监听线程
Thread listenerThread;
// 问询脚本
Script askScript;
// 设备映射路由
Map<String, SubDevice> subDeviceRoute;
// 构建规则
// 线程赋值
// 脚本编译
// 路由构建
public void build(){
....
}
// 运行
public void run(){
// 监听器上下文
Listener listener = new Listener();
ListenerContext context = new ListenerContext();
// 绑定线程及映射路由
context.setBindThread(bindThread);
context.setSubDeviceRoute(subDeviceRoute);
context.setThread(listenerThread);
// 开启监听线程
listener.execute(context);
// 执行问询脚本
ScriptExecute.execute(askScript);
// 由监听线程的interrupt决定bindThread的inerrupt
while(!listenerThread.getInerrupt()){
sleep(500);
}
}
}
// 监听器,监听com口返回的应答帧数据
public class Listener{
public void execute(ListenerContext context){
// 监听到应答帧
Message msg = getMessage();
// 从路由中获取子设备
SubDevice subDevice = context.getSubDeviceRoute.get(msg.getAddress);
// 执行子设备的解析脚本
ScriptExecute.execute(subDevice,msg);
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签: