Подключение кнопки к ардуино. Подключение кнопки к Arduino Кнопки тактовые виды и характеристики принцип работы

Подключение кнопки к ардуино. Подключение кнопки к Arduino Кнопки тактовые виды и характеристики принцип работы

20.04.2024

И 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(); void setup() { pinMode(2 ,INPUT); // кнопка на пине 2 digitalWrite(2 ,HIGH); bouncer .attach(2); // устанавливаем кнопку bouncer .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 )

{ //если кнопка нажата

Serial . println ("pressed" ) ; //вывод сообщения о нажатии

else Serial . println ("released" ) ; //вывод сообщения об отпускании

И еще один небольшой практически полезный пример. Пусть у нас есть кнопка, при длительности нажатии которой меньше 2 секунд происходит изменение переменной current_mode , в которой хранится текущий режим работы некоторого устройства. В этом примере режим будет изменяться от 0 до 5. Один раз нажали — режим имеет номер 1. Еще раз нажали — 2. И так до пяти. После пяти при очередном нажатии текущий режим становится первым и опять по кругу. Если же удерживать кнопку в нажатом состоянии более 2 секунд переменной current_mode присваивается значение 0.

#include #define pressed_long 2000 // долговременное нажатие = 2 секунды #define num_modes 5 // максимальный номер режима short int max_mode = num_modes + 1; // вспомогательная переменная Bounce bouncer = Bounce(); //создаем экземпляр класса Bounce unsigned long pressed_moment; // момент нажатия кнопки int current_mode = 0; // текущий режим 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) { //если кнопка нажата pressed_moment = millis(); // запоминаем время нажатия } else { // кнопка отпущена if((millis() - pressed_moment) < pressed_long) { // если кнопка была нажата кратковременно current_mode++; // увеличиваем счетчик текушего режима current_mode %= max_mode; // остаток от целочисленного деления if (current_mode == 0) current_mode = 1; // режим меняется от 1 до num_modes } else { // кнопка удерживалась долго current_mode = 0; pressed_moment = 0; // обнуляем момент нажатия } Serial.println("Current mode:"); Serial.println(current_mode); // выводим сообщение о текущем режиме } } }

#include

#define pressed_long 2000 // долговременное нажатие = 2 секунды

#define num_modes 5 // максимальный номер режима

short int max_mode = num_modes + 1 ; // вспомогательная переменная

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

unsigned long pressed_moment ; // момент нажатия кнопки

int current_mode = 0 ; // текущий режим

void setup ()

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

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

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

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

Инструкция

Кнопки бывают разные, но все они выполняют одну функцию - физически соединяют (или, наоборот, разрывают) между собой проводники для обеспечения электрического контакта. В простейшем случае - это соединение двух проводников, есть кнопки, которые соединяют большее количество проводников.
Некоторые кнопки после нажатия оставляют проводники соединёнными (фиксирующиеся кнопки), другие - сразу же после отпускания размыкают цепь (нефиксирующиеся).
Также кнопки делят на нормально разомкнутые и нормально замкнутые. Первые при нажатии замыкают цепь, вторые - размыкают.
Сейчас нашёл широкое применение тип кнопок, которые называют "тактовые кнопки". Тактовые - не от слова "такт", а скорее от слова "тактильный", т.к. нажатие хорошо чувствуется пальцами. Это кнопки, которые при нажатии замыкают электрическую цепь, а при отпускании - размыкают.

Кнопка - очень простое и полезное изобретение, служащее для лучшего взаимодействия человека и техники. Но, как и всё в природе, она не идеальна. Проявляется это в том, что при нажатии на кнопку и при её отпускании возникает т.н. " " ("bounce" по-). Это многократное переключение состояния кнопки за короткий промежуток времени (порядка нескольких миллисекунд), прежде чем она примет установившееся состояние. Это нежелательное явление возникает в момент переключения кнопки из-за упругости материалов кнопки или из-за возникающих при электрическом микроискр.
Увидеть своими глазами можно с помощью Arduino, что мы и сделаем чуть позже.

Чтобы подключить нормально разомкнутую тактовую кнопку к Arduino, можно поступить самым простым способом: один свободный проводник кнопки соединить с питанием или землёй, другой - с цифровым выводом Arduino. Но, вообще говоря, это неправильно. Дело в том, что в моменты, когда кнопка не замкнута, на цифровом выводе Ардуино будут появляться электромагнитные наводки, и из-за этого возможны ложные срабатывания.
Чтобы избежать наводок, цифровой вывод обычно подключают через достаточно большой резистор (10 кОм) либо к земле, либо к питанию. В первом случае это называется " с подтягивающим резистором", во втором - "схема со стягивающим резистором". Давайте рассмотрим каждую из них.

Сначала подключим к Arduino кнопку по схеме с подтягивающим резистором. Для этого один контакт кнопки соединим с землёй, второй - с цифровым выходом 2. Цифровой выход 2 также подключим через резистор номиналом 10 кОм к питанию +5 В.

Напишем вот такой скетч для обработки нажатий кнопки и загрузим в Arduino.
Теперь встроенный светодиод на выводе 13 постоянно горит, пока не нажата кнопка. Когда нажимаем кнопку, она принимает состояние LOW, и светодиод гаснет.

Теперь соберём схему со стягивающим резистором. Один контакт кнопки соединим с питанием +5 В, второй - с цифровым выходом 2. Цифровой выход 2 подключим через резистор номиналом 10 кОм к земле.
Скетч менять не будем.

Теперь светодиод не горит, пока кнопку не нажали.

Видео по теме

Совет 2: Как избавиться от дребезга контактов при подключении кнопки к Arduino

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

Вам понадобится

  • - Arduino;
  • - тактовая кнопка;
  • - резистор номиналом 10 кОм;
  • - светодиод;
  • - соединительные провода.

Инструкция

"Дребезг" контактов - это явление, свойственное механическим переключателям, кнопкам, тумблерам и реле. Из-за того, что контакты обычно из металлов и сплавов, которые обладают упругостью, при физическом замыкании они не сразу устанавливают надёжное соединение. В течение короткого промежутка времени контакты несколько раз смыкаются и отталкиваются друг от друга. В результате этого электрический ток принимает установившееся значение не моментально, а после череды нарастаний и спадов. Длительность этого переходного эффекта зависит от материала контактов, от их размера и конструкции. На иллюстрации показана типичная осциллограмма при замыкании контактов тактовой кнопки. Видно, что время от момента переключения до установившегося состояния составляет несколько миллисекунд. Это и "дребезгом".

Этот эффект не заметен в электрических управления освещением, или другими инерционными датчиками и приборами. Но в цепях, где идёт быстрое считывание и обработка информации (где частоты того же порядка, что и импульсы "дребезга", или выше), это является проблемой. В частности, Arduino UNO, который работает на частоте 16 МГц, отлично "дребезг" контактов, принимая последовательность единиц и нулей вместо единичного переключения от 0 к 1.

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

Чтобы реализовать данную задачу, первое, что приходит в голову:
- запоминать предыдущее состояние кнопки;
- сравнивать с текущим состоянием;
- если состояние изменилось, то меняем состояние светодиода.
Напишем такой скетч и загрузим в память Arduino.
При включении схемы в работу, сразу виден эффект от влияния дребезга контактов. Он проявляется в том, что светодиод загорается не сразу после нажатия кнопки, или загорается и тут же гаснет, или не выключается сразу после нажатия кнопки, а продолжает гореть. В общем, схема работает не стабильно. И если для задачи с включением светодиода это не столь критично, то для других, более серьёзных задач, это просто неприемлемо.

Постараемся исправить ситуацию. Мы знаем, что дребезг контактов проявляет себя в течение нескольких миллисекунд после замыкания контактов. Давайте после изменения состояния кнопки выжидать, скажем, 5 мсек. Это время для человека является практически мгновением, и нажатие кнопки человеком обычно происходит значительно дольше - несколько десятков миллисекунд. А Arduino прекрасно работает с такими короткими промежутками времени, и эти 5 мсек позволят ему отсечь дребезг контактов от нажатия кнопки.
В данном скетче мы объявим процедуру debounce() ("bounce" по-английски - это как раз "дребезг", приставка "de" означает обратный процесс), на вход которой мы подаём предыдущее состояние кнопки. Если нажатие кнопки длится более 5 мсек, значит это действительно нажатие.
Определив нажатие, мы меняем состояние светодиода.
Загрузим скетч в плату Arduino. Теперь всё гораздо лучше! Кнопка срабатывает без сбоев, при нажатии светодиод меняет состояние, как мы и хотели.

Аналогичная функциональность обеспечивается специальными библиотеками, например, библиотекой Bounce2. Скачать её можно по ссылке в разделе "Источники" или на сайте https://github.com/thomasfredericks/Bounce2. Для установки библиотеки помещаем её в директорию libraries среды разработки Arduino и перезапускаем IDE.
Библиотека "Bounce2" содержит следующие методы:
Bounce() - инициализация объекта "Bounce";
void interval(мсек) - устанавливает время задержки в миллисекундах;
void attach (номерПина) - задаёт вывод, к которому подключена кнопка;
int update() - обновляет объект и возвращает true, если состояние пина изменилось, и false в противном случае;
int read() - считывает новое состояние пина.
Перепишем наш скетч с использованием библиотеки. Можно также запоминать и сравнивать прошлое состояние кнопки с текущим, но давайте упростим алгоритм. При нажатии кнопки будем считать нажатия, и каждое нечётное нажатие будем включать светодиод, каждое чётное - выключать. Такой скетч смотрится лаконично, его легко прочитать и легко применить.

Источники:

  • Убираем дребезг контактов кнопки, подключённой к Arduino
  • Библиотека Bounce2

/*
* Набор для экспериментов ArduinoKit
* Код программы для опыта №5: sketch 05
*
* КНОПКИ
*
* Написано для сайта http://сайт
*
*
* Помощь сообщества Arduino.
* Посетите сайт http://www.arduino.cc
*
* Комментарий к программе написан
* 22 января 2014
* специально для http://сайт
*/

КНОПКИ.

Использование кнопок на цифровых входах.

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

Мы будем подключать один контакт кнопки проводом к заземлению, а другой контакт к цифровому порту. Когда Вы надавите на кнопку, произойдет замыкание цепи и земленой конец «-» присоединится к цифровому порту, а следовательно, полученный сигнал, Arduino будет считать как «низкий».

Но подождите — что происходит, когда кнопка не нажата? В этом состоянии, порт отключен от всего, т.е висит в воздухе, и это не понятное состояние мы называем «неопределенным», или плавующим. То есть, мы не можем с уверенностью сказать, как отреагирует на такое состояние Arduino. В зависимости от различных условий окружающей среды это может быть воспринято ей и как HIGH («ВЫСОКИЙ» +5 Вольт), и как LOW («НИЗКИЙ» — логический ноль).

Чтобы не возникало никакий разночтений, и микроконтроллер точно знал что в данный момент у него на входе, мы дополнительно соединим порт Arduino через ограничивающий резистор (подойдет любой с номиналом от 1КОм — 10KОм) с шиной +5 Вольт. Эта «подтяжка» будет гарантировать наличие постоянного ВЫСОКОГО +5V сигнала, а при нажатии, на кнопку цепь замкнется на Землю — «0», а значит для ардуино, сигнал на входе изменится с HIGH, на LOW, т.е. с ВЫСОКОГО +5V, на НИЗКИЙ «0».

(Дополнительно: Когда вы привыкнете к резисторами, и будете знать когда они необходимы, вы сможете активировать внутренние резисторы подтяжки, находящиеся в самом процессоре ATmega. Для информации смотрите http://arduino.cc/en/Tutorial/DigitalPins).

Подсоединение оборудования:

У кнопок есть два контакта, если кнопка нажата — контакт замкнут, если не нажата — разомкнут.

В кнопках мы будем использовать и два, и четыре контакта, но надо заметить, что в кнопках которые мы будем использовать сейчас, два контакта запараллелены.

Самый простой способ подключить кнопку — подключить провода к клеммам — наискосок (по диагонали).

Подключите любой контакт кнопки 1 к земле (GND).
Подключите другой контакт кнопки к цифровому порту 2.

Подключите любой контакт кнопки 2 к земле (GND).
Подключите другой контакт кнопки к цифровому порту 3.

На ножки кнопок идущие к цифровым портам 2,3, подключите «подтягивающие» резисторы по 10Kом (коричневый/черный/красный), а вторые выводы этих резисторов подключите к общему «-» (GND). Эти резисторы гарантируют, что на входе будет либо +5V (кнопка не нажата), либо «0», при нажатии, и не чего другого. (И не забывайте, что в отличии от аналоговых входов у цифровых всего два состояния ВЫСОКОЕ и НИЗКИЙ.)

Светодиод:

Большинство плат Arduino, в том числе и UNO, уже имеют установленный светодиод, с токоограничивающим резистором, подключенный к порту 13. И Вам не обязательно ставить свой.

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

Подсоедините положительный вывод светодиода к цифровому порту Arduino №13
Подсоедините отрицательный вывод светодиода к резистору 330 Ом.
Подсоедините другой вывод резистора к GND «-«.

// Сначало мы создадим константы, т.е. дадим имена кнопкам, которые будут
// неизменны до конца кода программы, и привяжем эти имена к портам Arduino.
// Это облегчает понимание и работу с кодом программы, а также позволяет
// обращаться к порту по имени.

const int button1Pin = 2; // кнопка №1 — порт 2
const int button2Pin = 3; // кнопка №2 — порт 3
const int ledPin = 13; // порт 13, для светодиода

void setup()
{
// Установим порты кнопок как входящие:
pinMode(button1Pin, INPUT);
pinMode(button2Pin, INPUT);

// Установим порт светодиода как исходящий:
pinMode(ledPin, OUTPUT);
}

void loop()
{
int button1State, button2State; // переменные для сохранения состояния кнопок

// Поскольку кнопки имеют только два состояния (нажаты и не нажаты) мы будем
// работать с ними используя цифровые порты ввода. Для того чтобы считывать
// информацию мы воспользуемся функцией digitalRead(). Эта функция позволяет
// получить один параметр с цифрового порта и возвратить либо HIGH (+5V),
// либо LOW («0»).

// Здесь мы читаем текущее состояние кнопок и помещаем их значение
// в две переменные:

button1State = digitalRead(button1Pin);
button2State = digitalRead(button2Pin);

// Вспомните, если кнопка нажата, то порт будет соединен с массой («-«).
// Если кнопка не нажата, порт, через подтягивающий резистор будет подключен к +5 вольт.

// Таким образом, состояние порта будет LOW (низким), когда кнопка нажата,
// и HIGH (высоким), когда она не нажата.

// Теперь мы будем использовать состояние портов чтобы контролировать светодиод.

// Что мы хотим сделать, условие:
// «Если какая-либо кнопка нажата, загорается светодиод»,
// «Но, если окажутся нажатыми обе кнопки, светодиод не загорится»
// Давайте переведем это в программный код.

// У Arduino есть специальные логические операторы, и операторы сравнения,
// которые часто используются при проверке условий, в частности:

// «==» (равенство) — Истинно, если обе стороны являются одинаковыми
// Пример:
// if (x == y) {
// тело условия
//}

// «&&» (логическое И) — Истинно только при выполнении обоих условий
// Пример:
// Истинно, если оба выражения Истинно (true)
// if (x > 0 && x < 5) {
// тело условия
//}

// «!» (логическое НЕ)
// Истинно если оператор ложен (false)
// Пример:
//if (!x) {
// тело условия
//}

// «||» (логическое ИЛИ) — Истинно, если хотя бы одно из условий выполняется
// Пример:
//if (x > 0 || y > 0) {
// тело условия
// }

// В данном случае Мы будем использовать конструкцию «if» для перевода всего
// выше сказанного в логические цепочки программы.
// (Не забудьте, НИЗКИЙ (LOW), означает что кнопка нажата)

// «Если одна из кнопок нажата, светодиод светится»
// получится:
// if ((button1State == LOW) || (button2State == LOW)) // зажечь светодиод

// «Если обе кнопки нажатые, светодиод не загорается»
// получится:
// if ((button1State == LOW) && (button2State == LOW)) // не зажигать светодиод

// Теперь давайте используем вышеуказанные функции и объединим их в одной инструкции:

if (((button1State == LOW) || (button2State == LOW)) // сравниваем, нажата ли одна из кнопок
&& ! // и если нет
((button1State == LOW) && (button2State == LOW))) // сравниваем, нажаты ли обе кнопки
// тогда…
{
digitalWrite(ledPin, HIGH); // включаем светодиод
}
else // в противном случае
{
digitalWrite(ledPin, LOW); // выключаем светодиод
}

// Как вы могли заметить, операторы могут быть объединены
// для решения комплексных задачь

// Не забудьте: Нельзя использовать оператор «=» при сравнении значений вместо
// «==», потому что оператор «=» присваивает значение переменным!
}

В следующей статье мы опубликуем код к уроку №5 в виде архива.

Очень часто используются в электронике. На первый взгляд, работа с ними не таит сюрпризов, но и тут есть "подводные камни".

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

Подключим кнопку без использования контроллера, пропустив ток из 5V . При нажатии кнопки цепь замкнётся и светодиод будет светиться. Ничего неожиданного.

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

Int buttonPin = 12; int ledPin = 3; void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT); } void loop() { bool val = digitalRead(buttonPin); digitalWrite(ledPin, val); }

Код прекрасно работает при нажатии кнопки. А когда мы отпускаем кнопку и создаём разрыв в цепи, то возникает проблема. Вывод 12 становится свободным и висит в неопределённом состоянии в режиме INPUT (вспоминаем урок про цифровые выводы). В результате мы получаем случайные значения и светодиод то включается, то выключается от наводок.

Чтобы избежать этой проблемы, можно добавить резистор от 10 до 100 кОм и прижать кнопку к земле. В этом случае цепь будет замкнута даже при отпущенной кнопке. В этом случае резистор называют стягивающим (pull down). Это рабочая схема, которую можно использовать в учебной программе.

Несмотря на рабочую схему с стягивающим резистором, мы получаем проблему при работе со сложным проектом. Дело в том, что возможна ситуация, когда многие устройства в схеме используют разные значения питания. И тогда придётся к каждой кнопке устройства подавать свой отдельный стягивающий резистор. На практике принято подключаться не к питанию, а к земле, которая всегда одинакова и равно 0. В этом случае сам резистор следует подключить к питанию - подтянуть. Резистор в этом случае является подтягивающим (pull up). Правда, при этом возникает другая проблема - поведение светодиода изменилось противоположным образом - при нажатии светодиод выключается, а при отпускании - включается. Решается проблема просто - меняем одну строчку кода.

DigitalWrite(ledPin, !val);

Мы просто меняем значение переменной на противоположное. Это стандартный подход при работе с кнопкой. Теперь вам будет легче разобраться с примерами из Arduino IDE.

Стоит отметить, что у платы Arduino у выводов уже есть встроенные подтягивающие резисторы (кроме вывода 13) и мы можем убрать внешний резистор. Но тогда надо также явно указать использование данного резистора через код с параметром INPUT_PULLUP .

Int buttonPin = 12; int ledPin = 3; void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT_PULLUP); } void loop() { bool val = digitalRead(buttonPin); digitalWrite(ledPin, !val); delay(100); }

