Pyserial readline() навсегда зависает в программе без чтения последовательных данных

При вызове функции pyserial.readline() моя программа зависает. Я выполнил трассировку программы, и нижний цикл продолжает повторяться.

transport.py(47):             self.sensor_data = self.serif.readline()
 --- modulename: serialposix, funcname: read
serialposix.py(477):         if not self.is_open:
serialposix.py(479):         read = bytearray()
serialposix.py(480):         timeout = Timeout(self._timeout)
 --- modulename: serialutil, funcname: __init__
serialutil.py(125):         self.is_infinite = (duration is None)
serialutil.py(126):         self.is_non_blocking = (duration == 0)
serialutil.py(127):         self.duration = duration
serialutil.py(128):         if duration is not None:
serialutil.py(129):             self.target_time = self.TIME() + duration
serialposix.py(481):         while len(read) < size:
serialposix.py(482):             try:
serialposix.py(483):                 ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout.time_left())
 --- modulename: serialutil, funcname: time_left
serialutil.py(139):         if self.is_non_blocking:
serialutil.py(141):         elif self.is_infinite:
serialutil.py(144):             delta = self.target_time - self.TIME()
serialutil.py(145):             if delta > self.duration:
serialutil.py(150):                 return max(0, delta)
serialposix.py(484):                 if self.pipe_abort_read_r in ready:
serialposix.py(491):                 if not ready:
serialposix.py(493):                 buf = os.read(self.fd, size - len(read))
serialposix.py(496):                 if not buf:
serialposix.py(503):                 read.extend(buf)
serialposix.py(516):             if timeout.expired():
 --- modulename: serialutil, funcname: expired
serialutil.py(135):         return self.target_time is not None and self.time_left() <= 0
 --- modulename: serialutil, funcname: time_left
serialutil.py(139):         if self.is_non_blocking:
serialutil.py(141):         elif self.is_infinite:
serialutil.py(144):             delta = self.target_time - self.TIME()
serialutil.py(145):             if delta > self.duration:
serialutil.py(150):                 return max(0, delta)
serialposix.py(481):         while len(read) < size:
serialposix.py(518):         return bytes(read)

Настройки серийного номера, которые я использую для своего интерфейса, определенного как «serif», следующие.

    self.serif = serial.Serial('/dev/ttyS1', 9600)
    self.serif.bytesize = serial.EIGHTBITS
    self.serif.parity = serial.PARITY_NONE
    self.serif.stopbits = serial.STOPBITS_ONE
    self.serif.timeout = 0.3

Я попытался добавить функцию self.serif.reset_input_buffer() перед запуском функции чтения, однако это, похоже, ухудшило ситуацию.

вот копия рассматриваемой функции перед функцией readline().

def rcv_data(self):
    """Receives data, cleans it and returns it to main()"""
    # CHECKS FOR DATA IN BUFFER
    serial_buffer = self.serif.inWaiting()
    if serial_buffer > 0:
        cnt = 0
        print("serial_buffer = %i" % serial_buffer)
        while self.serif.read().encode('hex') != '02':
            cnt += 1
            serial_buffer -= 1
        print("Eliminated %i peices of garbage" % (cnt))
        # Reads data from the buffer
        self.sensor_data = self.serif.readline()

Я не могу понять, почему этот код застревает в цикле serialposix.py. Если кто-нибудь может мне помочь, я был бы признателен!

Спасибо и дайте мне знать, если мне нужно отправить дополнительную информацию.


person rustysys-dev    schedule 13.02.2018    source источник


Ответы (1)


РЕДАКТИРОВАТЬ

Почему у меня это работало раньше, больше не является загадкой. Источник питания, который питал как мое устройство, так и подтягивающие/подтягивающие резисторы схемы RS485, был нестабилен. Таким образом, я получал шум там, где должен был быть мой SOF или EOF, и поэтому программа продолжала читать вечно. При этом я по-прежнему придерживался приведенного ниже обходного пути, поскольку он более понятен в отношении того, что я делаю (хотя и дольше...)

Кроме того, я добавил в перерыве к приведенному ниже ответу на случай, если SOF или EOF не могут быть найдены за определенное количество циклов чтения.

РЕДАКТИРОВАТЬ_END

Не совсем ответ, а обходной путь. Я начну с того, что подчеркну следующее.

  1. readline() зацикливается, потому что ожидает EOF \n (0x11 в шестнадцатеричном формате) i, а мои последовательные данные никогда этого не предоставляли. Почему у меня это работало раньше, было загадкой.
  2. Я до сих пор понятия не имею, почему это не прекращает цикл после установленного тайм-аута.

Мой обходной путь заключался в создании моей собственной функции readline() в некотором смысле и указании моего собственного EOF. Для этого я использовал следующий код.

def readline(self):
    SOF = '02'
    EOF = '03'
    # FIND START OF FRAME
    while serif.read().encode('hex') != SOF:
        continue
    # RECORD UNTIL END OF FRAME
    while True:
        temp = serif.read()
        if temp.encode('hex') == EOF:
            break
        else:
            sensor_data += temp

Моя исходная функция теперь будет выглядеть так.

def rcv_data(self):
    """Receives data cleans it and returns it to main()"""
    # CHECKS FOR DATA IN BUFFER
    if serif.inWaiting() > 0:
        readline()
    return sensor_data
person rustysys-dev    schedule 19.02.2018