検索
連載

チャタリング対策をソフトウェアだけで行う方法今岡通博の俺流!組み込み用語解説(8)(2/2 ページ)

今岡通博氏による、組み込み開発に新しく関わることになった読者に向けた組み込み用語解説の連載コラム。第8回は、第7回で取り上げた「チャタリング」への対策をソフトウェアだけで行う方法を紹介する。

Share
Tweet
LINE
Hatena
前のページへ |       

トグル動作

 前回の記事でトグル動作のチャタリング対策がされてないプログラムを紹介しましたが、今回はそのプログラムにチャタリング対策を施します。

 リスト2は11行目から始まっていますが、それより前の行にはリスト1で示したプログラムがあるものとします。

11: void loop() {
12:  static int led=0;
13:  while(digitalRead(sw));
14:  digitalWrite(LED,led=~led );
15:  delay(500);
16: }
リスト2 チャタリング対策済みのトグル動作のプログラム

 前回の記事で紹介したトグル動作のプログラムと異なる点のみ説明します。12行目で発光ダイオードの状態を保存するための整数変数ledを宣言し、初期値を0としています。

 14行目は発光ダイオードを点灯/消灯させる行なのですが、変数ledを反転させてledに代入しています。この操作により簡潔にトグル動作を実現できます。

 そして、肝心のチャタリング対策になるのが15行目のdelay関数です。引数は500ですが、これは500msの間次の命令を実行するまで待ちます。1行でチャタリング対策ができるのはとても良いことなのですが、タクトスイッチを500ms以上押しっぱなしにすると発光ダイオードの状態が遷移します。すなわち、発光ダイオードが点灯状態なら消灯し、その逆なら点灯します。それでもタクトスイッチを押下したままだと、500msごとに発光ダイオードが点灯と消灯を繰り返します。

 また、2回タクトスイッチを押下すれば、発光ダイオードの点灯/消灯の状態は元に戻るのですが、500msの間に2回タクトスイッチを押下すると、発光ダイオードは元の状態に戻りません。

 要は、タクトスイッチを速く押しても遅く押しても当初の仕様通りには動作しないということです。もう少し改良が必要そうですね。

ソフトウェアデバウンス

 リスト3は、チャタリングにより一定時間内に複数のオン/オフが検出された場合でも単一の入力と判断するためのアルゴリズムです。

11: void loop() {
12:   static uint8_t stat = 0,led=0;
13:   static uint32_t push_time = 0;
14:   if (digitalRead(sw) == HIGH) {
15:     if (stat == 0) push_time = millis();
16:    stat = 1;
17:  } else {
18:    if (stat == 1 && millis() - push_time >= 10) digitalWrite(LED,led=~led); 
19:    stat = 0;
20:  }
21: }
リスト3 一定時間内に複数のオン/オフが検出された場合でも単一の入力と判断するためのアルゴリズム

 では早速ソースコードを見ていきましょう。

 このリスト3もリスト2と同様に11行目から始まっていますが、それ以前の行はリスト1で示したプログラムがあるものとします。

 12行目ではタクトスイッチの状態を保存する変数statと発光ダイオードの状態を保存するledを定義し、それぞれ初期値を0としています。

 13行目ではタクトスイッチが押下されている時間を計測するための変数push_timeを定義し0に初期化します。

 14行目ではタクトスイッチの押下がリリースされた直後、push_timeに現在時間を記録します。そしてタクトスイッチがリリースされたことを示す変数statを1にします。

 17行目からはタクトスイッチが押下されている場合の処理です。スイッチが押下された瞬間、現時点の時間とスイッチがリリースされた瞬間の時間の差を取り、その時間が一定以上であれば、発光ダイオードのトグル動作を行います。そして19行目でスイッチの状態を示すstatに押下されたことを示す0を代入します。

 ここで18行目のif文の条件式の中に10というマジックナンバーが唐突に登場します。これによって、タクトスイッチがリリースされた時点から現時点まで10ms以上が経過していればこの条件文が真となり、発光ダイオードのトグル処理が発動します。

 なお、この10msは、スイッチを押下あるいは解放してからチャタリングが収まるまでの時間です。例えば、秋月電子通商で扱っているタクトスイッチの場合5msとなっています(データシートのBounce項目に記載があります)。

おわりに

 マイコンプログラムの中で状態遷移をメカニカルスイッチで行う場合はチャタリング対策は必須です。人間が押下/解放するUIとしてのメカニカルスイッチをマイコンでどのように扱うか、そのあたりにも配慮を傾けていただければ幸いです。マイコンと人間は時間的粒度が異なります。動作が緩慢な人間が扱うメカニカルスイッチを、ポーリングなどによってマイコンが全力でハンドリングするために起こる不具合なのかもしれません。

 今回紹介した手法以外にもソフトウェアでチャタリング対策を行うことは可能です。割り込みを用いるもの、状態遷移を利用するものなどあります。

 また、チャタリングの現象や対策の検証のためにトグル動作を事例としましたが、チャタリングの対策が必要なプログラムとしてはカウンターやロータリーエンコーダーのハンドリングなどがあります。これらについてはまたの機会にお届けできたらと思います。また、ハードウェアによる対策も色々ありますが、それらについてはFPGAを題材にしたときご紹介させてください。

⇒MONOist編集部へのご意見はこちらまで

Copyright © ITmedia, Inc. All Rights Reserved.

前のページへ |       
ページトップに戻る