今回は「割り込み」について動作確認するためにArduinoを引っ張り出してきました。
そもそも「割り込み」とはですが、普段の作業に対して、外部から特別な指示が来た時に臨時で行う作業のことです。
Arduionは電源が入ったら決まった動作(loop関数の処理)を行うのですが、あるボタンを押したときだけ特別な動作を行うとき等に割り込みを使います。
今回、LEDとスイッチの拡張を簡単に行うためにSeeed Studio社のGROVEシステムを使いました。GROVEシステムのGROVE BASE Shieldを利用するとコネクタの抜き差しだけで簡単に拡張できるんです。ですが、LANコネクタが実装されているArduino派生品ではLANコネクタが干渉してしまって上手く使えません。干渉しながらでも絶縁処理すれば使えないことはないのですが、万が一の短絡(ショート)と接触不良が怖いのでArduinoを引っ張り出してきた次第です。
GROVE – ベースシールド V1.3 amazonでも買えます。 |
Arduinoにシールドを装着するとこんな感じですね。UNOなら問題なく、スッキリ拡張。
さて、Arduinoで割り込み処理を記述するときにはまず割り込み処理内容を書き、どの割り込み番号に適用するかを決めなければいけません。
Arduino UNOに適用できる割り込みは0番と1番です。それぞれピン番号で言うと2番と3番に相当します。
下記ソースはArduinoのスケッチ例Blinkを元に、スイッチを押したタイミングで点滅と消灯が切り替わるプログラムです。
割り込み動作確認サンプル
/* Blink Turns on an LED on for one second, then off for one second, repeatedly. This example code is in the public domain. */ // Pin 13 has an LED connected on most Arduino boards. // give it a name: int led = 8; int mode = 0; // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); attachInterrupt(0, interruptsw, RISING ); // (1) } // the loop routine runs over and over again forever: void loop() { if(mode){ digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(led, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }else{ digitalWrite(led, HIGH); } } // the Interrupt routine (2) void interruptsw() { if(mode){ mode = 0; }else{ mode = 1; } }
割り込み関数の登録
割り込みの登録にはattachInterrupt関数を利用します。 attachInterrupt(割り込み番号, 割り込み関数, 割り込みモード );
割り込み番号は先ほども書いた通り、Arduino UNOでは0番と1番だけ使えます。スイッチを2番ピンに繋いでいるか、3番ピンに繋いでいるかで切り分けましょう。
さて、割り込み関数の大前提ですが、割り込み関数は引数も戻り値も登録してはいけません。割り込み仕事に元々の仕事を持って行ってはいけないですし、割り込み仕事から戻ってきた時に元の仕事で引きずってはいけません。「void」を使って「何もありませんよ」というのを明示しましょう。
実際に記述した割り込み関数interruptswは、変数modeを切り替える役目を担っています。関数が呼ばれるごとに変数modeは0と1が入れ替わります。
通常のお仕事であるloop関数のほうは変数modeの内容によって仕事が変わります。変数modeが0以外ならLEDを点滅させ、変数modeが0ならLEDを消灯させます。
最後に割り込みモードですが、信号の状態によって切り分けることができます。以下の説明ではスイッチを押した時にHIGH、離した時にLOWと仮定しています。
- LOW
信号がLOW(0V)の時に割り込みが走ります。信号がLOWの間、何回でも割り込み処理が走ります。
- CHANGE
信号の状態が変わった時だけ割り込み処理が走ります。低レベル→HIGH(5V)、HIGH→LOWの時ですね。スイッチで言うなら押したとき、離した時の両方です。
- RISING
信号の状態がLOW→HIGHに変化したときだけ割り込み処理が走ります。スイッチで言うなら押したときです。
- FALLING
信号の状態がHIGH→LOWに変化したときだけ割り込み処理が走ります。スイッチで言うなら離したときです。
- HIGH
信号がHIGHの時に割り込みが走ります。信号がHIGHの間、何回でも割り込み処理が走ります。
実際の動作
それでは上記ソースをコンパイル、書き込みして動作させましょう
消えたり…
点滅したり…
写真じゃ点滅と消灯の区別がつきませんね。
割り込み処理を使うのは難しそう…と思っていた方がいらしたかもしれませんが、Arduino(と派生品)に限って言えば難しくはありません。
押した時、離した時、押している間…シーンに合わせて割り込みを使ってみてはいかがでしょうか。