Глюк атмеги или спасительный Serial.println

Тема в разделе "Arduino & Shields", создана пользователем Kamikadze, 14 май 2018.

  1. Kamikadze

    Kamikadze Гик

    Добрый день, столкнулся по истину с мистической вещью. Есть некий код (около 4т строк, поэтому весь выкладывать я его тут не буду) в данной программе есть процедура обработки одной переменной. И эта процедура на отрез отказывалась работать. В процессе поиска ошибки пришлось выводить в сериал монитор значение чуть ли не всех переменных, и вы не поверите, после вывода в сериал монитор, заработало! вот пример кода, процедуры
    Код (C++):
    if (NumAct == 3)
      {
        Serial.print("NumAct");
        Serial.println(NumAct);
        if (millis() - timePush < 100000)
        {
          if(compasAngle < 2 || (compasAngle < 361 && compasAngle > 200))
          {
            fRoutTime(9, 700);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            PushGo = 0;
          }
          else if (compasAngle > 10 && compasAngle < 200)
          {
            fRoutTime(7, 1000);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            fRoutTime(8, 2000);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            PushGo = 0;
          }
          else if (compasAngle > 1 && compasAngle < 11)
          {
            fPoiskParaleli();
            Serial.print("parallel poisk ");
            Serial.print("CurrentRangeRangeUSO ");
            Serial.print(CurrentRangeRangeUSO);
            Serial.print(" CurrentRangeRangeUST ");
            Serial.print(CurrentRangeRangeUST);
            if (CurrentRangeRangeUSO > 110 && CurrentRangeRangeUSO > 110)
            {
              fCreateRout(2);
              return;
            }
            fRoutTime(8, parallelComp);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            PushGo = 0;
          }
        }
        else
        {
          if(compasAngle < 14 || (compasAngle < 361 && compasAngle > 200))
          {
            fRoutTime(9, 700);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            PushGo = 0;
          }
          else if (compasAngle > 27 && compasAngle < 200)
          {
            fRoutTime(7, 1000);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            fRoutTime(8, 2000);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            PushGo = 0;
          }
          else if (compasAngle > 13 && compasAngle < 28)
          {
            fPoiskParaleli();
            if (CurrentRangeRangeUSO > 110 && CurrentRangeRangeUST > 110)
            {
              Serial.println("popalsya");
              fRoutTime(4, 350);
              fRoutTime(8, 4700);
              fRoutTime(9, 250);
            }
            fRoutTime(8, parallelComp);
            if (naezdNaMetkuDA == 1)
            {
              return;
            }
            PushGo = 0;
          }
        }      
      }
    Самое то главное что когда я построчно выводил все в процедуре результата не было, как будто часть не выполнялось и зависало, но когда в начале процедуры добавил
    Код (C++):
    void compasOpros ()
    {
      Serial.print("NumAct ");
      Serial.print(NumAct);
      Serial.print(" timePush ");
      Serial.print(timePush);
      Serial.print(" millis ");
      Serial.print(millis());
      Serial.println("compas");
    В сериал монитор соответственно увидел верные значения переменных, и программа продолжило последующий вывод данных и свою работу как ни в чем не бывало... Т.е. Я ничего не менял и не добавлял все го лишь вывел значения используемых в алгоритме переменных в сериал монитор и программа раздуплилась и начала работать!!!
    Подскажите пожалуйста сталкивался ли кто с подобным, и как это можно объяснить?
     
    NikitOS нравится это.
  2. SergeiL

    SergeiL Оракул Модератор

    Ну, можно предположить, что какая-то переменная или буфер - переполняются, и меняется память других переменных.
    Вы добавляете строки типа "NumAct " и.т.п, и сдвигаете память, соответственно, начинает переполняться где-то в другом месте. ;)
     
  3. Kamikadze

    Kamikadze Гик

    Скетч использует 17834 байт (7%) памяти устройства. Всего доступно 253952 байт.
    Глобальные переменные используют 2759 байт (33%) динамической памяти, оставляя 5433 байт для локальных переменных. Максимум: 8192 байт.
     
  4. SergeiL

    SergeiL Оракул Модератор

    Я не об этом.
    Переменные в памяти располагаются подряд.
    К примеру, рядом в памяти, лежат буфер char из 10 элементов и переменная типа uint_16t (16 бит).
    Вы записываете в буфер не 10 байт, а 12. Что произойдет?

    Два последние байта пропишутся в конце буфера, но за его пределами, в памяти, куда указывает следующая переменная типа uint_16t, и перепишут ее значение на новое.
    А если это локальная переменная, то на месте презаписываемой переменной может быть и стек, и точка возврата из функции.

    Поэтому, ИМХО, нужно проверять размерность переменных, и размерность того, что туда записывается.

    Ну и еще, добавляя несколько Serial.print("Bla Bla Bla ") Вы добавляете задержку.
    Это тоже может влиять.
    По Вашему коду непонятно, что было до вызова функции.
     
    Последнее редактирование: 14 май 2018
  5. Kamikadze

    Kamikadze Гик

    Да записываются то корректные данные, и с типами ничего не напутал, единственное есть динамический массив
    Код (C++):
    String stringAngle =  String("0ukhkjhkljhkljhkljhkljhkjhkljhkljhkjhkljhkjhkl");

    char *StrAngle = stringAngle.c_str();
    такого вида, возможно вы и правы, но не совсем понятно как вызов в сериал переменной, которая используется следующим оператором, спасает ее от переполнения...
     
  6. SergeiL

    SergeiL Оракул Модератор

    Тут Вы заводите указатель с именем StrAngle на строку во внутреннем буфере stringAngle.
    Согласно Arduino Reference:
     
  7. AlexU

    AlexU Гуру

    Повреждение памяти конечно исключать нельзя, но если суть дела в том, что после добавления вывода данных в последовательный порт всё начинает корректно работать, то скорее дело в дополнительной задержке времени, которую вносит передача через последовательный порт.
    С классом String надо быть очень аккуратным. Если не знаете в точности как он работает, то лучше его не использовать. Да и вообще его (String) лучше не использовать.
     
  8. Kamikadze

    Kamikadze Гик

    Т.е. из-за данной переменной могу
    Господа данная переменная и не используется в процедуре. Она просто есть в программе но в данной программе она не используется! Конкретно в данной процедуре только переменные типа инт, юзигнед лонг, и будеан используются. И да вероятнее всего дело в задержке, я думал об этом
     
  9. SergeiL

    SergeiL Оракул Модератор

    Проверить задержку можно закомментировав Serial.print(), и вставив вместо него delay() с параметром в 20-30 мс.
     
  10. Kamikadze

    Kamikadze Гик

    суть в том что я закомментировал сериал для эксперимента и все заработало... И тут два варианта, либо троит кварц, либо все таки переполняются переменные. И самое парадоксальное вот что (работаем над проектом вдвоем). Мой товарищ сказал, что изначально все работало в первозданном виде. Спустя некоторое время (2.3 дня) работать все перестало (ну не все, а конкретная процедура). После вывода в сериал построчно переменных, все заработало, и вот опять все закомментировано, и продолжает работать...