Подключение кнопки к ардуино

Как подключить кнопку и светодиод к Ардуино

Для занятия нам понадобятся следующие детали:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • макетная плата;
  • светодиод;
  • 2 резистора 220 Ом;
  • 2 тактовых кнопки;
  • провода «папа-папа».


Схема для включения/выключения светодиода кнопкой от Ардуино

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

Обратите внимание, что тактовая кнопка на макетной плате подключена к микроконтроллеру без подтягивающего резистора. Пин 2 подключен к 5V через встроенный резистор, поэтому при отпущенной кнопке на входе пине 2 будет высокий уровень сигнала, а при нажатии кнопки будет низкий уровень

Скетч. Управление светодиодом Ардуино через кнопку

boolean buttonWasUp = true;
boolean ledEnabled = false;

void setup() {
  pinMode(10, OUTPUT);
  pinMode(2, INPUT_PULLUP);
}
 
void loop() {
   // узнаем, отпущена ли кнопка сейчас
   boolean buttonIsUp = digitalRead(2);
 
   // если кнопка была отпущена и не отпущена сейчас
   if (buttonWasUp && !buttonIsUp) {

      // исключаем дребезг контактов тактовой кнопки
      delay(10);

    // и считываем сигнал с кнопки снова
    buttonIsUp = digitalRead(2);

      // если кнопка нажата, то переворачиваем сигнал светодиода
      if (!buttonIsUp) {
         ledEnabled = !ledEnabled;
         digitalWrite(10, ledEnabled);
      }
   }
 
   // запоминаем состояние кнопки для новой итерации
   buttonWasUp = buttonIsUp;
}

Пояснения к коду:

  1. — это глобальная переменная Ардуино, которая может принимать всего два значения – true (истина) и false (ложь);
  2. задержка в программе позволяет избежать «дребезг контактов» кнопки и исключить ложное срабатывание.


Схема управления светодиодом двумя кнопками от Ардуино

Скетч. Управление двумя кнопками одним светодиодом

boolean button1WasUp = true;
boolean button2WasUp = true;

void setup() {
   pinMode(10, OUTPUT);
   digitalWrite(10, LOW);

   pinMode(2, INPUT_PULLUP);
   pinMode(4, INPUT_PULLUP);
}

void loop() {
   // узнаем, отпущены ли две кнопки сейчас
   boolean button1IsUp = digitalRead(2);
   boolean button2IsUp = digitalRead(4);

   // если кнопка 1 была отпущена и не отпущена
   if (button1WasUp && !button1IsUp) {
      delay(10);
      // повторно считываем сигнал с кнопки 1
      button1IsUp = digitalRead(2);
      if (!button1IsUp) { digitalWrite(10, LOW); }
   }

   // если кнопка 2 была отпущена и не отпущена
   if (button2WasUp && !button2IsUp) {
      delay(10);
      // повторно считываем сигнал с кнопки 2
      button2IsUp = digitalRead(4);
      if (!button2IsUp) { digitalWrite(10, HIGH); }
   }

   // запоминаем состояние двух кнопок ардуино
   button1WasUp = button1IsUp;
   button2WasUp = button2IsUp;
}

Пояснения к коду:

  1. данный пример программы позволяет включать светодиод нажатием одной кнопки и выключать светодиод нажатием второй кнопки;
  2. задержка Ардуино позволяет избежать «дребезг контактов» кнопки и исключить возможность ложного срабатывания.

Следующий пример тоже потребует для подключения к Ардуино две кнопки, два светодиода, как на предыдущей схеме. Но вместо простого включения/выключения диода, мы будем увеличивать и уменьшать яркость светодиода с помощью ШИМ сигнала микроконтроллера. Загрузите пример программы для «Светодиод и кнопка Ардуино ШИМ», чтобы получить понятие о принципе работы кнопки с Arduino Uno.

Скетч. Управление яркостью светодиода кнопкой Ардуино

#define PLUS_BUTTON   2
#define MINUS_BUTTON  4

