Menu
CoddyTech

ボタンのチャタリングを除去する

CoddyのArduinoジャーニー「入力」セクションの一部。レッスン 6/22。

このレッスンのボタンは本物で、スターターは前のレッスンで作ったカウンターです。実行してボタンを1回押してみましょう。カウントが1より大きく増えます。

ボタンの内部では、2つの金属接点が触れ合っています。接点が触れるとバウンスします。約1ミリ秒の間、接点はぶつかり、跳ね返り、またぶつかります。ボタンを離すときも同じことが起こります。loop()はその1ミリ秒の間にピンを何度も読み取り、バウンスのたびに押されたとカウントします。

この問題はチャタリング除去と呼ばれる方法で解決します。読み取り値が変わったら、その変化に対して1回だけ処理し、接点が安定するまで約20 ms待ってから再び読み取ります。人が20 msに気づくことはありません。

if (reading != lastReading) {
  if (reading == LOW) {
    presses++;
    Serial.println(presses);
  }
  delay(20);
}
lastReading = reading;

押したときだけでなく、変化するたびに待ちましょう。離すときもバウンスし、離れる途中のバウンスもそれぞれ新たな押下のように見えるからです。

challenge icon

チャレンジ

中級

カウンターを修正して、ボタンを押すたびに1回だけカウントされるようにします:

  • reading が lastReading と異なる場合、それが押された状態(LOW)ならカウントし、その後20 ms待ちます
  • loop() の最後に lastReading を保存し続けます

Run を押し、ボタンを数回押してカウントを確認してから、Check を押します。

自分で試してみよう

const int buttonPin = 2;

int presses = 0;
int lastReading = HIGH;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  int reading = digitalRead(buttonPin);
  if (reading == LOW && lastReading == HIGH) {
    presses++;
    Serial.println(presses);
  }
  lastReading = reading;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

入力のすべてのレッスン

自分で練習してみよう: Arduinoプレイグラウンド