Hobby Science&Experiment

愛と工作の日々

趣味でやっている工作や勉強したことのメモ書きです。

ESP32ボードのボタンノイズを対策(debounce)した【ソフトウェア編】

前回ESP32ボードでISR(割り込みサブルーチン)を利用したボタンカウンタを作成しましたが、ボタンが2重・3重に押されてしまう問題がありました。
ESP32のInterrupt Service Routine(割り込みサブルーチン)でButton counterを作る - 愛と工作の日々
調べてみるとチャタリング(chattering)、バウンス(bounce)等と呼ばれる現象のようです。
f:id:tara-chang:20210704172115p:plain
f:id:tara-chang:20210704172138p:plain
一回押しただけのつもりでもスイッチの接点が振動してしまっているような感じですね。
メジャーな現象のようで、回路を使った対策、ソフトを使った対策それぞれあるようです。英語では[chattering][button noise][debounce]などのワードで検索すると多くヒットします。
www.marutsu.co.jp
techtutorialsx.com
www.syncfusion.com
jumbleat.com
今回はソフト面から簡易的に対策してみることにしました。

修正コード

struct Button {
  const uint8_t PIN;
  uint32_t numberKeyPresses;
  bool pressed;
  uint32_t lastMillis;
};

Button button1 = {18, 0, false, 0};
Button button2 = {19, 0, false, 0};

void IRAM_ATTR isr() {
  if (millis() - button1.lastMillis > 500) {
    button1.numberKeyPresses += 1;
    Serial.printf("Button 1 has been pressed %u times\n", button1.numberKeyPresses);  
  }
  button1.lastMillis = millis();
}

void IRAM_ATTR isr2() {
  if (millis() - button2.lastMillis > 500) {
    button2.numberKeyPresses += 1;
    Serial.printf("Button 2 has been pressed %u times\n", button2.numberKeyPresses);  
  }
  button2.lastMillis = millis();
}

void setup() {
  Serial.begin(9600);
  pinMode(button1.PIN, INPUT_PULLUP);
  pinMode(button2.PIN, INPUT_PULLUP);
  attachInterrupt(button1.PIN, isr,  FALLING);
  attachInterrupt(button2.PIN, isr2, FALLING);
}

void loop() {
  if (button1.pressed) {
  }
  if (button2.pressed) {
  }
  delay(100);
}

FALLINGの検出をした際、前回の検出から500msec以上経過してる場合のみボタンプッシュとしてカウントするようにしました。500msecより早くボタン操作が出来ないことも意味していますが、そんなに連打する用途は今のところ想定していないので良しとします。動作は良好です。
f:id:tara-chang:20210704173325p:plain
今回はソフトウェア編ですがハードウェア編もあるかもしれません。ハード面からの対策もいろいろやってみましたがいまいちうまく行ってません。