int brightness = 100;
boolean plusUp = true;
boolean minusUp = true;
 
void setup() {
   pinMode(10, OUTPUT);
   pinMode(PLUS_BUTTON, INPUT_PULLUP);
   pinMode(MINUS_BUTTON, INPUT_PULLUP);
}
 
void loop() {
   analogWrite(10, brightness);
  
   // реагируем на нажатия кнопки с помощью функции handleClick
   plusUp = handleClick(PLUS_BUTTON, plusUp, +20);
   minusUp = handleClick(MINUS_BUTTON, minusUp, -20);
}

boolean handleClick(int buttonPin, boolean wasUp, int delta) {
   boolean isUp = digitalRead(buttonPin);
   if (wasUp && !isUp) {
      delay(10);
      isUp = digitalRead(buttonPin);
      // если был клик кнопки, меняем яркость в пределах от 0 до 255
      if (!isUp)
         brightness = constrain(brightness + delta, 0, 255);
   }
   return isUp;
}

Пояснения к коду:

  1. для подключения светодиода следует использовать пин с ШИМ модуляцией;
  2. начальное значение яркости равен ста, в программе прирост и уменьшение яркости (20) можно поменять по своему усмотрению.

Я смотрел, в библиотеке вроде как много файлов должно быть?

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

Чтобы я мог помещать сюда куски своего кода копипастом, я назову библиотеку SmartButton, ладно? Болванку MyLib можно прибить за ненадобностью.

По аналогии с предыдущим пунктом, создаём папку SmartButton, в ней:

SmartButton.h — То, что мы будем включать в наши программы. Там будут только определения, без кода.
SmartButton.cpp — Программный код класса

Это не скетч! Обратите внимание, что расширение файла cpp (C++). README.md — Файл описания библиотеки «для людей», то есть, документация

«md» означает MarkDown, то есть с разметкой. Достаточно назвать просто README.
library.json — описание библиотеки для Arduino IDE в хитром формате JSON.
examples — папка с примерами, которые будут потом видны в Arduino IDE. В ней должны лежать папки с именами примеров, в а них с тем же именем файлы с расширением ino — скетчи.

SmartButton.h

Давайте поясню суть затеи. Мы не знаем, что нам будет нужно от кнопки. Наш МКА умеет находиться в состояниях Клик, Нажатие, Удержание и СлишкомДолгоеУдержание, а так же выходить из этих состояний в состояние Выключен. Так как мы делаем библиотеку универсальную, то надо предоставить возможность другому программисту вставить свой код в обработчики состояний. В ООП есть для этого замечательное средство — наследование.

Мы делаем класс, у которого есть несколько методов (функций) и они пустые. То есть, они есть, они будут вызываться в нужный момент, но кода в них нет. Зачем это? Затем, что в скетче можно будет создать свой класс на базе нашего, определить там только нужные из методов и наполнить их своим кодом.

Например, мы захотим сделать кнопку-переключатель, то есть, одно нажатие — включено, другое — выключено. Будем зажигать и гасить светодиод и предоставим функцию isOn() для использования в классическом виде в функции loop().

Как видите, нас совершенно здесь не интересует МКА кнопочки из предыдущей статьи, кода этой кнопки нет, он спрятан. Мы добавили свою функциональность к базовому классу и сделали переключатель по клику. Наш новый класс Toggle тоже можно оформить в виде библиотеки, кстати или положить в отдельный файл Toggle.h рядом с вашим скетчем, вам достаточно будет его подключить директивой #include. Мы так же задаём ногу со светодиодом для подсветки кнопки

Обратите внимание, что мы просто создали два объекта (bt и drill) нового класса Toggle, а МКА обработки кнопки для нас скрыт и не заботит

Основываясь на классе SmartButton можно сделать свои классы, что понимают двойной клик, например, водят курсор по меню или поворачивают пулемётную турель медленно-быстрее в зависимости от времени удержания кнопки. Для этого достаточно определить свои методы, описанные в SmartButton.h как virtual. Все определять не обязательно, только нужные вам.