01.Basics: DigitalReadSerial (Чтение цифрового вывода)

Изучим пример DigitalReadSerial из File | Examples | 01.Basics .

Мы изучили, как правильно подключать кнопку и можем изучать встроенные примере. Будем считывать сигнал, идущий с цифрового вывода при нажатии кнопки.

Приблизительно собранная схема может выглядеть следующим образом:

Вкратце опишу на словах данную схему. Вставляем в центре макетной платы кнопку таким образом, чтобы между парными ножками проходил жёлоб макетной платы. Далее соединяем перемычками питание 5V и землю GND на Arduino с рельсами на макетной плате. Потом соединяем перемычкой цифровой вывод под номером 2 на Arduino с одной ножкой кнопки на макетной плате. Эту же ножку кнопки, но с другой стороны соединяем с резистором, который выполняет роль стягивающего резистора . После чего сам резистор соединяем с землёй. Третью ножку кнопки соединяем к положительной рельсе на макетной плате. Осталось только соединить между собой боковые рельсы на макетной плате, и мы готовы изучать новый пример.

Кнопка выполняет очень важную функцию - она замыкает цепь при нажатии. Когда кнопка не нажата, то ток не проходит между ножками кнопки, и не можем поймать сигнал с цифрового вывода под номером 2. Поэтому состояние вывода определяется системой как LOW или 0. При нажатии на кнопку его две ножки соединяются, позволяя току пройти от питания к цифровому выводу 2, а система считывает проходящий сигнал как HIGH или 1.

