Skip to content

Latest commit

 

History

History
130 lines (96 loc) · 9.13 KB

README_ru.md

File metadata and controls

130 lines (96 loc) · 9.13 KB

InterruptDrivenButton

InterruptDrivenButton v0.1.0

english version

Описание

Данная библиотека служит для обработки нажатия кнопок в Arduino. Ключевые особенности:

  • состояние кпопки отслеживается с помощью прерываний, что, в отличие от простого опроса кнопки в цикле, даёт возможность точно отслеживанить нажатие и отпускание даже при нагруженном процессоре;
  • отслеживается серия кликов, удержание кнопки, серия + удержание, а также удержание во время загрузки контроллера;
  • поддерживаются нормально замкнутые и нормально разомкнутые кнопки.

При нажатии несколько раз подряд библиотека считает количество кликов и оповещает только после того, как серия кликов завершена. При удержании кнопки библиотека считает количество "тиков" с определённой периодичностью.

Важно: кнопку необходимо цеплять на пин микроконтроллера, который поддерживает прерывания. Для Arduino Uno, Nano и Mini это пины 2 и 3. Для других микроконтроллеров список пинов можно посмотреть здесь.

Методы и функции

// конструктор объекта - нормально разомкнутая кнопка
InterruptDrivenButton button1(BTN_PIN);

// конструктор объекта - нормально замкнутая кнопка (второй аргумент - уровень сигнала при нажатии)
InterruptDrivenButton button1(BTN_PIN, LOW);

// вспомогательный макрос для создания функции-коллбэка для отлавливания прерываний (ISR)
DEFINE_IDB_ISR(button1) // создаётся функция void ISR__button1 { button1.onInterrupt(); }

// вспомогательный макрос для возвращения имени функции-коллбэка, созданной в DEFINE_IDB_ISR
IDB_ISR(button1) // вернёт ISR__button1

// инициализация кнопки в runtime, аргумент - имя коллбэк-функции (результат IDB_ISR(button1) )
button1.setup(ISR__callback);

// отработка внутреннего цикла
button1.loop();

// проверяет, есть ли событие от кнопки (типы событий - см. ниже)
// возвращает true или false
// hasEvent вызывать не обязательно, можно сразу дёргать pollEvent, 
// но поскольку в большинстве случаев событий от кнопки нет, такая предварительная проверка позволяет слегка оптимизировать алгоритм
button1.hasEvent();

// возвращает последнее событие (если есть)
InterruptDrivenButtonEvent event = button.pollEvent();

Структура InterruptDrivenButtonEvent содержит 3 поля:

  • byte type - тип события
  • byte clicks - количество кликов в серии кликов
  • byte holdTicks - количество "тиков" при удержании кнопки

Типы событий кнопки:

  • IDB_EVENT_NONE - нет события на данный момент
  • IDB_EVENT_CLICKS - обнаружена серия кликов, поле clicks содержит количетво кликов. Событие генерируется после того, как серия кликов завершена.
  • IDB_EVENT_HOLD - кнопка удерживается в данный момент, поле holdTicks содержит количество тиков (периодов с момента начала удержания), поле clicks МОЖЕТ содержать ненулевое количество кликов, если до удержания кнопка была кликнута. Событие генерируется во время удержания кнопки. Пример использования: плавное увеличение/уменьшение яркости лампы.
  • IDB_EVENT_BOOT_HOLD - кнопка была зажата во время запуска микроконтроллера. Событие генерируется после того, как кнопка была отпущена. Пример использования: сброс EEPROM контроллера.

Настройки

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

  • IDB_MIN_CLICK_DURATION - минимально возможное время клика (промежутка между нажатием и отпусканием кнопки) - простая защита от дребезга контактов. Клики за меньшее время игнорируются. По-умолчанию 20ms
  • IDB_MAX_CLICK_SERIES_WAIT_TIME - максимальное время между тем, как отпустили кнопку и как нажали снова, чтобы второе нажатие определилось как последовательность. Если второй раз нажали позже - это новое событие. По-умолчанию 500ms
  • IDB_HOLD_MIN_DURATION - время, которое необходимо зажимать кнопку, чтобы определилось удерживание (holdTicks == 1). Всё, что меньше, расценивается как клик. По-умолчанию 1000ms
  • IDB_HOLD_TICKS_PERIOD - периодичность тиков при удержании кнопки. По-умолчанию 500ms
  • IDB_BOOT_HOLD_MAX_MCU_START_TIME - если в течении этого времени после старта микроконтроллера кнопка будет зажата, будет остлеживаться IDB_EVENT_BOOT_HOLD. По-умолчанию 250ms Примечание: есть защита от срабатывания при обнулении счётика времени.
  • IDB_BOOT_HOLD_MIN_DURATION - сколько времени нужно ждать, чтобы удержание кнопки при старте микроконтроллера распозналось как IDB_EVENT_BOOT_HOLD. Если держали меньше - игнорируется. По-умолчанию 3000ms

Примеры

#include <InterruptDrivenButton.h>

InterruptDrivenButton myButton(BTN_PIN);

// вспомогательный макрос для создания ISR коллбэка (без этого не будет работать!) 
DEFINE_IDB_ISR(myButton)

void setup() {
    // IDB_ISR - ещё один вспомогательный макрос для передачи ISR коллбэка (без этого тоже не будет работать!)
    myButton.setup(IDB_ISR(myButton)); 
}

void loop() {
    myButton.loop();
    
    ...
    
    if (myButton.hasEvent()) {
        
        InterruptDrivenButtonEvent event = myButton.pollEvent(); 
        if (event.type != IDB_EVENT_NONE) {
            // несмотря на то, что hasEvent() == true, всё же стоит проверить обработанное событеи

            if (event.type == IDB_EVENT_CLICKS) {
                switch (event.clicks) {
                    case 1:
                        // 1 клик
                        break;
               
                    case 2:
                        // 2 клика 
                        break;
                
                    case 3:
                        // 3 клика
                        break;    
                    .....
                }
            } else if (event.type == IDB_EVENT_HOLD) {
                byte ticks = event.holdTicks; // 1, 2, 3, 4.... постепенно увеличивается при удержании кнопки
                byte clicks = event.clicks; // содержит количество кликов если кликали перед удержанием
            } else if (event.type == IDB_EVENT_BOOT_HOLD) {
                // удерживали кнопку при загрузке
            }
        }
    }
}

На идею вдохновила кнопка GyverButton от Alex Gyver.