こんにちは。hobbyhappyです。
今回は、Arduinoの割り込み処理で引っかかった内容についてご紹介します。
具体的には、Arduinoの割り込み処理【attachInterrupt】が、
同一のGPIOには1つしか割り当てられない。
という内容です。
やっかいなことに、このエラーですが、ArduinoIDEなんかで指摘してくれないです。
つまり、エラー表示はされず、コンパイルはされるけど、実際には動作しません….
この厄介なエラーですが、
引っかかっただけではなく、対策方法についても記載しています。
対策方法まで理解できれば、もう割り込み処理も怖くありません。
ぜひ最後までご覧ください。
Youtubeチャンネルにさまざまな動画を上げています。
↓↓↓こちらからYoutubeチャンネルにアクセス!! ↓↓↓
本ブログはアフィリエイトを用いた広告を掲載しています。
そもそもArduinoの割り込み処理【attachinterrupt】の使い方
さて、まずは割り込み機能を実装しましょう。
割り込みは、attachinterruptというコマンドを使用します。
公式リファレンスに詳しい使い方が書いてあります。
↑公式リファレンス
具体的な使い方の例としては、リファレンスにも記載されていますが、
解説も含めていったんソースコードを書いておきますね。
const byte ledPin = 12; // LEDを点灯させるピン。LEDと接続しておいて下さい。
const byte interruptPinB = 2; // このピンを割り込みのトリガーにします。
volatile byte state = LOW; // このbit の上げ下げでLEDを点滅させます。
void setup() {
pinMode(ledPin, OUTPUT); // LEDと接続しているpinは出力なのでOUTに設定。
pinMode(interruptPinB, INPUT_PULLUP); // 割り込みのトリガーなので、inputです。ボタンを想定しているのでpullupしておきます。
attachInterrupt(digitalPinToInterrupt(interruptPinB), blink, RISING); // ここで割り込みの詳細を指定しています。
}
// 常にstateを監視して、stateの状態によってLEDを点灯させるか消灯させるか決めています。
void loop() {
digitalWrite(ledPin, state);
}
// 割り込み(D2pinをトリガーとしたもの)が入ってきたら実行される関数。
void blink() {
state = !state;
}
今回割り込みに使用しているのはD5pinです。
D5pinの状態がRISINGの時に割り込みに入るように指定しています。
RISINGだけでなく、公式リファレンス的には、
LOWやCHANGEなんかもあります。
たぶんこうしたい人がいるはず。【ちょっと前の私】
一つのGPIOピンのFALLINGとRISINGどちらも見たいな。
その変化で割り込みをしたい。
ただ、そうすると、
このように記述するわけですが、
attachInterrupt(digitalPinToInterrupt(interruptPinB), blink, RISING); // ここで割り込みの詳細を指定しています。
attachInterrupt(digitalPinToInterrupt(interruptPinB), blink, FALLING); // ここで割り込みの詳細を指定しています。
こうすると、冒頭で説明した通り、エラー表示はないけど正しく機能しません。
原則:1つのGPIOピンで割り込みのトリガーに使えるのは1つの割り込みまで。
ということです。
RISINGとFALLINGを同じピンに割り当てたい:対策方法
さて、今回の例では、interruptPinBがRISINGでもFALLINGでも
blink()関数に飛んでほしいわけです。
では、どうするか….
じつはもうヒントが出ていたのですが、
RISINGでも、FALLINGでもなく、CHANGEを使うんです。
CHANGEが発動するイメージはこんな感じです。
const byte ledPin = 12; // LEDを点灯させるピン。LEDと接続しておいて下さい。
const byte interruptPinB = 2; // このピンを割り込みのトリガーにします。
volatile byte state = LOW; // このbit の上げ下げでLEDを点滅させます。
void setup() {
pinMode(ledPin, OUTPUT); // LEDと接続しているpinは出力なのでOUTに設定。
pinMode(interruptPinB, INPUT_PULLUP); // 割り込みのトリガーなので、inputです。ボタンを想定しているのでpullupしておきます。
attachInterrupt(digitalPinToInterrupt(interruptPinB), blink, CHANGE); // ここで割り込みの詳細を指定しています。
}
// 常にstateを監視して、stateの状態によってLEDを点灯させるか消灯させるか決めています。
void loop() {
digitalWrite(ledPin, state);
}
// 割り込み(D2pinをトリガーとしたもの)が入ってきたら実行される関数。
void blink() {
state = !state;
}
ただし注意ですが、この例で行くと、5Vになる瞬間(正パルス幅)
が短すぎるとうまくいきませんので正パルス幅にも気をつけましょう。
どうしてもRISINGとFALLINGだけでやりたいなら…
ここまででCHANGEを使えば行けると説明しましたが、
CHANGEにしなくても一応できる方法はあります。
それが、ピンを2本にする方法です。
前提として、1つのGPIOピンに割り込みのトリガーにできるのは1つという話なので、
GPIOピンをもう一つ追加してあげればいいんです。
const byte ledPin = 12; // LEDを点灯させるピン。LEDと接続しておいて下さい。
const byte interruptPinB = 2; // このピンを割り込みのトリガーにします。
const byte interruptPinG = 3;
volatile byte state = LOW; // このbit の上げ下げでLEDを点滅させます。
void setup() {
pinMode(ledPin, OUTPUT); // LEDと接続しているpinは出力なのでOUTに設定。
pinMode(interruptPinB, INPUT_PULLUP); // 割り込みのトリガーなので、inputです。ボタンを想定しているのでpullupしておきます。
attachInterrupt(digitalPinToInterrupt(interruptPinB), blink, RISING); // ここで割り込みの詳細を指定しています。
attachInterrupt(digitalPinToInterrupt(interruptPinG), blink, FALLING);
}
// 常にstateを監視して、stateの状態によってLEDを点灯させるか消灯させるか決めています。
void loop() {
digitalWrite(ledPin, state);
}
// 割り込み(D2pinをトリガーとしたもの)が入ってきたら実行される関数。
void blink() {
state = !state;
}
こんな感じですね。
どうしてもRISINGとFALLINGを使わないといけなくなったら参考にしてみてください。
今回のまとめ
今回はArduinoの割り込みで知らないと厄介なことを解説しました。
割り込みを2個以上組むことってあんまり趣味の範囲ではないような気もしますが、
もし必要になった時に結構混乱するやつ(エラー表示ない)なので、
予備知識としてもっておくといいかもしれません。
コメント