ESP, IoT Нужна помощь. Как избежать дребезга в прерывании?

LordZET

✩✩✩✩✩✩✩
1 Мар 2022
15
2
53
Здравствуйте!
Использую WEMOS esp8266, библиотека EncButton, нужно увеличивать счетчик в прерывании по кнопке.
Возможно что-то упустил в настройках, но вот результат: три нажатия и получаю непоследовательные числа
Как избежать дребезга в прерывании?
2025-01-27_12-17-02.png
C++:
// кнопка и прерывания
#include    <Arduino.h>
#include    <EncButton.h>
#define EB_DEB_TIME 80     // таймаут гашения дребезга кнопки (кнопка)
#define        BTN_PIN    D3
Button eb(BTN_PIN);
volatile byte screen = 0;  // текущий экран

// esp8266/esp32
IRAM_ATTR void isr() {
  screen++;
  if (screen > 9)screen = 0;
  eb.pressISR();
}

void setup() {
  Serial.begin(115200);
  attachInterrupt(BTN_PIN, isr, FALLING);
}

void loop() {
  eb.tick();
  if (eb.click()) {
    Serial.print("screen ");
    Serial.println(screen);
  }
  delay(100);  // имитация загруженной программы
}
Есть конечно же рабочее решение, и даже без дополнительной библиотеки по примеру Ловим событие,
C++:
#define        BTN_PIN    D3
volatile bool intFlag = false;   // флаг
volatile byte screen = 0;  // текущий экран

// esp8266/esp32
IRAM_ATTR void isr() {
  intFlag = true;   // подняли флаг прерывания
}

void setup() {
  Serial.begin(115200); // открыли порт для связи
  pinMode(BTN_PIN, INPUT_PULLUP);
  attachInterrupt(BTN_PIN, isr, FALLING);
}

void loop() {
  if (intFlag) {
    intFlag = false;    // сбрасываем
    screen++;
    if (screen > 9)screen = 0;
    Serial.print("screen ");
    Serial.println(screen);
  }
}
Но неужели EncButton с кучей настроек не может этого? Тем более что иногда всё таки есть необходимость выполнить короткое событие, которое обязательно обрабатывать сразу.
 

Сотнег

★★★★★★★
15 Янв 2020
4,484
1,526
@LordZET,
повисеть на паузе внутри прерывания, чтобы дать кнопке успокоиться - не то?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,280
1,304
Москва
В библиотеке EncButton предусмотрен программный антидребезг, т.е. событие клика будет срабатывать не чаще чем установленное значение. Все клики , что чаще будут просто игнорироваться.
А событие вызывает isr каждый раз с дребезгом.
Варианты рещения:
1. Программное. Запоминать время события и так же игнорировать если прошло слишком мало времени.
2. Аппаратное. собрать RC цепочку для кнопки. Поиск в помощь.
 

poty

★★★★★★✩
19 Фев 2020
3,287
952

@LordZET, прочитайте внимательно описание библиотеки. Класс сам считает нажатия и обрабатывает дребезг, но для этого нужно всё убрать из прерывания и пользоваться методами класса!
 

bort707

★★★★★★✩
21 Сен 2020
3,093
917
@LordZET, все просто и банально. Если вам понадобится антидребезг - значит процесс у вас не быстрый и вам не нужно прерывание.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,280
1,304
Москва
@poty, Кстати да, если надо только что бы экран менялся, то достаточно сделать так:

C++:
// кнопка и прерывания
#include    <Arduino.h>
#include    <EncButton.h>
#define EB_DEB_TIME 80     // таймаут гашения дребезга кнопки (кнопка)
#define        BTN_PIN    D3
Button eb(BTN_PIN);
volatile byte screen = 0;  // текущий экран

// esp8266/esp32
IRAM_ATTR void isr() { 
  eb.pressISR();
}

void setup() {
  Serial.begin(115200);
  attachInterrupt(BTN_PIN, isr, FALLING);
}

void loop() {
  eb.tick();
  if (eb.click()) {
    Serial.print("screen ");
    Serial.println(screen++);
    if (screen > 9)screen = 0;
  }
  delay(100);  // имитация загруженной программы
}
 

LordZET

✩✩✩✩✩✩✩
1 Мар 2022
15
2
53
@Старик Похабыч,Спасибо! Переменную "screen" брал с примера и просто не переназвал.
А вообще это я рассматриваю как аварийный вариант решения проблемы проекта SmartSocket2ch
 

poty

★★★★★★✩
19 Фев 2020
3,287
952

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

LordZET

✩✩✩✩✩✩✩
1 Мар 2022
15
2
53
@poty, Поверьте, я в курсе что дело не в названии. Этим я дал понять @Старик Похабыч, что переменная мне нужна не только для смены экрана, в ответ на его фразу "Кстати да, если надо только что бы экран менялся". По факту Ваши ответы, мне никак не помогли. И тем не менее, Большое спасибо за участие.!(y)
 

poty

★★★★★★✩
19 Фев 2020
3,287
952

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