ボタンを押す度にLチカの状態が反転【マイコンLチカ道場 Arduino編 1-2】

ハードによるチャタリング対策時の波形 Arduino
当サイトのリンクにはアフィリエイト広告が含まれています。
スポンサーリンク

はじめに

このページは「マイコンLチカ道場 Arduino編」の「1-2:ボタンを押す度にLチカの状態が反転」に対応するページです。スイッチを押す度にLEDがオン・オフするような動作をさせてみます。また、今回の動作ではチャタリングが問題となるので、プログラムでのチャタリング除去と、ハードウェアでのチャタリング除去を試してみました。

スポンサーリンク

回路図とブレッドボード接続図

今回の回路図・接続は前回の「ボタンを押している間Lチカ」と同じです。
1個の青色LEDと、1個のタクトスイッチを使用します。プルアップ抵抗は内蔵ではなく、外付けとしています。

回路図
回路図
ブレッドボード接続図
ブレッドボード接続イメージ

プログラムを書いてみる

プログラム(スケッチ)は下記になります。はじめは思ったように動かず、悩みに悩みましたが、if文の中の「==」を間違えて「=」と書いていた為でした。修正したら正常に動作することを確認しました。コンパイルエラーが出なくて気づきにくいので気を付けないといけないですね。

const int LED1 = 12; //LEDを接続するピン
const int SW1 = 2; //スイッチを接続するピン
int sw_state = HIGH; //スイッチの状態保存用の変数
int sw_latch = HIGH; //スイッチのラッチ用の変数
int led_state = LOW; //LEDの状態保存用の変数

void setup() {
  pinMode(LED1, OUTPUT); //LED1ピンを出力にする
  pinMode(SW1, INPUT); //SW1を入力に設定
}

void loop() {
  sw_state = digitalRead(SW1); //SW1の状態を読み込み、sw_stateに代入
  if (sw_latch == HIGH && sw_state == LOW){
 //sw_latchがHIGH、sw_stateがLOWであれば下記を実行
    led_state = !led_state; //led_stateの変数を反転
    digitalWrite(LED1, led_state); //led_stateの状態で点灯・消灯切り替え
  }
  sw_latch = sw_state; //sw_stateの状態をsw_latchに代入
  delay(50); //50msウェイト
}

主な動作の説明はコメント文に記載しています。補足として、「sw_latch」はスイッチの立下りでLEDの反転処理をさせるために入れています。「sw_latch」がHIGH、「sw_state」がLOWの時のみ、LEDを反転させます。これがないと、スイッチ押しっぱなしでLEDが点滅を繰り返すような動作になりました。

また、delay(50)は、チャタリングの除去のために入れています。これが無いと1回クリックしたのにダブルクリックしたことになったりと、壊れかけのマウスのようなイライラ動作になる恐れがあります。
delayを使うチャタリング対策は、シンプルですがdelayの間マイコンが待たされたり、スイッチ同時押しに対応できないなどの欠点があるようです。プログラムでの他の方法は、次回、複数のスイッチが出てきた際にトライしてみます。

実際にスイッチを押した時の入出力波形を、オシロスコープで見てみました。スイッチにチャタリングが発生していても問題なく動作しています。ディレイによる遅延は、MAX50msで、押すタイミングによってバラバラしています。

LEDオン時の波形
LEDオン時の波形
LEDオフ時の写真
LEDオフ時の写真

また、試しにディレイを無しにした際の動作もオシロスコープで見てみました。(単純にコメントアウトしました。)ディレイが無いので、スイッチに対して高速に反応していますが、チャタリングにより、LEDがオンしてすぐにまたオフしたりするような動作をしています。
※まだスイッチが新品なためか意外とチャタリングが発生せず、無理やり叩くように押して再現させました。劣化してくればもっと発生しやすいのかもしれません。

LEDオン時チャタリングによる誤動作の波形
LEDオン時チャタリングによる誤動作の波形
LEDオフ時チャタリングによる誤動作の写真
LEDオフ時チャタリングによる誤動作の写真

ハードウェアでのチャタリング対策

今回は、ハード側(回路側)でCRをつけるチャタリングの対策方法も試してみました。こちらのサイト(マルツ)を参考にさせてもらいました。参考にしたサイトの例では、シュミットトリガインバータ(74HC14)を使用していますが、Arduino Unoで使われているATmegaマイコンの入力はシュミットトリガになっているようなので、省略してみます。
R3=47kΩ、C1=1µFとし、放電時の時定数は、τ=RC=47msです。(今回はプログラムでのウェイトの時間と合わせてみました。)
スイッチオフ時はプルアップ抵抗R2を介してC1が充電されるため、もう少し大きい時定数になります。スイッチオンでC1を放電するので、立下り時は100%-63.2%=36.8%までC1を放電する時間ということになります。
また、コンデンサC1から、電源OFF時に入力ピン2(マイコン側)に瞬間的に放電して故障してしまう恐れがあるので、1kΩの抵抗を付けています。

回路図(CRによるチャタリング対策)
回路図(CRによるチャタリング対策)
ブレッドボード接続イメージ
ブレッドボード接続イメージ

このときのスイッチ電圧、マイコン入力電圧、出力電圧の波形をオシロスコープで見てみました。また久々に4チャンネルオシロが役に立ちました。
もちろんプログラムのディレイは無しとしています。また、内蔵プルアップは想定外の動きになったらいけないのでOFFにしています。

LEDオン時の波形(CRによるチャタリング対策)
LEDオン時の波形(CRによるチャタリング対策)
LEDオフ時の波形(CRによるチャタリング対策)
LEDオフ時の波形(CRによるチャタリング対策)

スイッチONにより、C1が放電してほぼ計算通り、時定数47msで入力ピン2の電圧は1.84V(5Vの36.8%)まで低下します。チャタリングが有っても放電が少し遅れるだけで、ほとんど影響を与えていません。
ArduinoのATmegaマイコンのスレッショルド電圧を下回ったらLEDがON・OFFしています。シュミットトリガ入力になっているので、入力にヒステリシスを持っておりこの中途半端な電圧でON・OFFを繰り返すようなことは無かったです。優秀ですね。
必要な部品はかなり増えますが、ノイズや静電気にも強そうなので安心感がありますね。

今回のシュミットトリガ入力のスレッショルド電圧について、下記の記事にまとめてみました。

まとめ

ボタンを押す度にLチカの状態を反転させることができました。また、プログラムでのチャタリング除去と、ハードウェアでのチャタリング除去を行ってみました。
引き続き難しいLチカに挑戦していきましょう。

このページの実験は下記の製品で試すことが出来ます。
タイトルとURLをコピーしました