使用modbus_tk进行通信时遇到的浮点数问题

        最近在做一个跟控制相关的项目,需要通过modbus对控制器进行数据读写,代码用python编写的,在进行real型数据读取时,并没有发生问题,但对于浮点数进行操作时,发现读取到的数据很奇怪。后来发现是字节序的问题,使用的控制器浮点数定义为32 bit float,并且是高低位互换的形式,及ABCD转为CDAB。

        struct提供了编码二进制的方法,但是其字节序只有大小端两种,即只能将浮点数表示为ABCD或DCBA,这就导致通信时的数据有误。

import modbus_tk.defines as cst
from modbus_tk import modbus_tcp

def TCP_write(a,start_address=0):              #a为写入的数据
    master = modbus_tcp.TcpMaster(host)        #host为IP地址
    master.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, start_address, output_value=a)

        定义一个TCP_Master用于写入数据,考虑到控制器的浮点数分为高低位,所以尝试先将须写入的浮点数进行拆分。

        从struct库中的定义可知,浮点数占4字节,而整数占2字节,对于ABCD 4字节浮点数,可拆分为两个整数,即AB和CD,然后将这两个整数大小端互换,就可以得到控制器中的字节序CDAB。

import struct
def float2int(a):
    return struct.unpack('<hh',struct.pack('<f',a)) #两次操作都为小端形式

>>> float2int(11.2)
>>> (13107,16691)

        这里先将浮点数a已浮点数的形式编码为二进制数据,然后解码时可将其拆分为两个有符号整数,然后将这两个按顺序写入控制器即可。


global host
host = '127.0.0.1'
a = float2int(11.2)
b = float2int(1.5)
c = float2int(12.3456798)
x = (a[0],a[1],b[0],b[1],c[0],c[1])
TCP_write_set_point(x,start_address=0)

在ModbusSlave中使用Float CD AB形式显示,可以看到正常的浮点数

         读取数据时也可以使用相同的思路,使用TcpMaster 读取保持寄存器数据的功能,读取上图中从站的数据,可得:

def TCP_read():
    master = TCP_Master(host)
    res_tuple = master.master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 8)
    return res_tuple

>>>a = TCP_read()
>>>(13107, 16691, 0, 16320, 34792, 16709, 0, 0)

        可以看到所读取的数据是按CDAB格式的十进制形式表达的,使用小端的两位整数编码高低两位数据,并同样使用小段浮点数解码,即可得到原始的数据。

>>>res = struct.unpack('<f',struct.pack('<hh',a[0],a[1]))
>>>(11.199999809265137,)

        由于时间紧急,当时没考虑modbus_tk是否自带有解决方案,如果有更好的方案欢迎大家分享。

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值