Управление кнопками на Ардуино

buttonsВ предыдущей статье я писал об организации индикации на светодиодах.

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

Не буду вдаваться в подробности схем подключения кнопок к цифровым (и не только) входам микроконтроллера. В данной статье рассматривается кнопка, подтянутая резистором к плюсу и замыкающая вход на землю.  Поэтому состояния нажатой кнопки LOW, а отпущенной HIGH.

Тип кнопки не имеет значения, например может быть таким

Схема1

Самый простой скетч работы с кнопкой выглядит так

Оператор delay(1000) задает задержку между нажатиями кнопки. Если время нажатия превысит 1000 мс, то происходит автоматическое повторное нажатие кнопки. Такой метод может разве что сгодиться для отладки, но в реальной жизни мало применим, так как delay не дает выполнятся остальным операторам скетча (если только не используются прерывания) и ограничивает минимальное время между нажатиями кнопки.

В следующем скетче попробую запоминать состояния кнопки

Все вроде бы работает, но иногда проскакивает два или более срабатывания. В чем же дело? Дело в дребезге контактов механической кнопки.

Обычное срабатывание кнопки выглядит так. Казалось бы все правильно.

Нажатие кнопки

Но иногда срабатывание может выглядеть и так

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

Или даже так

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

Особенно это заметно у изношенных или просто некачественных кнопок. Есть разные способы борьбы с этим эффектом, от установки конденсатора на цифровой вывод до целых электрических схем. Но у нас ведь есть целый микроконтроллер! Проанализировав работу кнопок, можно сделать вывод, что нажатие кнопки обычно длится более 150 мс, а дребезг контактов порождает импульсы длительностью 50 мс, ну очень редко чуть больше. Поэтому установив минимальное время между нажатиями кнопки в 50-100мс можно побороть эффект дребезга контактов «программным путем».

Иногда для уменьшения числа кнопок в устройстве применяют короткое и длинное нажатие на кнопку. В этом случае короткое нажатие фиксируется при отпускания кнопки А длинное нажатие при достижении заданного интервала. код получается такой.

Иногда, например в часах для установки времени, применяется режим, когда длинное нажатие кнопки вызывает срабатывание с заданным интервалом. Для реализации этой функции будет такой код.

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

В конструкторе класса указывается цифровой вход кнопки. А также четыре необязательных параметра:

  • Таймаут для игнорирования дребезга контактов (По умолчанию 50 мс )
  • Время длинного нажатия кнопки, мс. Если 0, то длинное нажатие не фиксируется. (По умолчанию отключено)
  • Время удержания кнопки, после которого происходит автонажатие кнопки. Если 0, то не происходит. (По умолчанию отключено)
  • Интервал срабатывания кнопки при автонажатии (По умолчанию 500 мс)

Функция begin() производит инициализацию цифрового входа.

Функция loop() вызывается в основном цикле или по таймеру, но достаточно часто и возвращает следующие значения:

  • SB_NONE — ничего не произошло
  • SB_CLICK — событие срабатывания кнопки
  • SB_AUTO_CLICK — событие автонажатия кнопки при длинном удержании
  • SB_LONG_CLICK — событие длинного нажатия кнопки
Скачать класс для работы с кнопками с примером

Пример работы с данным классом выглядит так:

Можно использовать для фиксации событий кнопки таймер при помощи библиотеки TimerOne, о которой я писал в предыдущей статье

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

Спасибо всем кто осилил )))

c112

 

Класс для работы с кнопками
2.3 KiB
1025 Downloads
Детали
Вы можете оставить отзыв или трекбек со своего сайта.

