Полный текст программы
// constants won’t change. They’re used here to set pin numbers: const int buttonPin = 2; // the number of the pushbutton pin const int ledPin = 13; // the number of the LED pin // Variables will change: int ledState = HIGH; // the current state of the output pin int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin // the following variables are unsigned longs because the time, measured in // milliseconds, will quickly become a bigger number than can be stored in an int. unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers void setup() { pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); // set initial LED state digitalWrite(ledPin, ledState); } void loop() { // read the state of the switch into a local variable: int reading = digitalRead(buttonPin); // check to see if you just pressed the button // (i.e. the input went from LOW to HIGH), and you’ve waited long enough // since the last press to ignore any noise: // If the switch changed, due to noise or pressing: if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() — lastDebounceTime) > debounceDelay) { // whatever the reading is at, it’s been there for longer than the debounce // delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { ledState = !ledState; } } } // set the LED: digitalWrite(ledPin, ledState); // save the reading. Next time through the loop, it’ll be the lastButtonState: lastButtonState = reading; }
Устранение эффекта
Чтобы устранить дребезг контактов, возможно использовать аппаратное или программное решение. К аппаратным решениям относится:
- Установка конденсаторов параллельно входу. Тогда может снижаться быстродействие реакции на нажатие при слишком большой ёмкости и неполного устранения дребезга при слишком маленькой.
- Введение триггеров Шмидта во входную цепь устройства. Более сложное решение, которое затруднительно для реализации в ходе доработки уже готового изделия, но и более технологичное и совершенное.
Если рассмотреть это явление на примере сдвигового регистра, то в этом видео наглядно показано его воздействие. После каждого нажатия кнопки должен загораться следующий светодиод.
https://youtube.com/watch?v=PR96GZdUz0s
Схема включения регистра и светодиодов на рисунке ниже:
Кнопка подключена так, как показано на схеме:
Пример осциллограммы сигнала с выраженным дребезгом:
Установив конденсатор на 1 мкФ параллельно кнопке для его подавления, получаем стабильное и точное срабатывание:
https://youtube.com/watch?v=idueJoJGiHU
Схема подавления:
А фронт сигнала переключения, как вы можете убедиться, действительно завален, зато без лишних всплесков.
Альтернативой такому решению защиты от этого эффекта, без заваливания фронта и с большим быстродействием является использование триггера Шмидта. Типовая его схема изображена ниже:
На следующем рисунке изображены другие варианты схем на логических элементах для борьбы с дребезгом контактов:
Кроме аппаратного устранения, как было сказано, есть и программный способ решения данной проблемы. Он заключается в написании кода, смысл которого в считывании изменения сигнала, выдержки определенного времени и повторного его считывания.
Теория
Что такое дребезг контактов? Когда вы нажимаете на кнопку или на микропереключатель или изменяете положение тумблера, два металлических контакта замыкаются. Для пользователя может показаться, что контакт наступил мгновенно. Это не совсем правильно. Внутри коммутатора есть движущиеся части. Когда вы нажимаете на коммутатор, он вначале создает контакт между металлическими частями, но только в кратком разрезе микросекунды. Затем он делает контакт немного дольше, а затем еще немного дольше. В конце коммутатор полностью замыкается. Коммутатор скачет (дребезжит) между состояниями наличия и отсутствия контакта. «Когда коммутатор замыкается, два контакта фактически разъединяются и снова соединяются обычно от 10 до 100 раз за время, примерно равное 1 мс» («Искусство схемотехники», Хоровиц и Хилл, второе издание). Обычно оборудование работает быстрее, чем дребезг, что приводит к тому, что оборудование думает, что вы нажали на кнопку несколько раз. Оборудование часто является интегральной микросхемой. Следующие скриншоты иллюстрируют типовой дребезг контактов без какой-либо обработки:
Осциллограмма дребезга контактов
Каждый коммутатор обладает своими собственными характеристиками относительно дребезга. Если вы сравните два одинаковых коммутатора, есть большая вероятность того, что они будут «дребезжать» по-разному.
Я покажу вам дребезг четырех разных коммутаторов. Я меня есть две микрокнопки, 1 кнопка и 1 тумблер:
Исследуемые коммутаторы
https://youtube.com/watch?v=WNHiq6XxhKQ
https://youtube.com/watch?v=fu6YBtuxfn4
https://youtube.com/watch?v=VVAvbm4KpH0
Аппаратный способ подавления дребезга кнопки
Подавление дребезга кнопки с помощью задержек в скетче – способ очень распространенный и не требующий изменения самой схемы. Но далеко не всегда его можно использовать – ведь 10 миллисекунд – это целая вечность для многих процессов в электроном мире. Также программный способ невозможно применять при использовании прерываний – дребезг приведет к многократному вызову функций и повлиять на этот процесс в скетче мы не сможем.
Более правильный (и более сложный) способ борьбы с дребезгом – использование аппаратного решения, сглаживающего импульсы, посылаемые с кнопки. Для этого, правда, придется внести изменения в схему.
Аппаратный способ устранения дребезга основан на использовании сглаживающих фильтров. Сглаживающий фильтр, как следует из названия, занимается сглаживанием всплесков сигналов за счет добавления в схему элементов, имеющих своеобразную “инерцию” по отношению к таким электрическим параметрам как ток или напряжение. Самым распространенным примером таких “инерционных” электронных компонентов является конденсатор. Он может “поглощать” все резкие пики, медленно накапливая и отдавая энергию, точно так же, как это делает пружина в амортизаторах.
За счет инерции устройство как утюгом походит по “мятому” сигналу с большим количеством пиков и впадин, создавая пусть и не идеальную, но вполне гладкую кривую, у которой легче определить уровень срабатывания.
Пример простого фильтра на базе RC-цепочки
Схема подключение фильтра для устранения дребезга:
Пример подключения к плате ардуино
Форма сигнала после использования фильтра:
Как видим, “лес” дребезга сменился достаточно плавной линией, с которой уже можно работать дальше.
Подавление дребезга с помощью триггера шмидта
Сделать квадратную форму сигнала с помощью простой RC цепочки невозможно. Для “огранения” сглаженных форм используется специальный компонент, который называется триггер шмидта. Его особенностью является срабатывание при достижении определенного уровня сигнала. На выходе триггера шмидта мы получим или высокий или низкий уровень сигнала, никаких промежуточных значений. Выход триггера инвертированный: при спаде входного сигнала он выдает на выходе включение и наоборот. Ниже представлена схема и результат работы с триггером шмидта.
Иллюстрация результата работы:
Как видим, мы практически полностью избавились от результатов переходных процессов, сперва превратив хаос в почти гладкую кривую линию, а затем с помощью триггера шмидта “отрубили” хвосты, придав сигналу практически идеальный вид. Подав его на вход ардуино, мы уже можем не беспокоиться о ложных срабатываниях и смело использовать в скетче метод digitalRead и прерывания.
Способы устранения и подавления дребезга
Без конструктивного изменения контактной системы устранить либо подавить дребезг принципиально невозможно. Примером таких конструктивных изменения можно наблюдать в узлах галетных переключателей или в кнопках типа П2К. В упомянутых конструкциях дребезг практически отсутствует. Нет его и у механического переключателя ползункового типа.
Аппаратный способ
С целью подавления дребезга в системах слаботочных электромеханических ключей прибегают к смачиванию ртутью контактов, которые помещают в изолирующие колбы. Жидкое состояние ртути частично гасит упругие силы, вызывающие дребезг, а также образует токопроводящие перемычки, не позволяющие разрывать электрическую цепь при соприкосновении контактов.
Для снижения уровня коммутационного износа в различных реле и силовых выключателях применяют искрогасящие цепочки:
- шунтирующие RC-цепи;
- варисторы, препятствующие скачкообразному изменению напряжения;
- обратные диоды, подавляющие напряжения самоиндукции;
- стабилитроны;
- комбинированные схемы (варистор +RC-цепь).
Эти цепочки помогают устранить дребезг путём выравнивания скачкообразных характеристик тока. Их подключают параллельно нагрузке либо к контактам реле. Существуют также схемы, в которых искрогасящие цепи подключаются одновременно и к нагрузке и к реле.
Схемы цепей изображены на рис. 3.
Рисунок 3. Схемы искрогасящих цепей
У каждого способа есть свои преимущества и недостатки. В зависимости от того какого результата необходимо достигнуть, применяют ту или иную схему.
Управление приборами чувствительными к дребезгу осуществляется через ФНЧ (например, через RC-цепочку). Обладая электрической емкостью, конденсатор забирает часть энергии в момент касания контактов. После разрыва цепи вследствие дребезга накопленная энергия возвращается. Таким образом, происходит сглаживание амплитуды колебаний.
Установки триггеров
Ещё один способ борьбы с дребезгом состоит в использовании специальных электронных схем, включающих rs-триггеры.
Роль триггеров заключается в преобразовании входного аналогового сигнала в цифровой и инверсии (переворачивания) логических уровней. Наглядно инверсию объясняет схема на рисунке 4.
Рис. 4. Наглядная схема инверсии сигнала
Устройство учитывает только части сигналов, превосходящие заданные пороговые значения, выдавая логические нули и единицы на выходе. Каждый раз восходящий или нисходящий сигнал переключает триггер, когда он проходит верхнее или нижнее пороговое значение. Проще говоря, провалы напряжения компенсируются инвертированными импульсами триггеров.
Простая схема с триггером показана на рисунке 5.
Рис. 5. Наглядная схема подключения rs-триггеров
Промежутки между пороговыми значениями называются гистерезисом. Форма таких импульсов используется для шумоподавления во время переключения логических сигналов. Сигнал от контакта поступает на схему, имеющую передаточную статическую характеристику в виде петли гистерезиса (триггер Шмидта). Только после этого сигнал с выходов триггера подаётся на вход цифрового устройства для тактирования.
Использование герконов
Выше упоминалось, что наличие ртути на контактах подавляет дребезг. Но общеизвестно, что пары этого жидкого металла очень ядовиты. Использовать их в открытых конструкциях, например в тактовых кнопках, небезопасно. Но контакты можно поместить в герметическую колбу, что позволяет применять ртуть. Такие конструкции называются герконами.
Управление контактами герконов осуществляется внешним магнитным полем. Для этого можно использовать постоянные магниты или электромагнитную индукцию. Устройства могут использоваться в маломощных цепях. Они имеют длительный срок службы, так как контакты в них не изнашиваются.
Что такое дребезг контактов
Дребезг контактов возникает во время замыкания или размыкания контактов. Посмотрите на рисунок:
Изначально контакт разомкнут.
Когда мы начинаем замыкать контакт (нажимаем на кнопку), то замыкание происходит не сразу.
Это нам кажется, что мы нажали на кнопку мгновенно. Однако на самом деле, если растянуть время достаточно сильно, по получится, что мы нажимаем кнопку постепенно. На механическом контакте надо обеспечить достаточное усилие, чтобы он окончательно замкнулся, а контакты, как правило, пружинят, и поэтому какое-то время контакт находится в переходном процессе. То есть быстро-быстро замыкается-размыкается.
Если мы включаем этой кнопкой лампочку, то мы не заметим этот переходный процесс. Нам будет казаться, что лампочка сразу включилась после нажатия кнопки.
Однако быстродействие микроконтроллера таково, что он заметит все (или почти все) замыкания-размыкания переходного процесса. Это будет означать, что программа микроконтроллера столько раз отреагирует на сигнал от кнопки, сколько раз будет изменяться сигнал во время переходного процесса.
А мы то ожидаем, что одно нажатие кнопки — это одно переключение входа микроконтроллера. Но на самом деле это не так. Потому что дребезг контактов вносит свою лепту в усложнение жизни инженеров.
Представьте, что наши кнопки — это клавиатура телефона. Мы нажимаем цифру 8, подразумевая, что эта цифра будет набрана телефоном один раз. Но телефон вместо этого набирает 5 или 10 восьмёрок, потому что разработчики телефона не удосужились предусмотреть защиту от дребезга контактов. Станете вы пользоваться таким телефоном?
Ну и напоследок надо сказать, что время дребезга контактов зависит от качества контактов, и обычно составляет от 10 до 100 мс.
Алгоритм подавления
Принцип аппаратного способа устранения дребезга состоит в следующем:
- При использовании конденсатора. Напряжение на нем не может измениться мгновенно, поэтому множество коротких переходных процессов соединяются в 1 процедуру.
- При использовании RS-триггера (триггера Шмитта). Это устройство, которое имеет только 1 активное положение — сброшен/установлен (логические ноль/единица).
RS-триггер представляет собой простейший управляющий автомат.
Алгоритм действия программного метода состоит в следующем:
- считать состояние клавиши;
- подождать фиксированный отрезок времени;
- проверить статус клавиши еще раз (если он не изменился, то считать кнопку нажатой, если обновился, то определить нажатие ложным и никак не реагировать на него).
Программирование ПЛИС. Изучение явления «дребезг контактов» и метод избавления от него
Мы продолжаем изучение ПЛИС и языка VHDL. В данной статье, ориентированной на новичков, мы изучим явление «дребезг контактов» и рассмотрим способ избавления от него. Итак, цель работы: Изучить явление «дребезг контактов», создать проект в Xilinx ISE Project Navigator: При нажатии на кнопку значение регистра увеличивается на 1.
Часть 1. Что такое «дребезг контактов»?
«Дре́безг — явление, возникающее в электрических и электронных переключателях, при котором они вместо некоторого стабильного сигнала выдают на выходе случайные высокочастотные колебания» (с) Википедия. Говоря проще, при нажатии и отпускании кнопки она переходит в нужное состояние не сразу. Какое-то время контакты кнопки «дребезжат» между собой, что будет воспринято микроконтроллером как многократные импульсы. Количество этих импульсов может превышать тысячи. Наглядно дребезг можно увидеть на осциллограмме, на которой показан момент отпускания кнопки:
Часть 2. Создание проекта.
В моей предыдущей статье было подробно описано создание нового проекта для Spartan-3E Starter Kit в Xilinx ISE Project Navigator v12.3. Создадим проект еще раз, назовем его, например, drebezg_habr и внесем в него некоторые изменения: 1. Нам потребуется одна кнопка и восемь светодиодов. Добавим входной сигнал btn и 8 выходных сигналов led в порты:
2. В файле pin.ucf напишем имена ножек, соответствующие кнопке и каждому светодиоду:
Ножка K17 соответствует нижней кнопке из имеющихся: Слово PULLUP подключает кнопку по следующей схеме (прямо внутри ПЛИС):
Часть 3. Программирование.
Переходим в файл drebezg_habr.vhd. Создадим 8-битный регистр-счетчик, который мы будем пытаться прибавлять на единицу при однократном нажатии кнопки: между architecture и begin пишем
И сразу же, после слова begin, направляем этот счетчик на наши светодиоды:
Теперь наша задача прибавить единицу к счетчику count_led при нажатии кнопки. Сразу же напрашивается решение сделать переменную, которая бы хранила предыдущее состояние кнопки и сравнивалась с ее текущим состоянием. Давайте так и сделаем:
Транслируем, зашиваем, тестируем. Уверен, что результат вас совершенно не устроит, ибо диоды будут просто совершенно неупорядоченно мигать. Это связано с тем, что событий if old_btn = ‘0’ and btn = ‘1’ then во время нажатия и отпускания кнопки очень много как раз из-за дребезга контактов. Чтобы избавиться от этого явления нам необходимо дождаться четко установившегося значения логической единицы. Для этого мы заведем счетчик, который увеличивается на 1, пока кнопка имеет значение логической единицы. Счетчик обнуляется, если кнопка приняла значение логического нуля. Таким образом, сколько бы не было импульсов во время нажатия кнопки из-за дребезга, настанет момент, когда значение btn четко установится в логическую единицу, счетчик достигнет определенного значения, и мы сможем судить о том, что действительно было совершено нажатие кнопки. Теперь нам не потребуется переменная old_btn.
Значение btn_wait было выбрано 0.25 секунды для того, чтобы значение count_led не прибавлялось слишком часто, пока кнопка находится в зажатом состоянии. Еще один вариант антидребезга (даже более надежный) — прибавление count на 1 когда btn является логической единицей, и вычитание из count 1 когда btn является нулем. При этом если значение count опускается до 0 значит кнопка не нажата, либо был дребезг. Ну а если count досчитал до заветного btn_wait значит произошло нажатие =) В качестве домашнего задания могу посоветовать дописать проект: сделайте прибавление count_led после того, как кнопка была нажата и отпущена. Итак, мы ознакомились на практике с явлением «дребезг контактов» и научились избавляться от него. Это явление можно наблюдать не только в кнопках, тумблерах и прочих подобных вещах, но даже иногда и в различных протоколах, например RS-232. Исходники проекта здесь. Желаю всем успехов в освоении ПЛИС!
Что такое дребезг контактов?
В конструкциях всех электромеханических устройств, предназначенных для замыкания-размыкания цепей, существует одна или несколько контактных пар. С их помощью происходит коммутация соответствующих электрических компонентов. Существенным недостатком электромеханических контактов являются произвольные неконтролируемые многократные повторы коммутации, вследствие упругости элементов контактной системы. Это явление получило название – дребезг контактов, а борьбу с ним ведут практически с того момента когда появились первые элементы автоматизированных систем.
Давайте разберёмся, какие физические факторы вызывают дребезжание и почему при этом возникают негативные последствия.
Причины возникновения
При взаимодействии упругих тел возникает деформация. Сила упругости возвращает первоначальную форму деформированного предмета, в результате чего он получает некий импульс движения. Иллюстрацией может служить металлический шарик, падающий на стальную плиту. Сила упругости возвращает его в положение, близкое к изначальному, откуда шарик снова падает на плиту и процесс повторяется. Происходит колебательное движение с затухающей амплитудой.
Аналогичные колебания происходят при соприкосновении твердых контактов, с той лишь разницей, что вместо силы тяжести на них действует упругость пружины или пластины. Амплитуда колебаний подвижных контактов, естественно, очень незначительная, но её вполне достаточно для провоцирования серии процессов кратковременного размыкания цепи. Результатом колебаний являются импульсы, в промежутке после нажатия и следующие сразу за отпусканием кнопки.
Разницу между идеальной и реальной формой импульсов видно на рис. 1.
Рисунок 1. Сравнение идеального импульса с реальным
Как видно из рисунка идеальным является сигнал с одним прямоугольным импульсом. На практике всё выглядит иначе. Дребезг изменяет осциллограмму сигнала. Определённые коррективы вносит искрение. Форма импульсов на рисунке сильно приукрашена. В реальной ситуации осциллограмма выглядит более потрёпанной.
Частота и количество касаний контактов зависит:
- от свойств компонентов коммутирующего узла;
- уровня напряжения на обмотках реле;
- от упругости пружины и некоторых других факторов.
Дребезг наблюдается и во время размыкания контактов. Обычно при механическом размыкании контакты меньше дребезжат.
На рисунке 2 наглядно изображена осциллограмма напряжения в результате коммутации электрического тока вследствие нажатия на кнопку.
Рисунок 2. Осциллограмма коммутационного тока
На осциллограмме видно серии импульсов, характеризующих процесс дребезга.
Вредное влияние дребезга
Чтобы понять негативные последствия от дребезга, рассмотрим процессы, возникающие при коммутации слабых и мощных электрических цепей. Как только расстояние между контактами оказывается достаточным для зажигания электрической дуги, между ними возникает разряд, который разрушает соприкасающиеся поверхности. Искрение, возникающее при механическом контакте, обычно имеет небольшую разрушающую силу. Но электрическая дуга большой мощности вызывает повышенный износ.
Слабое искрение также приводит к явлению износа контактов, хотя оно не такое разрушительное как при зажигании мощной дуги. В ряде случаев таким износом можно пренебречь. Например, для бытовых выключателей освещения проблемой дребезга никто не занимается, так как он почти не влияет на работу осветительных приборов. Во всяком случае, потребители не замечают последствий такого явления.
Цифровая электроника воспринимает их за чередование сигналов, состоящих из нулей и единиц. Устройствами считываются ложные коды, вызванные дребезгом при нажатиях кнопки, что приводит к сбоям в работе. Поэтому устранения дребезга является важнейшей задачей, которую приходится решать многим конструкторам и схемотехникам.
https://youtube.com/watch?v=Ekk2Cq9RZ-I
https://youtube.com/watch?v=bFqEjtEOaeY
Полный текст программы
// constants won’t change. They’re used here to set pin numbers: const int buttonPin = 2; // the number of the pushbutton pin const int ledPin = 13; // the number of the LED pin // Variables will change: int ledState = HIGH; // the current state of the output pin int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin // the following variables are unsigned longs because the time, measured in // milliseconds, will quickly become a bigger number than can be stored in an int. unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers void setup() { pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); // set initial LED state digitalWrite(ledPin, ledState); } void loop() { // read the state of the switch into a local variable: int reading = digitalRead(buttonPin); // check to see if you just pressed the button // (i.e. the input went from LOW to HIGH), and you’ve waited long enough // since the last press to ignore any noise: // If the switch changed, due to noise or pressing: if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() — lastDebounceTime) > debounceDelay) { // whatever the reading is at, it’s been there for longer than the debounce // delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { ledState = !ledState; } } } // set the LED: digitalWrite(ledPin, ledState); // save the reading. Next time through the loop, it’ll be the lastButtonState: lastButtonState = reading; }