Страницы

Поиск по вопросам

четверг, 23 января 2020 г.

COM Порт в python: как ждать данные, не нагружая CPU

#python #serial #com_порт


Есть программа, которая принимает данные из COM порта. Возникла проблема, как заставить
программу ждать данные и не выполняться дальше? 

При использовании бесконечного цикла while, программа нагружает ЦП до 50%.

forchar = 0
idcom = []

ser = serial.Serial(
    port = 'COM2',\
    baudrate=2400,\
    parity=serial.PARITY_NONE,\
    stopbits=serial.STOPBITS_ONE,\
    bytesize=serial.EIGHTBITS,\
    timeout=0)

print("connected to: " + ser.portstr)
count=1

while True:
    for line in ser.readline():
        forchar = forchar + 1
        idcom.append(line)
    if forchar >= 13:
        break

    


Ответы

Ответ 1



У вас порт настроен на неблокирующее чтение, так как установлен timeout=0, Либо уберите эту опцию, либо напишите timeout=None, тогда порт у вас будет ждать данные, до тех пор пока они не появятся. Если же вам все таки нужно неблокирующее соединение, то в цикл while надо добавить небольшую задержку time.sleep, тогда нагрузка процессора уйдет.

Ответ 2



Еще есть такая конструкция: while True: while ser.inWaiting() == 0: pass #необходимая работа с данными... Тут выполняется проверка на наличие данных в очереди порта. Такой способ ожидания, ЦП не нагружает совсем.

Ответ 3



Так понятнее while ser.inWaiting(): data = ser.read() пока в порте нет данных чтение не выполняетса

Ответ 4



допустим def recCode(data):# и поехали проверять по условиям - например if data == (b'\x05sRR\r\n') print(u'я получил сообщение ') while True: while ser.inWaiting() > 0:# даже если мы поставим без условия data = ser.readline() recCode(data) при таком построении алгоритма while True будет выполнятся постоянно и recCode(data) будет вызываться при приёме каждого символа (байта) в порт, а если 1 количество байтов в пакете не известно(работа по стартовому и конечному символу) или 2 надо ещё обслуживать графический интерфейс и в добавок 3 отправлять данные (сообщения ) в порт , то некоторые символы (принимаемые ) могут потеряться , да и программа (не зависимо сколько ядер у процессора ) будет занята только этим , а если надо 2 порта обслуживать ? в ассемблере (avr контроллеры), в VB6(x86 и 64), есть возможность применения аппаратных прерываний , т е событие (приём символа портом ) может (при правильной настройке аппаратного узла контроллера или машины), остановить выполнение (или перенаправить поток команд) основного тела программы , выполнить подпрограмму (прерывание) приёма одного символа с возможностью формирования строки по стартовым и конечным символам (\х05 и \r\n) и после приёма конечного символа непосредственно в подпрограмме (если условий мало ) обработать - изменив переменные или, выставить флаг готовности принятого сообщения для основной программы , или изменив глобальную переменную для других процессов. тогда while True может заниматься (допустим ) проверкой флагов готовности сообщения одного , второго , н-ого порта , обновлением процессов графической оболочки типа root=Tk() ..(графические элементы ) , и в место root.vfinloop() использовать root.update(), тк как графические интерфейсы управления достаточно медленные процессы

Комментариев нет:

Отправить комментарий