【问题标题】:Bidirectional communication between microcontroller and pyserial微控制器和pyserial之间的双向通信
【发布时间】:2012-06-22 05:24:00
【问题描述】:

我正在使用 Python 2.5.4 和 Windows 7。

我正在尝试创建一个使用 pygame 从微控制器传输和接收信息的程序。当微控制器仅将数据写入 pygame 时,此代码工作正常,但是当该行包含在接收信息的微控制器代码(readline)中时,pygame 窗口冻结(不只是关闭窗口,所以我可以看到问题所在)。我想知道是否有人在微控制器和 pygame/pyserial 相互交谈和倾听方面有任何经验?

我读过一篇可能类似的帖子,但我不理解代码,也不确定是否是同一个问题。我在这些论坛上阅读了“流量控制”一词,我想知道这是否是我的问题?

我的代码是:

import os, pygame, math, serial   
from pygame.locals import *
from pygame.compat import geterror
from time import clock, time
pygame.init()
w = 1100   #sets pygame screen width
h = 642   #sets pygame screen height
screen = pygame.display.set_mode((w, h),0,32)  #make and display screen

pygame.display.flip()   #Update screen
running = 1
font = pygame.font.Font(None, 36)
clock = pygame.time.Clock()
port = serial.Serial("COM2", 115200)

while running:          #Loop this
   for event in pygame.event.get():    #get user input
      if event.type == pygame.QUIT:    #if user clicks the close X
           running = 0                 #make running 0 to break out of loop

   temp = float(port.readline())
   clock.tick(100)
   value = font.render(str(temp), 1, (100, 100, 100))
   screen.blit(value, (280,165))
   pygame.display.flip()   #Update screen
   port.write('3')

【问题讨论】:

    标签: python microcontroller pyserial bidirectional


    【解决方案1】:

    可能 readline 在等待行终止字符时阻塞;回车和/或换行的某种组合。您的微控制器需要在 readline 返回之前发送其中一个或两个字符。您应该检查 pyserial 文档以查看 chars readline 期望的行术语,并通过查看终端甚至在串行流上执行 hexdump 来验证您的 uC 正在发送它们。

    【讨论】:

    • 嗨,杰夫,感谢您的回复,我很感激。奇怪的是,如果我只有一个将数据从微控制器发送到 python 程序的程序,它就可以正常工作。我假设我包含正确的线路终止。让我知道我是否偏离目标。我还创建了一个从 python 到微控制器的成功程序。只有当我将两者结合起来时,我才会遇到问题。有什么想法吗?
    • 我只是在想,如果只是微控制器一遍又一遍地写相同的东西而不试图读入,你可能会表明你不需要正确的线路终止?
    【解决方案2】:

    似乎最有可能出现的问题是:死锁

    稍微扩展一下 Jeff Laughlin 的帖子:

    很多很多人都遇到过这个死锁问题:

    • PC 无法发送任何字符,因为它处于阻塞 readline() 命令的中间,等待微控制器发送换行符。
    • 微控制器无法发送任何字符,因为它正在等待 PC 发送换行符的阻塞 readline() 命令。

    双方最终都永远等待对方做某事。

    双向通信系统陷入这种僵局的方式有很多种。 也许通过串行电缆的换行符被损坏了一点点,以至于它看起来不再像换行符了。 也许一个长字符串的传输速度比接收器处理它的速度快,溢出了一些缓冲区,丢失的字节之一是换行符。 这条换行符是朝微型到 PC 还是 PC 到微型方向发展都没有关系;无论哪种方式,我们都会陷入同样的​​僵局。

    解决方法 1:超时

    “import serial”加载的documentation for the pyserial package 有一个解决此问题的部分方法: 设置超时。文档特别推荐:

    请在打开串口时指定一个超时时间。 否则,如果没有收到换行符,它可能会永远阻塞。

    您能否在 PC 和微型计算机两端实现该变通方案?

    解决方法 2:非阻塞读取行

    许多人实现了一个非阻塞的 readline() 子例程,它的工作原理如下:

    def try_readline():
    
    • 串行端口中有新字节,还是串行缓冲区为空? (也许可以通过inWaiting() 之类的方式进行检查)。
    • 如果它仍然是空的,try_readline() 会立即返回空字符串。
    • (可选)距离我们上一次得到一个字节已经很久了吗?如果是这样,请将缓冲区重置为空字符串。
    • 从串行端口读取一个字节,并将其附加到内部缓冲区的末尾。
    • 缓冲区(比任何有效消息长几个字节)是否即将溢出?如果是,则将缓冲区重置为空字符串。
    • 我们刚刚读取的字节是换行符吗?
    • 如果不是换行符,try_readline() 会立即返回空字符串。
    • 嘿,这是换行符。终于!
    • 将消息从内部缓冲区复制到返回字符串。
    • 将缓冲区重置为空字符串。
    • try_readline() 在返回字符串中返回消息。

    进一步讨论

    无论采用哪种解决方法, 设置您的程序,使其 定期无条件地 -- try_readline 函数是否返回空字符串以外的任何内容;以及 readline() 函数是否超时或接收到有效消息—— 无条件发送信息行。

    您可能还会想,如果您在消息中途插入串行电缆,并且您的软件收到半条消息后跟一个换行符,那么究竟会发生什么。 另外,如果发送器连续发送一堆换行符会发生什么?

    双向通信是人类几乎无意识地做的事情之一,因此我们对它的复杂程度感到惊讶。

    p.s.:你见过PC-to-Arduino with Pyserial这个小程序吗?

    p.s.:也许您可以浏览一下Serial Programming Wikibook 的最新草稿并填补一两个缺口,或者至少帮助我们指出哪些缺口需要填补?

    【讨论】:

    • 太好了,非常感谢您的详细解释。我将根据您的提示进行一些研究/测试,并将更新!
    • 所以我认为原因是我用 readline 启动了微控制器和 python 代码。一旦我翻转 python 代码首先执行 writeline,它就不再挂起。这些技巧仍然有用。我暂时失去了沟通,所以超时会有所帮助,我认为围绕 2 的工作将使它成为一个更强大的过程。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2014-09-10
    • 1970-01-01
    相关资源
    最近更新 更多