pymodbus-dev/pymodbus

Reading registers from a Schneider Electric PM5340 with ModBus ID 255

saschaludwig opened this issue · 10 comments

Versions

  • Python: 3.12
  • OS: MacOS
  • Pymodbus: 3.7.3
  • Modbus Hardware (if used): Schneider Electric PM5340

Pymodbus Specific

  • Client: tcp - sync

Description

I'm trying to read a Schneider Electric PM5340 which has a ModBus Slave ID of 255 according to this FAQ: https://www.se.com/eg/en/faqs/FA341569/

Code and Logs

from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient('10.105.0.233')
client.connect()
result = client.read_input_registers(3000, count=1, slave=255)
print(result)
client.close()
python ./test.py
Exception Response(132, 4, IllegalFunction)

When I omit slave= while reading, I get this error:

python ./test.py
Exception Response(132, 4, GatewayPathUnavailable)

Setting slave=0 while reading, will result in this error:

python ./test.py
Modbus Error: [Input/Output] No Response received from the remote slave/Unable to decode response

What is the correct way of reading from a PM5340?

in v3.7.3 slave=255 is considered broadcast… I just added a commit to dev that changes that, I still however have to do a bit more testing.

v3.7.4 will be available in 1-2 weeks.

However it should not report illegal function, I will check that.

Can you please run slave=255, with debug log as the issue template asked you to do.....I want to see what is actually happening.

I suspect that the exception responses comes from your device, maybe address 3000 is not defined as input_register in your device.

But a debug log, will show clearly what happens.

import pymodbus
pymodbus.pymodbus_apply_logging_config("DEBUG")
from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient('10.105.0.233')
client.connect()
result = client.read_input_registers(3001, count=1, slave=255)
print(result)
client.close()

Here is the debug output from the code above, with pymodbus 3.7.3:

2024-10-16 11:29:24,769 DEBUG tcp:169 Connection to Modbus server established. Socket ('172.20.10.51', 54037)
2024-10-16 11:29:24,769 DEBUG transaction:182 Current transaction state - IDLE
2024-10-16 11:29:24,769 DEBUG transaction:188 Running transaction 1
2024-10-16 11:29:24,769 DEBUG transaction:296 SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0xff 0x4 0xb 0xb9 0x0 0x1
2024-10-16 11:29:24,770 DEBUG base:247 New Transaction state "SENDING"
2024-10-16 11:29:24,770 DEBUG transaction:320 Changing transaction state from "SENDING" to "WAITING FOR REPLY"
2024-10-16 11:29:24,772 DEBUG transaction:412 Changing transaction state from "WAITING FOR REPLY" to "PROCESSING REPLY"
2024-10-16 11:29:24,772 DEBUG transaction:327 RECV: 0x0 0x1 0x0 0x0 0x0 0x3 0xff 0x84 0x1
2024-10-16 11:29:24,772 DEBUG base:101 Processing: 0x0 0x1 0x0 0x0 0x0 0x3 0xff 0x84 0x1
2024-10-16 11:29:24,772 DEBUG factory:259 Factory Response[132]
2024-10-16 11:29:24,772 DEBUG base:119 Frame advanced, resetting header!!
2024-10-16 11:29:24,772 DEBUG transaction:66 Adding transaction 1
2024-10-16 11:29:24,772 DEBUG transaction:77 Getting transaction 1
2024-10-16 11:29:24,772 DEBUG transaction:253 Changing transaction state from "PROCESSING REPLY" to "TRANSACTION_COMPLETE"
Exception Response(132, 4, IllegalFunction)

With pymodbus@c868810 it's almost the same as far as I can see:

2024-10-16 11:35:25,395 DEBUG tcp:169 Connection to Modbus server established. Socket ('172.20.10.51', 54074)
2024-10-16 11:35:25,395 DEBUG transaction:184 Current transaction state - IDLE
2024-10-16 11:35:25,395 DEBUG transaction:190 Running transaction 1
2024-10-16 11:35:25,395 DEBUG transaction:298 SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0xff 0x4 0xb 0xb9 0x0 0x1
2024-10-16 11:35:25,395 DEBUG base:243 New Transaction state "SENDING"
2024-10-16 11:35:25,395 DEBUG transaction:322 Changing transaction state from "SENDING" to "WAITING FOR REPLY"
2024-10-16 11:35:25,397 DEBUG transaction:424 Changing transaction state from "WAITING FOR REPLY" to "PROCESSING REPLY"
2024-10-16 11:35:25,398 DEBUG transaction:329 RECV: 0x0 0x1 0x0 0x0 0x0 0x3 0xff 0x84 0x1
2024-10-16 11:35:25,398 DEBUG base:92 Processing: 0x0 0x1 0x0 0x0 0x0 0x3 0xff 0x84 0x1
2024-10-16 11:35:25,398 DEBUG decoders:264 Factory Response[132]
2024-10-16 11:35:25,398 DEBUG base:102 Frame advanced, resetting header!!
2024-10-16 11:35:25,398 DEBUG transaction:67 Adding transaction 1
2024-10-16 11:35:25,398 DEBUG transaction:78 Getting transaction 1
2024-10-16 11:35:25,398 DEBUG transaction:255 Changing transaction state from "PROCESSING REPLY" to "TRANSACTION_COMPLETE"
Exception Response(132, 4, IllegalFunction)

As you can see it is your device that returns the IllegalFunctionRequest, so there are no bug in pymodbus.

Most likely your device do not like slave 255.

I'm a bit puzzled what to do now. The manual and https://www.se.com/eg/en/faqs/FA341569/ states, clearly, that the ID is 255 according to Modbus standards for a standalone device. And it can't be changed. So what would be the correct way of reading from that meter with pymodbus?
Sadly, I don't have enough knowledge of the Modbus protocol to find out what is wrong with the communication.

I cannot tell you. I do not know all modbus devices, all I can say is that it seems pymodbus does exactly what it is supposed to do.

If you find indications that there are a bug in pymodbus, please let us know. Good luck with your device.

Are you sure the address you request is a input_register, that would explain the error.

Closing as this is not a pymodbus bug.

Okay, I found the issue! But first of all, thank you for your support! @janiversen
It was a holding_register I wanted to read initially, but due to the errors I tried different methods and finally went the wrong way :-)
On top of that, the registers in the Register-List of the PM5340 is off by one.
Reading in between registers throws an error on the PM5340.

Reading registers with the dev version of pymodbus and the correct offsets do work now :-)

Thank you very much!