Подключение тактовой кнопки. Подключение кнопки

02.02.2019

Кнопка — всем известное механическое устройство, которое может замыкать и размыкать электрическую цепь по желанию человека. Есть множество видов кнопок, работающих по разным правилам. Например, тактовая кнопка (push button), используемая в этом уроке, замыкает цепь только пока палец давит на неё. Кнопка на размыкание, напротив, разрывает цепь при нажатии.

Есть кнопки с группой контактов, одни из которых рвут цепь при нажатии, а другие в это время замыкают. Маленькие версии таких кнопок часто называют микропереключателями.

Тактовые кнопки, можно найти практически в каждом электронном приборе: в клавиатуре компьютера, в телефоне, в пульте от телевизора, и т.д.


Есть кнопки с фиксацией, работающие как кнопка на шариковой ручке: один раз нажали — цепь замкнулась, второй раз — разорвалась. На фото как раз одна из таких. Кнопки с фиксацией удобно использовать для переключения режима работы устройства. Например, можно переключать источник питания: батарея, или блок питания.

Или другой вариант — большие кнопки для экстренной остановки оборудования. Они окрашены в яркие цвета, чтобы привлекать внимание человека. По сути — обычные тактовые кнопки на размыкание, или кнопки с фиксацией.


Это лишь некоторые варианты. Кроме кнопок, в мире электричества есть и другие механизмы, например, тумблеры и рубильники. Все они призваны механически управлять течением тока в цепи.

1. Подключение

Итак, мы будем работать с самой простой тактовой кнопкой, которую попробуем подключить к Ардуино Уно . Обычно, при работе с беспаечными макетными платами используется кнопка с выводами под пайку. На фото в начале урока видно, что у такой кнопки есть четыре немного загнутых вывода. Есть кнопки и с двумя прямыми выводами, они тоже подходят для наших занятий.

На электрических схемах кнопка изображается так:

А вот так выглядит схема контактов в нашей кнопке:

Как правило, выводы тактовой кнопки размещаются на противоположных сторонах корпуса парами. То есть мы можем использовать либо пару контактов на одной стороне, либо пару на другой.

Так кнопка втыкается в макетную плату:


Теперь попробуем собрать на макетной плате самую простую цепь, которая продемонстрирует работу кнопки. Будем зажигать светодиод.


Полученная схема выполняет нехитрую функцию: нажимаем на кнопку — светодиод зажигается, отпускаем — гаснет. Точно такую же схему мы можем собрать и без кнопки. Достаточно вручную замыкать и размыкать любое из шести соединений на схеме.

2. Подключение к Ардуино Уно

Теперь, когда функция кнопки предельно ясна, попробуем подключить кнопку с микроконтроллеру, и написать соответствующую программу. Поставим перед собой простую задачу: пусть при однократном нажатии кнопки Ардуино Уно мигнет три раза светодиодом. Для решения этой задачи используем следующую схему:

На этой схеме мы видим уже привычную цепь для . Также видим кнопку, соединенную с выводом Ардуино №3. Здесь может вполне резонно возникнуть вопрос: зачем мы соединили кнопку ещё и с землей, через резистор 10кОм? Чтобы разобраться с этим вопросом, представим что мы подключили кнопку по «наивной» схеме без всяких подтяжек:)

Здесь между выводом №3 и землей изображен небольшой конденсатор, который способен накапливать заряд. Такая особенность есть у многих микроконтроллеров.

Теперь представим, что мы замыкаем кнопку. Ток начинает бежать от +5В, прямиком в контакт №3, попутно заряжая ёмкость. Ардуино успешно регистрирует нажатие кнопки. Но после того, как мы убираем палец с тактовой кнопки, вопреки нашим ожиданиями, микроконтроллер продолжает считать что кнопка нажата! Еще бы, ведь заряженный конденсатор постепенно отдает накопленный заряд в ногу №3. Это будет продолжаться до тех пор, пока ёмкость не разрядится ниже уровня логической единицы.

3. Программа

Наконец, мы разобрались с нюансами нашей схемы, и готовы к написанию программы. В уроке по мы познакомились с функциями настройки выводов pinMode и функцией вывода в цифровой порт digitalWrite . На этот раз нам понадобится ещё одна важная функция, которая обеспечивает ввод информации в микроконтроллер:

DigitalRead(номер_контакта);

Эта функция возвращает логическое значение, которое Ардуино считала с заданного контакта. Это означает, что если на контакт подать напряжение +5В, то функция вернет истину* . Если контакт соединить с землей, то получим значение ложь . В языке C++, истина и ложь эквивалентны числам 1 и 0 соответственно.