По просьбе целевой аудитории, вот пример класса PressButton, который предоставляет методы:

  • pressed() — кнопка была нажата, можно вызывать много раз.
  • ok() — я понял, слушай кнопку дальше, то есть сброс.

Таким образом мы получаем две независимо работающие «залипающие» кнопки, которые после нажатия находятся в состоянии pressed пока их не сбросить методом ok().

Если у вас есть меню, вы можете определить методы onClick() у кнопок «вверх» и «вниз», которые будут вызывать перемещение курсора меню на дисплее с соответствующем направлении. Определение onHold() у них может вызывать перемещение курсора в начало и конец меню, например. У кнопки «ентер» можно определить onClick() как выбор меню, onHold() как выход с сохранением, а onLongHold() как выход без сохранения.

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

SmartButton — это просто МКА, это инструмент для реализации поведения ваших кнопок.

Где же скрыта вся магия? Магия кроется в файле SmartButton.cpp

Логика местами спорная, я знаю :) Но это работает.

Теперь осталось заполнить файл README описанием вашей библиотеки и заполнить по аналогии файлик library.json, где поля вполне очевидны:

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

Ура! Библиотека готова. Можно запаковать папку в ZIP и раздавать друзьям или копировать на другие свои компьютеры.

По аналогии, можно сделать класс для любой МКА. Принцип общий: вы делаете класс, определяете виртуальные методы, которые потом надо будет переопределить, чтобы вставить свой код или готовые методы, если универсальность не требуется.

Как сделать библиотеку Arduino?

Это просто!

Сначала надо решить, как ваша библиотека будет называться. Пусть для примера, это будет MyLib.

Найдите, где лежат ваши скетчи на компьютере. Они лежат каждый в своей папочке, а рядом с ними есть папка libraries (библиотеки). Например, на маке /Users/Пользователь/Documents/Arduino/libraries и на виндоусе c:\Users\Пользователь\Документы\Arduino\libraries. Я сам сижу на маке и пути в виндах не знаю. Найдёте.

Вот в этой папке libraries создайте новую папку MyLib, то есть с именем своей библиотеки. Перейдите туда.

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

Расскажу, что здесь зачем. Конструкция ниже позволяет включать вашу библиотеку в код несколько раз без ошибок. Лучше использовать название вашей библиотеки большими буквами. Это не сурово прямо обязательно, но все так делают и вы не выделяйтесь. Задача стоит придумать уникальное слово, в нашем случае MYLIB_H, идентификатор для этого заголовочного файла.

То есть, в вашем скетче может оказаться несколько таких строк:

Вы скажете «тю, да я, да я слежу, да я…» и будете неправы. Лучше один раз написать в одном файле вот такую конструкцию, чем исправлять ваши готовые скетчи, если вдруг вы захотите вложить один в другой или ваша библиотека будет включена в другую итд. Данный код проверяет, определено ли слово MYLIB_H, если нет, то определяет его и включает дальнейший код. Если же слово уже определено, то второй раз код компилировать не нужно.

Следующий важный кусок кода:

Включает определения из исполняющей системы Arduino UDE. Без этого ваша библиотека просто не скомпилируется.

Всё. Закройте Arduino IDE, Откройте заново. Создайте новый скетч, пропишите там #include «MyLib.h» и ура, ваша библиотека есть и подключена!

Introduction: Fast DigitalRead(), DigitalWrite() for Arduino

By JRV31Follow

More by the author:

About: Jack passed away May 20, 2018 after a long battle with cancer. His Instructables site will be kept active and questions will be answered by our son-in-law, Terry Pilling. Most of Jack’s instructables are tu…

More About JRV31 »

It is possible to use lower level commands to greatly speed up the input/output.

There are three banks of pins on the Atmega 328 and 168 microcontrollers called B, C, and D.

  • The B bank is digital pins 8 — 13.
  • The C bank is the analog input pins.
  • Bank D is pins 0 — 7.

