Двунаправленная связь между микроконтроллером и pyserial

Я использую 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')

person user1473877    schedule 22.06.2012    source источник


Ответы (2)


Вполне вероятно, что readline блокируется в ожидании символа завершения строки; некоторая комбинация возврата каретки и/или перевода строки. Ваш микроконтроллер должен отправить один или оба этих символа, прежде чем readline вернется. Вы должны проверить pyserial docs, чтобы узнать, какие символы строковых терминов ожидает readline, и убедиться, что ваш UC отправляет их, заглянув в терминал или даже выполнив шестнадцатеричный дамп в последовательном потоке.

person Jeff Laughlin    schedule 22.06.2012
comment
Привет, Джефф, спасибо за ответ, я ценю это. Странно то, что если у меня просто есть программа, которая отправляет данные из микроконтроллера в программу python, она работает нормально. Я делаю предположение, что включаю правильное окончание строки. Дайте мне знать, если я отклонюсь от цели. Я также создал успешную программу, пишущую с python на микроконтроллер. Только когда я комбинирую два, у меня возникают проблемы. Любые идеи? - person user1473877; 23.06.2012
comment
Я просто думаю, что вы, возможно, указываете, что вам не нужно правильное завершение строки, если это просто микроконтроллер, записывающий одно и то же снова и снова и не пытающийся читать? - person user1473877; 23.06.2012

Наиболее вероятная проблема: взаимоблокировка

Немного расширив пост Джеффа Лафлина:

Многие люди сталкивались с этой проблемой взаимоблокировки:

  • ПК не может отправить никаких символов, потому что он находится в середине блокирующей команды readline(), ожидая, пока микроконтроллер отправит символ новой строки.
  • Микроконтроллер не может отправить никаких символов, потому что он находится в середине блокирующей команды readline(), ожидая, пока ПК отправит символ новой строки.

Оба в конечном итоге вечно ждут, пока другая сторона что-то сделает.

Существует множество способов, которыми система двунаправленной связи может застрять в этом тупике. Возможно, символ новой строки, проходящий по последовательному кабелю, немного искажается настолько, что больше не выглядит как новая строка. Возможно, длинная строка была передана быстрее, чем получатель мог ее обработать, переполнив какой-то буфер, и одним из потерянных байтов был символ новой строки. Неважно, идет ли эта новая строка в направлении микро-ПК или ПК-микро; мы застряли в том же тупике в любом случае.

Временное решение 1: тайм-аут

документация для пакета pyserial, который загружается с помощью "import serial", имеет одну частичную работу: вокруг этой проблемы: установите тайм-аут. Документация конкретно рекомендует:

Укажите тайм-аут при открытии последовательного порта. В противном случае он может заблокироваться навсегда, если не будет получен символ новой строки.

Можете ли вы реализовать этот обходной путь на обоих концах, ПК и микро?

Временное решение 2: неблокирующая строка чтения

Многие люди реализуют неблокирующую подпрограмму readline(), которая работает примерно так:

def try_readline():
  • В последовательный порт пришел новый байт или последовательный буфер пуст? (Возможно, проверьте что-то вроде inWaiting() ).
  • Если он по-прежнему пуст, функция try_readline() немедленно возвращает нулевую строку.
  • (необязательно) Прошло ли много времени с тех пор, как мы в последний раз получали байт? Если это так, сбросьте буфер до пустой строки.
  • Прочитайте байт из последовательного порта и добавьте его в конец внутреннего буфера.
  • Буфер (который на несколько байтов длиннее, чем любое действительное сообщение) вот-вот переполнится? Если это так, сбросьте буфер в пустую строку.
  • Является ли байт, который мы только что прочитали, символом новой строки?
  • Если это не символ новой строки, функция try_readline() немедленно возвращает нулевую строку.
  • Эй, это символ новой строки. Окончательно!
  • Скопируйте сообщение из внутреннего буфера в возвращаемую строку.
  • сбросить буфер на пустую строку.
  • try_readline() возвращает сообщение в возвращаемой строке.

Дальнейшее обсуждение

При любом обходном пути настройте свою программу так, чтобы она периодически и безоговорочно -- независимо от того, возвращает ли функция try_readline когда-либо что-либо, кроме нулевой строки; и независимо от того, истекло ли время ожидания функции readline() или получено ли действительное сообщение - безоговорочно отправляет строки информации.

Вы также можете подумать о том, что именно должно произойти, если вы подключите последовательный кабель на середине сообщения, а ваше программное обеспечение получит половину сообщения, за которым следует новая строка. Кроме того, что должно произойти, если передатчик отправляет кучу новых строк подряд?

Двустороннее общение — это одна из тех вещей, которые люди делают почти бессознательно, и поэтому мы удивляемся, насколько это сложно на самом деле.

p.s.: Вы видели эту маленькую программу, которая выполняет компьютер-to-Arduino с Pyserial?

p.s.: Возможно, вы могли бы просмотреть последний черновик Викикниги по последовательному программированию и заполнить один или две зияющие дыры или, по крайней мере, помочь нам, указав, где дыры, которые нужно заполнить?

person David Cary    schedule 23.06.2012
comment
Отлично, большое спасибо за подробное объяснение. Я собираюсь провести небольшое исследование / тестирование на основе ваших советов и обновить! - person user1473877; 23.06.2012
comment
Поэтому я думаю, что причина была в том, что я запускал код микроконтроллера и Python с помощью строки чтения. Как только я перевернул код Python, чтобы сначала выполнить строку записи, он больше не зависал. Однако эти советы по-прежнему полезны. Я на мгновение потерял связь, поэтому тайм-аут помогает, и я думаю, что работа вокруг 2 сделает этот процесс более надежным. Спасибо! - person user1473877; 11.07.2012