Разберём код по кусочкам

// Второй вывод связан с кнопкой int pushButton = 2; void setup() { Serial.begin(9600); pinMode(pushButton, INPUT); } void loop() { int buttonState = digitalRead(pushButton); Serial.println(buttonState); delay(1); // задержка для стабильности }

В функции setup() устанавливаем связь с портом для считывания данных на скорости 9600 бит в секунду с Arduino на ваш компьютер: Serial.begin(9600) .

Вторая строчка нам уже знакома, но здесь теперь используется параметр INPUT - мы устанавливаем второй цифровой вывод на режим чтения данных, поступающих с кнопки: pinMode(pushButton, INPUT);

В цикле считываем поступающую информацию. Для начала нам понадобится новая переменная buttonState , которая будет содержать значения 0 или 1, поступающие от функции digitalRead() .

Чтобы мы могли видеть поступающую информацию, нужно вывести получаемые результаты в окно Serial Monitor при помощи команды println() .

Для большей стабильности при чтении данных установим минимальную задержку.

Если вы сейчас запустите программу и откроете также окно Serial Monitor (меню Tools | Serial Monitor ), то на экране увидите бесконечные нули. Программа постоянно опрашивает состояние нашей конструкции и выводит результат - отсутствие тока. Если нажать на кнопку и удерживать её, то увидите, что цифры сменяются с 0 на 1. Значит в нашей цепи появился ток и информация изменилась.

