Python pyserial одна задержка записи - PullRequest
0 голосов
/ 22 марта 2020

У меня странная проблема с pyserial, с использованием Python 3.6.9, под управлением WSL Ubuntu 18.4.2 LTS

Я настроил простую функцию для отправки команд GCODE в последовательный порт:

def gcode_send(data):
    print("Sending: " + data.strip())
    data = data.strip() + "\n"  # Strip all EOL characters for consistency
    s.write(data.encode())  # Send g-code block to grbl

    grbl_out = s.readline().decode().strip()
    print(grbl_out)

Это вроде работает, но каждая отправляемая команда удерживается до отправки следующей.

например,

  1. I отправить G0 X0> устройство не реагирует
  2. отправляю G0 X1> устройство реагирует на G0 X0
  3. отправляю G1 X0> устройство реагирует на G0 X1
  4. и так далее ...

Мой установочный код:

s = serial.Serial(com, 115200)

s.write("\r\n\r\n".encode())  # Wake up grbl
time.sleep(2)  # Wait for grbl to initialize
s.flushInput()  # Flush startup text in serial input

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

Ответы [ 2 ]

0 голосов
/ 22 марта 2020

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

Это печатный терминал для использования консоли PyS60 Python на смартфонах Nokia серии Symbian через Bluetooth. Работает фантастически.


from serial import *
from thread import start_new_thread as thread
from time import sleep
import sys, os

# Original code works on Linux too
# The following code for gettin one character from stdin without echoing it on terminal
# has its Linux complement using tricks from Python's stdlib getpass.py module
# I.e. put the terminal in non-blocking mode, turn off echoing and use sys.stdin.read(1)
# Here is Win code only (for brevity):
import msvcrt

def getchar ():
    return msvcrt.getch()

def pause ():
    raw_input("\nPress enter to continue . . .")

port = raw_input("Portname: ")
if os.name=="nt":
    nport = ""
    for x in port:
        if x.isdigit(): nport += x
    port = int(nport)-1

try:
    s = Serial(port, 9600)
except:
    print >> sys.stderr, "Cannot open the port!\nThe program will be closed."
    pause()
    sys.exit(1)

print "Port ready!"
running = 1

def reader():
    while running:
        try:
            msg = s.read()
            # If timeout is set
            while msg=="":
                msg = s.read()
            sys.stdout.write(msg)
        except: sleep(0.001)

thread(reader,())

while 1:
    try: c = getchar()
    except Exception, e:
        running = 0
        print >> sys.stderr, e
        s.write('\r\n\x04')
        break
    if c=='\003' or c=='\x04':
        running = 0
        s.write('\r\n\x04')
        break
    s.write(c)

s.close()
pause()

0 голосов
/ 22 марта 2020

Здесь может быть много проблем, но будьте уверены, что это не вызывает псевериал. Он использует API базовой ОС для связи с драйвером UART. Это значит, что сначала вы должны протестировать свой код с реальным Linux, чтобы увидеть, вызывает ли его WSL. Т.е. правильно ли синхронизированы буферы Linux и Windows UART. Я сожалею, что не могу сказать, есть ли проблема в вашем коде или нет, потому что я не знаю устройство, которое вы используете, поэтому я не могу догадаться, что происходит на его конце канала связи. Имейте в виду, что один Windows может вести себя странно в лучших обстоятельствах, поэтому приготовьтесь к некоторым разочарованиям здесь. Проверьте драйверы материнской платы или конвертера USB2Serial, а также все, что вы используете.

Следующее, вы должны знать, что иногда связь сбивается с толку, если не установлены тайм-ауты. Почему? Никто на самом деле не знает. Поэтому попробуйте установить время ожидания. Проверьте, нужно ли вам программное обеспечение Xon / Xoff включено или нет, а также другие параметры RS232, которые могут потребоваться устройству, с которым вы обмениваетесь данными.

Также посмотрите, что происходит с s.readline (), я лично не использовал бы это. Таймауты могут помочь, или вы можете использовать s.read (1024) с таймаутами. Я не помню сейчас, но посмотрим, поддерживает ли pyserial асинхронную связь. Если это так, вы можете попробовать использовать его вместо стандартного режима блокировки.

Кроме того, проверьте, нужно ли принудительно вызывать sh последовательный буфер после s.write () или добавить спящий режим после него. Может случиться, что устройство не получит сообщение, но запрос на чтение активирован. Поскольку устройство не получило команду, оно не отвечает. После отправки другой команды буфер ввода-вывода очищается, а предыдущий доставляется и т. Д. Последовательное общение - это весело, но когда оно попадает в ловушку, оно может быть настоящим буквой А в А, поверьте мне.

Оу, PS Проверьте, отправляет ли устройство «\ r \ n \ r \ n» или Только "\ r \ n", или "\ r" или "\ n" в ответе. s.readline () может запутаться. Для начала попробуйте поместить два s.readline () один за другим и распечатать каждый вывод. Если устройство отправляет двойной EOL, то один s.readline () останавливается на пустой строке, и ваша программа получает пустой ответ, когда вы отправляете другую команду s.readline () проходит через буфер и возвращает полную строку, которая уже там, но не читал раньше.

...