Камрады, столкнулся с такой проблемой. Написал большущий проект. В одной части этого проекта понадобилось отладить участок кода. Полез в него и начал выводить через Serial нужные данные. И в какой-то момент ардуина стала глючить и перезагружаться при попытке вывести в Serial. Причем реагирует только на определенный набор символов - вывожу просто текст, не переменные. Например Код (C++): Serial.print("angle_course = "); всё работает, а при Serial.print("angle_course2 = "); выдает абракадбру в сериал и перезагружается. в проекте использую библиотеку AltSoftSerial - может из-за нее такой глюк быть? ну помимо этого у меня идет работа с GPS и радиомодулем. Питание от батарейки.
Без кода - пальцем в небо. Сколько свободной памяти, что компилятор говорит? Используется ли тип String или любые другие динамические запросы к памяти? Да, там до хрена всего может быть. Но, хоть с этого начните.
понимаю, что без кода никуда - но у меня там больше 10 файлов. String не использую. Компилятор при компиляции никаких варнингов и ошибок не выдает. Работаю в PlatformIO. Памяти использовано 70%. Даже не знаю как лучше ошибку искать. Когда первый раз появилась эта проблема - удалил кучу кода, пока искал эту проблему. Нашел проблемный участок кода - удалил нафиг всё и вроде всё заработало. А теперь опять(( и уже в другом месте
С динамическим выделением памяти - в одном месте при инициализации класса выделяется место под динамический массив. Но в момент возникновения проблемы - он не используется. Переделал код под выделение фиксированного размера массив - ошибка осталась.
сейчас подумал - у меня много мест, где я работаю с указателями - передаю их в функции и т.д. Может тут возникнуть подобные проблемы, если я по указателю неправильно что-нибудь запишу? Я в некоторых местах вручную перевожу float в массив байтов и наоборот. Формирую массивы байтов для отправки по радиоканалу.
Конечно. Вообще, как я уже говорил, без кода - пальцем в небо, но неожиданные и необъяснимые перезагрузки - это процентов на 80 "распашка" памяти. Это первое, где бы я искал проблему.
сейчас проверяю функцию отправки радиопакета. Если комментирую вызов этой функции, то ошибка исчезает. Правда странно исчезает. Вызываю эту функцию в двух местах. Если в одном из двух мест комментирую, то всё работает, а если сразу два вызова - то ошибка. Решил начать с этого участка. Код (C++): // отправляем данные местоположения дрона по Radio порту void Radio::sendDronPositionData(byte droneId, GeoPoint _point) { byte sendPacket[PACKET_SIZE] = {0}; sendPacket[DRONE_ID_BITE] = droneId; // Вставляем данные в пакет /********************************************************/ insertFloatDataIntoRadioPacket(sendPacket, LATITUDE_BITE, &_point.latitude); insertFloatDataIntoRadioPacket(sendPacket, LONGITUDE_BITE, &_point.longitude); /********************************************************/ sendData(sendPacket); } // Вставляем float данные в радиопакет void Radio::insertFloatDataIntoRadioPacket(byte *radio_packet, byte insertPosition, float *data) { radio_packet[insertPosition] = ((byte *)data)[0]; radio_packet[insertPosition + 1] = ((byte *)data)[1]; radio_packet[insertPosition + 2] = ((byte *)data)[2]; radio_packet[insertPosition + 3] = ((byte *)data)[3]; } // отправляем данные по Radio порту void Radio::sendData(byte *data) { byte sendPacket[PACKET_SIZE] = {0}; sendPacket[START_BITE] = START_CHAR; sendPacket[DRONE_ID_BITE] = 0x0; sendPacket[CRC_BITE] = 0x0; sendPacket[CRC_BITE + 1] = 0x0; sendPacket[END_BITE] = END_CHAR; int CRC = 0; // Вставляем полученные данные в пакет /********************************************************/ for (int i = DRONE_ID_BITE; i < CRC_BITE; i++) { sendPacket[i] = data[i]; } /********************************************************/ // считаем CRC for (int i = DATA_TYPE_BITE; i < CRC_BITE; i++) { CRC += sendPacket[i]; } // сохраняем CRC в пакет insertIntDataIntoRadioPacket(sendPacket, CRC_BITE, &CRC); // отправляем по радиоканалу serialObject->write(sendPacket, sizeof(radioPacket)); } долго разбирался с вопросом вставки и чтения float в массив byte. Не намудрил я тут?
да срыв стека у него. Банально не хватает ОЗУ для всяких строк и прочего, чего не делают не восьмибитках.
а ему вообще пофигу, что там с памятью происходит. Пофигу, потому как нету инструментов. Это ж всё-таки компилируемый язык, а не интерпретируемый.
Т.е. если не обращаться к Serial, то код будет работать без ошибок? В принципе я его отладил, но теперь переживаю - вдруг ошибки будут возникать
ну если проблема в нехватке ОЗУ во время обращения к Serial. Если без этого обращения ардуина нормально работает и не перезагружается, то она так и будет нормально работать. Или тут другая логика? нашел код проверки оставшейся свободной ОЗУ Код (C++): void display_freeram() { Serial.print(F("- SRAM left: ")); Serial.println(freeRam()); } int freeRam() { extern int __heap_start,*__brkval; int v; return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval); } чтобы найти кусок когда, который забирает последний объем ОЗУ - хочу раскидать по разным местам кода вызов этой функции. Я правильно мыслю?
сейчас изучаю вопрос оптимизации памяти - нашел такой момент: вместо Serial("text") использовать Serial(F("text")). Макрос F помещает текст на флэш память. В моем случае - это разумно?
разобрался с вопросом оптимизации памяти. Сейчас RAM - 63.5% (до этого было 89%). Глючить перестало, но как-то странно((( после загрузки в память и последующего запуска Serial Monitor иногда зависает(( Делаю Hardware Reset ардуины - всё отлично работает. Ну пока посмотрю, как она будет себя вести. Всем спасибо большое за помощь - разобрался с оптимизацией памяти. До этого даже на задумывался об этом, т.к. не было серьезных проектов. Двигаюсь потихоньку ))))
камрады, решил еще раз вернуться к совей теме, т.к. непонятные глюки продолжаются, хотя и реже. Замерил скриптом display_freeram() количество свободной ОЗУ на начало цикла Loop - 300 байт. Я так понимаю, что этого очень мало и поэтому во время выполнения программы периодически МК зависает. Да и во время выполнения кода в setup тоже иногда зависает. Я правильно мыслю?
Опять же, в отрыве от кода эта цира ничего не говорит. Вон у Аттини13 всего 64 байта памяти - и ведь на нем как-то тоже программы запускают. А если у вас 300 байт свободно, но в следующей строке вы выделяете динамический массив в 500 байт - то конечно 300 байт мало