02.Digital: Button

Работа с кнопкой рассматривается также в примере File | Examples | 02.Digital | Button . Кнопка соединяется с выводом 2, а светодиод с выводом 13. К кнопке также следует подвести питание и землю через резистор на 10K. Сам принцип работы остался без изменений. Только на этот раз мы не будем выводить информацию о состоянии кнопки на экран, а будем включать светодиод. Такой вариант более наглядный. При нажатии и отпускании кнопки встроенный светодиод должен загораться или гаснуть.

Const int buttonPin = 2; // вывод для кнопки const int ledPin = 13; // вывод для светодиода int buttonState = 0; // статус кнопки - нажата или отпущена void setup() { // режим вывода для светодиода pinMode(ledPin, OUTPUT); // режим ввода для кнопки pinMode(buttonPin, INPUT); } void loop() { // считываем состояние кнопки buttonState = digitalRead(buttonPin); // если кнопка нажата, то её состояние HIGH: if (buttonState == HIGH) { // включаем светодиод digitalWrite(ledPin, HIGH); } else { // иначе выключаем светодиод digitalWrite(ledPin, LOW); } }

Допустим, мы хотим изменить поведение - если кнопка не нажата - светодиод горит, а при нажатии - светодиод не горит. Достаточно изменить одну строчку кода.

