串口未正确刷新

Fus*_*ieb 6 linux pyserial python-3.x raspberry-pi

我有一个RPi (是的,我知道,也许有人认为这属于RPi网站,但我认为它与Linux有关,所以StackOverflow是正确的地方)我正在使用Python3通过MAX485在一些Arduinos之间进行通信和pySerial.这或多或少都有效,因为我发现我需要做一些奇怪的解决方法才能使一切正常"正常".

如果我发送数据:

GPIO.output(23, 1) # Pulling transmit pin high to send
comport.write("Some data".encode()) # Writing data
comport.flush() # Flushing the buffer
GPIO.output(23, 0) # Pulling pin down to receive
Run Code Online (Sandbox Code Playgroud)

Arduino接收数据并立即响应,但由于pySerial尚未准备就绪,它变得什么都没有,我们丢失了数据包.

但是,如果我这样尝试:

GPIO.output(23, 1)
comport.write("Some data".encode())
time.sleep(.001) # Add some delay of only 1ms
comport.flush()
GPIO.output(23, 0)
Run Code Online (Sandbox Code Playgroud)

然后数据被发送并被接收.这引出了一个问题:flush命令是否正常工作?我试了一下:

GPIO.output(23, 1)
comport.write("Some data".encode())
time.sleep(.001) # Add some delay
# -- No flush --
GPIO.output(23, 0)
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是它也有效.似乎睡眠"替换" flush命令.

为什么pySerial的缓冲区没有刷新?我知道,这可能是一种方法,但sleep只添加一个(通常)不必要的代码,导致整个代码等待(超过500行),这不是那么好.

我已经在互联网上搜索过,有些人说它是不支持的USB TTL适配器flush(这里不是这种情况,这个是板载的),其他人说这可能是一个Linux内核错误,所以没有什么真正有意义的对我来说.

如果有人能够解释为什么flush命令不起作用以及如何使它工作(如果有办法),我和这个问题的每个未来访问者都会非常高兴.

Ste*_*uch 3

您没有具体说明,但我认为可以公平地假设您在半双工模式下使用 MAX485。如果是这种情况,那么您尝试做的事情将无法可靠地工作。

问题是什么?

半双工通信使用同一对电线在任一方向上传输。但一次只能有一端进行传输。因此,这需要某种方式来协调当前正在传输的人。

在此输入图像描述

我相信您已经对问题有了很好的总结:

Arduino 收到数据并立即响应,但由于 pySerial 不知何故尚未准备好,所以它什么也没有返回,并且我们丢失了数据包。

然而,并不是 PySerial 没有准备好,而是你的 MAX485 和 GPIO-23 的状态。

一切尽在时机

这是摘自Moxa关于半双工 485 的优秀技术说明的图片,标题为“RS-485 半双工通信的秘密”

在此输入图像描述

此图显示您需要在适当的时候更改 GPIO-23(图中的 MASTER-RTS)的状态,否则通信将失败。该技术说明值得全文阅读,我相信它很好地描述了您面临的挑战。

我如何解决它?

答案是,这取决于。您的问题可能是太早或太晚切换 GPIO-23。如果可能的话,最简单但性能最低的方法是让 Arduino 在响应之前等待一段时间。这将允许您sleep()花一点时间来确保您的数据包已完成传输,然后在 Arduino 开始响应之前切换 GPIO-23 的状态。

如果此解决方案不可能或不可取,那么您将需要研究其他方法来驱动 GPIO-23。在 SW 中还有许多其他方法可以做到这一点,其中一些方法比其他方法效果更好。但请注意,仅使用 python 代码来切换 GPIO-23 线路永远不会 100% 可靠。如果需要高可靠性,几乎肯定需要某种硬件辅助。

最后一点,除非需要 RS-485,否则您可以考虑使用 RS-422 甚至 RS-232 全双工。