Arduino отправляет неверные данные ТОЛЬКО, когда не подключен при запуске моего приложения

Я пытаюсь написать небольшое приложение для чтения датчиков с датчиком освещенности, подключенным к Arduino, которое записывает информацию с датчика по последовательному порту. Я написал программу на Python для чтения данных из последовательного порта. Хорошей новостью является то, что моя программа работает совершенно нормально... только если я удостоверюсь, что Arduino USB подключен к моему ноутбуку, прежде чем запускать свою программу Python.

Я сам забыл подключить Arduino перед запуском программы, из-за чего она может зависнуть... пока вы не поймете и не подключите Arduino обратно. Было бы неплохо иметь окно, помогающее пользователям, если они когда-либо сделают та же ошибка.

Вот скетч Arduino, который я запускаю на своем Arduino.

int photoTran = A1; 
  int reading = 0;

void setup() {
  pinMode(photoTran, INPUT);
  Serial.begin(9600); 
}

void loop() {
  // Мы просто читаем значение на AnalogPin
  reading = analogRead(photoTran); 
  Serial.println(reading); 
  delay(100); 

}  

Вот небольшая часть скрипта Python, которая проверяет, подключен ли Arduino, прежде чем я перейду к основной части своего приложения. Когда я подключаю Arduino перед запуском скрипта Python, иногда может потребоваться несколько попыток перед подключением. (К вашему сведению: window(), кнопка, значения и переменные взяты из используемой мной среды PySimpleGUI.)

connected = False
while connected == False:
    button, values = window.Read(timeout=300)
    if button in (None, 'Exit'):
        break
    try:
        print("Attempting to connect")
        SER = serial.Serial(serial_port, baud_rate, timeout=0.1)
        connected = True
        ser.append(SER)
    except:
        time.sleep(0.1)
        attempts += 1
        window.FindElement('attempts').Update(attempts)
window.close()

# User exited from the GUI connection window
if not connected:
    sys.exit(0)

Позже в моем коде Python я хочу прочитать данные датчика, поступающие к нам от Arduino. ReadArduino и CleanThe — это функции, которые я использую для чтения данных с Arduino.

def ReadArduino( serialCon ):
""" Try to read in a value from the Arduino. Sometimes we might read a value from the serial
    port before the arduino has sent anything. In such cases we will wait a small time, and read again.
    Until we pick up our first non empty integer value."""
while True:
    val = serialCon.readline()
    print(val)
    val = cleanThe(str(val))
    if val != '':
        return val

def cleanThe( lineVal ):
""" The Arduino returns non-clean data back to us.
    We need to remove all the non-integer values to get
    a nice plottable integer value. Will accept '.' unconditionally for now,
    we may have to add conditions later. """
S = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.'}
clean = ''
for char in lineVal:
    if char in S:
        clean += char
return clean

Теперь самое запутанное. Когда я запускаю приложение без подключения Arduino к компьютеру. Он застревает в цикле whileconnected == False: while выше. Это именно то, что я хочу. Затем, когда я подключаю его, последовательный порт настраивается, и мы выходим из цикла. У меня даже есть объект последовательного порта, из которого я читаю.

Однако, когда я читаю из последовательного порта, я получаю обратно мусорные шестнадцатеричные значения без каких-либо признаков каких-либо полезных целочисленных значений, которые я ожидал бы.

Вот несколько примеров необработанных значений val, которые считываются, когда скрипт Python запускается с подключенным Arduino перед запуском: б'336\r\n' б'349\r\n' б'343\r\n' б'322\r\n'

Тогда вот вывод, который я получаю, когда Arduino не был подключен к моему компьютеру перед запуском скрипта Python.

b'\xe0\x00\xe0\x00\x00\xe0\x00\x00\x00\x00\x00\xe0\xe0\x00\x00\xe0\x00\xe0\x00\x00\xe0\x00\x00\x00\x00\x00\xe0\xe0\x00\x00\xe0\x00\xe0\x00\x00\xe0\x00\x00\xe0\x00\x00\xe0\xe0\x00\x00\xe0\x00\xe0\x00\x00\x00\x00\x00\xe0\x00\x00\xe0\xe0\x00\x00\xe0\x00\xe0\x00\x00\x00\x00\x00\xe0\xe0\x00\xe0\xe0\x00\x00\xe0\x00\xe0\x00\x00\x00\x00\x00\x00\xe0\x00\xe0\xe0\x00\x00\xe0\x00\xe0\x00\x00\x00\x00\x00\xe0\x00\x00\xe0\xe0\x00\x00\xe0\x00'

b'\x00\x00\x00\xe0\x00\x00\xe0\x00\x00\xe0'

Я заметил, что когда я запускаю свой скрипт с подключенным Arduino с самого начала (т.е. рабочий случай). Первое значение, которое я считываю с Arduino, представляет собой шестнадцатеричный мусор того же типа:

b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

