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