Arduino

スイッチを使う時のチャタリング防止について

スイッチには3端子搭載したモノや2端子搭載したモノがあります。3端子搭載したスイッチは、中央にある端子が左右のどちらかと繋がれば回路を切り替えられます。一方の2端子搭載したスイッチはボタンを押すか、押さないかで状態を切り替えることができます。後者のスイッチはボタンを押す際に端子と金属板が接触することで導通をするのですが、短い時間で端子と金属板がくっついたり離れたりすることで回路上では何度もボタンが押されたようにとらえられます。この現象をチャタリングやバウシングといいます。

チャタリングが起きると回路が意図しない動きをするため、例えばLEDを点灯する回路だとスイッチを押して点灯したつもりが2回押されたとカウントされてLEDが点灯→消灯となる場合があります。

そこで、今回はこのチャタリングを防止する2つの方法についてご紹介したいと思います。

チャタリングの発生原理

冒頭でもご紹介した通り、スイッチを押したときに端子と金属板が短時間でくっついたり離れたりを繰り返すことで発生します。

上図のようにスイッチを押した直後に何度も導通することで回路上High扱いになるため、不安定になります。図では押した直後しか表していませんが、スイッチから手を離した時も発生するため、Highになる想定がLOWになったりします。

チャタリングの実例

チャタリングを実際に発生させてみます。そのためにまず、以下の装置及び部品を用意しました。

Arduinoマイコン搭載の小型コンピュータ
ブレッドボード抵抗・ジャンパー線などを使って回路を作る基板
LED順方向に電圧を加えると発光する半導体
ジャンパー線電気を中継する線
抵抗512Ω電圧を下げる端子
抵抗10kΩ電圧を下げる端子
タクトスイッチボタンのON/OFF

作成した回路

回路としてはスイッチを押すとLEDが点灯し、もう一度スイッチを押すとLEDが消灯する仕組みです。なお、スイッチにはプルダウン抵抗を実装しています。

また、回路図は以下を参考にしてください。

プログラムコード

プログラムコードを以下の通りです。

const int BTN = 12;//スイッチを12番ポート
const int LED = 13;//LEDを13番ポート
int value = 0; //今回スイッチを押下したか状態
int bef_value = 0;//前回スイッチを押下したかの状態
int btn_status = -1;//スイッチの状態

void setup() {
  // put your setup code here, to run once:
 pinMode(BTN,INPUT);
 pinMode(LED,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

  value = digitalRead(BTN);
  

 if(value == HIGH)
 {
   btn_status = btn_status * -1;
   //delay(100);
 }
 
  if(btn_status > 0)
  {
    digitalWrite(LED,HIGH);
    //delay(100);

  }else
  {
    digitalWrite(LED,LOW);
    //delay(100);
  }

}
実行結果

実行した結果は以下の通りとなり、スイッチを押したらチャタリングが発生し動作が不安定となっています。(わかりずらいかもしれません。)

プログラムでチャタリング防止

チャタリングを防止するには2つの方法があります。そのうちのひとつがソフトウェア側でチャタリングを防止する方法です。具体的にはプログラム内でスイッチを押した直後にdelayを挟み強制的にプログラム処理を止めます。

プログラムコード

const int BTN = 12;//スイッチを12番ポート
const int LED = 13;//LEDを13番ポート
int value = 0; //今回スイッチを押下したか状態
int bef_value = 0;//前回スイッチを押下したかの状態
int btn_status = -1;//スイッチの状態

void setup() {
  // put your setup code here, to run once:
 pinMode(BTN,INPUT);
 pinMode(LED,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

  value = digitalRead(BTN);
  

 if(value == HIGH)
 {
   btn_status = btn_status * -1;
   delay(100);
 }
 
  if(btn_status > 0)
  {
    digitalWrite(LED,HIGH);
    delay(100);

  }else
  {
    digitalWrite(LED,LOW);
    delay(100);
  }

}

if文内にdelay(100)を記述し、強制的に100msプログラムを止めることでチャタリングを防止することができます。

実行結果

実行結果は以下の通りです。チャタリングがなくなり安定しています。

チャタリング防止回路の実装

もうひとつのチャタリングを防止する方法はハードウェア側で制御します。具体的にはチャタリングを防止するための回路を作成します。早速ですが、作成した回路図は以下の通りです。

下図の回路図の黒枠点線の中がチャタリング防止回路になります。

この回路のポイントは2つあります。ひとつ目がボタン出力の直後に抵抗を配置していることです。A点では、チャタリングが発生するため動作が不安定になります。その直後に設置した抵抗が電流を抑え急激に電荷が流れるのを防いでいます。

二つ目のポイントがコンデンサーを設定していることです。コンデンサーは電荷をためて電圧の変化を緩やかにする特性があります。そのため、B点では緩やかに電圧上昇が始まり安定します。

そして、C点の段階ではある一定の電圧を閾値として出力を反転するシュミットトリガ搭載ICを介すことで、精査しています。2回ICロジックを通しているのは反転の反転で正転に戻しているためです。

作成した回路

チャタリング防止回路の作成で使用した装置及び部品は以下の通りです。

Arduinoマイコン搭載の小型コンピュータ
フレットボード抵抗・ジャンパー線などを使って回路を作る基盤
LED順方向に電圧を加えると発光する半導体
ジャンパー線電気を中継する線
抵抗10kΩ電圧を下げる端子
抵抗512Ω×2電圧を下げる端子
スイッチボタンのON/OFF
コンデンサー10μF電荷を充放電して電圧を一定にしたり、直流分をカットして交流分のみを取り出す素子
シュミットトリガ搭載NOTゲート(74HC14AP)シュミットトリガ搭載のNOTゲートIC

作成した回路は以下を参考にしてください。プログラムコードは「チャタリングの発生原理」のプログラムコードをそのまま使います。

実行結果

実行結果は以下をご覧ください。

まとめ

今回はチャタリング防止の方法としてプログラムで制御する方法とチャタリング防止回路で制御する方法と二つご紹介しました。個人的には数msくらいの時間であれば許容範囲内とするならば、実装の手間と難易度を考えてもプログラムで制御する方法が良いと思います。

おそらくチャタリング防止回路を使う機会は電子工作の範疇ではあまりないのかもしれませんが、ソフトウェア以外でもチャタリングを防止する方法は知っていおいて損はないと思います。

参考書籍

Arduino電子工作