Наиболее вероятная проблема: взаимоблокировка
Немного расширив пост Джеффа Лафлина:
Многие люди сталкивались с этой проблемой взаимоблокировки:
- ПК не может отправить никаких символов, потому что он находится в середине блокирующей команды 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