前回はフォトインタラプタの入力をreadでポーリングして、フォトインタラプタの隙間にものがあるかどうかを調べた。
今回はポーリングではなく割り込みで処理することにした。
プログラムはさらに簡単に。
回路図も大幅な変更は無いので、メモ書き程度にとどめる。
回路図の変更
- 11番ピンから取り込んでいたフォトインタラプタの出力を、2番ピンに変更
- 適当なポート(今回は4を選んだ)からフォトインタラプタの出力状態がわかるように信号を出す。
- ポート4の先にはLEDをぶら下げておく
割り込み信号線がARDUINOのバージョン(UNOとLEONARDO)で異なっていたため、詰まってしまった。以下のサイトを参考にさせていただきました。
なんでも作っちゃう、かも。 Arduinoボードの違いまとめ(Uno, MEGA 2560, Leonardo, Due)
さて、ARDUINOの割り込みトリガはいくつかある。
どのトリガを採用するか検討する。
- LOW
- CHANGE
- RIZING
- FALLING
LOWとCHANGEはいわゆるレベルトリガとエッジトリガ。
LOWを使うには事前にプルアップ抵抗経由して電圧レベル持ち上げておく必要がある。
CHANGEはエッジ検出で動作する。今回はこれが都合よさそう。
RIZINGとFALLINGはクロック信号の立ち上がり/立ち下りで割り込みを発生させる。
シリアル通信で使うことになりそうだけども、今回はスルー。
というわけで、CHANGEのモードで使っていく。
ソフトウェア側の実装
#define IRRCV_PIN 2 // 割り込みハンドラ内で検出した値を格納する変数 volatile int g_object_detection = 1; // 割り込みハンドラ void ISR_photo_int(void) { g_object_detection = digitalRead(IRRCV_PIN); } // 初期化 void setup(){ pinMode(IRRCV_PIN, INPUT); pinMode(LED_PIN, OUTPUT); // 割り込みハンドラの登録 attachInterrupt(1, ISR_photo_int, CHANGE); } void loop(){ // 割り込みハンドラによって設定されたフォトインタラプタの状態をLEDで表す digitalWrite(LED_PIN, g_object_detection); }
コードの説明
初期化のタイミングで、割り込みハンドラを登録する。
1は割り込みの番号であり、LENNARDOのピン2に相当する。
登録するときには割り込み関数と割り込みトリガを設定する。
割り込みハンドラは、フォトインタラプタの出力が変化したときに呼び出される。
このとき、割り込み信号(ピン2)の値を直接読み取り、HIGHなのかLOWなのかを取り出す。これはg_object_detection変数に値をセットする。
この変数は、フォトインタラプタの状態を必ずメモリに書き出しておく必要があるのでvolatileとする。
最後に、ループ処理でこの値を読みだしてLEDに反映させる。
実験結果
起動直後はLEDは点灯状態。
フォトインタラプタの隙間にカードなんかを差し込むと、LEDが消灯する。
差し込んだカードを引き抜くとLEDが点灯状態に戻る。
まずは割り込みで処理できるようになった。
(割り込み信号線をreadするのは嫌な感じはするが、今回の用途では問題ない。)
課題
割り込み信号は2本しかないので、もっと大量の割り込み信号を使いたくなったときは割り込みコントローラとか入れてあげる必要がある。