見出し画像

スイッチでLEDをオルタネート動作させよう

 こんにちは、タクト工房へようこそ!前回、スイッチを使ったLED回路を作り、LEDを制御しました。しかし、LEDを点灯させるためにはボタンを押しっぱなしにする必要がありました。今回は、スイッチを一度押すだけでLEDの状態が切り替わるオルタネート動作を実現します。まだ前回の記事を見ていない方は、以下の記事を参考にしてください。


必要な材料と道具

  • Raspberry Pi

  • ブレッドボード

  • LED

  • 抵抗

  • タクタイルスイッチ

  • ジャンパーワイヤー

オルタネート動作の説明

 オルタネート動作とは、スイッチを押すたびにデバイスの状態が交互に変わる動作のことです。例えば、スイッチを1回押すとLEDが点灯し、もう1回押すとLEDが消灯します。これにより、スイッチを押し続ける必要がなくなり、1回の押下で状態を変更できる便利な仕組みが実現します。

回路設計

 回路は前回と同様の回路を作成します。以下に示す回路図に従って配線を行います。

フローチャート

 以下の図に今回のプログラムのフローチャートを示します。ここでは3つの変数を使ってオルタネート動作を行っています。

  • buttonstate:ボタンの状態を保存する変数。ボタンが押されていればHIGH、押されていなければLOWとなる。

  • lastButtonstate:1つ前のボタンの状態を保存する変数。

  • ledstate:LEDにHIGHかLOWを出力する変数。この値がHIGHになればLEDは点灯し、LOWになれば消灯する。

 変数の初期化を行います。先ほどの3つの変数をLOWに初期化します。
 ボタンの状態(HIGHかLOW)をbuttonstateに入れます。
 ボタンが押されたか判断します。
 ledstateの値を反転させます。
 ledstateがHIGHならLEDを点灯し、LOWなら消灯します。
 lastButtonstateに②のbuttonstateの状態を保存します。

 ここではボタンを押して再び押したときの例を挙げます。
 まず、最初に変数はすべてLOWに初期化されています。次にボタンを押したとき、buttonstateはHIGHになります。次に③の条件がYESとなり、④に行きます。ledstateの初期値はLOWなので、反転してHIGHになります。よって、LEDは点灯します。そして、⑥でlastButtonstateにHIGHになります。
 次にボタンを押し続けていた場合、②でbuttonstateはHIGHになり、③の条件式はNoとなって、⑥に移動しlastButtonstateはHIGHとなります。
 次にボタンを離した場合、同様に考えて、lastButtonstateがLOWになるだけです。
 そして再びボタンを押すと、③の条件式が満たされ、ledstateはHIGHだったため、LOWとなり、LEDは消灯します。

プログラム

次に、Raspberry Piに以下のC言語コードを入力します。

#include <wiringPi.h>
#include <stdio.h>

#define RED_PIN 17    // GPIO 17
#define GREEN_PIN 27  // GPIO 27
#define BLUE_PIN 22   // GPIO 22
#define BUTTON_PIN 21 // GPIO 21

int main(void) {
    wiringPiSetupGpio();
    pinMode(RED_PIN, OUTPUT);
    pinMode(GREEN_PIN, OUTPUT);
    pinMode(BLUE_PIN, OUTPUT);
    pinMode(BUTTON_PIN, INPUT);

    int ledState = LOW;
    int lastButtonState = LOW;

    while (1) {
        int buttonState = digitalRead(BUTTON_PIN);

        if (buttonState == HIGH && lastButtonState == LOW) {   // スイッチが押されたとき
            ledState = !ledState;  // LEDの状態を反転
            digitalWrite(RED_PIN, ledState);
            digitalWrite(GREEN_PIN, ledState);
            digitalWrite(BLUE_PIN, ledState);  // LEDの状態を設定
            
        }
        lastButtonState = buttonState;
    }

    return 0;
}

コンパイルと実行

 入力が完了したら、メニューの「ビルド>Build」をクリックします。コンパイルが完了したら「ビルド>Execute」をクリックし、プログラムを実行します。実行し、ボタンを押すたびにLEDが点灯・消灯を交互に繰り返します。

バウンシング対策

 先ほどのプログラムを実行すると、オルタネート動作が不安定になることがありました。この問題の原因として考えられるのが「バウンシング現象」です。バウンシング現象とは、スイッチが押されたときや離されたときに接点が短時間で複数回オン・オフを繰り返す現象です。これにより、マイコンのGPIOピンに予期しないパルス信号が入力され、スイッチが一度押されたのに複数回押されたと誤判定されることがあります。

 バウンシング現象は通常、スイッチの接点が安定するまでの数十ミリ秒の間に発生します。そのため、この現象を対策するためには、スイッチの状態が安定するまで待機する「デバウンス処理」を行う必要があります。デバウンス処理を追加することで、スイッチの正確な状態を検出し、意図しない誤作動を防ぐことができます。

フローチャート

 フローチャーを以下のように書き換えます

先ほどのフローチャートから⑦から⑨を付けたします。バウンシングは数十ms続くため、③の判定の後に20ms待ちます。そしてもう一度buttonstateにBUTTON_PINの状態を入力し、それでもHIGHであれば条件を満たすとします。条件を満たさない場合、バウンシング現象によって、誤動作が起こったとします。

プログラム

プログラムを以下のように改良します。

#include <stdio.h>
#include <wiringPi.h>

#define RED_PIN 17
#define GREEN_PIN 27
#define BLUE_PIN 22
#define BUTTON_PIN 21
int main(void){
    wiringPiSetupGpio();
    pinMode(RED_PIN,OUTPUT);
    pinMode(GREEN_PIN,OUTPUT);
    pinMode(BLUE_PIN,OUTPUT);
    pinMode(BUTTON_PIN,INPUT);
    
    int ledState=LOW;
    int lastButtonstate=LOW;

    while(1){
	int buttonstate=digitalRead(BUTTON_PIN);
	if(buttonstate==HIGH && lastButtonstate==LOW){
	    delay(20);
	    buttonstate=digitalRead(BUTTON_PIN);
	    if(buttonstate==HIGH){
	        ledState=!ledState;
	        digitalWrite(RED_PIN,ledState);
	        digitalWrite(GREEN_PIN,ledState);
	        digitalWrite(BLUE_PIN,ledState);
	    }
	}
        lastButtonstate=buttonstate;
    }
    return 0;
}

コンパイルと実行

 入力が完了したら、メニューの「ビルド>Build」をクリックします。コンパイルが完了したら「ビルド>Execute」をクリックし、プログラムを実行します。実行し、ボタンを押すたびに安定してLEDが点灯・消灯を交互に繰り返します。

まとめ

 これで、タクタイルスイッチを使ってLEDをオルタネート動作させるプロジェクトが完成です。スイッチを使った高度な制御方法を学び、より複雑な電子回路の設計に挑戦してみてください!

この記事が気に入ったらサポートをしてみませんか?