Для того, чтобы интересующий нас контакт заработал в режиме ввода информации, нам нужно будет установить его в определенный режим:

PinMode(номер_контакта, INPUT);

Наконец, соберем всё вместе, и напишем программу.

Const int led = 2; const int button = 3; int val = 0; void setup(){ pinMode(led, OUTPUT); pinMode(button, INPUT); } void loop(){ val = digitalRead(button); if(val){ for(int i=0; i<3; i++){ digitalWrite(led, HIGH); delay(500); digitalWrite(led, LOW); delay(500); } } }

Загружаем программу на Ардуино Уно, и проверяем работу программы. Если всё сделано правильно, должно получиться как на картинке:

Ну вот и всё. Теперь мы можем управлять нашими устройствами при помощи кнопок. Если вы уже прошли урок по , то мы вполне сможем сделать часы с будильником!

Примечания:

* В стандартах TTL логики, истина соответствует напряжению от 2В до 5В, а ложь от 0В до 0.8В


Это эксперимент по работе с кнопкой. Мы будем включать светодиод по нажатии кнопки и выключать по отпускании кнопки. Рассмотрим понятие дребезга и программные методы его устранения.

Необходимые компоненты:

В данном эксперименте мы будем использовать контакт D2 Arduino в качестве входа. Это позволяет подключить к нему кнопку для взаимодействия с проектом в режиме реального времени. При использовании Arduino в качестве входов используют pull-up- и pulldown-резисторы, чтобы вход Arduino не находился в «подвешенном» состоянии (в этом состоянии он будет собирать внешние наводки и принимать произвольные значения), а имел заранее известное состояние (0 или 1). Резисторы pull-up подтягивают вход к питанию +5 В, pull-down-резисторы подтягивают вход к GND. Кроме этого, pull-up- и pull-down-резисторы гарантируют, что кнопка не создаст короткого замыкания между +5 В и землей при нажатии. В нашем эксперименте для подключения кнопки мы будем использовать pulldown-резистор. Схема подключения представлена на рис. 2.1.

Рис. 2.1. Схема подключения кнопки и светодиода


Когда кнопка отключена, вход D2 будет подтянут к «земле» через резистор номиналом 10 кОм, который будет ограничивать поток тока, и на входном контакте будет установлено значение напряжения LOW. При нажатии на кнопку входной контакт напрямую связан с 5 В. Большая часть тока будет протекать по пути наименьшего сопротивления через замкнутую кнопку, и на входе генерируется уровень HIGH. При нажатии на кнопку включаем светодиод, при отпускании - гасим.
Код данного скетча приведен в листинге 2.1.

Const int LED=10; // вывод для подключения светодиода 10 (D10) void setup() { // Конфигурируем вывод подключения светодиода как выход (OUTPUT) pinMode(LED, OUTPUT); } void loop() { // включаем светодиод, подавая на вывод 1 (HIGH) digitalWrite(LED,HIGH); // пауза 1 сек (1000 мс) delay(1000); // выключаем светодиод, подавая на вывод 0 (LOW) digitalWrite(LED,LOW); // пауза 1 сек (1000 мс) delay(1000); }
Порядок подключения:

1. Длинную ножку светодиода (анод) подключаем к цифровому выводу D10 Arduino, другую (катод) - через резистор 220 Ом к выводу GND (см. рис. 2.1).
2. Один вход кнопки подключаем к +5 В, другой - через резистор 10 кОм к GND, выход кнопки подключаем к входу D2 Arduino (см. рис. 2.1).
3. Загружаем в плату Arduino скетч из листинга 2.1.
4. При нажатии на кнопку светодиод должен гореть, при отпускании - затухнуть.

Усложним задачу - будем переключать состояние светодиода (включен/выключен) при каждом нажатии кнопки. Загрузим на плату Arduino скетч из листинга 2.2.

Const int LED=10; // Контакт 10 для подключения светодиода const int BUTTON=2; // Контакт 2 для подключения кнопки int tekButton = LOW; // Переменная для сохранения текущего состояния кнопки int prevButton = LOW; // Переменная для сохранения предыдущего состояния // к нопки boolean ledOn = false; // Текущее состояние светодиода (включен/выключен) void setup() { // Сконфигурировать контакт светодиода как выход pinMode (LED, OUTPUT); // Сконфигурировать контакт кнопки как вход pinMode (BUTTON, INPUT); } void loop() { tekButton=digitalRead(BUTTON); if (tekButton == HIGH && prevButton == LOW) { // нажатие кнопки – изменить состояние светодиода ledOn=!ledOn; digitalWrite(LED, ledOn); } prevButton=tekButton; }

