今回はArduinoの割り込み処理について解説していきます。
割り込み処理というと、初心者が苦戦する難関の1つだと思います。
実際にArduinoで割り込み処理する時には、
attachinterrupt()を使います。
このattachinterrupt()の使い方も少しクセがあるので、
初心者には少しわかりにくいです。
基本となるsetとloopとも違う使い方ですから、
書き方も慣れないと戸惑う原因の1つかと思います。
また、割り込みは、
その名の通り通常のloop関数の中を回っている状態から、問答無用で切り替わります。
具体的には、設定した割り込みのトリガーが発動すると、
あらかじめ設定してあった割り込みの関数に飛びます。
この割り込みの関数に飛ぶというのが、
なかなかイメージしにくいかと思います。
このイメージのしにくさも割り込み処理を難しく感じさせる要因の1つだと思っています。
そんなわかりにくさがある割り込み処理について、
番外編も含めて今回から4記事に分けて解説していきます。
今回の記事では、まずArduinoにおける割り込み処理がどんなもので、
どんな時に使えるのか?について解説していきます。
この記事が理解できれば、
なんとなくArduinoの割り込み処理の使い方や、
使い道についてイメージしてもらえると思います。
Arduinoの割り込み処理についてイメージが湧く
Youtubeチャンネルにさまざまな動画を上げています。
↓↓↓こちらからYoutubeチャンネルにアクセス!! ↓↓↓
本ブログはアフィリエイトを用いた広告を掲載しています。
Arduinoにおける割り込み処理のイメージを掴む
まずはArduinoの割り込み処理についてイメージを掴みましょう。
そのためには、標準的な関数であるsetup関数とloop関数についても
イメージを掴んでおく必要があります。
ArduinoIDEをデフォルトで立ち上げるとこのような画面になりますよね?
こちらの画面に出てくるsetup()とloop()について
まずは解説して、そのあと割り込みの関数についてお話します。
ArduinoIDEの画面が出てきましたが、
Arduino初心者の方でも安心してください。初心者でもわかるように解説しています。
それでは早速イメージを解説していきます。
setup関数の役割とイメージ
setup関数とは、その名の通りセットアップする関数です。
つまり、初回の設定、いわゆる初期設定する役割だと思ってください。
初期設定なので、処理される順番は電源投入された直後。
もしくはArduinoのリセットがかかった直後に処理されます。
ここに書くのは、後ほど説明するloop関数で使うようなパラメータなど
あらかじめ設定しておきたい内容です。
void setup() {
// ここにかかれた指令は、電源投入時の最初の一回だけ実行される。
}
loop関数の役割とイメージ
setup関数のイメージがわかったところで、
次はloop関数のイメージを解説していきます。
先ほどのsetup関数は、電源投入直後に1回だけ実行されます。
それに対してこのloop関数は、基本的には電源供給が止まるか、
リセットボタンを押されるまで永遠に実行され続けます。
このloop関数の中に実行したい内容を記述しておけば、
何回繰り返すか?など特に考える必要はありません。
ただ、逆に言うと
意図せず止まらずに動き続ける。という現象も起きますので、
loop関数は超高速で常に実行され続けることを
意識しておきましょう。
void loop(){
// ここにかかれた指令は、常に実行され続ける。
}
割り込み関数の役割とイメージ
それではいよいよ割り込み関数です。
まずは割り込み関数の役割についてお話します。
割り込み関数は、loop関数が実行されている途中、
どうしても優先的な処理を行いたい場合に、
loop関数の処理の途中でも割り込みできるものです。
言葉で説明しても難しいので図で説明してみます。
まず、こちらの図をご覧ください。
ここに、setup関数、loop関数、割り込み処理の関数を用意しました。
割り込みが入らない場合のイメージとしては、このような流れになります。
つまり、制御の流れとしては、
A⇒B⇒C⇒D⇒B⇒C⇒D⇒…..となります。
一方で、割り込みが入る場合はどうか?
実は、loop関数のBの処理中でも、
Cの処理中でも、Dの処理中でも、
いつでも中断して割り込みの関数に飛びます。
つまり、割り込みが発動するタイミングによっては
どれでも発生するということになります。
ですから、A⇒Bのタイミングで
割り込みが入れば次に処理されるのはE。
入らなければC、といった具合です。
さて、最後に割り込みの関数についてイメージをお伝えします。
割り込み関数は、ここまでで解説したように、
loop関数の中で繰り返し処理されている途中で
中断して別の処理をさせるものです。
なので言葉の通り、
順序良く制御の文(プログラミング)を実行していて、
途中で条件によって割り込みが入る。ということです。
Arduinoにおける割り込み処理はどんな時に使うのか?
割り込みを使うタイミングとはいつなのか?どんな時なのか?
それは、モーターなどの動くものを止めたり、位置の確認をしたりするときに使われます。
そのほか、人間がイレギュラーに手動操作するときなんかにも登場することがあります。
そもそもなんでArduinoの割り込み処理が必要なのか?
そんなArduinoの割り込み処理の使いどころですが、
なんで割り込み処理なんかが必要なのか?気になりませんか?
割り込み処理を使わなくっても、当然loop関数の中に
センサーのON/OFFを見る行を作っておけば、そこで
センサーの状態がわかるじゃないか。と。
ただ、割り込みを使わないとうまくいかないこともあります。
それは、モーターなどの動くものを止めたり位置確認をしたりする時です。
先ほど割り込み処理の使いどころとして挙げていますね。
実は以前書いたこの記事では、センサーをloop内で監視していました。
つまり、割り込み処理を使わずにセンサーを確認する方法ですね。
これをモーターの制御の時に行うと困ったことが2つあります。
それがこの2つです。
なぜ割り込み処理が必要か?:loop関数のタイムラグに注意
1つめは、loop関数は超高速で繰り返していますが、
それでも1回loopが回るまでにタイムラグがあります。
そのタイムラグの間にモーターが動いてしまうと困る場合もありますよね。
最悪モーターが動きすぎて衝突する可能性もあるため注意が必要です。
もちろんそこまでシビアな制御が不要であれば、
loop関数の中で毎回センサーのon/offを見てあげるのも問題ありません。
例えば、モーターへの回転制御が1行あって、
その行のすぐ次の行でセンサーを確認する。
というのがあればそこまで大きな問題にはならないかもしれませんが、
モーターへの回転制御の行の位置に対して、
センサーを確認する行までの間に
重い(時間のかかる)処理が入っていた場合どうなるでしょうか…
Loop関数の所要時間が伸びるということは、
センサーのON/OFFを検知する感覚が伸びるということです。
ですから、センサーがONになったら危険なエリアなので
モーターを止める。という制御だった場合、
delay()の間に危険エリアに入り込む。というのは想像できますね。
なぜ割り込み処理が必要か?:センサー監視のタイミングに注意
2つ目の困ったことは、
「もしセンサーが反応している場合はモーターを停止する。」
と言った制御の場合、一度センサーに入るともうモーターを動かせなくなります。
センサーのON/OFFをloop関数で見ていますから、
loop関数とloop関数の間のとても短い時間の間に
センサーが反応する領域から脱出出来れば原理的には問題ないわけですが、
その方法では結構無理があります。
この現象を数字で説明しておきましょう。
例えば一般的なArduino UNO R3の場合は、
動作周波数はデフォルトで16MHzです。
これは、1秒間に16M回loop関数が実行されるのとほぼ同じです。
1M=1000k=1000000←とんでもない頻度で実行されることがわかる。
※loop関数の中でdelayを入れたり、重い処理を入れると
その分時間がかかるので、16M回から回数は減少します。
1秒間に16M回実行されるわけですから、
1回の実行時間は逆数になって、1/16000000秒に1回実行されることになります。
つまり、1/16000000秒のあいだにモータを動かして、
センサーが反応しない位置まで移動しないと
センサーがONになりっぱなしということです。
割り込み処理が活躍するのはこんな時
ここまでで、なぜArduinoに割り込み処理が必要かについて
ご理解いただけたかと思います。
では、割り込み処理はどんな時に活躍するのか?
具体例を2つほど上げてみます。それがこちら↓↓
モーターなどの動きものの制御をするとき
モーターや、何か物を動かす時、
注意すべきなのは、いかに素早く思い通りに動かせるか?です。
例えば、モーターを回転させて、
その回転をねじによって直進方向に変換させる、
いわゆる直動ステージがありますね。
モータードライバーはこんなのを使って、
Arduinoと接続すると直線方向に物体を動かすことが可能です。
これは、モーターを回転させる量に制限がかかることはわかりますよね?
永遠に回転させてしまうと、ステージの端でぶつかってしまうからです。
では、ステージの端でぶつかって破損させる前にどうするか?
それは、危険エリアをセンサーで見るのが一般的です。
例えば、このようなセンサーを2つ用意します。
このセンサーをステージの両端に1つずつ付けます。
そして、このセンサーが反応したら、ステージが端まで来た。
⇒もう危険エリアなのでモーターを停止しよう。
という流れになるわけです。
そのセンサーの反応ですが、
極端な話、ON/OFFの確認を5秒に1回しかしていない。となった場合、どうなるでしょうか?
当然、5秒のうちに危険エリアに入ると、最悪ステージの端に当たって破損するでしょう。
この5秒というのは少々大げさに聞こえるかもしれませんが、
loop関数の1周するまでの時間が5秒になっていれば当然こうなります。
delayで合計5秒になっていれば確実にアウトですね。
そんな時でも、割り込み処理であれば、
どんなにloop関数の1周期が長くても割り込み処理が実行されて、
センサーのON/OFFが瞬時に反映される。というわけです。
人間やその他イレギュラーなトリガーが入る場合
次は人間やその他のイレギュラーな要因がある場合です。
よくある話としては、
作業者が押したら動かす。や、止める。
作業者がここまでやったら、これを動かす。などなど。
これらは、すべて作業者つまり人間が次の動作のトリガーです。
つまり、言ってしまうと、装置側(Arduino側)としては、
いつ次の処理を始めればいいか待機している状態です。
そんな時、割り込み処理を使わず、
かつ、loop関数の1周期が5秒も10秒もある場合、
人間が押してから、5秒も10秒も待ってからArduinoが動くことになります。
これでは、はっきり言って使えないですよね…
実はこの状態には、他にも問題があって、
loop関数のうちの一部でセンサーを監視していますから、
loop関数の周期が5秒だったとして、
センサーを監視するのは5秒のうちほんの1mSecだったりするわけですね。
すると、5秒のうちのその一瞬を逃すと、
次のセンサーの監視まで5秒かかる。という話になります。
つまり、簡単に言ってしまうと、確実にセンサーのON/OFFを
Arduino側に伝えたいなら、5秒間センサーをONしないといけない。
ということになります。現実的ではないですよね…
今回のまとめ:Arduinoの割り込み処理は、文字通り割り込み。
今回は、Arduinoの割り込み処理について、
イメージをつかめるように解説してみました。
また、どんな時に割り込み処理が使われるのか?
なぜ割り込み処理が必要になるのか?についても解説しました。
割り込み処理は、
大体どんな感じで使えるのか?と想像だけでも
してもらえれば今回の記事の理解は完了です。
次の記事以降で、
実際の割り込み処理の記述方法や、
技術的な決まりなど詳しく徹底的に解説していきます。
この記事でイメージが付いたら、
是非その先の記事まで読んでみてくださいね。
コメント