Бесконечный l oop из «Во время обработки вышеупомянутого исключения произошло другое исключение», когда последовательное соединение прервано - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть Arduino, который правильно связывается с моим Ma c через последовательный порт с помощью библиотеки pySerialTransfer, работающей в течение нескольких часов. Затем происходит какое-то прерывание последовательного интерфейса - хотя я не смог определить причину, когда это происходит в одночасье, я довольно легко могу воспроизвести поведение, просто отключив USB-кабель Arduino от ноутбука. Код python на моем ноутбуке продолжает работать, но попадает в эту бесконечную ошибку l oop:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/pySerialTransfer/pySerialTransfer.py", line 257, in send
    self.connection.write(stack)
  File "/usr/local/lib/python3.7/site-packages/serial/serialposix.py", line 571, in write
    raise SerialException('write failed: {}'.format(e))
serial.serialutil.SerialException: write failed: [Errno 6] Device not configured
SENT (12 byte struct): (0, -55.836434114277004, 31.732435543849192)
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/serial/serialposix.py", line 537, in write
    n = os.write(self.fd, d)
OSError: [Errno 6] Device not configured

During handling of the above exception, another exception occurred:

Кажется, я не могу перехватить исключения, используя любые блоки try / кроме в моем python код, чтобы я мог обнаружить это и перезапустить или попытаться переподключиться. Ниже мой текущий python код - оцените любые указатели! Спасибо.

#!/usr/bin/python3

import sys
import time

import arduino
import messageboard

VERBOSE = arduino.VERBOSE
SN = '75835343130351802272'  # arduino uno serial

SIMULATE_ARDUINO = arduino.SIMULATE_ARDUINO
if '-s' in sys.argv:
  SIMULATE_ARDUINO = True

COMMAND_DELAY_TIME = 1  # send a command to servos every n seconds


def main():
  servos = arduino.OpenArduino(sn=SN)
  format_string = '<lff'
  format_byte_size = arduino.SizeOf(format_string)
  azimuth=90

  while True:

    if not servos and not SIMULATE_ARDUINO:
      servos = arduino.OpenArduino(sn=SN)
      if VERBOSE:
        print('Reopening connection')

    if servos or SIMULATE_ARDUINO:
      if azimuth == 90:
        azimuth = 85
      else:
        azimuth = 90
      values = (0, azimuth, 0)

      arduino.StuffObject(servos, values, format_string, format_byte_size)
      if not SIMULATE_ARDUINO:
        servos.send(format_byte_size)


    time.sleep(COMMAND_DELAY_TIME)


if __name__ == "__main__":
  main()

1 Ответ

0 голосов
/ 25 апреля 2020

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

Тем не менее, единственное, что я мог обнаружить, было то, что в stderr была зарегистрирована ошибка, и так что, если бы я мог перенаправить это и обнаружить там новую ошибку, то это привело бы меня на правильный путь. Введите это руководство , которое подтолкнуло меня к этому решению:

#!/usr/bin/python3

import sys
import time
import io

import arduino
import messageboard
import contextlib

VERBOSE = arduino.VERBOSE
SN = '75835343130351802272'  # arduino uno serial

SIMULATE_ARDUINO = arduino.SIMULATE_ARDUINO
if '-s' in sys.argv:
  SIMULATE_ARDUINO = True

COMMAND_DELAY_TIME = 1  # send a command to servos every n seconds


def main():
  servos = arduino.OpenArduino(sn=SN)
  format_string = '<lff'
  format_byte_size = arduino.SizeOf(format_string)
  azimuth=90

  while True:

    if not servos and not SIMULATE_ARDUINO:
      servos = arduino.OpenArduino(sn=SN)
      if VERBOSE:
        print('Reopening connection')

    if servos or SIMULATE_ARDUINO:
      if azimuth == 90:
        azimuth = 85
      else:
        azimuth = 90
      values = (0, azimuth, 0)

      # Detects any exceptions that print to stderr but are not raised to caller
      with io.StringIO() as buf, contextlib.redirect_stderr(buf):
        arduino.StuffObject(servos, values, format_string, format_byte_size)
        if not SIMULATE_ARDUINO:
          servos.send(format_byte_size)

        # if there's an exception, probably the connection failed; clear the connection
        # so that it can be reopened at top of loop
        if buf.getvalue():
          servos = None

    time.sleep(COMMAND_DELAY_TIME)


if __name__ == "__main__":
  main()

Это приводит к следующему выводу stdio, когда я вручную отключаю USB-кабель от Arduino, а затем снова подключаю его, 2x во время тестирования.

$ python3 arduino_servo_test.py 
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
Reopening connection
Reopening connection
Reopening connection
Reopening connection
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
Reopening connection
Reopening connection
Reopening connection
Reopening connection
Reopening connection
Reopening connection
Reopening connection
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)
SENT (12 byte struct): (0, 85, 0)
SENT (12 byte struct): (0, 90, 0)

Проблема решена - возможно, не самое элегантное решение, но, похоже, работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...