Перестает работать Serial port после переподключения USB
- Войдите на сайт для отправки комментариев
Вс, 20/02/2022 - 21:26
Добрый вечер, коллеги! Столкнулся с мистической проблемой., ума не приложу в чем разгадка. Передаю данные в последовательный порт Arduino Nano с датчика MPU6050, вот код решения:
#include <Wire.h> #include "MPU6050.h" MPU6050 mpu; String COMMAND =""; String RESULT =""; void setup() { Wire.begin(); Serial.begin(57600); mpu.initialize(); // запускаем датчик } void loop() { while(Serial.available()) { //delay(10); char c = Serial.read(); COMMAND+=c; } if(COMMAND.length()>0) { if(COMMAND.compareTo("33")==0) { int16_t ax = mpu.getAccelerationX(); // ускорение по оси Х // стандартный диапазон: +-2g ax = constrain(ax, -16384, 16384); // ограничиваем +-1g float angle = ax / 16384.0; // переводим в +-1.0 // и в угол через арксинус if (angle < 0) angle = 90 - degrees(acos(angle)); else angle = degrees(acos(-angle)) - 90; RESULT += String(angle,2); Serial.println(RESULT); COMMAND = ""; RESULT = ""; } if(COMMAND.compareTo("34")==0) { int16_t ay = mpu.getAccelerationY(); // ускорение по оси Y // стандартный диапазон: +-2g ay = constrain(ay, -16384, 16384); // ограничиваем +-1g float angle = ay / 16384.0; // переводим в +-1.0 // и в угол через арксинус if (angle < 0) angle = 90 - degrees(acos(angle)); else angle = degrees(acos(-angle)) - 90; RESULT += String(angle,2); Serial.println(RESULT); COMMAND = ""; RESULT = ""; } } }
Схема подключения: Датчик подключается на шину i2c (SDA -> A4, SCL -> A5, GND -> GND)
Проблема заключается в том что код работает только после первой загрузке скетча на Arduino Nano, если после загрузки скетча отключить Arduino от USB и подключить снова то код перестает работать., данные перестают передаваться в последовательный порт., помогает только повторная загрузка скетча на ардуинку.
Помогите пожалуйста разобраться., может кто-то сталкивался с подобной проблемой???
А если подключить и нажать «Reset» на плате Ардуино?
Все корректно работает, так и должно быть.
На компе открыт COM порт, который работает через устройство USB-Serial.
Вы отключаете USB-Serial, подключаете снова, порт создается снова, а подключение к нему не переинициализируется в терминалке.
Закройте терминалку, откройте снова - пойдут данные.
А если подключить и нажать «Reset» на плате Ардуино?
Пробовал нажимать Reset, не помогает
Идея, конечно, глупая, но... Попробуйте втиснуть delay(500); перед mpu.initialize();
Все корректно работает, так и должно быть.
На компе открыт COM порт, который работает через устройство USB-Serial.
Вы отключаете USB-Serial, подключаете снова, порт создается снова, а подключение к нему не переинициализируется в терминалке.
Закройте терминалку, откройте снова - пойдут данные.
Подскажите пожалуйста что за «Терминалка» которую нужно закрыть? Я не открываю никаких терминальных окон и не использую монитор порта из Arduino IDE.., по команде «33» я просто запрашиваю передачу данных с ардуинки в программу на C++., я тоже думал что проблема заключается в том что порт не переинициализируется., но дело в том что даже после перезагрузки ПК передача данных не восстанавливается! Ситуация вообще не понятная., ещё раз опишу проблему по шагам:
1. Загружаю указанный выше код на Arduino Nano (китайский клон) с помощью загрузчика Arduino IDE., все компилируется и загружается без ошибок;
2. Посылаю команду Serial.write(“33”) с Windows программы (написана на С++)., все отлично работает и данные с гироскопа передаются., пробовал закрывать/перезапускать программу и снова посылать запрос «33» на выдачу данных с гироскопа и все прекрасно работает до тех пор пока не отключить ардуинку из USB;
3. Отключаю Ардуинку от USB и снова подключаю., и все перестаёт работать., при отправке команды «33» Программа виснет и данные не передаются., перезагрузка ПК и перезапуск программы не помогает., передачу данных восстанавливает только повторная заливка программы через Arduino IDE;
4. Думал может быть при сбросе питания Ардуины слетает прошивка, но нет не слетает., для проверки загрузил простой пример с мигающим диодом, сбросил питание, повторно подключил и все ок работает, диод мигает!!!
Товарищи, это мистика какая-то я не могу понять где искать проблему дальше
Кроме мистической проблемы, у вас потенциально глючный код. (В том числе за счет использования compareTo)
Поставьте вывод диагностических сообщений.
Например
После старта -
Serial.println("--START--");
delay(10);
После проверки длины команды
Serial.print("L="); Serial.println(COMMAND.length());
Serial.println(COMMAND);
delay(10); // не обязательно 10, и не обязательно в этом месте
2. Посылаю команду Serial.write(“33”) с Windows программы (написана на С++).
В Windows мне не знакома библиотека для com-порта, в которой есть "Serial.write()". Тут бы немного уточнить. Пока не ясно, как у тебя одновременно открыт порт и в мониторе и в некой "программе". ;))
Ну и заодно совет: другую Ардуинку не пробовал?
У MPU явно не хватает VCC, судя по первопосту. Я бы на реальную схему соединений посмотрел таки.
Ещё моно попробовать поменять скорость порта. Попробуй 115200 . Если есть возможность подключиться программатором USBasp и программой AVRDUDE_PROG3.3 можно осуществить программный сброс прочитав фьюзы и снова их записав. После этого заработает ваша ардуинка? Бывало, что фьзы слетают. Попробуйте сохранить фьюзы сразу же как прошили ардуину и она в этот момент работает. А потом прочитайте их когда она уже не работает. Восстановите фьюзы из сохраненных и попробуйте снова запустится. Подозреваю, что установлен какой то из лок фьюзов.
Идея, конечно, глупая, но... Попробуйте втиснуть delay(500); перед mpu.initialize();
Попробовал, к сожалению не помогло((
Кроме мистической проблемы, у вас потенциально глючный код. (В том числе за счет использования compareTo)
Поставьте вывод диагностических сообщений.
Например
После старта -
Serial.println("--START--");
delay(10);
После проверки длины команды
Serial.print("L="); Serial.println(COMMAND.length());
Serial.println(COMMAND);
delay(10); // не обязательно 10, и не обязательно в этом месте
Добавил код который вы рекомендовали:
Если ввести команду "33" в мониторе порта Arduino IDE первый вывод получается такой:
Если ввести команду "33" в мониторе порта повторно то вывод следующий:
Как можно заметить., "L" удвоилась и данные с MPU 6050 при повторном вводе уже не подтянулись., получается что переменная "COMMAND" не обнуляется внутри блока if и при повторном вводе команды "33" блок if(COMMAND.compareTo("33")==0) уже не обрабатывается..., все бы ничего но, тогда я вообще не понимаю как этот код работает при первой загрузке прошивки на ардуино до отключения USB от ПК??? Если код кривой и проверять с помощью функции compareTo не правильно., подскажите пож-та как лучше реализовать алгоритм считывания цифровых команд на подобии "33" с серийного порта???
В Windows мне не знакома библиотека для com-порта, в которой есть "Serial.write()". Тут бы немного уточнить. Пока не ясно, как у тебя одновременно открыт порт и в мониторе и в некой "программе". ;))
Ну и заодно совет: другую Ардуинку не пробовал?
1. Serial.write я привел как абстрактный пример., для работы с COM портом я использую библиотеку boost там есть функция write, выглядит она следующим образом:
2. У меня не открыт порт одновременно в мониторе и в программе., я после загрузки скетча на ардуинку монитор порта вообще не открываю., после загрузки просто закрываю Arduino IDE и запускаю свою программу., в которой по нажатию кнопки в цикле с интервалом 100 миллисекунд выполняется код который посылает команду "33" в функцию write и как я уже ранее писал все прекрасно работает после загрузке скетча и до первого отсоединения ардуинки от USB:
3. Другую ардуинку пробовал., результат тот же...
У MPU явно не хватает VCC, судя по первопосту. Я бы на реальную схему соединений посмотрел таки.
Реальную схему соединения я привел в первом посте., вот она:
Схема подключения: Датчик подключается на шину i2c (SDA -> A4, SCL -> A5, GND -> GND, VCC ->+5v)
Чтобы исключить проблему с нехваткой питания подключал датчик MPU 6050 через вот такую плату расширения: https://ali.onl/1YLw
питал плату от 15v 4A, результат тот же - проблема не в нехватке питания.
Ещё моно попробовать поменять скорость порта. Попробуй 115200 . Если есть возможность подключиться программатором USBasp и программой AVRDUDE_PROG3.3 можно осуществить программный сброс прочитав фьюзы и снова их записав. После этого заработает ваша ардуинка? Бывало, что фьзы слетают. Попробуйте сохранить фьюзы сразу же как прошили ардуину и она в этот момент работает. А потом прочитайте их когда она уже не работает. Восстановите фьюзы из сохраненных и попробуйте снова запустится. Подозреваю, что установлен какой то из лок фьюзов.
Скорость менять пробовал., не помогло., к сожалению программатора нет и попробовать этот способ на текущий момент не смогу(( надеюсь что проблема не в этом., а в кривом коде или еще где нибудь
3. Другую ардуинку пробовал., результат тот же...
Тогда ответ очевиден: проблема в твоей программе. Не аккуратно работаешь с портом. Чудес же не бывает.
Ну перешей загрузчик, для очистки совести. И Попробуй свою програмку без гироскопа или что-ты-там подключаешь, запустить. Перепиши её для имитации.
Вот залил видео на котором видно что все работает при запуске после загрузки скетча до первого отключения от USB: https://dropmefiles.com/XoEiR
В программу с датчика передаются данные и моделька изменяет свой угол вращения.
Также заметил что после отключения от USB при попытке передачи команды "33" на ардуинке один раз промаргивает красный светодиод "L" и светодиоды Tx/Rx не подают признаков жизни., а если запускаю прогу после загрузки скетча., то Tx/Rx моргают в нормальном режиме и данные передаются...
Тогда ответ очевиден: проблема в твоей программе. Не аккуратно работаешь с портом. Чудес же не бывает.
Ну перешей загрузчик, для очистки совести. И Попробуй свою програмку без гироскопа или что-ты-там подключаешь, запустить. Перепиши её для имитации.
Хм.. странно., код сократил до минимума., отключил гироскоп.. результат тотже., после отключения USB все перестает работать...
На код со стороны программы я не грешу так как он оттестирован на сотню раз и все работает как часы., тот же самый код я по сути использую для комманд управления (вперед, назад, влево, вправо) и код на стороне ардуино там такойже., проверка команды проходит с помощью функции "compareTo"...
Прошу посоветовать., как лучше реализовать считывание цифровых команд на стороне ардуино?
Как перешить загрузчик? для этого нужен ASP программатор?
Вы в сообщении #11 не написали, работает ли код только после загрузки, или нет.
Потенциальная Глючность кода в том, что если по Serial по какой то причине придет что то кроме одиночного "33" или "34", например символ возврата строки, или 3334 подряд, или при включении питания какой то мусор (по не известной причине), то команды больше приниматься не будут.
В случае с IDE, L=4 получается скорее всего за счет того, что в мониторе COM порта включена передача NL&CR
Попробуйте для поиска использовать indexOf()
Вы в сообщении #11 не написали, работает ли код только после загрузки, или нет.
Потенциальная Глючность кода в том, что если по Serial по какой то причине придет что то кроме одиночного "33" или "34", например символ возврата строки, или 3334 подряд, или при включении питания какой то мусор (по не известной причине), то команды больше приниматься не будут.
В случае с IDE, L=4 получается скорее всего за счет того, что в мониторе COM порта включена передача NL&CR
С внесенными правками код не работает даже после загрузки.
В итоге сократил пример до минимума вот так., отключил даже MPU-6050:
Результат тот же...
Я вас спрашивал - как изменяется вывод в мониторе COM порта IDE для случаев - сразу после загрузки и после повторного включения.
Я вас спрашивал - как изменяется вывод в мониторе COM порта IDE для случаев - сразу после загрузки и после повторного включения.
В мониторе порта вывод никак не изменяется., работает... похоже есть баг в моей программе., может при записи команды в serial какой-то мусор передается., но опять таки загадка при загрузке скетча то ведь все работает., значит теоритически передача мусора исключена...
Так даже с монитором порта не работает
Вместо точек то надеюсь свои условия вставили? И мою n1 заменили на свою buff
Serial
.setTimeout(10);
// установить таймаут - это с какой целью делаете? Для проверки закомментируйте эту строчку.
И попробуйте из монитора порта передать символ воскл знака - !
Вместо точек то надеюсь свои условия вставили? И мою n1 заменили на свою buff
Да конечно
Serial
.setTimeout(10);
// установить таймаут - это с какой целью делаете? Для проверки закомментируйте эту строчку.
И попробуйте из монитора порта передать символ воскл знака - !
setTimeout в случае с методом parseInt() необходим так как по умолчанию данный метод дает отклик через 1 секунду., по этому задаю вручную таймаут., комментировать пробовал не помогает.
С восклицательным знаком работает из монитора порта... но не с моей программой., хоть убейте не могу понять почему после загрузки скетча работает., а после отключения usb перестает
Ну так а скорость порта пробовал менять?
Ну так а скорость порта пробовал менять?
да
Код из этого примера вообще работает? http://arduino.ru/Reference/Serial/Read
Минусовал не я, но справедливости ради - функция read (-1) может возвращать, поэтому int (скорее всего int16_t)
-1 в Serial.read() ???? как вы это представляете при передаче? Там диапазон строго 0-255. Мир сходит с ума.
Автор, а если не отключать ардуинку от порта, а просто нажать кнопку ресет на плате, программа продолжает работать, или нет?
-1 в Serial.read() ???? как вы это представляете при передаче? Там диапазон строго 0-255. Мир сходит с ума.
Ну не я же это придумал: http://arduino.ru/Reference/Serial/Read
Или тут на столько старая документация?
Да, вроде бы, нет: https://www.arduino.cc/reference/en/language/functions/communication/serial/read/
Если у меня возникает подозрение на МК, я заливают в него блинк.
а если так, как будет себя вести ваша городьба?
-1 в Serial.read() ???? как вы это представляете при передаче? Там диапазон строго 0-255. Мир сходит с ума.
Ну не я же это придумал: http://arduino.ru/Reference/Serial/Read
Или тут на столько старая документация?
Да, вроде бы, нет: https://www.arduino.cc/reference/en/language/functions/communication/serial/read/
там пишут функция read() возвращает "Следующий доступный байт или -1 если его нет (int)"
в данном контексте не актуально, так как эта функция стоит внутри if-а Serial.available()
Вам этого не достаточно?
Код из этого примера вообще работает? http://arduino.ru/Reference/Serial/Read
Работает., поведение тоже что и в других моих случаях
Автор, а если не отключать ардуинку от порта, а просто нажать кнопку ресет на плате, программа продолжает работать, или нет?
Да., если не отключать USB и сколько угодно раз нажимать Reset, программа продолжает работать
Я заливал блинк., все норм., после переподключения USB блинк продолжает работать., у меня конкретно проблема с пропаданием работы Serial
а если так, как будет себя вести ваша городьба?
Также ведет ((
Раз блинк не слетает, значит маловероятно, что дело в МК.
Предваряя вопрос: я не ясновидящий, навыков в телемедицине не имею. "Приносите, посмотрим" (C)
Пока фьюзы не увидим, дальше разговаривать нет смысла. Возможно еще загрузчик с ошибкой в идешке, или в боард файле что то прописано криво. Возьмите другой комп, установите с нуля ПО и попробуйте повторить советы.
Вообще говоря, я склоняюсь к двум вариантам развития:
- Первый уже озвученный - каким-то боком/раком "слетают" фьюзы, что приводит к вышеописанному эффекту.
- Второй вариант - глючная работа драйвера UART.
Еще есть третий вариант, но его пока не хочу озвучивать.
Как проверить фьюзы Вам выше написали - Вы проверяли? К слову USBasp программатор стоил раньше на много дешевле арлдуино, сейчас не на много - но его стОит приобрести. Давайте действовать последовательно.
При чём фьюзы на нане? За связь с USB отвечает совсем не нана. У неё только Rx Tx которые танком не свернуть. Искать надо проблемы в драйвере на компе. А проверять другой наной прицепленой на Rx Tx.
Какие вообще фьюзы?
В сообщении №15 был поставлен диагноз.
Соответственно, способ отладки: для начала полностью забыть о собственной программе на ПК, которая ведет обмен с Ардуино через USB, и все ее функции промоделировать из монитора порта. После тогоЖ, как появится уверенность, что связка из Ардуино и монитора порта работает нормально, пытаться подменить монитор порта собственной программой на ПК. Естественно, обратив внимание на то, как выбирается, как открывается и как закрывается порт в этой программе.
Друзья, большое спасибо за помощь и советы!!! В итоге пришлось переписать клиентскую часть на Win API и отказаться от boost, и все заработало!!!
Выпустил первый релиз своей программы для управления роботами на базе Ардуино (Arduino Robot Control)
Вот здесь обзорное видео: https://youtu.be/d011oGsGJ2k
Если кому интересно за ключами регистрации стучитесь в личку или на почту!!! Еще раз всем спасибо!!!
ну вот, а как пяткой в грудь себя бил - "моя программа на пк ошибок не имеет!!! проверена 100 тыс раз!!!"
Каждый раз, когда я такое читаю - всегда оказывается, что именно там и была проблема.