我是靠谱客的博主 传统哑铃,最近开发中收集的这篇文章主要介绍使用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是否自带有解决方案,如果有更好的方案欢迎大家分享。

最后

以上就是传统哑铃为你收集整理的使用modbus_tk进行通信时遇到的浮点数问题的全部内容,希望文章能够帮你解决使用modbus_tk进行通信时遇到的浮点数问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部