Как я уже писал ранее, была создана система плавным управлением двигателей через прерывания. Работало замечательно, пока не захотелось попробовать ручное управление через блютуз. Создал простенький механизм на RemoveXY состоящий из двух ползунков, каждый из которых должен управлять своим двигателем (почти как на тракторе). Запустил и увидел странное. При подключении блютуза переменные ответственные за состояние оборотов двигателя начали как то хаотично меняться. Вот на видео хорошо заметно дрожание светодиода имитирующего двигатель: Вроде бы реагируют правильно, но откуда то появляются плавающие значения там где их быть не должно. Впечатление такое, что в момент обработки прерывания происходит обработка другого прерывания (предположительно от SerialSoftware на чем висит bluetooth), которое каким то образом вредит переменной. Такое возможно? Принятые меры, не увенчавшиеся успехом: Переменные созданы с префиксом volatile. Перепробовал все 5 16битных таймера как A так и B, от этого меняется только вид помехи и номер пина с помехой - то первый то второй. Увеличивал время между прерываниями в несколько раз. Ума не приложу что еще может быть не так.
В подтяжке не может быть дело? Но если дело в ложном прерывании, то ложное можно как-то отсеять от верного програмным путем? А еще могут быть помехи, либо по причине неисправного блютуз, либо помехи связаны с электромагнитными полями. Конечно это только предположения.
Еще у меня была похожая проблема с мотором. Оказалось что некоторые пины на макетной плате со временем разболтались и просто VCC терялось. Может в контакте дело!
Информации маловато: что за прерывания? как используются? как управляются светодиоды (пины, каким сигналом)? и т.п. и т.д.?
Контакты не при чем. Меняется сама переменная. То есть если запустить Serial.print() то видно что значение меняется на несколько единиц само по себе.
Как теоретически может меняться переменная извне? Программно она меняется только в одном месте в прерывании как простая функция от другой переменной, которая не меняется в данный момент.
Блин, ну хоть убейте мне кажеться проблема в резисторе! У вас он стоит? Если да, то на сколько? И вообще, можно схему? Мне в одной из схем пришлось 5kOm ставить, потомучто, при меньшем сопротивлении аппарат глючил!
Не в приходящем сигнале дело, еще раз говорю! Самопроизвольно меняется содержимое переменной без видимой на то причины.
Было такое пару раз. Причин может много, в основном работа памятью, самые типичные работа с указателем, выход за пределы и т.д.. Но и с прерываниями, работа с переменными как в прерывании и в коде - атомарные операции и т.д.. Сложно понять, что там происходит, не видя кода. Если нет отладчика найти такую ошибку трудно, порой просто комментирую код, пока программа не начнет стабильно работать, а дальше добавление кода и проверки.
Я вот тоже грешу на проблемы с памятью. Но вроде бы неоткуда, во всяком случае в моем участке кода. Может в подключаемых библиотеках косяк?
Все может быть, но если речь о SerialSoftware, то сильно сомневаюсь, что там есть проблемы с памятью, ей уже давно не первый год. Сам пользуюсь данной библиотекой ни когда проблем не замечал. Больше всего прерываний с SerialSoftware было в такой конфигурации - она + прерывания UART + прерывания Timer1 и Timer2, работает как часы. Когда вызывается прерывание, все прерывания отключаются пока выполняется обработчик прерывания. Если в это время произойдет 1 прерывание, оно будет выполнено после, если несколько, то только 1 будет выполнено после, остальные потеряются. Именно поэтому прерывания должны быть минимальными по времени исполнения. Если Вы потеряли прерывание, то это не изменит переменную произвольно. Кроме того, что уже сказал, если используются глобальные переменные добавьте static перед volatile - http://www.c-cpp.ru/books/staticheskie-globalnye-peremennye. Больше на ум с ходу ни чего не приходит.
На библиотеку RemoteXY думаю, а у нее свой SerialSoftware зачем то. Пока прерывания не используются, все замечательно. Может какой то массив выпирает за свои пределы? Собрал переменные в структуру, так вообще одна из них вообще начала плавать от 0 до -254 случайным образом как будь то от непритянутого аналогового входа. Как такое возможно?
Сам иногда задаюсь подобными вопросами. Вот график analogRead простейшего датчика освещенности. Не вел бы записей - не удивлялся:
Там нет своей реализации, там своя обертка для стандартного SerialSoftware, но сама отправка происходит стандартной библиотекой. Если Вы думаете, что проблема в нем, воспользуйтесь HardwareSerial, у Вас же Mega. Возможно, когда ошибка в вызове аналогичной функции, стоила мне дня жизни. Код (C++): static void __attribute__ ((noinline)) s_struct_w(uint8_t *cb,uint8_t siz) { while(siz--) *cb++ = read8(); } Сложно, что-то сказать не видя кода, мне сложно понять зачем прерывания. К примеру 1-но на ADC, ШИМ для моторов. Для ШИМ если не ошибаюсь, есть режим формирования без прерываний. Посмотрите так же используются ли одни и те же регистры, как в прерывании, так и в коде программы. Отмечу, что еще не желательно делать в прерываниях. 1. Вызывать функции, тем более которые вызываются в вне прерывания. 2. Разрешать прерывания sei. И что требуется. 1. Очень хорошо и просто написано, поэтому процитировал. Очень полезная статья - http://easyelectronics.ru/avr-uchebnyj-kurs-podprogrammy-i-preryvaniya.html, читайте с заголовка Бег по граблям. Если у Вас есть осциллограф, а лучше логический анализатор можно попробовать разобраться когда происходит сбой. Выставлять значение на портах во время прерывания, так можно оценить загрузку, а так же сравнивать значение переменной с эталонным. К примеру 1 прерывание 2 пин вверх, если там переменной отхождение от эталона 13 порт вверх, конец прерывания 2 порт вниз. и т.д. Так же в программе проверять переменную, так Вы поймете после чего произошел сбой, так же подсказал когда-то Megakoteyka.
Прерывание обрабатывается меньше двух миллисекунд. Ничего лишнего там нет. Попинал немного библиотеку, перезаписал оформление типов, вроде бы успокоилось. В чем причина была так до конца и не понял. При использовании чужих наработок всегда есть риск что что-нибудь пойдет не так. Но объять необъятное тоже нелегко.