If (buttonState == LOW)

А теперь загадка! Вы загрузили первый вариант скетча на плату, и вдруг ваш компьютер сломался. Вы не можете отредактировать скетч, чтобы использовать второй вариант. Как можно выйти из положения?

Нужно поменять полярность цепи! Провод от резистора, который на землю, нужно воткнуть в 5V, а провод, который шёл из 5V к кнопке, перекинуть на землю. При включении ток пойдёт из питания на вывод 2 без всяких помех и будет получено значение HIGH . При нажатии кнопки получится другая цепь, и вывод 2 останется без питания.

02.Digital: StateChangeDetection

В примере File | Examples | 02.Digital | StateChangeDetection идёт подсчёт щелчков кнопки и состояние кнопки (включён или выключен). Схема осталась прежней. Кнопка соединяется с выводом 2, а светодиод с выводом 13 (можно использовать встроенный). К кнопке также следует подвести питание и стягивающий резистор к земле на 10K.

Const int buttonPin = 2; // кнопка на выводе 2 const int ledPin = 13; // светодиод на выводе 13 int buttonPushCounter = 0; // счётчик нажатия кнопки int buttonState = 0; // текущее состояние кнопки int lastButtonState = 0; // предыдущее состояние кнопки void setup() { // устанавливаем режим ввода для кнопки pinMode(buttonPin, INPUT); // устанавливаем режим вывода для светодиода pinMode(ledPin, OUTPUT); // включаем последовательную передачу данных Serial.begin(9600); } void loop() { // считываем показания с вывода кнопки buttonState = digitalRead(buttonPin); // сравниваем состояние с предыдущим состоянием if (buttonState != lastButtonState) { // если состояние изменилось, увеличиваем счётчик if (buttonState == HIGH) { // если текущее состояние HIGH, значит кнопка включена buttonPushCounter++; Serial.println("on"); Serial.print("number of button pushes: "); Serial.println(buttonPushCounter); } else { // если текущее состояние LOW, значит кнопка выключена Serial.println("off"); } // небольшая задержка для устранения эффекта дребезга delay(50); } // сохраняем текущее состояние как последнее состояние для следующего раза lastButtonState = buttonState; // включаем светодиод при каждом четвёртом нажатии, проверяя деление по остатку счётчика нажатий if (buttonPushCounter % 4 == 0) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }

