问题
pymodbus主/客户端可以向从/服务器发送请求。从/服务器使返回的东西做好准备,并等待主/客户端获取它们。尽管服务器/从服务器已经就绪,但主/客户机只返回错误"Modbus错误:输入/输出Modbus错误:接收到的无效消息不完整消息,预期至少有2个字节(0接收)“。
设置
我使用膝上型计算机作为服务器/从服务器与此适配器: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 -针连接的覆盆子是在教程中。
我把这个程序作为服务器/从机放在我的笔记本电脑上:
#!/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()
测试与分析
我尝试过覆盆子Pi 3以及BananaPi。同样的结果。
我试过baudrate= 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's的权利是:
$ 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就不能工作。这个假设正确吗?)
我知道有些人正在谈论的覆盆子Pi是3.3V的引脚和不工作的5V引脚单位。尽管如此,所有的教程似乎都忽略了这一事实和工作。-还是他们只是假装成功了?TTL规格说明所有2.5V以上都将被接受为高电压。因此,理论上,3.3V应该是可以的,正如教程所建议的那样。
我有目的,但还没有附加任何电阻在tx/rx电线上,以向上/向下。这些教程不建议他们。
我用modbus温湿度传感器测试了坐在笔记本电脑上的RS85适配器.这似乎无懈可击。因此,这一事实指向了BananaPi/Raspberry和RS485适配器组合+软件+设置的方向,这些设置都有一定的缺陷。
发布于 2019-07-07 21:23:01
正如上面Marcos G.所建议的,我是否修改了pymodbus以控制所选择的GPIO。
我选择了软件解决方案,因为我现在只需要一些快速工作的东西,而不是订购新的硬件和等待。我稍后会找到一个合适的/更好的硬件。
修改pymodbus的软件解决方案
在文件夹"client“中找到"sync.py”文件,以修改安装程序的客户机/主端。
我在这里修改客户机/主程序,因为我的RS485硬件很差。如果您有两个‘差’硬件,您可能也需要修改服务器端。
文件sync.py可能可以在
~/.local/lib/python3.5/site-packages/pymodbus/client
这可能因您使用的python版本而有所不同。目前我的是3.5。"~/“部分意味着它在您的主文件夹中。在“本地”前面的点使文件隐藏为标准。在终端中,您也可以使用命令"ls -al“显示隐藏文件。Linux发行版的图形用户界面肯定也能以某种方式显示隐藏的文件。
在文件"sync.py“的开头,添加以下代码:
import RPi.GPIO as GPIO
pin_de_re = 7
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin_de_re, GPIO.OUT, initial=GPIO.HIGH)
这可以看起来类似于以下几个方面:
more imports ...
from pymodbus.transaction import ModbusSocketFramer, ModbusBinaryFramer
from pymodbus.transaction import ModbusAsciiFramer, ModbusRtuFramer
from pymodbus.client.common import ModbusClientMixin
import RPi.GPIO as GPIO
pin_de_re = 7
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin_de_re, GPIO.OUT, initial=GPIO.HIGH)
# --------------------------------------------------------------------------- #
# Logging
# --------------------------------------------------------------------------- #
import logging
_logger = logging.getLogger(__name__)
...more code
根据您的选择设置引脚号。我有我的控制引脚作为GPIO4 -那是针7在覆盆子派/香蕉派。
接下来,您向下滚动并找到名为
# --------------------------------------------------------------------------- #
# Modbus Serial Client Transport Implementation
# --------------------------------------------------------------------------- #
我修改本节,因为我使用Modbus RTU,因此是串行的数据传输。
在这一节中,您必须找到“发送”的定义:
def _send(self, request):
""" Sends data on the underlying socket
在该函数中,找到一行:
size = self.socket.write(request)
用针的控制来拥抱它:
_logger.debug("GPIO - Setting pin high")
GPIO.output(pin_de_re, 1)
time.sleep(.300)
size = self.socket.write(request)
time.sleep(.300)
_logger.debug("GPIO - Setting pin low")
GPIO.output(pin_de_re, 0)
我使用‘_logger.debug’行(“GPIO-设置引脚高/低”)的原因是,我可以在终端的日志中看到,程序执行这些事情,如果它们被执行,我可以放心。如果他们不出现在日志里,我就在错误的地方做了-或者别的什么.
使用time.sleep(.300)的原因是为了让硬件有时间行动。.300为0.3秒。在这方面有很大的数字。
当我使用上面的解决方案时,我会得到以下日志。
从/服务器:
2019-07-07 23:08:43,532 MainThread DEBUG sync :45 Client Connected [/dev/ttyUSB0:/dev/ttyUSB0]
2019-07-07 23:08:43,533 MainThread DEBUG sync :522 Started thread to serve client
2019-07-07 23:08:47,534 MainThread DEBUG rtu_framer :232 Frame check failed, ignoring!!
2019-07-07 23:08:47,535 MainThread DEBUG rtu_framer :128 Resetting frame - Current Frame in buffer - 0x3 0x4 0x0 0x1 0x0 0x82
2019-07-07 23:08:59,543 MainThread DEBUG rtu_framer :180 Getting Frame - 0x4 0x0 0x1 0x0 0x2
2019-07-07 23:08:59,544 MainThread DEBUG factory :137 Factory Request[ReadInputRegistersRequest: 4]
2019-07-07 23:08:59,544 MainThread DEBUG rtu_framer :115 Frame advanced, resetting header!!
2019-07-07 23:08:59,544 MainThread DEBUG context :64 validate: fc-[4] address-2: count-2
2019-07-07 23:08:59,544 MainThread DEBUG context :78 getValues fc-[4] address-2: count-2
2019-07-07 23:08:59,545 MainThread DEBUG sync :143 send: [ReadRegisterResponse (2)]- b'030404000500050846'
硕士/客户:
ModbusSerialClient(rtu baud[115200])
2019-07-07 23:08:55,839 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:165 ===================================
2019-07-07 23:08:55,840 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:166 Read input registers
2019-07-07 23:08:55,841 MainThread DEBUG pymodbus_sync_client_example_2019.07.05-1319:167
2019-07-07 23:08:55,842 MainThread DEBUG transaction :111 Current transaction state - IDLE
2019-07-07 23:08:55,842 MainThread DEBUG transaction :116 Running transaction 1
2019-07-07 23:08:55,843 MainThread DEBUG transaction :215 SEND: 0x3 0x4 0x0 0x1 0x0 0x2 0x21 0xe9
2019-07-07 23:08:55,843 MainThread DEBUG sync :79 New Transaction state 'SENDING'
2019-07-07 23:08:55,844 MainThread DEBUG sync :538 GPIO - Setting pin high
2019-07-07 23:08:55,845 MainThread DEBUG sync :541 GPIO - Setting pin low
2019-07-07 23:08:55,845 MainThread DEBUG transaction :224 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2019-07-07 23:08:59,516 MainThread DEBUG transaction :300 Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2019-07-07 23:08:59,518 MainThread DEBUG transaction :229 RECV: 0x3 0x4 0x4 0x0 0x5 0x0 0x5 0x8 0x46
2019-07-07 23:08:59,519 MainThread DEBUG rtu_framer :180 Getting Frame - 0x4 0x4 0x0 0x5 0x0 0x5
2019-07-07 23:08:59,519 MainThread DEBUG factory :266 Factory Response[ReadInputRegistersResponse: 4]
2019-07-07 23:08:59,520 MainThread DEBUG rtu_framer :115 Frame advanced, resetting header!!
2019-07-07 23:08:59,521 MainThread DEBUG transaction :379 Adding transaction 3
2019-07-07 23:08:59,522 MainThread DEBUG transaction :390 Getting transaction 3
2019-07-07 23:08:59,522 MainThread DEBUG transaction :189 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
ReadRegisterResponse (2)
传输可能并不总是这样,但它确定了问题的原因,从而找到了潜在的解决方案。
我还不知道我会有什么下场。更稳定的硬件是肯定的。
关于修改pymodbus或其他有关这个问题的软件,我想引用在另一个威胁中吗?
任何在linux或windows等多任务操作系统上运行modbus的人都无法满足串行规范的要求,这方面没有争论,任务通常是10 as,所以满足3.5us的定时要求是不合适的,而且永远也不会满足。
硬件方面的解决方案更可取。
多亏了马科斯G。
https://stackoverflow.com/questions/56922031
复制相似问题