问题
I' trying to connect from my Mac laptop to a Modbus device (MR-SI4) using a serial connection using a USB RS485 converter that gets "mounted" to /dev/cu.SLAB_USBtoUART
.
This is my code:
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
from pymodbus.constants import Endian
from pymodbus.constants import Defaults
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.transaction import ModbusRtuFramer
# settings for USB-RS485 adapter
SERIAL = '/dev/cu.SLAB_USBtoUART'
BAUD = 19200
# set Modbus defaults
Defaults.UnitId = 1
Defaults.Retries = 5
client = ModbusClient(method='rtu', port=SERIAL, stopbits=1, bytesize=8, timeout=3, baudrate=BAUD, parity='E')
connection = client.connect()
print "Readout started"
#result = client.read_discrete_inputs(0)
#result = client.read_holding_registers(12,19)
result = client.read_input_registers(0,1)
print(result)
The output in the console is:
$ sudo python test.py
Readout started
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:send: 0x1 0x4 0x0 0x0 0x0 0x1 0x31 0xca
DEBUG:pymodbus.client.sync:will sleep to wait for 3.5 char
DEBUG:pymodbus.transaction:recv:
DEBUG:pymodbus.transaction:getting transaction 1
Modbus Error: [Input/Output] No Response received from the remote unit
I would love to have a little help understanding the error I'm getting. I tried with the configuration of pymodbus
and also with different functions like read_discrete_inputs
or read_holding_registers
. Any help?
Thanks
回答1:
When working with modbus, even if you're using an high-level library, it's always useful to have close at hand the offical modbus documentation. With the documentation, you can check what each byte of your frame means:
0x01 0x04 0x00 0x00 0x00 0x01 0x31 0xCA
The first byte is the device address (0x01)
The second byte is the function code (0x04, Read Input Registers)
Third and fourth bytes are the starting position (0x00, 0x00)
Fifth and sixth bytes are the quantity of outputs (0x00, 0x01)
The last 2 bytes are the CRC control (0x31, 0xCA)
This means that you are asking for one (0x00, 0x01)
registers from the input registers (0x04)
from the first position in memory (0x00, 0x00)
from device with address 1 (0x01)
.
The frame by itself is correct, and if the device software/firmware follows the modbus standard, you should have an answer: the register that you asked for OR an error frame (0x01, 0x80, crc, crc)
.
This said, we can check why you do not receive an answer from your device. For doing this, if you're not sure about your code/on what you're asking/how your device behave, you can use an external tool to compare the results. I'd suggest you somethink like docklight, that helps you to set up your connection and send/receive modbus frame.
First thing I'd check are the connection parameters:
client = ModbusClient(method='rtu', port=SERIAL, stopbits=1, bytesize=8, timeout=3, baudrate=BAUD, parity='E')
Method is correct, since is the protocol you're asking for.
The port is correct, otherwise it gives back a system error.
Timeout is what raise the error: in a given time, no response was received. Anyway the problem is probably not here, since you set a high value for timeout.
Stopbits should not interfere with the frame reception.
The problem could be in baudrate and parity: an error here can cause the error raised by your code.
If you do not know the correct value for baudrate and/or parity, you can try with the most commons baudrates and the parity values: 'N', 'E', 'O', 'M', 'S'
(stands for: None, Even, Odd, Mark, Space. Default is None).
If i've to bet, i'd start by replacing Even parity with None (parity = 'N'
).
If you still have the problem, the device address (0x01
) may be wrong. The address can be represented a value from 0 (0x00
) to 255 (0xFF
).
By protocol standard, even if the starting address (0x00, 0x00
), the quantity of outputs (0x00, 0x01)
or the crc (0x31, 0xCA
) are wrong, the device should respond something, but it's no always like that: if you think you're in this situation, research for device's specific documentation.
The last possibility is to use a low level library, such as PySerial, and you define your own protocol.
回答2:
Check this Stack_post.
You can handle the error:
if not result.isError():
'''isError() method implemented in pymodbus 1.4.0 and above'''
print(result.registers) # Note.
else:
# Handle Error.
print('Unable to read or there is the connection problem.')
[NOTE]:
- In many cases, RTU parity is None:
parity='N'
- Make sure from root permission on your serial port (
/dev/cu.SLAB_USBtoUART
).
回答3:
I was able to work around this issue by setting the constant RetryOnEmpty
to True
.
from pymodbus.constants import Defaults
Defaults.RetryOnEmpty = True
It also may be useful to configure a timeout and some retries.
Defaults.Timeout = 5
Defaults.Retries = 5
https://pymodbus.readthedocs.io/en/v1.3.2/library/constants.html
来源:https://stackoverflow.com/questions/47817634/modbus-error-input-output-no-response-received-from-the-remote-unit