Похоже, что в рабочем случае все шестнадцатеричные данные отправляются в одной строке. Где, как и в нерабочем случае, эти шестнадцатеричные значения, похоже, отправляются с перерывами меньшими порциями. Возможно, я мог бы добавить проверку в код Arduino, чтобы записывать значения обратно в последовательный порт, только если они хорошие? Я понимаю, что это может быть скорее проблема с последовательным интерфейсом Python, чем проблема с Arduino, дайте мне знать, если это так, и я перенесу пост.

Кто-нибудь сталкивался с подобной проблемой раньше?

, 👍0

Обсуждение

В зависимости от загрузчика вы можете получить его попытки подключиться к его аналогу на вашем ПК. Вы проверяли, как "мусор" сопоставляется с протоколом загрузчика? -- Еще одна мысль: байты xe0 и x00 могут указывать на непревзойденную скорость передачи данных., @the busybee

Я знаю, что опоздал на этот вопрос на месяц, но просто из любопытства, вы решили его? Вы пробовали использовать Serial.flush() после Serial.println в коде Arduino?, @ChatterOne

Нет, мне пока не удалось найти работающее решение. Я был бы очень заинтересован, чтобы найти исправление мысли. Попробую, спасибо за предложение., @Matthew Naybour

Хорошо, поэтому после того, как я повозился, я нашел довольно разумное решение проблемы. Раньше мое приложение мгновенно входило в бесконечно повторяющийся цикл while, пытаясь подключиться к Arduino через последовательный порт, как только оно началось, ожидая успешного подключения к указывают, что устройство было подключено., @Matthew Naybour

Вместо этих автоматических повторных попыток подключения я запрограммировал кнопку «Подключиться» в графическом интерфейсе своего приложения с окном, говорящим о подключении устройства перед попыткой подключения. Я думаю, что автоматические попытки подключения к arduino сразу после запуска приложения означали, что успешное последовательное соединение произойдет, пока arduino находится в какой-то фазе настройки. Позволяя пользователю щелкнуть соединение, всегда есть некоторая разумная задержка между подключением Arduino к моему ноутбуку и первой попыткой последовательного соединения., @Matthew Naybour


2 ответа


0

На стороне Arduino сделайте код неблокирующим:

 unsigned long timeStamp = 0;
 unsigned long timerDelay = 1000; // 1 секунда

 setup(){....}

void loop() {
// Мы просто читаем значение на AnalogPin
 if (millis() - timestamp > timerDelay ) {
     reading = analogRead(photoTran); 
     Serial.print(reading); // вместо println, который отправляет дополнительные \r\n
     timeStamp =millis();  // сбросить таймер вместо delay(100);
 }
}

На стороне Phyton попробуйте реализовать подпрограмму, ожидающую первого символа, а затем начните чтение со следующего сообщения. 1 секунды между отправками на Arduino должно быть достаточно, чтобы обеспечить его работу. Мусорные символы могут быть последовательностью инициализации из драйвера порта — это не может исходить из вашего кода,

,

Эй, спасибо за ответ! Я попробовал это на стороне Arduino, но я все еще сталкиваюсь с такими же проблемами. Одна вещь, которую я пробовал, — это закрытие последовательного соединения в python после его первой установки. Затем снова открыть его позже, когда я действительно хочу начать считывать данные с Arduino. Это изменение вызвало ошибку другого рода. Когда я пытаюсь повторно открыть последовательную связь во второй раз, я получаю сообщение об ошибке в своей консоли Python: [Errno 16] не удалось открыть порт /dev/ttyACM0: [Errno 16] Устройство или ресурс занят: '/ dev/ttyACM0', @Matthew Naybour


1

Чтобы явно показать, что я изменил в своем коде Python, я решил ответить на свой вопрос. Решение, которое я нашел, оказалось в Python, но другие предложения были полезны для очистки вывода моего Arduino. Вот старое решение для автоматического подключения.

connected = False
window = sg.Window('Arduino Connection').Layout(layout)
attempts = 0
while connected == False:
    print("In connection while loop")
    button, values = window.Read(timeout=300)
    if button in (None, 'Exit'):
        break

    try:
        print("Attempting to connect")
        SER = serial.Serial(serial_port, baud_rate, timeout=0.02)
        print(SER)
        connected = True
        ser.append(SER)
    except:
        time.sleep(0.1)
        attempts += 1
        window.FindElement('attempts').Update(attempts)

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

    connected = False
window = sg.Window('Arduino Connection').Layout(layout)
attempts = 0
while connected == False:
    print("In connection while loop")
    button, values = window.Read(timeout=300)
    if button in (None, 'Exit'):
        break
    if button == 'Ok':
        try:
            print("Attempting to connect")
            SER = serial.Serial(serial_port, baud_rate, timeout=0.02)
            print(SER)
            connected = True
            ser.append(SER)
        except:
            time.sleep(0.1)
            attempts += 1
            window.FindElement('attempts').Update(attempts)
,