一、目的
利用电脑上的MThings(摩尔信使:Modbus通讯助手)、网络调试助手(NetAssist)、Python代码分别实现对毗连在卓岚串口服务器上的RS485温湿度传感器的温湿度读取。
二、预备工作
2.1 硬件
1.导线;
2.网线;
3.电脑;
4.开关电源(220V互换 转 24V直流);
5.卓岚RS485单串口服务器(ZLAN5143D);
6.温湿度传感器(5V-36V);
| 输入寄存器功能界说 | | 协议所在 | PLC所在 | 功能形貌 | | 0000H | 30001 | 温度值
单位:℃
分析方法:固定1位小数点
(1)正温度:寄存器数据<10000
例:寄存器值为250,实际湿度值: 250x0.1=25℃
(2)负温度:寄存器数据>=10000
例:寄存器值为10250
实际湿度值: -1*(10250 -10000) *0.1=-25℃ | | 0001H | 30002 | 湿度值.
单位:%RH
分析方法:固定1位小数点
例:寄存器值为500,实际湿度值: 500*0.1=50 (%RH) | | 0002H | 30003 | 温度值
单位:℃
分析方法:32 位浮点数,大端模式 | | 0003H | 30004 | | 0004H | 30005 | 湿度值
单位:%RH
分析方法:32 位浮点数,大端模式 | | 0005H | 30006 |
| 保持寄存器功能界说 | | 协议所在 | PLC所在 | 功能形貌 | | 0000H | 30001 | 温度值
单位:℃
分析方法:固定1位小数点
(1)正温度:寄存器数据<10000
例:寄存器值为250,实际湿度值: 250x0.1=25℃
(2)负温度:寄存器数据>=10000
例:寄存器值为10250
实际湿度值: -1*(10250 -10000) *0.1=-25℃ | | 0001H | 30002 | 湿度值.
单位:%RH
分析方法:固定1位小数点
例:寄存器值为500,实际湿度值: 500*0.1=50 (%RH) | | 0002H | 30003 | 温度值
单位:℃
分析方法:32 位浮点数,大端模式 | | 0003H | 30004 | | 0004H | 30005 | 湿度值
单位:%RH
分析方法:32 位浮点数,大端模式 | | 0005H | 30006 | | 000AH | 40011 | RS485总线所在/站号(1 ~255)。
出厂默认:1
注:此参数掉电生存,修改后重新上电即可收效 | | 000BH | 40012 | 0:4800
1:9600 (出厂默认)
2:14400
3:19200
4:38400
5:56000
6:57600
7:115200
注:此参数掉电生存,修改后重新.上电即可收效 | 2.2 软件
1.ZLVirCom563(卓岚RS485单串口服务器装备管理工具);
2.MThings(摩尔信使:Modbus通讯助手);
3.NetAssist(网络调试助手)
4.设置好Python的VScode,而且安装好第三方库:socket、struct、crcmod
三、接线图
四、通讯参数设置
4.1 电脑通讯参数设置
1.确保网线将电脑和卓岚单串口服务器接好(串口服务器上指示灯Link为绿色大概蓝色)
2.打开“网络和Internet”设置——高级网络设置——更改适配器选项——找到“以太网”图标,右键属性;
3.选择“Internet 协议版本4(TCP/IPv4)”;
4.点选“利用下面的IP所在”——输入IP所在和子网掩码(留意:IP所在必须和串口服务器的所在在同一个网段下。即192.168.1是一样的,背面的字段不一样)——点击“确定”——完成电脑的以太网IP设置;
4.2 卓岚RS485单串口服务器通讯参数设置
1.电脑打开“ZLVirCom5.63.exe”软件;
2.点击“装备管理”——“自动搜刮”——搜刮得到串口服务器装备;
3.点击“编辑装备”——修改IP所在(这里设置192.168.1.10,端口4196,必要与电脑设置的IP在同一个网段下,否则通讯不上)——修改波特率为9600(温湿度传感器的默认波特率就是9600)——其他默认即可——点击“修改设置”;
五、MThings操纵
5.1 通讯设置
1.打开MThings调试软件——点击右上角的通道管理;
2. 进入通道界面管理的小窗口后,点击新增网络毗连;
3.链接模式选择“TCP客户端”;传输协议选择“MODBUS-RTU”(外貌上利用TCP通讯,但其通讯的报文是是MODBUS-RTU的);目的域名/IP和目的端口填写“IP192.168.1.10 端口4196”(四、通讯参数设置——4.2卓岚RS485单串口服务器通讯参数设置——3);填写完根本信息后点击确定;查抄链接是否添加乐成;
4.回到MThings主界面——点击左上角“+”符号——进入“添加装备”小窗口——通道选择我们上一步创建的网络链接“NET001”——装备范例“模仿主机”(由于卓岚模块是属于从机)——点击“添加”;
5.上一步添加乐成之后,再进入到“通道管理”内里可发现“NET001”的状态已酿成了绿色的“已毗连”,就体现MThings调试软件已经与卓岚串口服务器毗连上了,接下来就创建数据表,并举行通讯了;
6.回到MTings主界面,然后点击界面上方的“数据”——进入到“数据”选项卡后——点击上方的“+”符号添加数据行;
7.温湿度值都存储于输入寄存器(保持寄存器)中,所在0存储温度值,所在1存储湿度值,我们可以先创建这4个数据行,2个输入寄存器的温度和湿度行,2个保持寄存器的温度和湿度行;
我们还可以添加两个输入寄存器起始所在为0的数据行、两个保持寄存器起始所在为0的数据行,然后寄存器数目我们可以设置为2,意思是温湿度两个值一起读过来酿成32位整数,本身可以选择性试一试。
温湿度传感器的出厂设置的寄存器在保持寄存器,起始所在10。
温湿度传感器的波特率设置的寄存器在保持寄存器,起始所在11。
5.2 读取温湿度值(ModbusRTU读数据)
5.1步调完成之后,我们就可以利用MThinngs誊写数据,并观察其报文格式(背面可以利用网络调试助手来验证),起首将右上方的“报文”勾选上。
5.2.1 读取温度值(读输入寄存器,起始所在0,数目1)
客户端(电脑)发送:01 04 00 00 00 01 31 CA
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节00 00起始所在0,2个字节00 01读取的寄存器数目1个,2个字节31 CACRC校验码,2个字节服务器(温湿度传感器)相应:01 04 02 01 1C B9 69
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节02数据长度:2个字节01 1C16进制温度值,转换成10进制是284,2个字节B9 69CRC校验码,2个字节 5.2.2 读取湿度值(读输入寄存器,起始所在1,数目1)
客户端(电脑)发送:01 04 00 01 00 01 60 0A
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节00 01起始所在1,2个字节00 01读取的寄存器数目1个,2个字节60 0ACRC校验码,2个字节服务器(温湿度传感器)相应:01 04 02 02 C3 F8 01
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节02数据长度:2个字节02 C316进制湿度值,转换成10进制是707,2个字节F8 01CRC校验码,2个字节 5.2.3 读取温湿度值(读输入寄存器,起始所在0,数目2)
客户端(电脑)发送:01 04 00 00 00 02 71 CB
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节00 00起始所在0,2个字节00 02读取的寄存器数目2个,2个字节71 CBCRC校验码,2个字节服务器(温湿度传感器)相应:01 04 04 01 1C 02 C3 7A 8F
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节04数据长度:4个字节01 1C16进制温度值,转换成10进制是284,2个字节(所在为0的输入寄存器值)02 C316进制湿度值,转换成10进制是707,2个字节(所在为1的输入寄存器值)7A 8FCRC校验码,2个字节 5.2.4 读取温度值(读保持寄存器,起始所在0,数目1)
客户端(电脑)发送:01 03 00 00 00 01 84 0A
01从站所在1,一样平常默认都是1,1个字节03功能码,读保持寄存器的功能码是03,1个字节00 00起始所在0,2个字节00 01读取的寄存器数目1个,2个字节84 0ACRC校验码,2个字节服务器(温湿度传感器)相应:01 03 02 01 1C B8 1D
01从站所在1,一样平常默认都是1,1个字节03功能码,读输入寄存器的功能码是03,1个字节02数据长度:2个字节01 1C16进制温度值,转换成10进制是284,2个字节B8 1DCRC校验码,2个字节 5.2.5 读取湿度值(读保持寄存器,起始所在1,数目1)
客户端(电脑)发送:01 03 00 01 00 01 D5 CA
01从站所在1,一样平常默认都是1,1个字节03功能码,读保持寄存器的功能码是03,1个字节00 01起始所在1,2个字节00 01读取的寄存器数目1个,2个字节D5 CACRC校验码,2个字节服务器(温湿度传感器)相应:01 03 02 02 C3 F9 75
01从站所在1,一样平常默认都是1,1个字节03功能码,读保持寄存器的功能码是03,1个字节02数据长度:2个字节02 C316进制湿度值,转换成10进制是707,2个字节F9 75CRC校验码,2个字节 5.2.6 读取温湿度值(读保持寄存器,起始所在0,数目2)
客户端(电脑)发送:01 03 00 00 00 02 C4 0B
01从站所在1,一样平常默认都是1,1个字节03功能码,读保持寄存器的功能码是03,1个字节00 00起始所在0,2个字节00 02读取的寄存器数目2个,2个字节C4 0BCRC校验码,2个字节服务器(温湿度传感器)相应:01 03 04 01 1C 02 C3 7B 38
01从站所在1,一样平常默认都是1,1个字节03功能码,读保持寄存器的功能码是03,1个字节04数据长度:4个字节01 1C16进制温度值,转换成10进制是284,2个字节(所在为0的保持寄存器值)02 C316进制湿度值,转换成10进制是707,2个字节(所在为1的保持寄存器值)7B 38CRC校验码,2个字节5.3 设置温湿度传感器出厂设置与波特率(ModbusRTU写数据)
5.3.1 规复出厂设置
客户端(电脑)发送:01 06 00 0A 00 01 68 08
01从站所在1,一样平常默认都是1,1个字节06功能码,写保持寄存器的功能码是06,1个字节00 0A起始所在10,2个字节(十六进制A就是十进制10)00 01写入保持寄存器的数值1,2个字节68 08CRC校验码,2个字节服务器(温湿度传感器)相应:01 06 00 0A 00 01 68 08
01从站所在1,一样平常默认都是1,1个字节06功能码,写保持寄存器的功能码是06,1个字节00 0A起始所在10,2个字节00 01写入保持寄存器乐成的数值1,2个字节68 08CRC校验码,2个字节5.3.2 设置波特率
客户端(电脑)发送:01 06 00 0B 00 01 39 C8
01从站所在1,一样平常默认都是1,1个字节06功能码,写保持寄存器的功能码是06,1个字节00 0B起始所在11,2个字节(十六进制B就是十进制11)00 01写入保持寄存器的数值1,2个字节39 C8CRC校验码,2个字节服务器(温湿度传感器)相应:01 06 00 0B 00 01 39 C8
01从站所在1,一样平常默认都是1,1个字节06功能码,写保持寄存器的功能码是06,1个字节00 0B起始所在11,2个字节(十六进制B就是十进制11)00 01写入保持寄存器乐成的数值1,2个字节39 C8CRC校验码,2个字节 六、网络调试助手操纵
通过以上MThings操纵温湿度传感器的步调可以发现,每读写一次数据,我们的客户端电脑就会向温湿度传感器发送一串十六进制数据,温湿度传感器作为相应也会发送一串十六进制数据给电脑。利用MThings软件我们只要关心我们必要读写的寄存器所在、数目以及我们要写入的数值,而报文怎么编写不是我们必要关心的。
但如果我们筹划利用网络TCP的情势去举行通讯的话,那么我们必要就必要知道ModbusRTU的报文是怎样编写的,而且知道报文怎样分析。
1.打开网络调试助手(NetAssist.exe),按下列步调完成操纵。
客户端(电脑)发送:01 04 00 00 00 01 31 CA
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节00 00起始所在0,2个字节00 01读取的寄存器数目1个,2个字节31 CACRC校验码,2个字节服务器(温湿度传感器)相应:01 04 02 01 1C B9 69
01从站所在1,一样平常默认都是1,1个字节04功能码,读输入寄存器的功能码是04,1个字节02数据长度:2个字节01 1C16进制温度值,转换成10进制是284,2个字节B9 69CRC校验码,2个字节2.这里只展示了读取温湿度传感器的温度值(输入寄存器所在0,读取数目1个),如果想要读取湿度值,大概想要将某个值写入指定的保持寄存器中,我们可以根据上面的ModbusRTU报文格式,本身定一条写保持寄存器的报文,并发送给ModbusRTU装备即可,并学会分析ModbusRTU报文格式,知道数据值存放在什么地方,并转换为我们能看懂的10进制。
七、Python操纵
如果我们想要用这个温湿度传感器做更多的变乱,最简单的好比说,我想每隔一段时间收罗一次温湿度值,并记载在excel表中。
那么以上两款调试助手均不能做到,可以利用恣意一种编程语言来实现。这里利用的是Python编程语言,固然Python可以安装第三方库pymodbus实现modbus通讯,但是这个库利用ModbusTCP通讯时,其通讯协议只能是ModbusTCP,而不能选择ModbusRTU协议。
以是利用Python时,我们必要利用的第三方库是socket,然后在TCP网络通讯的根本上以ModbusRTU为通讯报文,也就是必要本身写步调分析读取报文,尚有天生报文,此中包罗了CRC校验码的天生。
7.1 第三方库的安装
如果没有安装第三方库的话,请按照以下方式举行安装,我这里利用pip指令举行安装,win+R键打开运行窗口,输入cmd,回车打开下令行窗口,第三方库可以在内里安装,以下安装指令都在cmd窗口中实验:
1.利用pip指令安装socket库,用于网络通讯:2.利用pip指令安装struct库,用于分析十六进制报文,并天生报文: 3.利用pip指令安装crcmod库,用于天生CRC校验码: 7.2 编写Modbus通讯代码
以下是实例代码:- import socket,struct,crcmod
- '''
- struct打包解包格式:
- x:跳过一个字节
- b:有符号字节
- B:无符号字节
- h:有符号短整数(2字节)
- H:无符号短整数(2字节)
- i:有符号整数(4字节)
- I:无符号整数(4字节)
- f:单精度浮点数(4字节)
- d:双精度浮点数(8字节)
- '''
- #CRC-MODBUS校验码计算
- def crc16(data): #参数data是十六进制数据
- crc16 = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000) #固定参数
- crc = crc16(data)
- return struct.pack('H',crc) #得到的校验码(转换成无符号短整形2个字节的十六进制数)
- #关于TCP通信,走ModbusRTU协议的类
- class ModbusTcpRtuClinet():
- #初始化函数
- def __init__(self,IP,port):
- dest_address = (IP, port) #TCP通信所需要的远程IP与端口
- # 创建一个TCP socket对象,创建UDP套接字
- #socket.AF_INET IPv4
- #socket.AF_INET6 IPv6
- #socket.SOCK_STREAM TCP协议
- #socket.SOCK_DGRAM UDP协议
- self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #选择IPv4模式、TCP通信协议
- self.client_socket.connect(dest_address) #连接到TCP客户端
- #读多个输入寄存器
- #address:读取输入寄存器的起始地址
- #count:读取输入寄存器的个数
- #unit:从站地址(默认为1)
- def read_input_registers(self,address,count,unit=1):
- #向从站发出读数据请求
- send_data_byte = struct.pack('>B',unit) + struct.pack('>B',3) + struct.pack('>H',address) + struct.pack('>H',count)
- send_data_byte += crc16(send_data_byte) #将读输入寄存器输入的报文加上CRC校验码
- self.client_socket.send(send_data_byte) #发送这一串16进制的读输入寄存器报文
- #接收从站数据
- receive_data_byte = self.client_socket.recv(1024) #接收数据,一次读取1024个字节 #接收RTU从站响应的报文(高字节在后,低字节在前)
- data_len = struct.unpack('>xxB%sxx'%(count*"xx"),receive_data_byte)[0] #解析读取的寄存器数据总长度(单位:字节)
- unpack_format = '>BBB%sH'%(int(data_len/2)*'h') #2个字节一个h,短整型
- return list(struct.unpack(unpack_format,receive_data_byte)[3:-1]) #解析数据最终将我们要的寄存器数据提取出来
- #读多个保持寄存器
- #address:读取输入寄存器的起始地址
- #count:读取输入寄存器的个数
- #unit:从站地址(默认为1)
- def read_holding_registers(self,address,count,unit=1):
- #向从站发出读数据请求
- send_data_byte = struct.pack('>B',unit) + struct.pack('>B',3) + struct.pack('>H',address) + struct.pack('>H',count)
- send_data_byte += crc16(send_data_byte) #将读保持寄存器输入的报文加上CRC校验码
- self.client_socket.send(send_data_byte) #发送这一串16进制的读保持寄存器报文
- #接收从站数据
- receive_data_byte = self.client_socket.recv(1024) #接收数据,一次读取1024个字节 #接收RTU从站响应的报文(高字节在后,低字节在前)
- data_len = struct.unpack('>xxB%sxx'%(count*"xx"),receive_data_byte)[0] #解析读取的寄存器数据总长度(单位:字节)
- unpack_format = '>BBB%sH'%(int(data_len/2)*'h') #2个字节一个h,短整型
- return list(struct.unpack(unpack_format,receive_data_byte)[3:-1]) #解析数据最终将我们要的寄存器数据提取出来
- #写单个保持寄存器
- def write_holding_register(self,address,value,unit=1):
- #向从站发出读数据请求
- send_data_byte = struct.pack('>B',unit) + struct.pack('>B',6) + struct.pack('>H',address) + struct.pack('>h',value)
- send_data_byte += crc16(send_data_byte) #将读保持寄存器输入的报文加上CRC校验码
- self.client_socket.send(send_data_byte) #发送这一串16进制的读保持寄存器报文
- #接收从站数据
- receive_data_byte = self.client_socket.recv(1024) #接收数据,一次读取1024个字节 #接收RTU从站响应的报文(高字节在后,低字节在前)
- if receive_data_byte == send_data_byte: #如果接受到的数据跟发送出去的报文数据一样,则说明保持寄存器写入成功
- return True #保持寄存器写入成功返回True
- else:
- return False #保持寄存器写入失败返回False
- #关闭客户端
- def close(self):
- self.client_socket.close() #关闭客户端
- #开始通信读写数据
- client = ModbusTcpRtuClinet("192.168.1.10", 4196) #连接到设备,填写IP和端口
- print("温度(输入寄存器,地址0,数量1):",client.read_input_registers(0,1)) #读输入寄存器地址0,数量1
- print("湿度(输入寄存器,地址1,数量1):",client.read_input_registers(1,1)) #读输入寄存器地址1,数量1
- print("温湿度(输入寄存器,地址0,数量2):",client.read_input_registers(0,2)) #读输入寄存器地址0,数量2
- print("温度(保持寄存器,地址0,数量1):",client.read_holding_registers(0,1)) #读保持寄存器地址0,数量1
- print("湿度(保持寄存器,地址1,数量1):",client.read_holding_registers(1,1)) #读保持寄存器地址1,数量1
- print("温湿度(保持寄存器,地址0,数量2):",client.read_holding_registers(0,2)) #读保持寄存器地址0,数量2
- print("恢复出厂设置(保持寄存器,地址10,写入数值1):",client.write_holding_register(10,1)) #写保持寄存器地址10,值为1,恢复出厂设置
- print("波特率是否设置成功(保持寄存器,地址11,写入数值1):",client.write_holding_register(11,1)) #写保持寄存器地址11,值为1,修改温湿度传感器波特率,修改成功返回True,失败返回False
- client.close() #关闭客户端
复制代码 运行效果:
从终端运行的效果可以瞥见,已经乐成读取和写入寄存器值,读取到的寄存器值存储在python列表中,也就是存储在中括号中。现在获取到的温湿度值还必要除以10,得到的才是真正的温湿度值。写入寄存器乐成返回True,写入失败返回False。
八、结论
本篇文章紧张陈诉了通过MThings、网络调试助手、编写Python脚原来实现TCP上的ModbusRTU协议通讯,比力特别的地方是利用了以太网转RS485模块。除了这些尚有各种各样的方式可以实现,其核心只要在于ModbusRTU通讯的报文发送和吸收。如果没有利用串口服务器的话,可以利用Mthings、串口调试助手、Python中的pymodbus第三方库来实现。以此简单的温湿度传感器为例,盼望能为各人提供有代价的参考和资助。如有标题可举行品评大概私信我,看到后我会第一时间复兴各人。
|