Each bank of pins has three 8 bit registers used to control it:

  • The DDR register is the data direction, 0 = input, 1 = output.
  • The PIN register is used to read the digital value of the pin.
  • The PORT register has two functions:
    • If the DDR register is set to output 0 sets the pin low and 1 sets it high.
    • If the DDR register is set to input 1 turns on the internal pull-up resistor.

Arduino pinMode() scope

This post focuses on the 8-bit AVR Arduino boards such as the Uno, Mega, and Leonardo. The processors on these boards are the ATmega328, ATmega2560, and ATmega32u4, in that order.  For the most part, this information does apply to non-AVR and 32-bit Arduino variants. When in doubt, double check with the Arduino Reference pages for details to specific platforms.

Startup State

On power-up, all pins initialize as a digital high-impedance INPUT. This state reduces the chance of short circuits, especially if they become OUTPUTs later. One downside to this approach is it could leave some devices, like MOSFETs, floating. You should pull the gate of a MOSFET high or low using a pull-up or pull-down resistor.

For boards with a built-in LED, there is an exception. For most boards, this is Pin 13. On power-up, the main chip runs a special program called the bootloader.  The primary purpose of the bootloader is to listen to the serial pins to see if there is new code to load into PROGMEM. The bootloader flashes the built-in LED.  This action temporarily configures the pin as an OUTPUT.  Once finished, bootloader returns the LED’s pin to the INPUT state. Usually, this is not a concern, and you could probably continue to use the pin as a regular I/O pin.

Something you need to consider: can your circuit tolerate the LED Pin temporarily becoming an OUTPUT? Can it also tolerate that pin toggling between HIGH and LOW? Even though there are buffer circuits on most boards, an additional 1k current limiting resistor may be a good idea, just in case.

Analog Input

Analog Input pins are used to measure a voltage. Sometimes I see people use Arduino’s pinMode() to configure it as an INPUT. However, this is not necessary, for two reasons.

  1. pinMode() sets up a pin for use as a digital input, not analog input.
  2. When calling analogRead(), it reconfigures the Analog Pin for “input.”

Analog Input pins are unique because they connect to an analog multiplexer, which connects to the single analog-to-digital converter (ADC).  So for analogRead() to work, the multiplexer has to be configured first.  This automatic step eliminates the need to call pinMode() on analog pins.

I still call pinMode() in my setup() function for analog pins. This way when I glance at the code, I know which pins I am using–and how.

Analog Output (PWM)

Unlike digitalRead(), which can be used on both INPUT and OUTPUT, analogWrite() only works for OUTPUT.  (Read this article if you did not know digitalRead() could be used on digital OUTPUTs.)  analogWrite() works on pins which support Pulse-Width Modulation (PWM), so it only makes sense to use it as an OUTPUT.  That being the case, like analogRead(), analogWrite() automatically sets the pin to OUTPUT when called.

Again using the Arduino pinMode() on an “analogWrite()” pin is not necessary. However, I find placing it in setup() with a comment that it will be used for PWM a great way to see all pins at a glance.

Pull-Up Resistors

The Arduino IDE 1.0.1 added a new pinMode() mode: INPUT_PULLUP.   Adding this mode changed the default behavior of pinMode()’s INPUT.  In case you are porting code or still using an older version of the Arduino library, here is what changed.

Controlling a Digital Potentiometer Using SPI

Digital potentiometers are useful when you need to vary the resistance in a circuit electronically rather than by hand. Example applications include LED dimming, audio signal conditioning and tone generation. In this example we will use a six channel digital potentiometer to control the brightness of six LEDs. The steps we will cover for implementing SPI communication can be modified for use with most other SPI devices.

Introduction to the AD5206 Digital Potentiometer

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors (potentiometers) built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer. The individual variable resistor pins are labeled Ax, Bx and Wx, ie. A1, B1 and W1.
For example, in this tutorial we will be using each variable resistor as a voltage divider by pulling one side pin (pin B) high, pulling another side pin (pin A) low and taking the variable voltage output of the center pin (Wiper).
In this case, the AD5206 provides a maximum resistance of 10k ohm, delivered in 255 steps (255 being the max, 0 being the least).

