You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法连接Modbus RTU over TCP:modpoll正常但pymodbus失败求排查

Troubleshooting Your pymodbus RTU over TCP Connection Issue

Let's break down what's going on here—your modpoll command works perfectly, so the device is reachable and responding correctly. The problem almost certainly lies in mismatched configuration between your modpoll call and your pymodbus code. Let's go through the critical details step by step:

1. You're Using the Wrong Framer for RTU over TCP

Modbus RTU over TCP (encapsulated RTU) is different from standard Modbus TCP. Your modpoll uses -m enc to enable this mode, but pymodbus defaults to standard Modbus TCP framing. You need to explicitly use the RTU framer when creating your client.

For pymodbus v3.x:

from pymodbus.client import ModbusTcpClient
from pymodbus.transaction import ModbusRtuFramer

# Initialize client with RTU framer
client = ModbusTcpClient(
    host="192.168.1.1",
    port=4660,
    framer=ModbusRtuFramer,
    timeout=5  # Match modpoll's timeout (adjust if needed)
)

# Check connection status
if client.connect():
    print("Connected to device successfully")
else:
    print("Failed to connect—verify IP/port and device status")

For pymodbus v2.x:

from pymodbus.client import ModbusClient
from pymodbus.transaction import ModbusRtuFramer

client = ModbusClient(
    method="tcp",
    host="192.168.1.1",
    port=4660,
    framer=ModbusRtuFramer,
    timeout=5
)
client.connect()

2. Register Address Mismatch (1-Based vs 0-Based)

This is the most common pitfall! Modpoll uses 1-based register addressing, but pymodbus uses 0-based addressing by default. Your modpoll command uses -r60 (starting at register 60), so in pymodbus you need to subtract 1 to get the correct 0-based address: 59.

Additionally, since you're reading a float (-t4:float), which occupies 2 consecutive 16-bit registers, you need to set count=2 in your read call.

3. Correct Register Type & Slave ID

Your modpoll specifies:

  • -t4: Input registers (Modbus function code 04)
  • -a3: Slave ID (device address) 3

Make sure your pymodbus read call matches these:

# Read 2 input registers starting at 0-based address 59 (modpoll's 60)
response = client.read_input_registers(
    address=59,
    count=2,
    slave=3  # Critical: match the -a3 parameter from modpoll
)

# Check for errors
if response.isError():
    print(f"Modbus Error: {response}")
else:
    # Decode the 2 registers into a float
    from pymodbus.payload import BinaryPayloadDecoder
    from pymodbus.constants import Endian

    decoder = BinaryPayloadDecoder.fromRegisters(
        response.registers,
        byteorder=Endian.Big,  # Adjust based on your device's byte order
        wordorder=Endian.Big
    )
    float_value = decoder.decode_32bit_float()
    print(f"Read float value: {float_value}")

4. Verify Byte Order

Modpoll's -t4:float uses a default byte/word order that might match your device, but if the decoded float is garbage, you may need to adjust the byteorder and wordorder in the decoder. Common alternatives are Endian.Little for either parameter—test both combinations if needed.

5. Clean Up the Connection

Don't forget to close the client when you're done to avoid hanging connections:

client.close()

Putting all this together should align your pymodbus code with the working modpoll configuration, and resolve your connection/response issues.

内容的提问来源于stack exchange,提问作者Gordio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:16:34