Добрый день, столкнулся по истину с мистической вещью. Есть некий код (около 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"); В сериал монитор соответственно увидел верные значения переменных, и программа продолжило последующий вывод данных и свою работу как ни в чем не бывало... Т.е. Я ничего не менял и не добавлял все го лишь вывел значения используемых в алгоритме переменных в сериал монитор и программа раздуплилась и начала работать!!! Подскажите пожалуйста сталкивался ли кто с подобным, и как это можно объяснить?
Ну, можно предположить, что какая-то переменная или буфер - переполняются, и меняется память других переменных. Вы добавляете строки типа "NumAct " и.т.п, и сдвигаете память, соответственно, начинает переполняться где-то в другом месте.
Скетч использует 17834 байт (7%) памяти устройства. Всего доступно 253952 байт. Глобальные переменные используют 2759 байт (33%) динамической памяти, оставляя 5433 байт для локальных переменных. Максимум: 8192 байт.
Я не об этом. Переменные в памяти располагаются подряд. К примеру, рядом в памяти, лежат буфер char из 10 элементов и переменная типа uint_16t (16 бит). Вы записываете в буфер не 10 байт, а 12. Что произойдет? Два последние байта пропишутся в конце буфера, но за его пределами, в памяти, куда указывает следующая переменная типа uint_16t, и перепишут ее значение на новое. А если это локальная переменная, то на месте презаписываемой переменной может быть и стек, и точка возврата из функции. Поэтому, ИМХО, нужно проверять размерность переменных, и размерность того, что туда записывается. Ну и еще, добавляя несколько Serial.print("Bla Bla Bla ") Вы добавляете задержку. Это тоже может влиять. По Вашему коду непонятно, что было до вызова функции.
Да записываются то корректные данные, и с типами ничего не напутал, единственное есть динамический массив Код (C++): String stringAngle = String("0ukhkjhkljhkljhkljhkljhkjhkljhkljhkjhkljhkjhkl"); char *StrAngle = stringAngle.c_str(); такого вида, возможно вы и правы, но не совсем понятно как вызов в сериал переменной, которая используется следующим оператором, спасает ее от переполнения...
Тут Вы заводите указатель с именем StrAngle на строку во внутреннем буфере stringAngle. Согласно Arduino Reference:
Повреждение памяти конечно исключать нельзя, но если суть дела в том, что после добавления вывода данных в последовательный порт всё начинает корректно работать, то скорее дело в дополнительной задержке времени, которую вносит передача через последовательный порт. С классом String надо быть очень аккуратным. Если не знаете в точности как он работает, то лучше его не использовать. Да и вообще его (String) лучше не использовать.
Т.е. из-за данной переменной могу Господа данная переменная и не используется в процедуре. Она просто есть в программе но в данной программе она не используется! Конкретно в данной процедуре только переменные типа инт, юзигнед лонг, и будеан используются. И да вероятнее всего дело в задержке, я думал об этом
Проверить задержку можно закомментировав Serial.print(), и вставив вместо него delay() с параметром в 20-30 мс.
суть в том что я закомментировал сериал для эксперимента и все заработало... И тут два варианта, либо троит кварц, либо все таки переполняются переменные. И самое парадоксальное вот что (работаем над проектом вдвоем). Мой товарищ сказал, что изначально все работало в первозданном виде. Спустя некоторое время (2.3 дня) работать все перестало (ну не все, а конкретная процедура). После вывода в сериал построчно переменных, все заработало, и вот опять все закомментировано, и продолжает работать...