Преобразовать два необработанных значения в 32-разрядное число с плавающей точкой IEEE - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь декодировать некоторые данные с измерителя мощности Shark 100 по протоколу TCP Modbus. Я успешно вытащил необходимые мне регистры, и у меня осталось два необработанных значения из регистров, например:

[17138, 59381]

Из руководства я знаю, что мне нужно преобразовать эти два числа в 32-битные. IEEE число с плавающей точкой. Из руководства я также знаю, что «регистр с меньшим адресом является половиной старшего порядка (т. Е. Содержит показатель степени)». Первый номер в приведенном выше списке - регистр с меньшим адресом.

Используя Python (любая библиотека будет делать это при необходимости), как бы я взял эти два значения и превратил их в 32-битное значение IEEE с плавающей запятой.

Я пытался использовать различные онлайн-конвертеры и калькуляторы, чтобы выяснить непрограммистический c способ сделать это, однако, все, что я пробовал, дает мне результат, который выходит за пределы (я в этом случае считывается вольт, поэтому конечный результат должен составлять примерно 120-122 от указанных выше значений).

Ответы [ 3 ]

1 голос
/ 23 января 2020

Работает следующий код:

import struct
a=17138
b=59381
struct.unpack('!f', bytes.fromhex('{0:02x}'.format(a) + '{0:02x}'.format(b)))

Дает

(121.45304107666016,)

Адаптировано из Преобразование шестнадцатеричного числа в число с плавающей запятой и Преобразование целого числа в шестнадцатеричное в Python

0 голосов
/ 06 февраля 2020

Я прочитал в комментариях, и @Sanju разместил эту ссылку: https://github.com/riptideio/pymodbus/blob/master/examples/common/modbus_payload.py

Для тех, кто использует pymodbus, BinaryPayloadDecoder полезен, поскольку он встроен. Очень просто передать result.registers, как показано в примере. Кроме того, в него встроен logging, так что вы можете помочь отладить, почему преобразование не работает (например, неправильный порядок байтов).

Таким образом, я сделал рабочий пример для этого вопроса (используя pymodbus==2.3.0):

from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder


a = 17138
b = 59381
registers = [a, b]
decoder = BinaryPayloadDecoder.fromRegisters(registers, byteorder=Endian.Big)
decoder.decode_32bit_float()  # type: float

Вывод: 121.45304107666016

0 голосов
/ 06 февраля 2020

Обновление для Python 3.6+ (f-строки).

Я не уверен, почему ответ @ B Go был заполнен только 2. Кроме того, поскольку порядок байтов был прямым порядком байтов, я жестко запрограммировал его как таковой.

import struct
a = 17138
b = 59381
struct.unpack('>f', bytes.fromhex(f"{a:0>4x}" + f"{b:0>4x}"))[0]

Вывод: 121.45304107666016

...