При нажатии кнопки светодиод должен изменять свое состояние. Но это будет происходить не всегда. Виной тому - дребезг кнопок.
Кнопки представляют из себя механические устройства с системой пружинного контакта. Когда вы нажимаете на кнопку вниз, сигнал не просто меняется от низкого до высокого, он в течение нескольких миллисекунд меняет значение от одного до другого, прежде чем контакты плотно соприкоснутся и установится значение HIGH.
Микроконтроллер зафиксирует все эти нажатия, потому что дребезг неотличим от настоящего нажатия на кнопку. Устранить влияние дребезга можно программно. Алгоритм следующий:

1. Cохраняем предыдущее состояние кнопки и текущее состояние кнопки (при инициализации LOW).
2. Cчитываем текущее состояние кнопки.
3. Если текущее состояние кнопки отличается от предыдущего состояния кнопки, ждем 5 мс, потому что кнопка, возможно, изменила состояние.
4. После 5 мс считываем состояние кнопки и используем его в качестве текущего состояния кнопки.
5. Если предыдущее состояние кнопки было LOW, а текущее состояние кнопки HIGH, переключаем состояние светодиода.
6. Устанавливаем предыдущее состояние кнопки для текущего состояния кнопки.
7. Возврат к шагу 2. Добавляем к нашему скетчу подпрограмму устранения дребезга.
Получаем код, показанный в листинге 2.3.

Const int LED=10; // Контакт 10 для подключения светодиода const int BUTTON=2; // Контакт 2 для подключения кнопки int tekButton = LOW; // Переменная для сохранения текущего состояния кнопки int prevButton = LOW; // Переменная для сохранения предыдущего состояния // к нопки boolean ledOn = false; // Текущее состояние светодиода (включен/выключен) void setup() { // Сконфигурировать контакт светодиода как выход pinMode (LED, OUTPUT); // Сконфигурировать контакт кнопки как вход pinMode (BUTTON, INPUT); } // Функция сглаживания дребезга. Принимает в качестве // аргумента предыдущее состояние кнопки и выдает фактическое. boolean debounce(boolean last) { boolean current = digitalRead(BUTTON); // Считать состояние кнопки, if (last != current) // если изменилось... { d elay(5); // ж дем 5 м с current = digitalRead(BUTTON); // считываем состояние кнопки return current; // возвращаем состояние кнопки } } void loop() { tekButton = debounce(prevButton); if (prevButton == LOW && tekButton == HIGH) // если нажатие... { ledOn = !ledOn; // инвертировать значение состояния светодиода } prevButton = tekButton; digitalWrite(LED, ledOn); // изменить статус состояния светодиода }

Загружаем скетч в плату Arduino и проверяем работу. Теперь все работает нормально, каждое нажатие кнопки приводит к изменению состояния светодиода.

Листинги программ

И Arduino здесь не является исключением, после того, как помигает светодиодом пробует подключать кнопку и управлять с ее помощью миганием этого самого светодиода. Особенно сложного здесь ничего нет, но есть один нюанс, называемый «дребезг контактов». О том как правильно подключать кнопку к Arduino , что такое «дребезг контактов», как этот эффект проявляется и методах борьбы с ним и пойдет сегодня речь.

Простейшая схема подключения кнопки к микроконтроллеру выглядит следующим образом:

Если ключ S 1 разомкнут (кнопка отпущена), то на цифровом входе D in микроконтроллера мы будем иметь напряжение 5В, соответствующее логической единице. При нажатой кнопке вход D in подключается к земле, что соответствует уровню логического нуля и все напряжение у нас упадет на резисторе R 1 , величину которого выбирают исходя из того, чтобы при нажатой кнопке через него протекал не слишком большой ток (обычно порядка 10÷100 кОм).

Если же просто подключить кнопку между цифровым входом и землей (без резистора R 1 , подключенного к +5В) или между входом и +5В, то в положении, когда кнопка не нажата на цифровом входе микроконтроллера будет присутствовать неопределенное напряжение (может соответствовать уровню 0, а может и 1) и мы бы считывали случайные состояния. Поэтому используется резистор R 1 , который, как говорят, «подтягивает» вход к +5В при отпущенной кнопке.

Считывая состояние цифрового входа микроконтроллера, мы сможем определить нажата кнопка (состояние логического 0) или же нет (будем получать на входе логическую единицу).

Подключение кнопки к Arduino