Code

/*
  Digital Pot Control
  This example controls an Analog Devices AD5206 digital potentiometer.
  The AD5206 has 6 potentiometer channels. Each channel’s pins are labeled
  A — connect this to voltage
  W — this is the pot’s wiper, which changes when you set it
  B — connect this to ground.
 The AD5206 is SPI-compatible,and to command it, you send two bytes,
 one with the channel number (0 — 5) and one with the resistance value for the
 channel (0 — 255).
 The circuit:
  * All A pins  of AD5206 connected to +5V
  * All B pins of AD5206 connected to ground
  * An LED and a 220-ohm resisor in series connected from each W pin to ground
  * CS — to digital pin 10  (SS pin)
  * SDI — to digital pin 11 (MOSI pin)
  * CLK — to digital pin 13 (SCK pin)
 created 10 Aug 2010
 by Tom Igoe
 Thanks to Heather Dewey-Hagborg for the original tutorial, 2005
*/// inslude the SPI library:#include <SPI.h>// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;void setup() {
  // set the slaveSelectPin as an output:
  pinMode(slaveSelectPin, OUTPUT);
  // initialize SPI:
  SPI.begin();}void loop() {
  // go through the six channels of the digital pot:
  for (int channel = ; channel < 6; channel++) {
    // change the resistance on this channel from min to max:
    for (int level = ; level < 255; level++) {
      digitalPotWrite(channel, level);
      delay(10);
    }
    // wait a second at the top:
    delay(100);
    // change the resistance on this channel from max to min:
    for (int level = ; level < 255; level++) {
      digitalPotWrite(channel, 255 — level);
      delay(10);
    }
  }}void digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, LOW);
  delay(100);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  delay(100);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, HIGH);}

Original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito

See Also:

  • Arduino SPI LIbrary — Your reference for the SPI library.
  • BarometricPressureSensor — Using SPI to read a Barometric Pressure Sensor.

Last revision 2018/05/17 by SM

1.0.1 and Later

Starting with 1.0.1,  if pinMode() is called with INPUT, the internal pull-up resistor is explicitly disabled.  However, when pinMode() is called with INPUT_PULLUP, the pull-up will be enabled.  You can still override the state of the pin after pinMode() has been called by using digitalWrite(), like in pre-1.0.1.

Conclusion

So when it comes down to it, when do you use Arduino pinMode()?  The only time you MUST call pinMode() is to set up a pin for use as a digital OUTPUT.  As a best practice, if you plan to use a pin as a digital INPUT or analog OUTPUT (PWM), you should call pinMode() in setup(), even though it is optional.  That way when you, or someone else, reads your code, you quickly see the pins in use.

Defining Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT

Digital pins can be used as , , or . Changing a pin with changes the electrical behavior of the pin.

Pins Configured as INPUT

Arduino (ATmega) pins configured as with are said to be in a high-impedance state. Pins configured as make extremely small demands on the circuit that they are sampling, equivalent to a series resistor of 100 Megohms in front of the pin. This makes them useful for reading a sensor.

If you have your pin configured as an , and are reading a switch, when the switch is in the open state the input pin will be «floating», resulting in unpredictable results. In order to assure a proper reading when the switch is open, a pull-up or pull-down resistor must be used. The purpose of this resistor is to pull the pin to a known state when the switch is open. A 10 K ohm resistor is usually chosen, as it is a low enough value to reliably prevent a floating input, and at the same time a high enough value to not draw too much current when the switch is closed. See the Digital Read Serial tutorial for more information.

If a pull-down resistor is used, the input pin will be when the switch is open and when the switch is closed.

If a pull-up resistor is used, the input pin will be when the switch is open and when the switch is closed.

Pins Configured as INPUT_PULLUP

