見出し画像

割り込み処理を使ってLEDを制御しよう

  こんにちは、タクト工房へようこそ!今回は、Raspberry Piを使って割り込み処理を導入し、LEDを制御するプロジェクトに挑戦します。通常時はLEDが点滅しており、ボタンが押されると順番にLEDが点灯し、消灯する動作を実現します。前回および前々回と同様の回路を再利用し、プログラムを改良していきます。もし、まだ前回の記事をご覧になっていない方は、以下の記事を参考にしてください。


必要な材料と道具

  • Raspberry Pi

  • ブレッドボード

  • LED

  • 抵抗

  • タクタイルスイッチ

  • ジャンパーワイヤー

割り込み処理

割り込み処理とは

 割り込み処理とは、特定のイベント(この場合はスイッチが押されること)が発生したときに、通常のプログラムの実行を中断して特別な処理を行う仕組みです。これにより、リアルタイム性が求められる処理を効率的に実行することができます。例えば、スイッチが押された瞬間に即座に反応することで、ユーザーの操作に遅延なく対応できます。

 また、割り込みが発生しないときは、メインプログラムに集中して実行することができるため、システム全体の効率も向上します。

 以下の図に割り込み処理の流れを簡単に示します。通常時はメインプログラムが実行されており、割り込み(スイッチが押されるなど)が発生すると、メインプログラムが中断し、割り込み処理を行い、その後再びメインプログラムに戻るという流れです。このように、割り込み処理を用いることで、重要なイベントに迅速に対応できるため、システムの応答性と効率が大幅に向上します。

割り込みの関数

 割り込み処理を実現するためには、プログラムに次の関数を使用します。

wiringPiISR(GPIO番号、エッジタイプ、割り込み処理関数)

 エッジタイプには、LからHに切り替わる立ち上がり、HからLに切り替わる立ち下がり、そしてその両方を検出する3つの選択肢があります。今回はスイッチを押したときに切り替えたいので、立ち上がりに切り替わるINT_EDGE_RISINGに設定します。

  • INT_EDGE_FALLING:立ち下りエッジを検出

  • INT_EDGE_RISING:立ち上がりエッジを検出

  • INT_EDGE_BOTH:立ち下がり、立ち上がりエッジの両方を検出

回路設計

 では、今回の割り込み処理を行う回路を作成します。回路は前回と同様です。以下に示す回路図に従って配線を行ってください。また、ピン配列が分からない方は以下の記事を参考にしてください。

プログラム

割り込み処理を行うプログラムを作成します。

プログラム1

まず、通常時はLEDが点滅しており、ボタンが押されたら消灯するプログラムを作成します。

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

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


void int_button(void);
int main(void){
    wiringPiSetupGpio();
    pinMode(RED_PIN,OUTPUT);
    pinMode(GREEN_PIN,OUTPUT);
    pinMode(BLUE_PIN,OUTPUT);
    pinMode(BUTTON_PIN, INPUT);
    
    wiringPiISR(BUTTON_PIN,INT_EDGE_RISING,int_button);
    
    while(1){
		digitalWrite(RED_PIN, HIGH);
		digitalWrite(GREEN_PIN, HIGH);
		digitalWrite(BLUE_PIN, HIGH);
		delay(500);
		digitalWrite(RED_PIN,LOW);
		digitalWrite(GREEN_PIN,LOW);
		digitalWrite(BLUE_PIN,LOW);
		delay(500);
	    }

    return 0;
}
void int_button(void)
{
    digitalWrite(RED_PIN,LOW);
    digitalWrite(GREEN_PIN,LOW);
    digitalWrite(BLUE_PIN,LOW);
}

wiringPiISR(BUTTON_PIN, INT_EDGE_RISING, int_button):割り込み処理を設定しています。INT_EDGE_RISINGで立ち上がりを検出します。BUTTON_PINがLOWからHIGHに切り替わったとき、通常時はmain関数内を実行していますが、割り込み処理が発生し、int_button関数が実行されます。そして再びmain関数が実行されます。

プログラム2

 プログラム1では、ボタンを押したときに一瞬しかLEDが消灯しませんでした。そこで、あまり面白くなかったので、ボタンを押したときにLEDが順番に点灯し消灯するように改良しました。割り込み処理の関数内ではdelayを使用できないため、ボタンが押されたときに割り込み処理でbutton_pressedを1にし、メイン関数でbutton_pressedが1のときにLEDが順番に点灯し消灯するようにしました。

 割り込み関数では、短時間で処理を完了させることが重要です。割り込み処理関数の中で複雑な処理や長時間の処理が必要な場合は、今回のようにメイン関数で処理するように工夫します。割り込み関数での負荷が大きいと、システム全体の作業効率が悪くなります。

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.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

volatile int button_pressed = 0; // ボタンが押されたことを示すフラグ

// プロトタイプ宣言
void int_button(void);

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

    // BUTTON_PINの立ち上がりエッジで割り込み発生
    wiringPiISR(BUTTON_PIN, INT_EDGE_RISING, int_button);

    while(1){
        if (button_pressed) {
            // ボタンが押された場合の処理
            button_pressed = 0; // フラグをクリア

            digitalWrite(RED_PIN, HIGH);
            delay(500);
            digitalWrite(RED_PIN, LOW);

            digitalWrite(GREEN_PIN, HIGH);
            delay(500);
            digitalWrite(GREEN_PIN, LOW);

            digitalWrite(BLUE_PIN, HIGH);
            delay(500);
            digitalWrite(BLUE_PIN, LOW);
        }

        // 通常の点滅処理
        digitalWrite(RED_PIN, HIGH);
        digitalWrite(GREEN_PIN, HIGH);
        digitalWrite(BLUE_PIN, HIGH);
        delay(500);
        digitalWrite(RED_PIN, LOW);
        digitalWrite(GREEN_PIN, LOW);
        digitalWrite(BLUE_PIN, LOW);
        delay(500);
    }
    return 0;
}

void int_button(void) {
    button_pressed = 1; // 割り込みハンドラ内でフラグをセット
}

コンパイルと実行

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

まとめ

 今回、割り込み処理を使ってLEDを制御しました。このLEDの制御は割り込み処理を使わずに行うこともできますが、今後複雑な回路を作るうえで割り込み処理が必要になる場面が出てきます。そのため、割り込み処理に関してはしっかり理解しておきたいです。皆さんもぜひ割り込み処理を実践して理解を深めてください。

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