02.Digital: Debounce (Дребезг)

У кнопок существует такой эффект, как "дребезг". При замыкании и размыкании между пластинами кнопки возникают микроискры, провоцирующие до десятка переключений за несколько миллисекунд. Явление называется дребезгом (англ. bounce). Это нужно учитывать, если необходимо фиксировать «клики». Поэтому первичным показаниям верить нельзя. По этой причине часто в скетчах делают небольшую задержку, а уже потом считывают показания. В обычном состоянии, когда мы не нажимаем кнопку или держим кнопку нажатой, эффекта дребезга не наблюдается. Иногда для этих целей в учебных примерах используют функцию delay() , но на практике следует использовать функцию millis() , как в примере File | Examples | 02.Digital | Debounce . Схема подключения остаётся без изменений.

Const int buttonPin = 2; // кнопка на выводе 2 const int ledPin = 13; // светодиод на выводе 13 int ledState = HIGH; // текущее состояние светодиода int buttonState; // текущее состояние вывода для кнопки int lastButtonState = LOW; // предыдущее состояние вывода для кнопки // используем тип без знака, чтобы использовать большие числа unsigned long lastDebounceTime = 0; // последнее время unsigned long debounceDelay = 50; // задержка, увеличьте в случае необходимости void setup() { pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); digitalWrite(ledPin, ledState); } void loop() { // считываем состояние кнопки int reading = digitalRead(buttonPin); // если нажали кнопку, // то немного ожидаем, чтобы исключить дребезг // если состояние изменилось (дребезг или нажатие) if (reading != lastButtonState) { // сбрасываем таймер 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 (reading != buttonState) { buttonState = reading; // переключаем светодиод, если новое состояние кнопки стало HIGH if (buttonState == HIGH) { ledState = !ledState; } } } // устанавливаем светодиод digitalWrite(ledPin, ledState); // сохраняем состояние кнопки. В следующий раз в цикле это станет значением lastButtonState: lastButtonState = reading; }

