modbus数据获取与数据解析

#代码部分

首先注意一点Python版的modbus要获取modbus值必须先装【环境包】
pip install serial 
# serial为串口包,需要打开串口,也就是usb
pip install crcmod
# crcmod 用来crc校验的
pip install modbus_tk
# modbus_tk 就是满足modbus协议的Python包
import crcmod
from binascii import unhexlify
import modbus_tk
import time
import serial
from modbus_tk import modbus_rtu
from modbus_tk import defines as cst
import loggingdef crc16Add(read):try:crc16 = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)readcrcout = hex(crc16(unhexlify(read))).upper()str_list = list(readcrcout)if len(str_list) == 5:str_list.insert(2, '0')  # 位数不足补0,在列表中下标为2的加入元素0crc_data = "".join(str_list)read = read.strip() + crc_data[4:] + crc_data[2:4]return readexcept:# print("crc校验出错'")logging.warning('crc校验出错')flag_value = True
def modbus_getdate(slave_id, start_addr, date_len):try:master = modbus_rtu.RtuMaster(serial.Serial(port=PORT,baudrate=19200,bytesize=8,parity='N',stopbits=1,xonxoff=0))# # logger = modbus_tk.utils.create_logger(name="console", record_format="%(message)s")master.set_timeout(3)master.set_verbose(True)# holding_date = master.execute(slave_id, cst.READ_HOLDING_REGISTERS, start_addr, date_len)holding_date = master.execute(slave=slave_id,function_code=cst.READ_HOLDING_REGISTERS,quantity_of_x=date_len,starting_address=start_addr)holding_data125 = list()for i in range(len(holding_date)):holding_data125.append('%04x' % (holding_date)[i])  # append()在Tmp1列表末尾添加新的对象all_holding_data = '0103' + '%02x' % (date_len * 2) + ''.join(holding_data125)  ## return str(all_holding_data)return crc16Add(all_holding_data) #这里crc校验了,如果单纯的看数据可以不校验except modbus_tk.modbus_rtu.ModbusInvalidResponseError as err:# print(err)logging.warning(err)def get_s16(val):'''作用为解析16进制有符号数,值得注意的是modbus poll是不支持有符号数的,一会先讲个modbus poll的用法'''if val > 65536:return val/100 elif val > 32768:#因为我传的数是需要有2位小数的,但是16进制中没有小数点的概念,所以数本身扩大100倍,然后做处理再除以100,就得到小数点后2位return (val - 65536)/100else:return val/100def f_analysis(x):'''解析4位一个的16进制数'''les = len(x)print(les,'数据长度')for i in range(les):if i % 4  == 0:# print(i,j)datas = int(x[i:i+4],16)print(i,get_s16(datas),datas) # i代表循环位置,get_s16()为解析16进制有符号数,datas为16进制数if __name__ == '__main__':PORT = 'COM12'flag = Truefor i in range(2):if flag:da = modbus_getdate(slave_id=1,start_addr=0,date_len=16)print(da) # modbus取出的值# master.execute(slave=1, function_code=cst.WRITE_MULTIPLE_REGISTERS, starting_address=0,#                data_format='0')f_analysis(da[6:-4])# 不需要前6个和后四个原因是,前6个值是我为了协议拼接的,后四个是crc校验生成的,所以它们不是数据,不需要。
结果如下 ,因为是8个温度探头,但只有前三个接了真正的探头,所有只有前三个有值,而且还重复了,不过这不影响。哈哈
01032007920793084ef510f510f510f510f51007920793084ef510f510f510f510f510B741
64 数据长度
0 19.38 1938
4 19.39 1939
8 21.26 2126
12 -28.0 62736
16 -28.0 62736
20 -28.0 62736
24 -28.0 62736
28 -28.0 62736
32 19.38 1938
36 19.39 1939
40 21.26 2126
44 -28.0 62736
48 -28.0 62736
52 -28.0 62736
56 -28.0 62736
60 -28.0 62736
讲个modbus poll 的用法,其实modbus poll 和我上面的代码的作用是一样的,但是modbus poll 是写好的工具,
且只支持215次 以内的数据,也就是32768,这个整数,一旦你要发送有符号数,216次 时它就不能解析了。
下面请看不能解析的部分

在这里插入图片描述

这不是我要的结果
正确结果为,因为 前3个是采集的温度数据,所以19381956是变化的,想表示的就是19.38摄氏度。

在这里插入图片描述

讲讲modbus poll和我代码之间的关系
modbus poll参数设置

在这里插入图片描述

    端口为 com12

在这里插入图片描述

子站数为1,地址从0开始,取16个寄存器的值
代码参数设置

在这里插入图片描述

这个代码参数设置,在代码中可以找到

在这里插入图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部