Как избавиться от дребезга контактов при подключении кнопки к Arduino
Мы уже рассматривали подключение кнопки к Arduino и затрагивали вопрос «дребезга» контактов. Это весьма неприятное явление, которое вызывает повторные нажатия кнопки и усложняет программную обработку нажатий кнопки. Давайте же поговорим о том, как избавиться от дребезга контактов.
Инструкция по гашению дребезга контактов с помощью Arduino
Для проекта нам понадобится:
- Arduino UNO или иная совместимая плата;
- тактовая кнопка;
- резистор номиналом 10 кОм (рекомендую приобрести набор резисторов с номиналами от 10 Ом до 1 МОм);
- светодиод (к примеру, вот из такого набора);
- соединительные провода;
- макетная плата (breadboard);
- персональный компьютер со средой разработки Arduino IDE.
1Проявление эффекта «дребезга» контактов
«Дребезг» контактов – это явление, свойственное механическим переключателям, кнопкам, тумблерам и реле. Из-за того, что контакты обычно делают из металлов и сплавов, которые обладают упругостью, при физическом замыкании они не сразу устанавливают надёжное соединение. В течение короткого промежутка времени контакты несколько раз смыкаются и отталкиваются друг от друга. В результате этого электрический ток принимает установившееся значение не моментально, а после череды нарастаний и спадов. Длительность этого переходного эффекта зависит от материала контактов, от их размера и конструкции. На иллюстрации показана типичная осциллограмма при замыкании контактов тактовой кнопки. Видно, что время от момента переключения до установившегося состояния составляет несколько миллисекунд. Это и называется «дребезгом».
Данные осциллограммы получены с помощью дешёвого любительского осциллографа DSO138, подробно мы рассматривали его здесь.
Этот эффект не заметен в электрических цепях управления освещением, двигателями или другими инерционными датчиками и приборами.
Но в цепях, где идёт быстрое считывание и обработка информации (где частоты того же порядка, что и импульсы «дребезга», или выше), это является проблемой. В частности, Arduino UNO, который работает на частоте 16 МГц, отлично ловит «дребезг» контактов, принимая последовательность единиц и нулей вместо единичного переключения от 0 к 1.
2Подключение кнопки к Arduino для демонстрации подавления «дребезга»
Давайте посмотрим, как дребезг контактов влияет на правильную работу схемы. Подключим к Arduino тактовую кнопку по схеме со стягивающим резистором. Будем по нажатию кнопки зажигать светодиод и оставлять включённым до повторного нажатия кнопки. Для наглядности подключим к цифровому выводу 13 внешний светодиод, хотя можно обойтись и встроенным.
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); // зажигаем или гасим светодиод }
При включении схемы в работу, сразу виден эффект дребезга контактов. Он проявляется в том, что светодиод загорается не сразу после нажатия кнопки, или загорается и тут же гаснет, или не выключается сразу после нажатия кнопки, а продолжает гореть. В общем, схема работает не стабильно. И если для задачи с включением светодиода это не столь критично, то для других, более серьёзных задач, это просто неприемлемо.
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 <Bounce2.h> // подключаем библиотеку 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.