问题
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()
服务器/从机上的Python版本为:
$ python3 --version
Python 3.5.2
我用这个命令开始:
$ python3 pymodbus_sync_serv_example_2019.07.05-1316.py
我在树莓派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()
测试和分析
我已经尝试了树莓派3和香蕉派。结果相同。
我已经尝试了波特率为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
树莓派/香蕉派上/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协议发送简单的数字。它们可以从主控/Raspberry/BananaPi发送到笔记本电脑,但反过来就不行。
我设置了错误的设备权限吗?...
我做错了什么?...
我错过了什么?...
由于RS485只能在单向上工作,我不认为pymodbus是问题所在(?)...(我的逻辑认为pymodbus内置了RS485标准,如果RS485底层不工作,pymodbus也不会。这个假设正确吗?)
我知道有些人谈论树莓派在引脚上是3.3V,并且不能与5V引脚单元一起使用。尽管如此,所有教程似乎都忽略了这一点并正常工作。-或者他们只是在假装它工作吗? TTL规格表明,高于2.5V的全部接受为HIGH。所以理论上,3.3V应该没问题,就像教程中建议的那样。
我故意没有在tx/rx线上附加任何电阻器进行上/下拉。教程中也没有建议。
我已经用一个modbus温湿度传感器在笔记本电脑上测试了RS85适配器。这似乎运行无误。因此,这一事实指向BananaPi/Raspberry Pi和RS485适配器组合+软件+设置出现了某些问题。