【问题标题】:How to convert value hex to float32 big endian in PyModbus如何在 PyModbus 中将值 hex 转换为 float32 big endian
【发布时间】:2021-01-30 17:33:25
【问题描述】:

我目前正在使用包 pymodbus 在 python 中编码 modbus rtu。 在这种情况下,我将使用功能代码 4/读取输入寄存器从 TDS 传感器读取数据(请参阅 Aquas SMR-08 数据表)。数据成功获取,我将其转换为十六进制 ,但数据必须再次转换为正确的值。我尝试使用 scadacore(在线十六进制转换器)转换十六进制值,我在 Float Big Endian (ABCD) 上看到了正确的数据

十六进制值为 41FB:

转换结果为 31.375(这是温度值):

那么,pymodbus如何算法或什么代码像scadacore(在线六进制转换)一样转换?

谁能帮忙? 提前致谢,抱歉我的英语不好 hihihi

这是我的代码

import time
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.constants import Defaults
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
Defaults.RetryOnEmpty = True
Defaults.Timeout = 5
Defaults.Retries = 5

client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=2, stopbits=1, bytesize=8, 
parity='N', baudrate=19200)
client.connect()


while True:

tds1 = client.read_input_registers(address=0, count=2, unit=1)

bacatds1 = tds1.registers[0]
bacatds2 = tds1.registers[1]

tds1hex = hex(bacatds1)
tds2hex = hex(bacatds2)

print(tds1hex)
print(tds2hex)

decoder1 = BinaryPayloadDecoder.fromRegisters(tds1.registers, Endian.Little)
hasil1 = decoder1.decode_32bit_float()

print(hasil1)
print('==================================')
time.sleep(1)

# ----------------------------------------------------------------
tds2 = client.read_input_registers(address=1, count=2, unit=1)

bacatds3 = tds2.registers[0]
bacatds4 = tds2.registers[1]

tds3hex = hex(bacatds3)
tds4hex = hex(bacatds4)

print(tds3hex)
print(tds4hex)

decoder2 = BinaryPayloadDecoder.fromRegisters(tds2.registers, Endian.Big)
hasil2 = decoder2.decode_32bit_float()
print(hasil2)
print('===================================')
time.sleep(1)

【问题讨论】:

  • 您能否发布有关您正在使用的传感器的 Modbus 寄存器信息的链接?
  • 有SMR08的datasheet,Link

标签: python pymodbus


【解决方案1】:

我对python不太了解,但是我在java中看到过类似的问题。

我认为您没有使用十六进制基础。 我正在为您提供实现您要求的步骤。

  1. 将您的hex 视为string
  2. string 转换为float,基数为16。

完成这两个步骤后,您将获得输出。

我在下面为您提供示例链接。

Write hexadecimal values into register with leading zeros

Convert hex to float

希望对你有帮助。

【讨论】:

    【解决方案2】:

    我在将获取的值转换为浮点值时遇到了类似的问题

    在检查 pymodbus 的内部代码库时

    我想出了下面的函数

    import struct
    
    def decodeRegisters_float(in_registers,bit_size=32,step=2):
    
        n = len(in_registers)
    
        float_res = []
        for i in range(0,n,step):
            if bit_size == 32:
                pack_string = '!2H'
                unpack_string = '!f'
                raw = struct.pack(pack_string, in_registers[i] ,in_registers[i+1])
            elif bit_size == 64:
                pack_string = '!4H'
                unpack_string = '!d'
                raw = struct.pack(pack_string, in_registers[i] ,in_registers[i+1],in_registers[i+2],in_registers[i+3])
            value = struct.unpack(unpack_string, raw)[0]
            float_res += [value]
    
        return float_res
    

    函数的参数如下

    in_registers - Register values read from holding/input resistors

    bit_size - 32,64

    step - 2 for 32 and 4 for 64

    一旦你读取了这些值,上面的函数可以被认为是一个包装器,并且需要将它们隐式地转换为相应的浮点值

    以下是示例用法-

    def _read_register_dtype_float(client,unit,nreg,registers=2,type='holding',bit_size=32,step=2):
    
            assert bit_size in [32,64],"Only 32 and 64 bit size is allowed to be read"
    
            if bit_size == 32:
                registers = nreg * registers
            elif bit_size == 64:
                registers = nreg * registers * 2
                step = 4
    
            if type == 'holding':
                res = client.read_holding_registers(0,registers,unit=unit)
    
            if type == 'input':
                res = client.read_input_registers(0,registers,unit=unit)
    
            return decodeRegisters_float(res.registers,bit_size=bit_size,step=step)
    
    

    【讨论】:

      猜你喜欢
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      相关资源
      最近更新 更多