20 комментариев на «Управление кнопками на Ардуино»

  1. Марат:

    Алексей, спасибо за статью по кнопкам. Я не совсем понял — что за параметры передаются в класс. 4 — пин дуины. 50 и 500 тайминги короткого и длинного нажатий. А остальное (2000 и 4000) что такое?
    Спасибо.

    • Alexey Alexey:

      /**
      * Конструктор класса кнопки
      * Кнопка это цифровой пин подтянутый к питанию и замыкаемый на землю
      * Событие срабатывания происходит по нажатию кнопки (возвращается 1)
      * и отпусканию кнопки (возвращается время нажатия кнопки, мсек)
      * tm1 — таймаут дребезга контактов. По умолчанию 50мс
      * tm2 — время длинного нажатия клавиши. По умолчанию 2000мс
      * tm3 — врямы перевода кнопки в генерацию серии нажатий. По умолсанию отключено
      * tm4 — время между кликами в серии. По умолчанию 500 мс. Если tm3 = 0 то не работает
      */
      SButton::SButton(uint8_t pin,uint16_t tm1, uint16_t tm2,uint16_t tm3, uint16_t tm4){

      • Максим:

        Уважаемый Алексей ! а как замутить код короткого и длинного нажатия двух кнопок ик пульта для управления лед диммером ? тоесть первую коротко нажали включение 255 вторую коротко нажали 0 первая длинное удерживание яркость + аналогично вторая яркость — . За ранее спасибо !

  2. Марат:

    Извиняюсь. Правильночитание у меня хромает. Оно хорошее, но почему-то хромает. (С)

  3. Otto:

    Большое спасибо за полезную и качественную + подробную статью!)))) Очень полезно!

  4. Виктор:

    Алексей, спасибо за статьи, эту и другие. Как задать параметры tm2, tm3, tm4 если мне не нужно у кнопки использовать длинное нажатие и серии нажатий?
    И можно ли использовать этот класс для реализации кнопки включения/выключения (длинное нажатие — прибор выключается, короткое — включается).

    • Alexey Alexey:

      Если не нужно длинное нажатие и автоповторение, то tm2-tm4 = 0
      Для включения выключения класс использовать можно, но при этом придется вручную задавать режим сна при длинном нажатии и в этом режиме кнопку посадить на прерывание, чтобы из режима сна выходить. Иначе выключение не имеет смысла — потребление контроллера будет большим

  5. Сергей:

    Спасибо огромное автору за статью.Респект.

  6. Иван:

    Алексей, огромное спасибо за статью, за «Класс для работы с кнопками». Мне, как новичку это очень помогло, взял на вооружение и буду пользовать с благодарностью. Кнопочки работают просто шик, но нехватка свободных пинов…, вынуждает обратиться с просьбой о помощи, адаптировать данный класс для работы с «аналоговыми кнопками». Перекопал кучу материала, но из-за нехватки опыта, знаний а может быть уже и возраста одолеть эту задачку самостоятельно не удается.

  7. Сергей:

    Хорошо. Научились нажимать кнопку и отправлять её эхо на комп. Как теперь прикрутить светодиод на эту кнопку? К примеру кнопка на D2 светик на D3
    Я только начал разбираться в этой теме.

  8. Алексей:

    Большое спасибо за статью. Пересмотрел кучу примеров, но Ваши примеры оказались наиболее легки для понимания. Строю управление светом в доме:
    плавное вкл.\выкл.
    case SB_AUTO_CLICK:
    if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
    }
    Двойной клик в Ваш класс добавить возможно? Для записи в eeprom максимальной яркости светодиода.

  9. Nick:

    Спасибо! очень хороший пример! Но не могу сообразить как? «Данный класс можно адаптировать для работы с «аналоговыми кнопками» (несколько кнопок подключенных к аналоговому входу через делитель с разными номиналами сопротивлений).»
    Если не трудно прдскажите куда копать?

  10. Kairat:

    Здравствуйте, Алексей. Я, к сожалению, никогда не сталкивался с ардуино. Но мне очень нужно подключить три кнопки к ардуино про мини, для управления компьютером ( например: Предыдущий трек, следующий трек и пауза и играть). Я могу воспользоваться Вашим классом и схемой подключения кнопок? Спасибо

  11. Евгений:

    Здравствуйте, Алексей! Очень удобная библиотека, спасибо. Попробовал ее применить, но столкнулся с неприятной вещью:
    «Long press button 1» посылается в Монитор последовательного порта еще до отпускания кнопки. Поэтому при удержании кнопки более 4 секунд, сначала передается сообщение «Long press button 1», а уже потом «Auto press button 1». Т.е. передается паразитное сообщение. Может это как-то можно исправить?

  12. Евгений:

    Разобрался. Видимо, для использования Auto press button нужно отключать Long press button.

  13. Лиля:

    Всем большой ПРИВЕТ! Помогите вставить две кнопки,нажатие на первую запускает движение в одну сторону и потом мотор просто останавливается,а нажатие на вторую кнопку запускает процесс в обратную сторону.Если нажимать одну и туже кнопку то мотор каждый раз начинает движение в одну сторону.

    #include

    #define HALFSTEP 8

    // Определение пинов для управления двигателем

    #define motorPin1 3 // IN1 на 1-м драйвере ULN2003

    #define motorPin2 4 // IN2 на 1-м драйвере ULN2003

    #define motorPin3 5 // IN3 на 1-м драйвере ULN2003

    #define motorPin4 6 // IN4 на 1-м драйвере ULN2003

    // Инициализируемся с последовательностью выводов IN1-IN3-IN2-IN4

    // для использования AccelStepper с 28BYJ-48

    AccelStepper stepper1 (HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);

    void setup (){ stepper1.setMaxSpeed (800.0);

    stepper1.setAcceleration (100.0);

    stepper1.setSpeed (200);

    stepper1.moveTo (20000);

    } void loop (){

    // Изменяем направление, если шаговик достигает заданного положения

    if (stepper1.distanceToGo ()==0)

    stepper1.moveTo (-stepper1.currentPosition ());

    stepper1.run (); }

  14. Лиля:

    в этом скетче мотор не останавливаясь крутится то в одну то в другую сторону медленно разгоняясь и медленно останавливаясь.

Ваш отзыв