Ардуино – один из удобнейших и популярнейших микроконтроллеров на сегодняшний день. Всё это благодаря упрощенным механикам эксплуатации, проектировки систем и наличию большого количества библиотек в открытом доступе, что в несколько раз облегчает жизнь инженерам, желающим воплотить свои задумки.
Но даже в такой идеальной, казалось бы, системе, встречаются недочеты и поломки, которые могут мешать работе или просто раздражать пользователей. Давайте же разберёмся с одной из них, а именно, почему в Ардуино встречается дребезг контактов, и что с ним делать.
Причины дребезга контактов
На самом деле, данное явление встречается достаточно часто и является крайне пугающим и неприятным для начинающих ардуинщиков, которые всё ещё не знают, как с ним бороться, и что это вообще такое. С этим «багом» система может работать вполне исправно, вырубаясь лишь на короткие промежутки времени, но именно эти отключения и являются основной причиной недоумения новичков и множества проблем, поэтому справиться с проблемой стараются как можно быстрее.
Чаще всего с дребезгом сталкиваются при подключении кнопки, но почему так происходит? Вот пример при котором это будет:
void loop() { if (digitalRead(PIN_BUTTON)) { Serial.println("1"); } else { Serial.println("0"); } }
Кнопка – это один из видов дополнительных модулей под Ардуино, служащих для ввода информации. В основе работы такого механизма лежит простой алгоритм работы – вы надавливаете на механический переключатель, он смыкает контакты, лежащие под оболочкой, и запускается какой-нибудь скрипт. Таким образом, при помощи давления, которое формируется при нажатии, происходит схождение или расхождение металлических пластин, которые и выступают наиболее популярными триггерами.
Программисту остается лишь написать код, который будет как-то засекать данное событие и выполнять определённые действия.
Пример программного решения проблемы:
int currentValue, prevValue; void loop() { currentValue = digitalRead(PIN_BUTTON); if (currentValue != prevValue) { // Что-то изменилось, здесь возможна зона неопределенности // Делаем задержку delay(10); // А вот теперь спокойно считываем значение, считая, что нестабильность исчезла currentValue = digitalRead(PIN_BUTTON); } prevValue = currentValue; Serial.println(currentValue); }
Алгоритм работы казался бы простым, но всегда стоит помнить, что идеализированные системы не применимы на практике, и на той же практике вам приходится сталкиваться с различными их недочетами, как серьезными, так и мелкими, например, отсутствием гладких поверхностей, неровностями на контактах и, для более продвинутых, паразитной емкостью.
Соответственно, в реальности контакты соприкасаются не моментально, из-за недочетов конструкции и на короткий промежуток времени на границах пластин меняется сопротивление, вместе с взаимной емкостью.
Всё это приводит к разнообразным изменениям уровня тока и напряжения, и вместо идеальной диаграммы в виде равнобедренной прямоугольной трапеции, мы получаем промежуток из максимумов и минимумов, прежде, чем система уравновесится. Все эти процессы называются в электротехнике переходными, и, зачастую, просто незаметны для обывателя. Простейшим примером будет включение света в комнате, ведь лампа накаливания разогревается и меняет свою яркость не моментально. Но наш мозг не способен зарегистрировать всё это сам по себе.
Однако, когда мы сталкиваемся с системами, способными фиксировать состояние объектов вплоть до миллисекунды, все эти процессы становятся заметными и крайне проблемными. А всё дело в том, что каждая строчка кода, которую вы прописываете при программировании системы, каким-то образом должна учитывать и обрабатывать все сигналы, в том числе и тот самый пресловутый «дребезг контактов».
Сделать это не так легко, а неприспособленный код, хоть и скомпилируется, но будет вести себя непредсказуемо, что станет кошмаром для любого инженера. Мы разобрались в причинах, но какие же ошибки нам стоит ожидать из-за дребезга?
Ошибки дребезга кнопки
Проще всего заметить основные проблемы, которые доставляет дребезг контактов на Аrduino, на непосредственном проекте, в котором прописан код для обработки события нажатия кнопки.
Если вы уже работали с подобной задачей, то должны помнить, что для этого используется специальный цикл, дабы постоянно проверять состояние рычага и в нужный момент преобразить систему под необходимые условия, например, подав напряжение на выход. 1 такой цикл проходит за промежуток времени, зависящий от мощности процессора, но, зачастую, не превышающий нескольких миллисекунд.
Этого времени вполне достаточно, чтобы код успел отреагировать на «шумы» при нажатии кнопки. А теперь представьте себе ситуацию – в вашей программе прописано запускать процесс, как только кнопка нажимается, и выключать, как только её отпускают. Для регистрации обоих событий применяется перепад напряжения. В результате цикл будет несколько раз запускать и закрывать функции, пока происходит дребезг контактов. Если всё это происходит ещё и в многопоточном режиме, то нагрузку в стеке микроконтроллера не сложно вообразить.
Борьба с дребезгом кнопки с помощью библиотеки Ардуино
Мы поняли, что проблема чисто аппаратная, но, как ни парадоксально, со стороны «железа» её сложно исправить. Вы же не можете лично под микроскопом отполировать контакты, да ещё и просить пользователя нажимать на кнопку лишь с одной силой и на постоянной основе.
Поэтому нам придется хитрить со стороны кода и пытаться каким-то образом вписать в обработчик событий этот непростой процесс. А так как мы уже знаем природу этого явления, то примерно представляем, как его обойти или хотя бы постараться минимизировать нагрузку на систему в этот момент.
А всё на самом деле просто, ведь перед нами стоит такой перечень условий:
- На срок до 10-100 мС, система пребывает в нестабильном состоянии и может выдавать ошибки.
- Далее идет срок от 1 до 2-ух секунд, что в 10 раз больше от предыдущего, пока кнопку нажимают.
- И вновь, под конец, 10-100 мС, длится дребезг.
Все, кто работал с многопоточностью на Си, уже заприметили очевидные триггеры, от которых мы и будем отталкиваться. Дело в том, что для предотвращения проблем по программной части нам достаточно выдержать тишину на каком-то промежутке времени, пока дребезг не пройдет, то есть достаточно воспользоваться уже готовой функцией delay().
Борьба с дребезгом библиотекой "bounce"
Как вариант борьбы с дребезгом в Ардуино - библиотека Bounce, которую можно скачать на Github.
Методы библиотеки:
Название | Назначение |
---|---|
Bounce() | инициализация объекта "Bounce"; |
void interval (мсек) | устанавливает время задержки в миллисекундах; |
void attach (номерПина) | задаёт вывод, к которому подключена кнопка; |
int update() | обновляет объект и возвращает true, если состояние пина изменилось, и false в противном случае; |
int read() | считывает новое состояние пина. |
Сам код.
#include <Bounce2.h>; #define PIN_BUTTON 2 #define PIN_LED 13 // Создаем объект Bounce debouncer = Bounce(); void setup() { // Устаовили тип пина pinMode(PIN_BUTTON, INPUT_PULLUP); // Даем бибилотеке знать, к какому пину мы подключили кнопку debouncer.attach(PIN_BUTTON); debouncer.interval(5); // Интервал, в течение которого мы не буем получать значения с пина //Setup the LED : pinMode(PIN_LED, OUTPUT); } void loop() { // Даем объекту бибилотеки знать, что надо обновить состояние - мы вошли в новый цкил loop debouncer.update(); // Получаем значение кнопки int value = debouncer.read(); // Теперь мы точно знаем, в каком состоянии находится наша кнопка if ( value == LOW ) { digitalWrite(PIN_LED, HIGH ); } else { digitalWrite(PIN_LED, LOW ); } }
Подавление дребезга с помощью триггера Шмидта
Хоть аппаратно баг и тяжело правится, но это возможно. Вам потребуется лишь подключить триггер Шмидта.
Это небольшое устройство, которое позволяет «сглаживать» углы трапеции, убирая все скачки напряжения. Делает оно это достаточно просто: устройство ожидает, пока сигнал достигнет определённого уровня и лишь тогда направляет его на контроллер.
На выходе мы получаем аналогию с алгоритмом, описанным выше, но в аппаратной реализации. Оно попросту выжидает те самые скачки, и лишь затем подает напряжение, что позволяет полностью избавиться от дребезга.