Problem
pymodbus 主站/客户端可以向从站/服务器发送请求。从属/服务器准备好返回的东西,并等待主控/客户端来接收它们。尽管服务器/从站已准备就绪,但主站/客户端仅返回错误“Modbus 错误:[输入/输出] Modbus 错误:[无效消息] 收到不完整消息,预计至少 2 个字节(已收到 0)”。
Setup
我使用笔记本电脑作为带有此适配器的服务器/从属设备:
我有一个 Raspberry Pi 3 / BananaPi 作为主/客户端,并附有此适配器:https://www.aliexpress.com/item/32781613765.html?spm=a2g0s.9042311.0.0.1aec4c4d0EXx8M 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 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()
服务器/从站上的 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)
master/client 上的 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 的电压都将被视为高电平。所以从理论上讲,3.3V 应该没问题,正如教程所建议的那样。
我特意没有在 tx/rx 线上连接任何电阻来上拉/下拉。教程不建议它们。
我已经使用 modbus 温度湿度传感器测试了笔记本电脑上的 RS85 适配器。这似乎工作完美。所以这个事实表明 BananaPi/Raspberry Pi 和 RS485 适配器组合 + 软件 + 设置存在某种缺陷。