Непонятная перезагрузка платы из за serial

Тема в разделе "Arduino & Shields", создана пользователем cfif, 1 июн 2023.

  1. cfif

    cfif Нерд

    Камрады, столкнулся с такой проблемой. Написал большущий проект. В одной части этого проекта понадобилось отладить участок кода. Полез в него и начал выводить через Serial нужные данные. И в какой-то момент ардуина стала глючить и перезагружаться при попытке вывести в Serial. Причем реагирует только на определенный набор символов - вывожу просто текст, не переменные. Например
    Код (C++):
    Serial.print("angle_course = ");
    всё работает, а при Serial.print("angle_course2 = "); выдает абракадбру в сериал и перезагружается.
    в проекте использую библиотеку AltSoftSerial - может из-за нее такой глюк быть? ну помимо этого у меня идет работа с GPS и радиомодулем. Питание от батарейки.
     
  2. Asper Daffy

    Asper Daffy Иксперд

    Без кода - пальцем в небо.

    1. Сколько свободной памяти, что компилятор говорит?
    2. Используется ли тип String или любые другие динамические запросы к памяти?

    Да, там до хрена всего может быть. Но, хоть с этого начните.
     
  3. cfif

    cfif Нерд

    понимаю, что без кода никуда - но у меня там больше 10 файлов. String не использую. Компилятор при компиляции никаких варнингов и ошибок не выдает. Работаю в PlatformIO. Памяти использовано 70%.
    Даже не знаю как лучше ошибку искать. Когда первый раз появилась эта проблема - удалил кучу кода, пока искал эту проблему. Нашел проблемный участок кода - удалил нафиг всё и вроде всё заработало. А теперь опять(( и уже в другом месте
     
    Последнее редактирование: 1 июн 2023
  4. cfif

    cfif Нерд

    С динамическим выделением памяти - в одном месте при инициализации класса выделяется место под динамический массив. Но в момент возникновения проблемы - он не используется. Переделал код под выделение фиксированного размера массив - ошибка осталась.
     
  5. cfif

    cfif Нерд

    сейчас подумал - у меня много мест, где я работаю с указателями - передаю их в функции и т.д. Может тут возникнуть подобные проблемы, если я по указателю неправильно что-нибудь запишу? Я в некоторых местах вручную перевожу float в массив байтов и наоборот. Формирую массивы байтов для отправки по радиоканалу.
     
  6. Asper Daffy

    Asper Daffy Иксперд

    Конечно. Вообще, как я уже говорил, без кода - пальцем в небо, но неожиданные и необъяснимые перезагрузки - это процентов на 80 "распашка" памяти. Это первое, где бы я искал проблему.
     
    Последнее редактирование: 1 июн 2023
    DetSimen и cfif нравится это.
  7. cfif

    cfif Нерд

    понял, спасибо. Попробую перелопатить код в этом направлении
     
  8. cfif

    cfif Нерд

    сейчас проверяю функцию отправки радиопакета. Если комментирую вызов этой функции, то ошибка исчезает. Правда странно исчезает. Вызываю эту функцию в двух местах. Если в одном из двух мест комментирую, то всё работает, а если сразу два вызова - то ошибка. Решил начать с этого участка.
    Код (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. Не намудрил я тут?
     
  9. parovoZZ

    parovoZZ Гуру

    да срыв стека у него. Банально не хватает ОЗУ для всяких строк и прочего, чего не делают не восьмибитках.
     
    cfif нравится это.
  10. parovoZZ

    parovoZZ Гуру

    а ему вообще пофигу, что там с памятью происходит. Пофигу, потому как нету инструментов. Это ж всё-таки компилируемый язык, а не интерпретируемый.
     
  11. cfif

    cfif Нерд

    Т.е. если не обращаться к Serial, то код будет работать без ошибок? В принципе я его отладил, но теперь переживаю - вдруг ошибки будут возникать
     
  12. Asper Daffy

    Asper Daffy Иксперд

    Кто это Вам сказал?
     
  13. cfif

    cfif Нерд

    ну если проблема в нехватке ОЗУ во время обращения к 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);
    }
     
    чтобы найти кусок когда, который забирает последний объем ОЗУ - хочу раскидать по разным местам кода вызов этой функции. Я правильно мыслю?
     
  14. cfif

    cfif Нерд

    сейчас изучаю вопрос оптимизации памяти - нашел такой момент: вместо Serial("text") использовать Serial(F("text")). Макрос F помещает текст на флэш память. В моем случае - это разумно?
     
  15. parovoZZ

    parovoZZ Гуру

    он там и так лежит. Безо всяких макросов.
     
  16. Asper Daffy

    Asper Daffy Иксперд

    Да.
     
    cfif нравится это.
  17. cfif

    cfif Нерд

    разобрался с вопросом оптимизации памяти. Сейчас RAM - 63.5% (до этого было 89%). Глючить перестало, но как-то странно((( после загрузки в память и последующего запуска Serial Monitor иногда зависает(( Делаю Hardware Reset ардуины - всё отлично работает. Ну пока посмотрю, как она будет себя вести.
    Всем спасибо большое за помощь - разобрался с оптимизацией памяти. До этого даже на задумывался об этом, т.к. не было серьезных проектов. Двигаюсь потихоньку ))))
     
  18. cfif

    cfif Нерд

    камрады, решил еще раз вернуться к совей теме, т.к. непонятные глюки продолжаются, хотя и реже. Замерил скриптом display_freeram() количество свободной ОЗУ на начало цикла Loop - 300 байт. Я так понимаю, что этого очень мало и поэтому во время выполнения программы периодически МК зависает. Да и во время выполнения кода в setup тоже иногда зависает. Я правильно мыслю?
     
  19. b707

    b707 Гуру

    Опять же, в отрыве от кода эта цира ничего не говорит. Вон у Аттини13 всего 64 байта памяти - и ведь на нем как-то тоже программы запускают.
    А если у вас 300 байт свободно, но в следующей строке вы выделяете динамический массив в 500 байт - то конечно 300 байт мало
     
    cfif и Igor68 нравится это.