Как бороться с дребезгом контактов в Ардуино?
25 июля в 18:29
Ардуино – один из удобнейших и популярнейших микроконтроллеров на сегодняшний день. Всё это благодаря упрощенным механикам эксплуатации, проектировки систем и наличию большого количества библиотек в открытом доступе, что в несколько раз облегчает жизнь инженерам, желающим воплотить свои задумки.
Но даже в такой идеальной, казалось бы, системе, встречаются недочеты и поломки, которые могут мешать работе или просто раздражать пользователей. Давайте же разберёмся с одной из них, а именно, почему в Ардуино встречается дребезг контактов, и что с ним делать.
Причины дребезга контактов
На самом деле, данное явление встречается достаточно часто и является крайне пугающим и неприятным для начинающих ардуинщиков, которые всё ещё не знают, как с ним бороться, и что это вообще такое.
С этим «багом» система может работать вполне исправно, вырубаясь лишь на короткие промежутки времени, но именно эти отключения и являются основной причиной недоумения новичков и множества проблем, поэтому справиться с проблемой стараются как можно быстрее.
Чаще всего с дребезгом сталкиваются при подключении кнопки, но почему так происходит? Вот пример при котором это будет:
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 ; #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 ); } }
Подавление дребезга с помощью триггера Шмидта
Хоть аппаратно баг и тяжело правится, но это возможно. Вам потребуется лишь подключить триггер Шмидта.
Это небольшое устройство, которое позволяет «сглаживать» углы трапеции, убирая все скачки напряжения. Делает оно это достаточно просто: устройство ожидает, пока сигнал достигнет определённого уровня и лишь тогда направляет его на контроллер.
На выходе мы получаем аналогию с алгоритмом, описанным выше, но в аппаратной реализации. Оно попросту выжидает те самые скачки, и лишь затем подает напряжение, что позволяет полностью избавиться от дребезга.
Источник: https://ArduinoPlus.ru/arduino-drebezg-kontaktov/
Дребезг контактов кнопки ардуино и его подавление и удаление
Дребезг контактов кнопки ардуино — одно из самых неприятных и непонятных явлений, с которыми сталкивается начинающий ардуинщик.
Устранение дребезга необходимо для корректной работы проекта, в противном случае на короткий отрезок времени схема становится практически неуправляемы. В этой статье мы рассмотрим основные причины возникновения и способы подавления дребезга.
О том, что такое кнопка, как правильно подключать модуль и писать для него скетч вы можете прочитать в первой статье, посвященной кнопкам в ардуино.
Причины дребезга кнопок
Кнопка ардуино — один из самых популярных и простых видов датчиков. В основе работы любой кнопки лежит механический способ смыкания-размыкания контактов. Нажимая на любую, даже самую простую тактовую кнопку, мы формируем определенное давление на внутренние механизмы (пластины или пружины), в результате чего происходит сближение или расхождение металлических пластин.
Мы люди взрослые и хорошо понимаем, что идеального в мире ничего не существует, в том числе идеально гладких поверхностей, контактов без неровностей, сопротивления и паразитной емкости.
В нашем неидеальном мире в момент нажатия на кнопку в месте соединения контакты не соприкасаются мгновенно, микро-неровности на поверхности не позволяют пластинам мгновенно соединиться.
Из-за этого в короткий промежуток времени на границе пластинок меняется и сопротивление, и взаимная емкость, из-за чего возникают масса разнообразных изменений уровня тока и напряжения. Другими словами, возникают очень интересные, хотя и не очень приятные процессы, которые в электротехнике называют переходными.
Переходные процессы протекают очень быстро и исчезают за доли миллисекунд. Поэтому мы редко их замечаем, например, когда включаем свет в комнате.
Лампа накаливания не может менять свою яркость с такой скоростью, и тем более не может реагировать на изменения наш мозг.
Но, обрабатывая сигал от кнопки на таком быстром устройстве, как Arduino, мы вполне можем столкнуться с такими переходными эффектами и должны их учитывать при программировании.
В идеальном мире форма сигнала после нажатия на кнопку должна быть строго прямоугольная. В реальных же условиях вместе резкого перехода мы видим множество пиков и спадов.
Ошибки дребезга кнопки
Как отразится дребезг на нашем проекте? Да самым прямым образом — мы будем получать на входе совершенно случайный набор значений. Ведь если мы считываем значение с кнопки непрерывно, в каждом новом рабочем цикле функции loop, то будем замечать все «всплески» и «падения» сигнала. Потому что пауза между двумя вызовами loop составляет микросекунды и мы измерим все мелкие изменения.
Если мы хотим отследить ситуацию, когда кнопка была отпущена после нажатия, то получим множество ложных сигналов — она будет «нажата-отпущена» десятки раз, хотя мы выполнили лишь однократное нажатие.
Вот пример скетча, в котором непременно обнаружится ошибка дребезга. Мы сможем увидеть в мониторе порта в первые мгновения после нажатия целый набор нулей и единиц в случайной последовательности (не важно, что означает 1 — нажатие или отпускание кнопки, важен сам факт появления хаоса).
void loop() { if (digitalRead(PIN_BUTTON)) { Serial.println(“1”); } else { Serial.println(“0”); }
}
Естественно, такое поведение ни к чему хорошему не приведет и нам нужно придумать способ борьбы с дребезгом. В нашем арсенале есть два способа: программный и аппаратный. Первый довольно простой, но не всегда его можно использовать в реальных проектах. Второй — более надежный, но требует существенных изменений в схеме. Давайте рассмотрим оба способа подробнее.
Программный способ устранения дребезга кнопок
Самым простым способом справиться с проблемой дребезга кнопки является выдерживание паузы. Мы просто останавливаемся и ждем, пока переходный процесс не завершится.
Для этого можно использовать функцию delay()или millis() (за подробной информации можете обратиться к статье про использование функций delay() и millis() в ардуино).
10-50 миллисекунд – вполне нормальное значение паузы для большинства случаев.
int currentValue, prevValue;
void loop() { currentValue = digitalRead(PIN_BUTTON); if (currentValue != prevValue) { // Что-то изменилось, здесь возможна зона неопределенности // Делаем задержку delay(10); // А вот теперь спокойно считываем значение, считая, что нестабильность исчезла currentValue = digitalRead(PIN_BUTTON); } prevValue = currentValue; Serial.println(currentValue);
}
В данном примере мы использовали задержку в программе, чтобы не реагировать на случайные всплески и определить реальную смену сигнала.
Борьба с дребезгом кнопки с помощью библиотеки ардуино
Проблема с дребезгом настолько популярна, что есть специальные библиотеки, в которых вам не надо организовывать ожидание и паузы вручную – это все делается внутри специального класса. Пример популярной библиотеки для борьбы с дребезгом кнопок – библиотека Bounce.
Пример использования библиотеки:
#include ;
#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 ); }
}
Аппаратный способ подавления дребезга кнопки
Подавление дребезга кнопки с помощью задержек в скетче — способ очень распространенный и не требующий изменения самой схемы.
Но далеко не всегда его можно использовать – ведь 10 миллисекунд – это целая вечность для многих процессов в электроном мире.
Также программный способ невозможно применять при использовании прерываний — дребезг приведет к многократному вызову функций и повлиять на этот процесс в скетче мы не сможем.
Более правильный (и более сложный) способ борьбы с дребезгом – использование аппаратного решения, сглаживающего импульсы, посылаемые с кнопки. Для этого, правда, придется внести изменения в схему.
Аппаратный способ устранения дребезга основан на использовании сглаживающих фильтров.
Сглаживающий фильтр, как следует из названия, занимается сглаживанием всплесков сигналов за счет добавления в схему элементов, имеющих своеобразную «инерцию» по отношению к таким электрическим параметрам как ток или напряжение.
Самым распространенным примером таких «инерционных» электронных компонентов является конденсатор. Он может «поглощать» все резкие пики, медленно накапливая и отдавая энергию, точно так же, как это делает пружина в амортизаторах.
За счет инерции устройство как утюгом походит по «мятому» сигналу с большим количеством пиков и впадин, создавая пусть и не идеальную, но вполне гладкую кривую, у которой легче определить уровень срабатывания.
Пример простого фильтра на базе RC-цепочки
Схема подключение фильтра для устранения дребезга:
Пример подключения к плате ардуино
Форма сигнала после использования фильтра:
Как видим, «лес» дребезга сменился достаточно плавной линией, с которой уже можно работать дальше.
Подавление дребезга с помощью триггера шмидта
Сделать квадратную форму сигнала с помощью простой RC цепочки невозможно. Для «огранения» сглаженных форм используется специальный компонент, который называется триггер шмидта. Его особенностью является срабатывание при достижении определенного уровня сигнала.
На выходе триггера шмидта мы получим или высокий или низкий уровень сигнала, никаких промежуточных значений. Выход триггера инвертированный: при спаде входного сигнала он выдает на выходе включение и наоборот. Ниже представлена схема и результат работы с триггером шмидта.
Иллюстрация результата работы:
Как видим, мы практически полностью избавились от результатов переходных процессов, сперва превратив хаос в почти гладкую кривую линию, а затем с помощью триггера шмидта «отрубили» хвосты, придав сигналу практически идеальный вид. Подав его на вход ардуино, мы уже можем не беспокоиться о ложных срабатываниях и смело использовать в скетче метод digitalRead и прерывания.
Заключение
Явление дребезга кнопок — распространенная проблема, встающая перед всеми разработчиками ардуино. У нас в арсенале есть несколько возможностей устранения дребезга.
Программный метод заключается в добавлении задержки в процессе измерения сигнала. Аппаратный способ подавления дребезга с помощью сглаживающего фильтра и триггера шмидта более сложный, но надежный.
Выбирайте подходящий вариант, в зависимости от требований к проекту и ваших возможностей.
В статье использовались материалы сайтов: http://codius.ru, https://uscr.ru
Источник: https://ArduinoMaster.ru/datchiki-arduino/ustranenie-drebezg-kontaktov-knopki/
Что такое дребезг контактов и как его устранить
Дребезг контактов – это паразитное явление, которое вносит проблемы преимущественно в электронных схемах. Его суть заключается в повторном многократном и ложном прерывании и подаче сигнала на вход. В результате система, которая его принимает, неверно реагирует. Давайте более подробнее рассмотрим причины дребезга контактов и способы борьбы с ним.
Определение и суть проблемы в электронике
Дребезг контактов возникает при нажатии на кнопку и переключатель, он возникает из-за реальных вибраций контактной пластины при её перемещении. Любой переключатель устроен так, что у него есть подвижный и неподвижный контакт. Как видно из названия, подвижным называется тот, что соединен с толкателем или рычагом, на который уже нажимает человек или механизм при работе устройства.
Так как кнопки имеют механическое устройство, то от их качества зависит то, как точно они отрабатывают нажатия. При этом в любом случае полностью устранить явление дребезга нельзя. К чему он приводит?
Если клавиша управляет каким-то электронным устройством с цифровым входом, например, микроконтроллера, логического элемента и пр., то его вход распознает столько нажатий, сколько было импульсов послано в результате возникновения дребезга.
Пример осциллограммы дребезга контактов изображен на рисунке ниже:
Устранение эффекта
Чтобы устранить дребезг контактов, возможно использовать аппаратное или программное решение. К аппаратным решениям относится:
- Установка конденсаторов параллельно входу. Тогда может снижаться быстродействие реакции на нажатие при слишком большой ёмкости и неполного устранения дребезга при слишком маленькой.
- Введение триггеров Шмидта во входную цепь устройства. Более сложное решение, которое затруднительно для реализации в ходе доработки уже готового изделия, но и более технологичное и совершенное.
Если рассмотреть это явление на примере сдвигового регистра, то в этом видео наглядно показано его воздействие. После каждого нажатия кнопки должен загораться следующий светодиод.
Схема включения регистра и светодиодов на рисунке ниже:
Кнопка подключена так, как показано на схеме:
Пример осциллограммы сигнала с выраженным дребезгом:
Установив конденсатор на 1 мкФ параллельно кнопке для его подавления, получаем стабильное и точное срабатывание:
Схема подавления:
А фронт сигнала переключения, как вы можете убедиться, действительно завален, зато без лишних всплесков.
Альтернативой такому решению защиты от этого эффекта, без заваливания фронта и с большим быстродействием является использование триггера Шмидта. Типовая его схема изображена ниже:
На следующем рисунке изображены другие варианты схем на логических элементах для борьбы с дребезгом контактов:
Кроме аппаратного устранения, как было сказано, есть и программный способ решения данной проблемы. Он заключается в написании кода, смысл которого в считывании изменения сигнала, выдержки определенного времени и повторного его считывания.
Пример программного подавления дребезга контактов в Arduino IDE вы можете скачать, перейдя по ссылке: код для подавления дребезга.
Дребезжание реле
Кроме дребезга кнопок в цифровых электронных схемах также доставляет проблемы дребезг контактов в схемах управления реле. К таким схемам можно отнести сумеречное реле или различные датчики протока, а также регуляторы температуры.
Когда датчик выдаёт сигнал на пороге срабатывания устройства, получается неопределенное состояние и логика схемы то включает, то отключает его. И при срабатывании реле не всегда наблюдается устойчивое удержание контактов, оно начинает как бы вибрировать, включаясь и отключаясь.
На эпюре ниже наглядно изображена эта проблема на примере регулятора температуры:
Решением этой проблемы также является установка порогового элемента петлей гистерезиса в его передаточных статических характеристиках, то есть триггера Шмидта или Компаратора на операционном усилителе. На схеме ниже изображен исходный вариант с рассмотренной на графике проблемой:
А так выглядит схема с дополнением в виде задержки включения на логических элементах 2И-НЕ отечественной микросхемы К561ЛА7:
Иногда с этой же проблемой справляются с помощью установки стабилитрона в сигнальные цепи.
Аналогично дребезгу кнопок при включении реле, его контакты могут повторно несколько раз перекоммутироваться. Явление опасно тем, что в этот момент происходит зажигание и гашение дуги, что значительно снижает срок службы аппарата. Особенно часто это происходит при срабатывании реле на переменном токе.
Всё это связано с механической структурой герконов, реле и других коммутаторов. Их контакты замыкаются не моментально, а в течении долей, единиц или десятков миллисекунд. Чтобы продлить срок службы реле, ознакомьтесь со способами, которые мы описывали в статье о том, почему искрят контакты.
Также рекомендуем посмотреть хорошее видео на эту тему:
Теперь вы знаете, что такое дребезг контактов реле и какие способы борьбы с ним наиболее эффективны. Если возникли вопросы, задавайте и в комментариях под статьей!
Материалы по теме:
Источник: https://samelectrik.ru/chto-takoe-drebezg-kontaktov-i-kak-ego-ustranit.html
Дребезг контактов, и как с ним бороться
В данной статье мы рассмотрим, что такое дребезг контактов и способы борьбы с ним. Сначала я рассмотрю теорию, а позже покажу вам некоторые способы обработки дребезга и аппаратно, и программно.
Теория
Что такое дребезг контактов? Когда вы нажимаете на кнопку или на микропереключатель или изменяете положение тумблера, два металлических контакта замыкаются. Для пользователя может показаться, что контакт наступил мгновенно. Это не совсем правильно. Внутри коммутатора есть движущиеся части.
Когда вы нажимаете на коммутатор, он вначале создает контакт между металлическими частями, но только в кратком разрезе микросекунды. Затем он делает контакт немного дольше, а затем еще немного дольше. В конце коммутатор полностью замыкается. Коммутатор скачет (дребезжит) между состояниями наличия и отсутствия контакта.
«Когда коммутатор замыкается, два контакта фактически разъединяются и снова соединяются обычно от 10 до 100 раз за время, примерно равное 1 мс» («Искусство схемотехники», Хоровиц и Хилл, второе издание). Обычно оборудование работает быстрее, чем дребезг, что приводит к тому, что оборудование думает, что вы нажали на кнопку несколько раз.
Оборудование часто является интегральной микросхемой. Следующие скриншоты иллюстрируют типовой дребезг контактов без какой-либо обработки:
Осциллограмма дребезга контактов
Каждый коммутатор обладает своими собственными характеристиками относительно дребезга. Если вы сравните два одинаковых коммутатора, есть большая вероятность того, что они будут «дребезжать» по-разному.
Я покажу вам дребезг четырех разных коммутаторов. Я меня есть две микрокнопки, 1 кнопка и 1 тумблер:
Исследуемые коммутаторы
Настройка оборудования
Все коммутаторы будут подключены одинаково (это важно, если мы собираемся сравнивать результаты). Сначала мы увидим, как коммутаторы ведут себя без обработки. Основой нашей схемы будет HCF4017BE.
Это десятичный счетчик/делитель, производимый STMicroelectronics. Они больше не производят эту микросхему, так как этот тип устарел.
Тем не менее, есть много других производителей, которые всё еще выпускают эту маленькую микросхему, и они часто совместимы по контактам.
Микросхема получает тактовый импульс на вывод 14, после чего загорается светодиод, подключенный к Q1. Когда принимается следующий тактовый импульс, микросхема отключает Q1 и зажигает Q2, и так далее. Когда счетчик достигает Q8 (вывод 9), он подает импульс на вывод 15, который является выводом сброса. Это означает запуск отсчета, начиная с Q0.
Наша основная схема:
Схема тестового макета (описание выше)
Сначала мы попробуем не обрабатывать дребезг совсем. Схемы подачи тактового сигнала показаны ниже:
Тактовый вывод удерживается на уровне лог. 0, импульс – лог. 1Тактовый вывод удерживается на уровне лог. 1, импульс – лог. 0
На видео мы используем схему справа. Тактовый вывод удерживается на уровне логической единицы, импульс соответствует уровню логического нуля.
Видео:
Теперь давайте посмотрим некоторые скриншоты осциллографа. Здесь мы использовали левый вариант схемы подачи импульсов: тактовый вывод удерживается на уровне логического нуля, импульс соответствует уровню логической единицы.
Для коммутатора A:
Дребезг контактов коммутатора A
Для коммутатора B:
Дребезг контактов коммутатора B
Для коммутатора C:
Дребезг контактов коммутатора C
Для коммутатора D:
Дребезг контактов коммутатора D
И один скриншот я снял для коммутатора C при использовании правой схемы подачи импульсов: тактовый вывод удерживается на уровне логической единицы, импульс соответствует уровню логического нуля.
Дребезг контактов коммутатора C (импульс соответствует логическому нулю)
Как вы можете видеть, микросхеме кажется, что было несколько нажатий на коммутатор. Хотя это и не так, поскольку на коммутатор было выполнено только одно нажатие.
Добавим керамический конденсатор:
Тактовый вывод удерживается на уровне лог. 0, импульс – лог. 1Тактовый вывод удерживается на уровне лог. 1, импульс – лог. 0
При добавлении конденсатора мы создаем RC-цепь. RC-цепи здесь не обсуждаются.
Новые скриншоты осциллографа сильно отличаются от полученных ранее. Это показывает, что RC-цепь отфильтровывает дребезг.
Данное видео показывает, как работает схема с керамическим конденсатором 0,1 мкФ:
Для коммутатора A:
Сигнал с коммутатора A после добавления конденсатора
Для коммутатора B:
Сигнал с коммутатора B после добавления конденсатора
Для коммутатора C:
Сигнал с коммутатора C после добавления конденсатора
Для коммутатора D:
Сигнал с коммутатора D после добавления конденсатора
Для коммутатора C (импульс соответствует логическому нулю):
Сигнал с коммутатора C после добавления конденсатора (импульс соответствует логическому нулю)
Эти скриншоты говорят нам о том, что дребезг устранен, и что микросхема «видит» только одно нажатие или переключение. Это то, чего мы и хотели.
Программное подавление дребезга
При работе с микроконтроллерами мы можем справиться с дребезгом контактов по-другому, что позволит сэкономить и место под детали, и деньги.
Некоторые программисты не задумываются о дребезжащих коммутаторах и просто добавляют 50 мс задержки после первого «отскока». Это заставляет микроконтроллер ждать остановку дребезга 50 мс, а затем продолжить работу программы.
На самом деле это не очень хорошая практика, так как она удерживает микроконтроллер в ожидании окончания задержки.
Другой способ – использовать прерывание для обработки дребезга контактов. Имейте в виду, что прерывание может быть запущено и при нарастающем, и при спадающем фронте, а некоторые микроконтроллеры могут добавлять одно прерывание в стек. Существуют разные мнения о том, как это использовать, но прерывание, вызванное подавлением дребезга, здесь не обсуждается.
Ниже показано простое программное подавление дребезга контактов для Arduino.
/* Программное подавление дребезга * * При каждом переходе от LOW к HIGH или от HIGH к LOW * выполняется подавление дребезга во входном сигнале * путем выборки по нескольким считываниям в течение * нескольких миллисекунд. Входной сигнал не считается * устоявшимся на уровне LOW или HIGH до тех пор, пока * не будет считан по крайней мере в течение * “debounce_count” (10) миллисекунд в новом состоянии. * * Примечания: * Отрегулируйте значение debounce_count, чтобы * отобразить время, в течение которого входной * сигнал может дребезжать, прежде чем перейдет * в устойчивое состояние. * */ int inPin = 7; // номер входного вывода int outPin = 13; // номер выходного вывода int counter = 0; // сколько раз мы должны получить новое значение int reading; // текущее значение, прочитанное с входного вывода int current_state = LOW; // входное значение, полученное после подавления дребезга // следующая переменная long, потому что время, измеренное в миллисекундах, // быстро станет числом, большим, чем может храниться в int. long time = 0; // время последней выборки входного вывода int debounce_count = 10; // количество миллисекунд/выборок для решения, что сигнал на входе принял устойчивое состояние void setup() { pinMode(inPin, INPUT); pinMode(outPin, OUTPUT); digitalWrite(outPin, current_state); // установить выход светодиода в начальное состояние } void loop() { // Если мы перешли к следующей миллисекунде if(millis() != time) { reading = digitalRead(inPin); if(reading == current_state && counter > 0) { counter–; } if(reading != current_state) { counter++; } // Если вход показывает одно значение достаточно долго, давайте переключим его if(counter >= debounce_count) { counter = 0; current_state = reading; digitalWrite(outPin, current_state); } time = millis(); } }
Код выше был написан в Arduino IDE.
Следующая программа мигает двумя светодиодами, подключенными к PIC микроконтроллеру. Код может быть похожим на этот:
// включения #include #include #include // конфигурация #pragma config FOSC = INTOSCIO // Биты выбора генератора (INTOSC генератор: I/O функция на выводе RA6/OSC2/CLKOUT, I/O функция на выводе RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Бит включения сторожевого таймера (WDT выключен) #pragma config PWRTE = OFF // Бит включения таймера включения (PWRT выключен) #pragma config MCLRE = ON // Бит выбора функции вывода RA5/MCLR/VPP (функция вывода RA5/MCLR/VPP – это is MCLR) #pragma config BOREN = ON // Бит включения обнаружения просадки питания (BOD включен) #pragma config LVP = ON // Бит включения низковольтного программирования (функция вывода RB4/PGM – это PGM, низковольтное программирование включено) #pragma config CPD = OFF // Бит защиты данных памяти eeprom (защита данных памяти eeprom выключена) #pragma config CP = OFF // Бит защиты кода Flash памяти программ (защита кода выключена) // Определения #define _XTAL_FREQ 4000000 #define LED1 PORTBbits.RB3 #define LED2 PORTBbits.RB2 #define BTN PORTBbits.RB5 // Переменные char BTN_pressed = 0; char BTN_press = 0; char BTN_release = 0; char Bouncevalue = 500; // Основная программа int main(int argc, char** argv) { // Компараторы выключены CMCON = 0x07; // Направления портов, RB5 вход, остальные – выходы TRISA = 0b00000000; TRISB = 0b00100000; // Состояние портов, на всех лог. 0 PORTA = 0b00000000; PORTB = 0b00000000; // Начинаем с включенным (лог. 1) LED1 и выключенным (лог. 0) LED2 LED1 = 1; LED2 = 0; while (1) { // Если кнопка BTN нажата if (BTN == 1) { // Дребезг началсь, поэтому увеличим BTN_press на 1 при каждом отскоке к высокому логическому уровню BTN_press++; // “сбросить” BTN_release BTN_release = 0; // Если отскоков столько, что BTN_press больше Bouncevalue, // кнопка должно быть нажата if (BTN_press > Bouncevalue) { // Это первоначальное значение BTN_pressed. // Если программа дошла до этого места, кнопка должно быть нажата if (BTN_pressed == 0) { // Поменять состояния светодиодов LED1 ^= 1; LED2 ^= 1; // Устанавливаем BTN_pressed в 1, убеждаясь что мы // не попадем снова в этот блок кода BTN_pressed = 1; } // Светодиоды переключены, установить BTN_press в 0, чтобы мы могли снова войти // в блок переключающего кода BTN_press = 0; } } else { // Увеличить “низкий уровень” на 1 для подавления дребезга BTN_release++; BTN_press = 0; // Если BTN_release больше Bouncevalue, то кнопка у нас не нажата if (BTN_release > Bouncevalue) { BTN_pressed = 0; BTN_release = 0; } } } return (EXIT_SUCCESS); }
Этот пример написан MPLAB X с компилятором XC8. Микроконтроллер – это PIC 16F628A, и я использовал внутренний генератор на 4 МГц. Вам необходимо поэкспериментировать с Bouncevalue. У меня лучше всего программа работала со значением 500.
Микроконтроллер без какого-либо подавления дребезга контактов:
Это пример того, как коммутатор может «запутать» микроконтроллер. Нормального переключения светодиодов не получилось. Похоже, что при нажатии кнопки они живут своей жизнью.
Микроконтроллер с управлением подавлением дребезга контактов:
Как видите, светодиоды хорошо включаются и выключаются по нажатию кнопки.
Заключение
В данной статье мы рассмотрели, что такое дребезг контактов, как он влияет на вашу систему, и различные способы борьбы с ним. Используемые примеры очень просты, но они должны дать вам представление о том, что происходит, когда вы нажимаете на кнопку. При разработке системы вы всегда должны учитывать дребезг контактов переключателя.
Оригинал статьи:
- Switch Bounce and How to Deal with It
Источник: https://radioprog.ru/post/251
Дребезг контактов и способы подавления дребезга
Дребезг контактов на экране осциллографа
Дребезг контактов — явление, возникающее в электрических и электронных переключателях, при котором они вместо некоторого стабильного переключения производят случайные многократные неконтролируемые замыкания и размыкания контактов (происходит в момент переключения, приблизительно в течение 40—100 мс). Иными словами — это явление, вызванное неизбежным несовершенством технологии изготовления переключателей.
При нажатии на тактовую кнопку, перед тем, как контакты плотно соприкоснутся, они будут колебаться (т.е. «дребезжать»), порождая множество срабатываний вместо одного. Соответственно, микроконтроллер «поймает» все эти нажатия, потому что дребезг не отличим от настоящего нажатия на кнопку. В статье рассмотрены несколько способов, позволяющих избежать дребезга.
Для понимания сути, нам нужно рассмотреть простой код, который зажигает встроенный в плату Arduino светодиод на пине 13 при нажатии кнопки и гасит светодиод при следующем нажатии. Кнопка подключена ко второму пину (о подключении кнопки читайте статью « Как подключить кнопку к Arduino »):
byte led=0; //Состояние светодиодаbyte oldled=1; //Последнее состояние светодиода, для исключения ложных переключенийif(digitalRead(2)==HIGH) { //Когда нажата кнопка if (led==oldled) { //Проверка, что состояние кнопки изменилосьdigitalWrite(13,led); //Переключаем светодиод |
Это рабочий код, но из-за дребезжания контактов кнопки он поймает много лишних срабатываний.
Причём всё происходит так быстро, что программа успеет поймать ложные срабатывания несколько раз и несколько раз включить-выключить светодиод. В итоге, ваше устройство будет работать случайным образом.
Если повезёт — светодиод будет гореть после нажатия. Не повезёт — цикл проскочит на состояние, когда светодиод окажется выключенным.
Программный способ избавления от дребезга
Суть программного способа в том, чтобы внутри программы отличить случайные срабатывания из-за дребезга от настоящего нажатия. Самый простой способ: добавить задержку сразу после первого срабатывания. Тогда при срабатывании кнопки мы останавливаем выполнение программы и дожидаемся, пока контакты кнопки перестанут дребезжать. Ложных срабатываний не будет.
byte led=0; //Состояние светодиодаbyte oldled=1; //Последнее состояние светодиода, для исключения ложных переключенийif(digitalRead(2)==HIGH) { //Когда нажата кнопка delay(100); //Защита от дребезга if (led==oldled) { //Проверка, что состояние кнопки изменилосьdigitalWrite(13,led); //Переключаем светодиод |
Этот способ прост и понятен, но имеет недостаток: выполнение программы останавливается при нажатии кнопки, что может быть недопустимо в некоторых случаях, а при использовании прерывания невозможно в принципе. Следующий вариант избавления от дребезга, засекать время, прошедшее от первого срабатывания кнопки с помощью функции millis:
byte led=0; //Состояние светодиодаbyte oldled=1; //Последнее состояние светодиода, для исключения ложных переключенийlong previousMillis = 0; //Время последнего нажатия кнопкиif(digitalRead(2)==HIGH) { //Когда нажата кнопка //Если от предыдущего нажатия прошло больше 100 миллисекунд if (millis() – previousMillis > 100) { //Запоминаем время первого срабатывания previousMillis = millis(); if (led==oldled) { //Проверка, что состояние кнопки изменилосьdigitalWrite(13,led); //Переключаем светодиод |
Этот код обеспечивает избавление от дребезга и при этом не блокирует выполнение программы, как это происходит при использовании функции delay.
Еще одним способом избавлением от дребезга является использование библиотеки Bounce. В ней уже все предусмотрено, и для чтения значения на входе используются специальные функции:
// подключение библиотеки Bounce// Создание объекта Bounce.// В качестве параметров конструктору передаются номер пина кнопки// и время дребезга в миллисекундах.Bounce bouncer = Bounce(2,5);byte led=0; //Состояние светодиодаbyte oldled=1; //Последнее состояние светодиода, для исключения ложных переключений // Опрос изменения состояния кнопки if ( bouncer.update() ) { if ( bouncer.read() == HIGH) { //Когда нажата кнопка if (led==oldled) { //Проверка, что состояние кнопки изменилось } else { //Когда не нажатаdigitalWrite(13,led); //Переключаем светодиод |
Вот так просто работает эта библиотека. Предположительное значение дребезга лучше подбирать экспериментально, оно сильно зависит от качества изготовления конкретной кнопки.
Аппаратный способ подавления дребезга
Аппаратные решения всегда ценились за их надёжность и возможность облегчить написание программы.
https://www.youtube.com/watch?v=ROkX02k8lq0
Вот как выглядела схема подключения кнопки без аппаратной защиты от дребезга:
Схема подключения кнопки к Arduino
Добавив пару дополнительных элементов в схему мы сможем полностью избавиться от дребезга, не усложняя при этом код. А добавим мы инвертирующий триггер Шмитта и конденсатор. Мы построим RC-цепь с инвертирующим триггером.
Вот так это выглядит на схеме:
Резистор 10 кОм у нас теперь подтягивает вывод не к земле, а к +5В. Причём подтягивается не вход Ардуино, а вход инвертирующего триггера и заодно, конденсатор. Кнопка же, наоборот, подключена к земле. Сделано это в связи с тем, что триггер у нас инвертирующий. Суть такова: входящий аналоговый сигнал может быть восходящим, либо нисходящим.
Внутри триггера определены пороговые значения: ~1,6 В — для нисходящего сигнала и ~0,9 В — для восходящего. Выход триггера становится логической единицей (5 В), при прохождении нисходящим сигналом через свой порог в 0,9 В, при этом нисхождение восходящим сигналом верхнего порога в 1,6 В будет проигнорировано.
Аналогично, выход триггера становится логическим нулём (0 В), только когда восходящий сигнал проходит свой порог в 1,6 В, при этом проигнорируется прохождение нисходящим сигналом нижнего порога в 0,9 В. Зона неопределённости между порогами называется гистерезисом. То есть триггер переворачивает сигнал.
Конденсатор с резистором образует RC-цепь. RC — от английских названий резистора и конденсатора (resistor и capacitor). RC-цепь замедляет затухание сигнала. То есть при снятии напряжения, оно пропадёт не сразу, а будет плавно снижаться.
При нажатии кнопки мы прижмём RC-цепь к земле, конденсатор начнёт разряжаться и напряжение начнёт плавно падать. После отпускания кнопки, напряжение начнёт так же плавно расти:
График изменения напряжения RC-цепи
Инвертирующий триггер выполняет 2 функции:
1) он инвертирует (переворачивает) логические уровни: единица становится нулём, а ноль становится единицей.
2) он преобразует аналоговый сигнал в цифровой. То есть, в определённый момент, когда конденсатор разрядится до определённого уровня, триггер выдаст логическую единицу. Затем это нужно? При отпускании кнопки, при достижении определённого уровня заряда конденсатора, триггер установит на выходе низкий уровень. Сигнал на выходе триггера не будет зависеть от дребезга:
График изменения напряжения на выходе инвертирующего триггера Шмитта
Источник: https://uscr.ru/drebezg-kontaktov-i-sposoby-podavleniya-drebezga/
Как избавиться от дребезга контактов при подключении кнопки к Arduino
- Arduino;
- тактовая кнопка;
- резистор номиналом 10 кОм;
- светодиод;
- соединительные провода.
«Дребезг» контактов – это явление, свойственное механическим переключателям, кнопкам, тумблерам и реле.
Из-за того, что контакты обычно делают из металлов и сплавов, которые обладают упругостью, при физическом замыкании они не сразу устанавливают надёжное соединение. В течение короткого промежутка времени контакты несколько раз смыкаются и отталкиваются друг от друга.
В результате этого электрический ток принимает установившееся значение не моментально, а после череды нарастаний и спадов. Длительность этого переходного эффекта зависит от материала контактов, от их размера и конструкции. На иллюстрации показана типичная осциллограмма при замыкании контактов тактовой кнопки.
Видно, что время от момента переключения до установившегося состояния составляет несколько миллисекунд. Это и называется «дребезгом».
Так выглядит эффект дребезга контактов на осциллограммах
Этот эффект не заметен в электрических цепях управления освещением, двигателями или другими инерционными датчиками и приборами.
Но в цепях, где идёт быстрое считывание и обработка информации (где частоты того же порядка, что и импульсы «дребезга», или выше), это является проблемой. В частности, Arduino UNO, который работает на частоте 16 МГц, отлично ловит «дребезг» контактов, принимая последовательность единиц и нулей вместо единичного переключения от 0 к 1.
2Подключение кнопки к Arduino для демонстрации подавления «дребезга»
Давайте посмотрим, как дребезг контактов влияет на правильную работу схемы. Подключим к Arduino тактовую кнопку по схеме со стягивающим резистором. Будем по нажатию кнопки зажигать светодиод и оставлять включённым до повторного нажатия кнопки. Для наглядности подключим к цифровому выводу 13 внешний светодиод, хотя можно обойтись и встроенным.
Схема подключения кнопки к Arduino для демонстрации подавления эффекта «дребезга» контактов
3Алгоритм подавления«дребезга» контактов
Чтобы реализовать задачу подавления дребезга контактов, первое, что приходит в голову:
- запоминать предыдущее состояние кнопки;
- сравнивать с текущим состоянием;
- если состояние изменилось, то меняем состояние светодиода.
Напишем такой скетч и загрузим в память Arduino.
int switchPin = 2; // вывод считывания кнопки int ledPin = 13; // вывод светодиода boolean lastButton = false; // предыдущее состояние кнопки boolean ledOn = false; // включён или выключен светодиод void setup() { pinMode(switchPin, INPUT); // состояние кнопки считываем (in) pinMode(ledPin, OUTPUT); // светодиод запитываем (out) } void loop() { int pressed = digitalRead(switchPin); /* состояние кнопки: HIGH, true – нажата, LOW, false – нет */ if (pressed == true && lastButton == false) { /* если кнопка сейчас нажата, а до этого была не нажата */ ledOn = !ledOn; // меняем состояние светодиода lastButton = true; // запоминаем новое состояние кнопки } else { lastButton = digitalRead(switchPin); // считываем состояние кнопки } digitalWrite(ledPin, ledOn); // зажигаем или гасим светодиод }<\p>
При включении схемы в работу, сразу виден эффект дребезга контактов. Он проявляется в том, что светодиод загорается не сразу после нажатия кнопки, или загорается и тут же гаснет, или не выключается сразу после нажатия кнопки, а продолжает гореть. В общем, схема работает не стабильно. И если для задачи с включением светодиода это не столь критично, то для других, более серьёзных задач, это просто неприемлемо.
4Подавление дребезга контактовс помощью задержки
Постараемся исправить ситуацию. Мы знаем, что дребезг контактов проявляет себя в течение нескольких миллисекунд после замыкания контактов. Давайте после изменения состояния кнопки выжидать, скажем, 5 мсек.
Это время для человека является практически мгновением, и нажатие кнопки человеком обычно происходит значительно дольше – несколько десятков миллисекунд.
А Arduino прекрасно работает с такими короткими промежутками времени, и эти 5 мсек позволят ему отсечь дребезг контактов от нажатия кнопки.
int switchPin = 2; // пин кнопки int ledPin = 13; // пин светодиода boolean lastButton = false; // предыдущее состояние кнопки boolean currentButton = false; // текущее состояние кнопки boolean ledOn = false; // состояние светодиода void setup() { pinMode (switchPin, INPUT); pinMode (ledPin, OUTPUT); } void loop() { currentButton = debounce (lastButton); // получаем состояние кнопки без дребезга if (lastButton == false && currentButton == true) { // если кнопка была нажата дольше 5 мсек, ledOn = !ledOn; // то меняем состояние светодиода } lastButton = currentButton; // обнуляем состояние нажатия кнопки digitalWrite (ledPin, ledOn); // зажигаем/гасим светодиод } // Процедура определения нажатия кнопки без дребезга: boolean debounce(boolean last) { boolean current = digitalRead(switchPin); // считываем текущее состояние кнопки if (last != current) { // если состояние изменилось delay(5); // делаем задержку на 5 мсек, пока уляжется дребезг current = digitalRead(switchPin); // и считываем снова } return current; // возвращаем текущее состояние кнопки }
В данном скетче мы объявим процедуру debounce() (“bounce” по-английски – это как раз «дребезг», приставка “de” означает обратный процесс), на вход которой мы подаём предыдущее состояние кнопки. Если нажатие кнопки длится более 5 мсек, значит это действительно нажатие. Определив нажатие, мы меняем состояние светодиода.
Загрузим скетч в плату Arduino. Теперь всё гораздо лучше! Кнопка срабатывает без сбоев, при нажатии светодиод меняет состояние, как мы и хотели.
5Библиотеки для подавлениядребезга контактов
Аналогичная функциональность обеспечивается специальными библиотеками, например, библиотекой Bounce2. Для установки библиотеки помещаем её в директорию /libraries/ среды разработки Arduino и перезапускаем IDE.
Библиотека Bounce2 содержит следующие методы:
Bounce() | инициализация объекта “Bounce”; |
void interval (мсек) | устанавливает время задержки в миллисекундах; |
void attach (номерПина) | задаёт вывод, к которому подключена кнопка; |
int update() | обновляет объект и возвращает true, если состояние пина изменилось, и false в противном случае; |
int read() | считывает новое состояние пина. |
Перепишем наш скетч с использованием библиотеки. Можно также запоминать и сравнивать прошлое состояние кнопки с текущим, но давайте упростим алгоритм.
#include // подключаем библиотеку const int switchPin = 2; // пин кнопки const int ledPin = 13; // пин светодиода int cnt = 0; // счётчик нажатий Bounce b = Bounce(); // инстанциируем объект Bounce void setup() { pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); // включаем подтягивающий резистор pinMode(ledPin, OUTPUT); b.attach(switchPin); // объект Bounce будет слушать кнопку на пине switchPin b.interval(5); // устанавливаем время задержки в [мс] } void loop() { if (b.update() && b.read() == 0) { // если зарегистрировано событие и кнопка нажата, cnt += 1; // инкрементируем счётчик нажатий if (cnt %2 == 0) digitalWrite(ledPin, LOW); // если нажатий чётное число, гасим светодиод else digitalWrite(ledPin, HIGH); // иначе – зажигаем светодиод } }
При нажатии кнопки будем считать нажатия, и каждое нечётное нажатие будем включать светодиод, каждое чётное – выключать. Такой скетч смотрится лаконично, его легко прочитать и легко применить.
Подавление дребезга контактов с помощью Arduino
Ну и напоследок пара видео от Джереми Блюма, где он рассказывает о способах подавления дребезга контактов на примере подключения тактовой кнопки к Arduino.
Источник: https://soltau.ru/index.php/arduino/item/393-kak-izbavitsya-ot-drebezga-kontaktov-pri-podklyhttps-