问题
pymodbus 主/客户端可以向从/服务器发送请求。从机/服务器使东西准备好返回,并等待主/客户端来接它们。尽管服务器/从机准备就绪,主/客户端只是返回错误“Modbus 错误:[输入/输出] Modbus 错误:[无效消息] 收到不完整的消息,预计至少 2 个字节(收到 0)”。
设置
我通过此适配器将笔记本电脑用作服务器/从机:https ://www.amazon.com/dp/B076WVFXN8/ref=twister_B076X1BS4H?_encoding=UTF8&psc=1
我有一个 Raspberry Pi 3 / BananaPi 作为主/客户端,并附有此适配器:https ://www.aliexpress.com/item/32781613765.html?spm=a2g0s.9042311.0.0.1aec4c4d0EXx8M
我正在关注本教程的大部分设置,除了 Arduino 与笔记本电脑适配器交换:https ://circuitdigest.com/microcontroller-projects/rs485-serial-communication-between-arduino-and-raspberry-pi - Raspberry 的引脚连接与教程中的一样。
我有这个程序作为我的笔记本电脑上的服务器/从机:
#!/usr/bin/env python
from pymodbus.server.sync import StartTcpServer
from pymodbus.server.sync import StartUdpServer
from pymodbus.server.sync import StartSerialServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusBinaryFramer
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s'
' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
def run_server():
slave_store1 = ModbusSlaveContext(co=ModbusSequentialDataBlock(0, [1]*16))
slave_store2 = ModbusSlaveContext(di=ModbusSequentialDataBlock(0, [1]*16))
slave_store3 = ModbusSlaveContext(ir=ModbusSequentialDataBlock(0, [5]*16))
slave_store4 = ModbusSlaveContext(hr=ModbusSequentialDataBlock(0, [5]*16))
slaves = {
0x01: slave_store1,
0x02: slave_store2,
0x03: slave_store3,
0x04: slave_store4,
}
context = ModbusServerContext(slaves=slaves, single=False)
identity = ModbusDeviceIdentification()
identity.VendorName = 'Pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '2.2.0'
# RTU:
StartSerialServer(context, framer=ModbusRtuFramer, identity=identity, port='/dev/ttyUSB0', timeout=4, baudrate=115200, stopbits=1, bytesize=8, parity='N')
if __name__ == "__main__":
run_server()
server/slave 上的 python 版本是:
$ python3 --version
Python 3.5.2
我用这个命令开始它:
$ python3 pymodbus_sync_serv_example_2019.07.05-1316.py
我在 Raspberry Pi 3 / BananaPi 上有以下作为主/客户端:
#!/usr/bin/env python
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
'%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
UNIT = 0x1
def run_sync_client():
client = ModbusClient(method='rtu', port='/dev/ttyS2', timeout=4, baudrate=115200, stopbits=1, bytesize=8, parity='N')
print(client)
client.connect()
log.debug("===================================")
log.debug("Read input registers")
log.debug("")
rr = client.read_input_registers(1, 2, unit=3)
print(rr)
client.close()
if __name__ == "__main__":
#for _ in range(10):
run_sync_client()
测试和分析
我尝试过 Raspberry Pi 3 和 BananaPi。结果相同。
我试过波特率 = 9600、38400,现在是 115200。
正如您在代码中看到的那样,超时已经很高了。
服务器/从属的日志:
2019-07-07 13:35:00,333 MainThread DEBUG sync :45 Client Connected [/dev/ttyUSB0:/dev/ttyUSB0]
2019-07-07 13:35:00,333 MainThread DEBUG sync :522 Started thread to serve client
2019-07-07 13:35:08,341 MainThread DEBUG rtu_framer :180 Getting Frame - 0x4 0x0 0x1 0x0 0x2
2019-07-07 13:35:08,341 MainThread DEBUG factory :137 Factory Request[ReadInputRegistersRequest: 4]
2019-07-07 13:35:08,341 MainThread DEBUG rtu_framer :115 Frame advanced, resetting header!!
2019-07-07 13:35:08,342 MainThread DEBUG context :64 validate: fc-[4] address-2: count-2
2019-07-07 13:35:08,342 MainThread DEBUG context :78 getValues fc-[4] address-2: count-2
2019-07-07 13:35:08,342 MainThread DEBUG sync :143 send: [ReadRegisterResponse (2)]- b'030404000500050846'
上面的服务器/从服务器只是在最后一条日志行之后用闪烁的光标等待......
主/客户端的日志:
ModbusSerialClient(rtu baud[115200])
2019-07-07 13:35:04,428 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:165 ===================================
2019-07-07 13:35:04,429 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:166 Read input registers
2019-07-07 13:35:04,430 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:167
2019-07-07 13:35:04,430 MainThread DEBUG transaction :111 Current transaction state - IDLE
2019-07-07 13:35:04,430 MainThread DEBUG transaction :116 Running transaction 1
2019-07-07 13:35:04,431 MainThread DEBUG transaction :215 SEND: 0x3 0x4 0x0 0x1 0x0 0x2 0x21 0xe9
2019-07-07 13:35:04,431 MainThread DEBUG sync :73 New Transaction state 'SENDING'
2019-07-07 13:35:04,432 MainThread DEBUG transaction :224 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2019-07-07 13:35:08,439 MainThread DEBUG transaction :234 Transaction failed. (Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received))
2019-07-07 13:35:08,440 MainThread DEBUG rtu_framer :235 Frame - [b''] not ready
2019-07-07 13:35:08,441 MainThread DEBUG transaction :390 Getting transaction 3
2019-07-07 13:35:08,442 MainThread DEBUG transaction :189 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)
主/客户端上的python版本是:
$ python3 --version
Python 3.5.2
我用这个命令开始它:
$ python3 pymodbus_sync_client_example_2019.07.05-1319.py
Raspberry/BananaPi 上 /dev 的权限是:
$ ls -l /dev/ttyS*
crw--w---- 1 root tty 249, 0 Jul 7 11:21 /dev/ttyS0
crw-rw---- 1 root dialout 249, 1 Jul 7 11:22 /dev/ttyS1
crw-rw---- 1 root dialout 249, 2 Jul 7 13:35 /dev/ttyS2
crw-rw---- 1 root dialout 249, 3 Jul 7 11:20 /dev/ttyS3
在笔记本电脑上的服务器/从机上:
$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0 Jul 7 13:35 /dev/ttyUSB0
我尝试使用 RS485 协议发送简单的数字。它们可以从 master/Raspberry/BananaPi 发送到笔记本电脑,但不能反过来。
我的设备权限设置错误吗?...
我究竟做错了什么?...
我错过了什么?...
由于 RS485 只能以一种方式工作,我认为 pymodbus 不是问题(?)...(我的逻辑是 pymodbus 建立在 RS485 标准中,如果 RS485 的底层不起作用,pymodbus 将不会. 这个假设正确吗?)
我知道有些人在谈论 Raspberry Pi 的引脚电压为 3.3V,不适用于 5V 引脚单元。尽管如此,所有教程似乎都忽略了这一事实并起作用。- 或者他们只是假装它有效?TTL 规范表明所有高于 2.5V 的电压都将被视为 HIGH。所以在理论中,3.3V 应该没问题,正如教程所建议的那样。
我故意还没有在 tx/rx 线上连接任何电阻用于上拉/下拉。教程不建议它们。
我已经使用 modbus 温湿度传感器测试了笔记本电脑上的 RS85 适配器。这似乎完美无缺。所以这个事实表明 BananaPi/Raspberry Pi 和 RS485 适配器组合 + 软件 + 设置在某种程度上存在缺陷。