微控制器和pyserial之间的双向通信

时间:2012-06-22 05:24:01

标签: python microcontroller pyserial bidirectional

我使用的是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')

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

扩展Jeff Laughlin的帖子:

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

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

两人最终都在等待另一方做某事。

双向通信系统有很多方法可以陷入这种僵局。 也许穿过串行电缆的换行符会有一点点损坏,以至于它不再像换行符那样。 也许一个长字符串的传输速度比接收者可以处理的速度快,溢出一些缓冲区,其中一个丢失的字节是换行符。 如果这条换行符是在微到PC或PC到微方向上进行的,那就无所谓了;无论如何,我们陷入了同样的僵局。

解决方法1:超时

由"导入序列"加载的documentation for the pyserial package有一个部分解决这个问题的方法: 设置超时。文档特别建议:

  

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

你能在两端,PC和micro上实现这种解决方法吗?

解决方法2:无阻塞读取线

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

def try_readline():
  • 串口中是否有新字节,或者串口缓冲区是空的? (也许请查看inWaiting())。
  • 如果它仍为空,则try_readline()会立即返回空字符串。
  • (可选)自从我们上次获得一个字节以来已经很长时间了吗?如果是这样,请将缓冲区重置为空字符串。
  • 从串口读取一个字节,并将其附加到内部缓冲区的末尾。
  • 缓冲区(比任何有效消息长几个字节)是否会溢出?如果是这样,请将缓冲区重置为空字符串。
  • 我们刚刚读取换行符的字节吗?
  • 如果它不是换行符,则try_readline()会立即返回null字符串。
  • 嘿,这是换行符。终于来了!
  • 将消息从内部缓冲区复制到返回字符串。
  • 将缓冲区重置为空字符串。
  • try_readline()返回返回字符串中的消息。

进一步讨论

无论是解决方法, 设置你的程序,使它 定期无条件地 - try_readline函数是否返回除null字符串以外的任何内容;以及readline()函数是否超时或收到有效消息 - 无条件地发出信息。

如果您将串行电缆插入到消息的中途,并且软件收到半消息后跟换行符,您可能还会想到应该发生什么。 此外,如果发送器连续发送一串新行,会发生什么?

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

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

ps:也许你可以浏览Serial Programming Wikibook的最新草稿并填入一个或两个间隙孔,或者至少通过指出哪些洞需要填充来帮助我们?