02.Digital: DigitalInputPullup (Встроенный подтягивающий резистор)

У цифровых выводов уже есть резисторы на 20 кОм, которые можно использовать в качестве подтягивающих при работе с кнопками. Рассмотрим пример File | Examples | 02.Digital | DigitalInputPullup .

Схема подключения - соединим первый вывод кнопки с выводом 2 на плате, а второй вывод кнопки с выводом GND . Во время работы скетча будем считывать показания второго вывода.

Void setup() { Serial.begin(9600); // настроим вывод 2 на режим ввода и включим встроенный подтягивающий резистор pinMode(2, INPUT_PULLUP); pinMode(13, OUTPUT); // светодиод } void loop() { // снимаем показания кнопки int sensorVal = digitalRead(2); // выводим в Serial Monitor Serial.println(sensorVal); // Помните, что при использовании подтягивающего к питанию резистора, состояние кнопки инвертировано // В не нажатом состоянии кнопка имеет значение HIGH, и LOW при нажатии. // При нажатии на кнопку включим светодиод, при отпускании - выключим if (sensorVal == HIGH) { digitalWrite(13, LOW); } else { digitalWrite(13, HIGH); } }

Если запустить скетч, то увидим, что на монитор выводятся числа 1 (HIGH ). При нажатии на кнопку значения поменяются на 0 (LOW ).

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

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

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

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

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

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

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

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

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

Если посмотреть внутрь четырехтактной кнопки, то можно увидеть вот такую схему:

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

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

С этой кнопкой сложно запутаться: два контакта, которые соединяются при нажатии кнопки.

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

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

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

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

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

Принципиальная схема


Внешний вид макета


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

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

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

Подключение модуля тактовых кнопок ROC к Ардуино

Специально для ваших проектов мы в RobotClass сделали модуль из двух тактовых кнопок. На модуле уже есть необходимые резисторы и даже два светодиода для индикации нажатия кнопок.


Разберемся с подключением этого модуля к Ардуино Уно.

Принципиальная схема


Внешний вид макета


Как можно было заметить, независимо от того, какие всё-таки кнопки мы будем использовать — схема подключения не сильно меняется. Не будет менять и программа для работы с ними.

Программа для работы с кнопкой на Ардуино

Наконец, мы разобрались с нюансами нашей схемы, и готовы к написанию программы. В уроке по мы познакомились с функциями настройки выводов 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 == HIGH){
// цикл от 0 до 2, с шагом 1
for(int i=0; i<3; i++){
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
}
}
}

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

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