The ATmega microcontroller on the Arduino has internal pull-up resistors (resistors that connect to power internally) that you can access. If you prefer to use these instead of external pull-up resistors, you can use the argument in .

See the Input Pullup Serial tutorial for an example of this in use.

Pins configured as inputs with either or can be damaged or destroyed if they are connected to voltages below ground (negative voltages) or above the positive power rail (5V or 3V).

Pins Configured as OUTPUT

Pins configured as with are said to be in a low-impedance state. This means that they can provide a substantial amount of current to other circuits. ATmega pins can source (provide current) or sink (absorb current) up to 40 mA (milliamps) of current to other devices/circuits. This makes them useful for powering LEDs because LEDs typically use less than 40 mA. Loads greater than 40 mA (e.g. motors) will require a transistor or other interface circuitry.

Pins configured as outputs can be damaged or destroyed if they are connected to either the ground or positive power rails.

Defining Pin Levels: HIGH and LOW

When reading or writing to a digital pin there are only two possible values a pin can take/be-set-to: and .

HIGH

The meaning of (in reference to a pin) is somewhat different depending on whether a pin is set to an or . When a pin is configured as an with , and read with , the Arduino (ATmega) will report if:

  • a voltage greater than 3.0V is present at the pin (5V boards)

  • a voltage greater than 2.0V volts is present at the pin (3.3V boards)

A pin may also be configured as an INPUT with , and subsequently made HIGH with . This will enable the internal 20K pullup resistors, which will pull up the input pin to a reading unless it is pulled by external circuitry. This can done alternatively by passing as argument to the funtion, as explained in more detail in the section «Defining Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT» further below.

When a pin is configured to OUTPUT with , and set to with , the pin is at:

  • 5 volts (5V boards)

  • 3.3 volts (3.3V boards)

In this state it can source current, e.g. light an LED that is connected through a series resistor to ground.

LOW

The meaning of also has a different meaning depending on whether a pin is set to or . When a pin is configured as an with , and read with , the Arduino (ATmega) will report LOW if:

  • a voltage less than 1.5V is present at the pin (5V boards)

  • a voltage less than 1.0V (Approx) is present at the pin (3.3V boards)

When a pin is configured to with , and set to with , the pin is at 0 volts (both 5V and 3.3V boards). In this state it can sink current, e.g. light an LED that is connected through a series resistor to +5 volts (or +3.3 volts).

Defining Pin Levels: HIGH and LOW

When reading or writing to a digital pin there are only two possible values a pin can take/be-set-to: and .

HIGH

The meaning of (in reference to a pin) is somewhat different depending on whether a pin is set to an or . When a pin is configured as an with pinMode(), and read with digitalRead(), the Arduino (ATmega) will report if:

  • a voltage greater than 3.0V is present at the pin (5V boards)

  • a voltage greater than 2.0V volts is present at the pin (3.3V boards)

A pin may also be configured as an INPUT with , and subsequently made HIGH with digitalWrite(). This will enable the internal 20K pullup resistors, which will pull up the input pin to a reading unless it is pulled by external circuitry. This can done alternatively by passing as argument to the funtion, as explained in more detail in the section «Defining Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT» further below.

When a pin is configured to OUTPUT with , and set to with , the pin is at:

  • 5 volts (5V boards)

  • 3.3 volts (3.3V boards)

In this state it can source current, e.g. light an LED that is connected through a series resistor to ground.

LOW

The meaning of also has a different meaning depending on whether a pin is set to or . When a pin is configured as an with , and read with , the Arduino (ATmega) will report LOW if:

  • a voltage less than 1.5V is present at the pin (5V boards)

  • a voltage less than 1.0V (Approx) is present at the pin (3.3V boards)

When a pin is configured to with , and set to with , the pin is at 0 volts (both 5V and 3.3V boards). In this state it can sink current, e.g. light an LED that is connected through a series resistor to +5 volts (or +3.3 volts).

Оцените статью:
Оставить комментарий