Arduinokit
Arduino проекты. Уроки, программирование, управление и подключение ардуино.
Гирлянда на Arduino. Функция debounce().
const int buttonPin = 2; // Определим, что тактовая кнопка подключена к контакту «2»
const int ledPin = 13; // Определим, что светодиод подключен к контакту «13»
int buttonState = 0; // Зададим некую переменную и изначально присвоим ей нулевое значение (присвоим низкий уровень)
void setup()
<
pinMode(ledPin, OUTPUT); // Конфигурируем режим работы контакта «13» на выход
pinMode(buttonPin, INPUT); // Конфигурируем режим работы контакта «2» на вход
>
void loop()
<
buttonState = digitalRead(buttonPin); // Задаем, что переменная buttonState принимает значение с buttonPin (с контакта «2»)
if (buttonState == HIGH)
<
digitalWrite(ledPin, HIGH); // Подаем высокий уровень. Светодиод включается
>
else
<
digitalWrite(ledPin, LOW); // Подаем низкий уровень. Светодиод выключается
>
>
Для того чтобы осуществить «переключение» необходимо добавить новую переменную, которая будет хранить значение уровня сигнала предыдущего нажатия на кнопку. Помимо нее необходимо указать еще одну переменную. Она понадобится нам в теле функции void loop(). Поскольку обе переменные могу принимать только два значения, то разумно присвоить им тип данных boolean.
boolean lastButton = LOW;
boolean enable = LOW;
Основной код устроен достаточно просто. Алгоритм переделанной программы выглядит так: изначально lastButton = LOW, переменная buttonState хранит текущий уровень сигнала на выходе кнопки, а условие if проверяет, если кнопка зажата, и предыдущее значение lastButton было LOW, то переменная enable инвертируется (LOW станет HIGH). После этого вне условия if функция digitalWrite() запишет уровень, который хранит переменная enable на контакт, к которому подключен светодиод. Финальный вид программы выглядит так:
const int buttonPin = 2; // Определим, что тактовая кнопка подключена к контакту «2»
const int ledPin = 13; // Определим, что светодиод подключен к контакту «13»
int buttonState = 0; // Зададим некую переменную и изначально присвоим ей нулевое значение (присвоим низкий уровень)
boolean lastButton = LOW;
boolean enable = LOW;
void setup()
<
pinMode(ledPin, OUTPUT); // Конфигурируем режим работы контакта «13» на выход
pinMode(buttonPin, INPUT); // Конфигурируем режим работы контакта «2» на вход
>
void loop()
<
buttonState = digitalRead(buttonPin); // Задаем, что переменная buttonState принимает значение с buttonPin (с контакта «2»)
lastButton = buttonState; // Запоминаем значение кнопки. При следующем нажатии на кнопку, значение buttonState будет сравниваться с этой переменной
digitalWrite(ledPin,enable); // Состояние светодиода управляется переменной enable
>
const int buttonPin = 2; // Определим, что тактовая кнопка подключена к контакту «2»
const int ledPin = 13; // Определим, что светодиод подключен к контакту «13»
boolean buttonState = LOW; // Зададим некую переменную и изначально присвоим ей нулевое значение (присвоим низкий уровень)
boolean lastButton = LOW; // Хранит состояние предыдущего нажатия
boolean enable = LOW; // Переменная «переключатель»
void setup()
<
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
>
boolean debounce(boolean last)
<
boolean current = digitalRead(buttonPin);
if(last != current)
<
delay(5);
current = digitalRead(buttonPin);
>
return current;
>
lastButton = buttonState;
digitalWrite(ledPin,enable);
>
const int buttonPin = 2; // Определим, что тактовая кнопка подключена к контакту «2»
int pins[] = <3,5,6,9,10,11>; // Определим все подключенные светодиоды через массив
boolean buttonState = LOW; // Зададим некую переменную и изначально присвоим ей нулевое значение (присвоим низкий уровень)
boolean lastButton = LOW; // Хранит состояние предыдущего нажатия
boolean enable = LOW;
void setup()
<
pinMode(buttonPin, INPUT);
for(int mode = 0; mode
Как избавиться от дребезга контактов при подключении кнопки к Arduino
Мы уже рассматривали подключение кнопки к Arduino и затрагивали вопрос «дребезга» контактов. Это весьма неприятное явление, которое вызывает повторные нажатия кнопки и усложняет программную обработку нажатий кнопки. Давайте же поговорим о том, как избавиться от дребезга контактов.
Инструкция по гашению дребезга контактов с помощью Arduino
Для проекта нам понадобится:
- Arduino UNO или иная совместимая плата;
- тактовая кнопка;
- резистор номиналом 10 кОм (рекомендую приобрести набор резисторов с номиналами от 10 Ом до 1 МОм);
- светодиод (к примеру, вот из такого набора);
- соединительные провода;
- макетная плата (breadboard);
- персональный компьютер со средой разработки Arduino IDE.
1 Проявление эффекта «дребезга» контактов
«Дребезг» контактов – это явление, свойственное механическим переключателям, кнопкам, тумблерам и реле. Из-за того, что контакты обычно делают из металлов и сплавов, которые обладают упругостью, при физическом замыкании они не сразу устанавливают надёжное соединение. В течение короткого промежутка времени контакты несколько раз смыкаются и отталкиваются друг от друга. В результате этого электрический ток принимает установившееся значение не моментально, а после череды нарастаний и спадов. Длительность этого переходного эффекта зависит от материала контактов, от их размера и конструкции. На иллюстрации показана типичная осциллограмма при замыкании контактов тактовой кнопки. Видно, что время от момента переключения до установившегося состояния составляет несколько миллисекунд. Это и называется «дребезгом».
Так выглядит эффект дребезга контактов на осциллограммах
Данные осциллограммы получены с помощью дешёвого любительского осциллографа DSO138, подробно мы рассматривали его здесь.
Этот эффект не заметен в электрических цепях управления освещением, двигателями или другими инерционными датчиками и приборами.
Но в цепях, где идёт быстрое считывание и обработка информации (где частоты того же порядка, что и импульсы «дребезга», или выше), это является проблемой. В частности, Arduino UNO, который работает на частоте 16 МГц, отлично ловит «дребезг» контактов, принимая последовательность единиц и нулей вместо единичного переключения от 0 к 1.
2 Подключение кнопки к Arduino для демонстрации подавления «дребезга»
Давайте посмотрим, как дребезг контактов влияет на правильную работу схемы. Подключим к Arduino тактовую кнопку по схеме со стягивающим резистором. Будем по нажатию кнопки зажигать светодиод и оставлять включённым до повторного нажатия кнопки. Для наглядности подключим к цифровому выводу 13 внешний светодиод, хотя можно обойтись и встроенным.
Схема подключения кнопки к Arduino для демонстрации подавления эффекта «дребезга» контактов
3 Алгоритм подавления«дребезга» контактов
Чтобы реализовать задачу подавления дребезга контактов, первое, что приходит в голову:
- запоминать предыдущее состояние кнопки;
- сравнивать с текущим состоянием;
- если состояние изменилось, то меняем состояние светодиода.
Напишем такой скетч и загрузим в память Arduino.
Скетч обработки нажатия кнопки без учёта эффекта дребезга контактов
При включении схемы в работу, сразу виден эффект дребезга контактов. Он проявляется в том, что светодиод загорается не сразу после нажатия кнопки, или загорается и тут же гаснет, или не выключается сразу после нажатия кнопки, а продолжает гореть. В общем, схема работает не стабильно. И если для задачи с включением светодиода это не столь критично, то для других, более серьёзных задач, это просто неприемлемо.
4 Подавление дребезга контактовс помощью задержки
Постараемся исправить ситуацию. Мы знаем, что дребезг контактов проявляет себя в течение нескольких миллисекунд после замыкания контактов. Давайте после изменения состояния кнопки выжидать, скажем, 5 мсек. Это время для человека является практически мгновением, и нажатие кнопки человеком обычно происходит значительно дольше – несколько десятков миллисекунд. А Arduino прекрасно работает с такими короткими промежутками времени, и эти 5 мсек позволят ему отсечь дребезг контактов от нажатия кнопки.
Скетч обработки нажатия кнопки с задержкой для устранения эффекта дребезга контактов
В данном скетче мы объявим процедуру debounce() («bounce» по-английски – это как раз «дребезг», приставка «de» означает обратный процесс), на вход которой мы подаём предыдущее состояние кнопки. Если нажатие кнопки длится более 5 мсек, значит это действительно нажатие. Определив нажатие, мы меняем состояние светодиода.
Загрузим скетч в плату Arduino. Теперь всё гораздо лучше! Кнопка срабатывает без сбоев, при нажатии светодиод меняет состояние, как мы и хотели.
5 Библиотеки для подавлениядребезга контактов
Аналогичная функциональность обеспечивается специальными библиотеками, например, библиотекой Bounce2. Для установки библиотеки помещаем её в директорию /libraries/ среды разработки Arduino и перезапускаем IDE .
Библиотека Bounce2 содержит следующие методы:
Название | Назначение |
---|---|
Bounce() | инициализация объекта Bounce; |
void interval (мсек) | устанавливает время задержки в миллисекундах; |
void attach (номерПина) | задаёт вывод, к которому подключена кнопка; |
int update() | обновляет объект и возвращает true, если состояние пина изменилось, и false в противном случае; |
int read() | считывает новое состояние пина. |
Перепишем наш скетч с использованием библиотеки. Можно также запоминать и сравнивать прошлое состояние кнопки с текущим, но давайте упростим алгоритм.
Скетч обработки нажатия кнопки с использованием библиотеки для устранения влияния дребезга контактов
При нажатии кнопки будем считать нажатия, и каждое нечётное нажатие будем включать светодиод, каждое чётное – выключать. Такой скетч смотрится лаконично, его легко прочитать и легко применить.
Подавление дребезга контактов с помощью Arduino
Ну и напоследок пара видео от Джереми Блюма, где он рассказывает о способах подавления дребезга контактов на примере подключения тактовой кнопки к Arduino.
Arduino.ru
Азы — debounce
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Добрый день, недавна начал изучать ардуино по книге Джеремми Блума. Повторно вернулся к теме дребезга контактов, хочу попросить разъеснения простым языком следующей части кода.
Вот весь супер код дебоунса :
Помогите понять зачем вот тут:
к значению функции debounce в скобках как бы дано значение lastButton.
Буду рад за понятное разъеснение.
Коментарии типа «ЛОХ это ж просто» прошу писать более развёрнуто.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
delay(5); // ждём затухание дребезга
это Блум такому гавну учит?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Коментарии типа «ЛОХ это ж просто» прошу писать более развёрнуто.
ОК. Разверну. Очевидно вопрос идет о 26 строке, ну понятно загадки любят все, но искать нужную строку по содержимому не интересн. Очевидно Вы считаете это тривиально простым. Допустим, но тогда какого перца Вы не поискали где еще в коде встречается это самое currentButton , которое в стр.26 присваеваем переменной «currentButton» значение вызываемой функции «debounce . Там к коменту просто добавит нечего. А встречается currentButton аж два раза в 27 и 31 строках. Причем в 31 currentButton сохраняется в lastButton .
Теперь смотрим стр 27. Проверка условия. lastButton в котором сохранено значение currentButton из предыдущего цикла должно быть низким а свеженькое currentButton — уже высоким. А что это вместе и одновременно может означать еще кроме как изменения состояния входного сигнала с низкого на высокий?! Что в коментах откровенно и написано. Ну и кто Вы после этого?
ПС. Я эту книгу не читал. Пример мне не понравился. Вопервых тема борьбы с дребезгом — плохая, проблема сильно надуманая. Во вторых подход с делеем для формирования временных интервалов сильно плох, заслужено заплеван на форуме. Выучившись писать так прийдется переучиватся, причем сильно «поперек» этого подхода. Переворачивать мозги трудней чем сразу учится правильному.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Вопервых тема борьбы с дребезгом — плохая, проблема сильно надуманая.
да, но зачем тогда практически во всех серийных бытовых приборах с плёночными или резиновыми кнопками стоят задержки срабатывания чуть ли не по 400 миллисекунд?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Действительно, зачем?! Вот даже и на клавиатуре есть. И я её ща уберу до нуля. ОООООООООККККККККК. ППППоооооллллллуууччччииииииллллооосььььь. ввввввеееееррррррррррнуууууууу ввввввв зззззззаааааадддддд.
Можете сами убедится. Эта задержка только мешает и снижает скорость ввода ;) Только был ли это дребезг?;)
ПС. Эту тему ТС создал чтоб о его лоховстве писали, а не о лоховстве Клапауция , не флудь, о твоем лоховстве тут тем хватает.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
ПС. Эту тему ТС создал чтоб о его лоховстве писали, а не о лоховстве Клапауция , не флудь, о твоем лоховстве тут тем хватает.
так, не я же утверждаю, что программно фильтровать дребезг плохая идея — нужно донести сию гениальную мысль до мировых производителей кнопочных девайсов, предварительно запатентовав.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Только был ли это дребезг?;)
не — это не дребезг. это, сцуко, утка.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Опять этот Джеремми Блум. Изучение программирование по нему это очень хитрая диверсия или заговор. Это как учить математику римскими цифрами или славянскими знаками. Мол раз они появились раньше, то и новичкам следует начинать с них.
Теперь по теме. Для чего нужны кнопки. Разумеется управлять устройством. Но если в схемотехнике это понятно. Нажал кнопку , потек ток, зажглась лампочка. По в программировании в использовании кнопок народ тупит по черному. Нажатие кнопки прежде всего должна вызывать функцию сделать что-то. Чаще всего однократное нажатие должно вызывать однократное действие. Но из-за того что кнопка механическая, и контакт дребезжит, то идет серия импульсов при нажатии и серия импульсов при отжатии. Вот и получается что однократное нажатие вызывает несколько раз функции обрабатывающие это нажатие. Поэтому если вы начались бороться с дребезгом , то определите вначале программа дожна сделать в случае нажатия кнопки. Опять же у кнопки может как минимум 4 события — кнопка нажата, кнопка отжата , кнопка только что нажата и кнопка только что отжата. И это еще не все.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Опять же у кнопки может как минимум 4 события — кнопка нажата, кнопка отжата , кнопка только что нажата и кнопка только что отжата. И это еще не все.
[разжигает в пыточном камине огонь и аккуратно раскладывает в нём крючья]
*только что — это когда?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Опять же у кнопки может как минимум 4 события — кнопка нажата, кнопка отжата , кнопка только что нажата и кнопка только что отжата. И это еще не все.
Нет. Здесь 2 события и 2 состояния.
Кнопку нажимает человек. И его возможности и желания ограничены. Он не может нажимать кнопку чаще 200мсек и удерживать её менее 100мсек. Потому проверять её часто, чаще 20-50мсек безсмыслено. Как только этот факт приймете — дребезг перестанет обнаруживатся вобще. Пишите софт грамотно — и о дребезге узнаете только из сочинений теоретиков. Мал того, сформировав интервал опроса кнопок допустим в 50мсек все остальные интервалы работы с клавой формируются уже не в мсек а в интервалах опроса, т.е. вместо 500мсек до повтора обработки нажатия будет 10 интервалов опроса. Что явно компактней хранить и считать. Приучайтесь к красивому, удобному и простому.
// Чаще всего однократное нажатие должно вызывать однократное действие.
Да. А длительное удержание — многократный повтор действия. Перед вами клавиатура, повторяем функционал, зачем выдумывать велосипед. Обнаружилось нажатие — выполняем действие а нажатость кнопки просто игнорим полсекунды, затем если все еще нажата — повторяем действие, а после него снова игнорим кнопку, но уже 200мсек и т.д. Нажать и удержать куда полезней чем долбить. Особенно в навигации по меню, регулировке уровней, управлении механизмами и др. типичных применениях.