我尝试使用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_inputs或read_holding_registers等不同的函数.有帮助吗?
谢谢
解决方法:
使用modbus时,即使您使用的是高级库,也可以随时关注官方modbus documentation.
通过文档,您可以检查框架的每个字节的含义:
0x01 0x04 0x00 0x00 0x00 0x01 0x31 0xCA
第一个字节是设备地址(0x01)
第二个字节是功能代码(0x04,读取输入寄存器)
第三个和第四个字节是起始位置(0x00,0x00)
第五个和第六个字节是输出数量(0x00,0x01)
最后2个字节是CRC控制(0x31,0xCA)
这意味着您要求来自输入寄存器(0x04)的一个(0x00,0x01)寄存器来自存储器中的第一个位置(0x00,0x00),地址为1(0x01)的设备.
框架本身是正确的,如果设备软件/固件遵循modbus标准,您应该有一个答案:您要求的寄存器或错误帧(0x01,0x80,crc,crc).
这就是说,我们可以检查您的设备没有收到答案的原因.为此,如果您不确定您的代码/您所询问的内容/设备的行为方式,您可以使用外部工具来比较结果.我建议你像docklight那样思考,它可以帮助你设置连接和发送/接收modbus帧.
我要检查的第一件事是连接参数:
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.
如果您不知道波特率和/或奇偶校验的正确值,可以尝试使用most commons baudrates和奇偶校验值:’N’,’E’,’O’,’M’,’S'(代表:无,Even,Odd,Mark,Space.默认为None).
如果我打赌,我首先用无替换偶数奇偶校验(奇偶校验=’N’).
如果仍有问题,则设备地址(0x01)可能错误.地址可以表示从0(0x00)到255(0xFF)的值.
按协议标准,即使起始地址(0x00,0x00),输出数量(0x00,0x01)或crc(0x31,0xCA)都是错误的,设备也应该响应一些东西,但它并不总是这样:如果你认为你是在这种情况下,研究设备的具体文档.
最后一种可能性是使用低级库,例如PySerial,并定义自己的协议.