Программа для кнопки-триггера

Еще один пример, заслуживающий внимания — кнопка-триггер. Работает она так: один раз нажали кнопку — светодиод загорелся, второй раз нажали — потух.

Чтобы реализовать такое поведение кнопки, нам потребуется дополнительная переменная, которую часто называют «переменной состояния» или «флагом».

Const int led = 2;
const int button = 3;
int val = 0;
byte state = 0; // переменная состояния
void setup(){
pinMode(led, OUTPUT);
pinMode(button, INPUT);
}
void loop(){
// записываем в переменную val состояние кнопки
val = digitalRead(button);
// если состояние кнопки - истина, выполняем действие
if(val == HIGH){
// меняем состояние на противоположное
state = !state;
if(state == HIGH){
// если текущее состояние - истина, зажигаем светодиод
digitalWrite(led, HIGH);
} else {
// если текущее состояние - ложь, гасим светодиод
digitalWrite(led, LOW);
}
delay(300);
}
}

Загружаем программу на Ардуино и проверяем работу схемы. Быстро нажмем кнопку — светодиод зажжется. Снова нажмем — погаснет. А вот если нажать кнопку и не отпускать, то светодиод начнет мигать с периодом 600мс! Почему так? Попробуйте разобраться.

Задания

В качестве тренировки попробуем решить несколько простых задачек с кнопкой и светодиодом.

  • В схеме присутствует две кнопки и один светодиод. Пусть при нажатии на первую кнопку светодиод зажигается, а при нажатии на вторую — гаснет.
  • Пианино. В схеме присутствует семь кнопок кнопка и один динамик. При нажатии на каждую из семи кнопок динамик должен воспроизводить соответствующую ноту. Потребуется изучить .
  • Игра «Ковбои». В схеме присутствуют две кнопки, один зуммер и два светодиода. После запуска программы зуммер должен издать короткий звук. Сразу после этого, каждый из игроков должен как можно быстрее нажать свою кнопку. У того игрока, который сделает это первым, загорится светодиод. Потребуется изучить урок про прерывания.

© 2024 hecc.ru - Новости компьютерных технологий