Микроконтроллеры Atmel AVR ATmega (на базе которых и строится Arduino ) имеют встроенные программно подключаемые нагрузочные резисторы R н величиной 20 кОм и мы можем воспользоваться ими, упростив схему подключения.


Подключается внутренний нагрузочный резистор путем записи логической единицы в требуемый бит порта.

Пример скетча Arduino , который включает и выключает встроенный светодиод на 13 пине, в зависимости от того, нажата или отпущена кнопка, подключенная ко второму пину, используя внутренний нагрузочный резистор:

void setup() { pinMode(13, OUTPUT); //светодиод на 13 пине pinMode(2, INPUT); //2 пин - в режиме входа. Кнопка подключена к земле. digitalWrite(2, HIGH); //подключаем подтягивающий резистор } void loop() { digitalWrite(13, !digitalRead(2)); // считываем состояние кнопки и переключаем светодиод }

Здесь мы инвертируем значение, считанное с входного порта, путем использование логического НЕ , обозначаемого восклицательным знаком перед функцией digitalRead , так как при нажатой кнопке мы считываем 0, а для включения светодиода в порт нам нужно отправить 1.

Дребезг контактов

Все бы ничего, если бы мы жили в идеальном мире с идеальными кнопками. Реальные механические контакты, которые присутствуют в кнопках никогда не замыкаются и не размыкаются мгновенно. В течении непродолжительного промежутка времени происходит многократное замыкание и размыкание контактов ключа (кнопки) в результате чего на вход микроконтроллера поступает не единичный перепад напряжения, а целая пачка импульсов. Это явление носит название «дребезг контактов».

В примере выше, когда при помощи кнопки мы просто включали и выключали светодиод мы не заметили это, так как включение/выключение светодиода в момент «дребезга» происходило очень быстро и мы просто не увидели это глазом.

Эта библиотека включает следующие методы:

  • Bounce () — инициализация объекта Bounce
  • void interval (unsigned long interval) — устанавливает время антидребезга в миллисекундах
  • void attach (int pin) — устанавливает пин, к которому подключена кнопка и подключает на этом выводе встроенный подтягивающий резистор
  • int update () — поскольку Bounce не использует , вы «обновляете» объект до того, как считываете его состояние и это нужно делать постоянно (например, внутри loop ). Метод update обновляет объект и возвращает TRUE (1), если состояние пина изменилось (кнопка была нажата или же, наоборот, отпущена) и FALSE (0) в противном случае. Вызов метода update внутри loop необходимо производить только один раз.
  • int read () — возвращает обновленное состояние пина

По умолчанию, библиотека Bounce использует интервал стабилизации (stable interval ) для реализации антидребезга. Это проще для понимания и позволяет не знать длительность дребезга.


Параметр stable interval библиотеки Bounce

Определив

#define BOUNCE_LOCK-OUT

#define BOUNCE_LOCK-OUT

в файле Bounce.h можно включить альтернативный метод борьбы с дребезгом. Этот метод позволяет быстрее реагировать на изменение состояния кнопки, однако, требует установить продолжительность дребезга, а эта величина, как я отметил выше увеличивается с течением времени, а значит, потребуется вносить изменения в код, либо установить заведомо большее значение.


Приведу пример использования этой библиотеки:

#include Bounce bouncer = Bounce(); //создаем экземпляр класса Bounce void setup() { pinMode(2 ,INPUT); // кнопка на пине 2 digitalWrite(2 ,HIGH); // подключаем встроенный подтягивающий резистор bouncer .attach(2); // устанавливаем кнопку bouncer .interval(5); // устанавливаем параметр stable interval = 5 мс Serial.begin(9600); //установка Serial-порта на скорость 9600 бит/сек } void loop() { if (bouncer.update()) { //если произошло событие if (bouncer.read()==0) { //если кнопка нажата Serial.println("pressed"); //вывод сообщения о нажатии } else Serial.println("released"); //вывод сообщения об отпускании } }

#include

Bounce bouncer = Bounce () ; //создаем экземпляр класса Bounce

void setup ()

pinMode (2 , INPUT ) ; // кнопка на пине 2

digitalWrite (2 , HIGH ) ; // подключаем встроенный подтягивающий резистор

bouncer . attach (2 ) ; // устанавливаем кнопку

bouncer . interval (5 ) ; // устанавливаем параметр stable interval = 5 мс

Serial . begin (9600 ) ; //установка Serial-порта на скорость 9600 бит/сек

void loop ()

if (bouncer . update () )

{ //если произошло событие

if (bouncer . read () == 0 )