Modbus错误:[输入/输出]无从远程单元收到响应

时间:2017-12-14 16:05:54

标签: python modbus pymodbus pymodbus3

我尝试使用USB RS485转换器使用串行连接从Mac笔记本电脑连接到Modbus设备(MR-SI4),该转换器已“挂载”到/dev/cu.SLAB_USBtoUART

这是我的代码:

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)

控制台中的输出是:

$ 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

我很乐意帮助理解我得到的错误。我尝试使用pymodbus的配置以及read_discrete_inputsread_holding_registers等不同功能。有帮助吗?

由于

3 个答案:

答案 0 :(得分:2)

使用modbus时,即使您使用的是高级库,也可以随时关注官方modbus documentation。 通过文档,您可以检查框架的每个字节的含义:

0x01 0x04 0x00 0x00 0x00 0x01 0x31 0xCA

第一个字节是设备地址(0x01)

第二个字节是功能代码(0x04, Read Input Registers)

第三个和第四个字节是起始位置(0x00, 0x00)

第五个和第六个字节是输出数量(0x00, 0x01)

最后2个字节是CRC控制(0x31, 0xCA)

这意味着您要求来自地址为(0x00, 0x01)的设备的内存(0x04)中第一个位置的输入寄存器(0x00, 0x00)中的一个(0x01)个寄存器。

框架本身是正确的,如果设备软件/固件遵循modbus标准,您应该得到答案:您要求的寄存器或错误帧(0x01, 0x80, crc, crc)

这就是说,我们可以检查您的设备没有收到答案的原因。为此,如果您不确定您的代码/您所询问的内容/设备的行为方式,您可以使用外部工具来比较结果。我建议你像docklight那样思考,它可以帮助你建立连接和发送/接收modbus帧。

我要检查的第一件事是连接参数:

client = ModbusClient(method='rtu', port=SERIAL, stopbits=1, bytesize=8, timeout=3, baudrate=BAUD, parity='E')
  

方法是正确的,因为这是你要求的协议。

     

端口正确,否则会返回系统错误。

     

超时是导致错误的原因:在给定时间内,未收到任何响应。无论如何,问题可能不在这里,因为您为超时设置了一个较高的值。

     

Stopbits不应干扰帧接收。

     

问题可能出在波特率和奇偶校验中:此处的错误可能导致代码引发错误。

如果您不知道波特率和/或奇偶校验的正确值,可以尝试使用most commons baudrates和奇偶校验值:'N', 'E', 'O', 'M', 'S'(代表:无,偶数,奇数,标记,空格。默认为无)。

如果我打赌,我首先将偶数奇偶校验替换为无(parity = 'N')。

如果仍有问题,设备地址(0x01)可能有误。地址可以表示从0(0x00)到255(0xFF)的值。

按协议标准,即使起始地址(0x00, 0x00),输出数量(0x00, 0x01)或crc(0x31, 0xCA)错误,设备也应该做出回应,但是它并不总是那样:如果您认为自己处于这种状况,请研究设备的具体文档。

最后一种可能性是使用低级库,例如PySerial,并定义自己的协议。

答案 1 :(得分:0)

选中此Stack_post

您可以处理该错误:

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.')

[注意]:

  • 在许多情况下,RTU奇偶校验为None:parity='N'
  • 请确保您的串行端口(/dev/cu.SLAB_USBtoUART)具有root权限。

答案 2 :(得分:0)

我可以通过将常数RetryOnEmpty设置为True来解决此问题。

from pymodbus.constants import Defaults
Defaults.RetryOnEmpty = True

配置超时和重试可能也很有用。

Defaults.Timeout = 5
Defaults.Retries = 5

https://pymodbus.readthedocs.io/en/v1.3.2/library/constants.html