在Python中处理Modbus异常

在Python中处理Modbus异常,python,minimalmodbus,Python,Minimalmodbus,我正在尝试创建一个小型家庭监控系统。我有一系列的无线发射机,可以将测量数据传输到基站。我可以使用Modbus RTU查询该基站,以了解每个发射机的最新测量值 为了存储测量值并可视化,我使用了XDB和Grafana。我的一切都在Raspberry Pi 3B+型上运行,包括与基站的RS-485通信 我选择使用Python从Modbus RTU读取数据,然后将其转发到XDB进行存储,因为Python已经为这两种设备准备好了库。然而,我正在努力使Python脚本保持稳定。不可避免地,我会时不时地在Mo

我正在尝试创建一个小型家庭监控系统。我有一系列的无线发射机,可以将测量数据传输到基站。我可以使用Modbus RTU查询该基站,以了解每个发射机的最新测量值

为了存储测量值并可视化,我使用了XDB和Grafana。我的一切都在Raspberry Pi 3B+型上运行,包括与基站的RS-485通信

我选择使用Python从Modbus RTU读取数据,然后将其转发到XDB进行存储,因为Python已经为这两种设备准备好了库。然而,我正在努力使Python脚本保持稳定。不可避免地,我会时不时地在Modbus传输中出现CRC错误,当Modbus库引发其中一个异常时,脚本似乎会卡住

我不知道该如何解决这个问题

目前我正在使用try-except-else结构,但因为我是Python的新手,所以无法让它按我想要的方式工作。如果我丢失了一个测量点也没关系。这意味着,如果我得到一个CRC错误,我可以忘记那个测量,然后像什么都没发生过一样继续

我目前使用的代码(最小化)如下所示:

[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
#/user/bin/env python
导入最小Modbus
导入时间
从influxdb导入InfluxDBClient
#XDB材料
influx=InfluxDBClient(host='localhost',port=8086)
inflox.switch_数据库('dbname'))
#最简单的东西
最小Modbus.BAUDRATE=9600
仪器=最小Modbus.仪器('/dev/ttyUSB0',1)
errorcounter=0
循环计数器=0
尽管如此:
尝试:
sid1te=仪器读取寄存器(247,1,4)
打印“SID 1 TE:”,sid1te
influxquery=[
{“测量”:“sid1”,“字段”:{“te”:sid1te},
{“测量”:“系统”,“字段”:{“errorcounter”:errorcounter},
{“测量”:“系统”,“字段”:{“循环计数器”:循环计数器}
]
打印“InfluxDB查询结果:”,influx.write_点(influxquery)
除异常作为错误外:
出现打印“[!]异常:”,错误
errorcounter=errorcounter+1
其他:
打印“[i]完成一个周期。”
循环计数器=循环计数器+1
时间。睡眠(30)
最终发生的情况是,脚本可以像梦一样运行数小时,然后,当传输中出现单个CRC错误时,它会进入一个永无止境的异常循环,如下所示:

[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred:  Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
当我使用CTRL-C退出时,脚本实际上看起来是在sleep命令中:

^CTraceback (most recent call last):
  File "temp.py", line 92, in <module>
    time.sleep(30)
KeyboardInterrupt
^CTraceback(最近一次通话最后一次):
文件“temp.py”,第92行,在
时间。睡眠(30)
键盘中断
所以我很困惑,如果它实际上在程序循环中,为什么它不向控制台输出正常的打印命令

在实际的脚本中,我有三十多个instrument.read\u寄存器调用,所以我不确定是否应该创建一个单独的函数,在其中处理每次read\u寄存器调用上的异常,还是什么?在过去的一周里,我尝试了半打这种代码的变体,但是我在Grafana中得到的数据非常糟糕,因为脚本陷入了异常循环


有什么建议吗?

我现在发布了MinimalModbus的新版本,默认情况下,在串行总线上进行任何通信之前刷新输入和输出串行缓冲区,以清除任何旧错误。请试一试


免责声明:我是MinimalModbus的维护者。

我使用不同的USB/RS-485转换器以及不同的Modbus RTU设备进行了尝试。同样的问题依然存在。我99%相信问题在于Linux串行端口处理。我不知道如何/为什么,但它有时会给出pyserial/minimamodbus不完整的字节序列,导致minimamodbus将erroneus序列作为响应进行评估。例如,minimalmodbus抱怨0x11响应太短,然后紧接着minimalmodbus抱怨0x03 0x06 0xAE 0x41 0x56 0x52 0x43 0x40 0x49 0xAD在CRC中有错误。实际上,如果将这两条消息作为一条消息接收,那么这将是一个完全有效的响应

我不知道如何解决这个问题,但我很确定这个问题比Python级别的问题还要严重


编辑:这不是硬件/Linux问题,而是Python/pyserial/Modbus的问题。我拼凑了一个Python脚本,它执行一个外部C语言Modbus RTU查询程序并解析输出。在一个多星期的时间里,它100%都像一个魔咒一样工作。

Modbus链路连接好了吗?如果是这样,您是如何连接电缆的?您在Pi上使用什么来连接RS485链路(USB适配器、品牌、型号等)?您的Pi和基站是否使用可靠的电源?这些是通过电源共享相同的GND,还是您有额外的GND电缆?你还知道其他噪音源吗?是的,是有线的。我使用的是芬兰建筑自动化公司Produal提供的完整系统。这是他们的FLTA基站和MPCC Modbus配置工具。它直接插入Pi的USB,为FLTA基站供电,还提供RS-485链路。在使用Home Assistant的六个多月里,这种完全相同的设置非常有效,因此我确信这是我的Python脚本的一个软件问题。我不确定Home Assistant是否发生了CRC错误,但无论如何,我应该能够安全、理智地从总线通信中的任何错误中恢复过来。对不起,我没有仔细阅读您的问题。当然,预计您会不时收到CRC错误。我不明白为什么一个错误会引发这种反应。它看起来像一只虫子。如果删除代码上的try/except,是否会发生这种情况?我不完全确定,但我认为minimalmodbus能够容忍其o上的CRC错误