python - Pymodbus TCP `read_holding_registers` 返回陈旧/旧数据

标签 python python-3.x modbus modbus-tcp pymodbus

我已经开始使用 pymodbus 从 modbus 读取值以存储在异地数据库中。我一直在努力解决响应中收到的值与我在 Jace 上看到的值不同的问题。

我也尝试过 modbus-tk 并且我得到了同样的错误响应,所以它一定是我的 Python 代码中的某些东西导致了这个问题。从我们的遗留系统 (VB.Net) 检索的读数与我在 Jace 上看到的输出相同。

这是从 modbus 检索数据的简单函数。我们在 4016040162 处有 2 个寄存器,第一个正在读取 366,这是正确的,第二个正在读取 367(这是我遇到的问题)。我也看到了与其他寄存器相同的问题,即使我可以在 Jace 上看到值已经增加,读数也不会更新。

# -*- coding: utf-8 -*-

from __future__ import division, print_function, unicode_literals

from pymodbus.client.sync import ModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder

def get_modbus_register_data(ip_address, register, device, count=2):
        """
        Retrieve modbus data.
        """
        client = ModbusTcpClient(ip_address, timeout=10)
        client.connect()

        # Read registers
        response = client.read_holding_registers(
            address=register,  # 40162
            count=count,       # 2
            unit=device)       # 4

        decoder = BinaryPayloadDecoder.fromRegisters(
            registers=response.registers,
            byteorder=Endian.Big,
            wordorder=Endian.Little)

        value = decoder.decode_32bit_float()

        client.close()

        return value # 366 and it should be 367

Pymodbus 调试日志

DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x4 0x3 0x0 0xa0 0x0 0x2
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x0 0x1 0x0 0x0 0x0 0x7 0x4 0x3 0x4 0x0 0x0 0x43 0xb7
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x1 0x0 0x0 0x0 0x7 0x4 0x3 0x4 0x0 0x0 0x43 0xb7
DEBUG:pymodbus.factory:Factory Response[ReadHoldingRegistersResponse: 3]
DEBUG:pymodbus.transaction:Adding transaction 1
DEBUG:pymodbus.transaction:Getting transaction 1
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'

Jace reading

Config

更新

在 Sanju 的帮助下,有人向我指出我使用的偏移量可能不正确。确实如此,通过将偏移量更改为 1 (40162 - 40001 = 161),我能够从寄存器中检索到正确的值,wordorder 需要更改为 Endian.Big

更新代码

def get_modbus_register_data(ip_address, register, device, count=2):
        """
        Retrieve modbus data.
        """
        client = ModbusTcpClient(ip_address, timeout=10)
        client.connect()

        # Read registers
        response = client.read_holding_registers(
            address=register,  # 40161
            count=count,       # 2
            unit=device)       # 4

        decoder = BinaryPayloadDecoder.fromRegisters(
            registers=response.registers,
            byteorder=Endian.Big,
            wordorder=Endian.Big)

        value = decoder.decode_32bit_float()

        client.close()

        return value # 367

最佳答案

对于 pymodbus,您必须注意 pymodbus 如何处理偏移量,偏移量 0 映射到寄存器 40001,因此 40162 的偏移量将为 40162-40001,即 0xa140160 类似,偏移量将是 0x9f。 有关更多信息,请参阅 https://pymodbus.readthedocs.io/en/latest/source/library/pymodbus.html#pymodbus.register_read_message.ReadHoldingRegistersRequest

另请注意,BinaryPayloadDecoder 假定的默认 EndiannessEndian.Little for byteorder Endian.Big 用于 wordorder 。如果这些顺序不正确,您最终会得到错误的解码值。

关于python - Pymodbus TCP `read_holding_registers` 返回陈旧/旧数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51900315/

相关文章:

python - 图像处理 1 位图像

python - 了解 Python 函数

python - 如何重新启动我的 python 3 脚本?

python - 如何将嵌套字典变成矩阵列表?

python通信MODBUS TCP/IP树莓派和HMI-写入值

python - 我应该在使用功能后返回吗?

python - Python中许多列表的连接

python - DataFrame:如何根据行的另一个单元格切换单元格值?

c - STM32F3如何使用MODBUS TCP?

python-3.x - 如何在 Python 中重新排列字节数组中的字节?