Debounce

はじめに

チャタリング対策を行います。

チャタリングとは、ボタンスイッチなどをONやOFFにしたとき、一時的にボタンの状態にHIGHとLOWとが繰り返し現れる現象です。

このとき、素直にボタンの状態に追従して機器の操作を行うと不要な操作を行うことになります。例えば、ボタンのON/OFFに合わせて、LEDを点灯/消灯するような場合には、ボタンを押した瞬間に、LEDが点滅することになります。

今回の例題はこのチャタリングをソフトウェアで防止するためのものです。一定時間以上ボタンの状態が変わらなければ、ボタンの状態が変わったと判断します。

プログラム

定義等

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
  Debounce

  Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
  press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's a
  minimum delay between toggles to debounce the circuit (i.e. to ignore noise).

  The circuit:
  - LED attached from pin 13 to ground through 220 ohm resistor
  - pushbutton attached from pin 2 to +5V
  - 10 kilohm resistor attached from pin 2 to ground

  - Note: On most Arduino boards, there is already an LED on the board connected
    to pin 13, so you don't need any extra components for this example.

  created 21 Nov 2006
  by David A. Mellis
  modified 30 Aug 2011
  by Limor Fried
  modified 28 Dec 2012
  by Mike Walters
  modified 30 Aug 2016
  by Arturo Guadalupi

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Debounce
*/

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
 

このプログラムで利用する大域変数を定義します。

lastButtonStateは、最後にbuttonPinからの入力を読んだときの状態を保存しておく変数です。プログラム開始時はLOWが設定されています。

lastDebounceTimeは、最後にボタンの状態が変更された時の時刻(Arduinoボードが起動してからの時間)を保存する変数です。最初に説明した一定時間を表すのが debounceDelayでこのプログラムでは50(ミリ秒)に設定されています。

setup()

44
45
46
47
48
49
50
51
void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}
 

pinMode()を使って、ledPin(13番ピン)を出力モードに、buttonPinを入力モードに設定します。

loop()

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }

  // set the LED:
  digitalWrite(ledPin, ledState);

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;
}

まず、digitalRead()を使ってbuttonPinの状態を読み取り、その結果をreadingに代入します。

次に、今読み取ったreadingとその前に読み取ったlastButtonStateとを比較し、それらの値が異なれば、lastDebounceTimeに現在の時刻を代入します。最後に状態が変わった時刻を保存しておきます。同じ状態の場合は、lastDebounceTimeは変更しません。

現在の時刻とlastDebounceTimeの差を計算し、それがdebounceDelayよりも大きければ、その状態が正しい状態と考え、buttonStateを更新します。

その後、digitalWrite()を使って、ledPinにbuttonStateに代入されている値を出力します。

最後に、lastButtonStateにbuttonPinから読み取った値を代入します。

模式図を以下に示します。見てわかるとおり、実際にボタンを押してから、ボタンが押されたとみなすまでに時間がかかるため、利用するボタンの特性に合わせてdebounceDelayをうまく調整しないと、操作感が悪くなります。

バージョン

Hardware:Arduino Uno
Software:Arduino 1.8.16

最終更新日

September 11, 2021

inserted by FC2 system