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, дайте мне знать, если это так, и я перенесу пост.
Кто-нибудь сталкивался с подобной проблемой раньше?
@Matthew Naybour, 👍0
Обсуждение2 ответа
На стороне 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
Чтобы явно показать, что я изменил в своем коде 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)
- Может ли Arduino/Python получать данные датчика и управлять серводвигателем одновременно?
- Какова работа pulseIn?
- Сколько датчиков может поддерживать один модуль Arduino?
- Получение BPM из данного кода
- Как подключить более 10 датчиков к Arduino uno r3
- Как использовать два ультразвуковых датчика для управления двигателем 5 Вольт?
- Чтение датчика давления от 4 до 20 мА с использованием uno
- Последовательная связь Arduino с Python: отправка массива
В зависимости от загрузчика вы можете получить его попытки подключиться к его аналогу на вашем ПК. Вы проверяли, как "мусор" сопоставляется с протоколом загрузчика? -- Еще одна мысль: байты
xe0
иx00
могут указывать на непревзойденную скорость передачи данных., @the busybeeЯ знаю, что опоздал на этот вопрос на месяц, но просто из любопытства, вы решили его? Вы пробовали использовать
Serial.flush()
послеSerial.println
в коде Arduino?, @ChatterOneНет, мне пока не удалось найти работающее решение. Я был бы очень заинтересован, чтобы найти исправление мысли. Попробую, спасибо за предложение., @Matthew Naybour
Хорошо, поэтому после того, как я повозился, я нашел довольно разумное решение проблемы. Раньше мое приложение мгновенно входило в бесконечно повторяющийся цикл while, пытаясь подключиться к Arduino через последовательный порт, как только оно началось, ожидая успешного подключения к указывают, что устройство было подключено., @Matthew Naybour
Вместо этих автоматических повторных попыток подключения я запрограммировал кнопку «Подключиться» в графическом интерфейсе своего приложения с окном, говорящим о подключении устройства перед попыткой подключения. Я думаю, что автоматические попытки подключения к arduino сразу после запуска приложения означали, что успешное последовательное соединение произойдет, пока arduino находится в какой-то фазе настройки. Позволяя пользователю щелкнуть соединение, всегда есть некоторая разумная задержка между подключением Arduino к моему ноутбуку и первой попыткой последовательного соединения., @Matthew Naybour