attachInterrupt関数を用いたArduinoでの外部割込み

こんにちは、ばいろんです。

最近、Arduinoで割り込み処理をする機会があったので使うシーンと使い方をまとめてみます。

 

attachInterrupt(interrupt, function, mode

 

  • interrupt:割り込み番号(0 or 1)

どのピンを外部割込みに使用するか決めるパラメータ。Arduino Unoの場合は次の2つのピンを利用することができます。

割り込み0(2ピン)

割り込み1(3ピン)

外部割込みで2ピンを使いたいときは値を0にする。ピン番号とパラメータが一致していないので注意

  • function:割り込み発生時に呼び出す関数

ここで指定した関数が外部割込みが起きたときに呼び出されます。呼び出される関数の特徴(制約)をいくつか挙げておきます

1.引数と返り値を持つことができない
2.delay()関数は機能しない
3.millis()関数の戻り値が増加しない
4.シリアル通信により受信したデータは、失われる可能性がある
5.割り当てた関数のなかで値が変化する変数にはvolatileをつけて宣言する

気をつけないといけないのは1番と5番ですね。外部割込みは突然発生するイベントに対する処理なので引数と返り値は当然持つことができません。

そのかわり、グローバル変数を使って値のやり取りを行うことができます。このとき、もしもint型の変数を使いたいときはvolatile intと宣言する必要があります。

(ちなみにvolatileを付けることによって変数をレジスタからではなくRAMからロードするようコンパイラに指示するらしい。どうやら意図しない最適化など外部割込みがかかわる特定の条件でレジスタから値をロードすると不正確な値を読み込むのだそうだ。)

  • mode:割り込みを発生させるトリガ

LOW: ピンがLOWのとき発生
CHANGE: ピンの状態が変化したときに発生
RISING: ピンの状態がLOWからHIGHに変わったときに発生
FALLING: ピンの状態がHIGHからLOWに変わったときに発生

必要なもの

 

 

外部割込みを使う場面

 

外部割込みを使う場面は端的に言うと、センサーやタクトスイッチの入力に対して素早く機敏な反応が要求される場面です。

たとえば、マウスやキーボードなども外部割込みを利用して値を検知することでレスポンスを良くして、ユーザーを待たせないようにしています。

突然発生するイベントの処理を行うことができるのでユーザビリティが要求される入力装置などで利用されることが多いのではないでしょうか。

 

analogRead()関数の反応が悪くなるスケッチの例

 

一般的にArduinoが外部からの入力を受け取るときはanalogRead()関数やdigitalRead()関数を利用します。例えば次のスケッチです。

void loop() {
  value = analogRead(PIN);
  hoge();//何かしらの処理
}

外部からの入力を受け取り、hoge()という処理を行うスケッチです。

しかし、入力に利用されるanalogRead()などの関数がうまく動作しない場合があります。例えば次のスケッチがそれに当たります。

void loop() {
  value = analogRead(PIN);
  for(int i = 0; i < 30000; i++){
    for(int j = 0; j < 50000; j++){
      hoge();//何かしらの処理
    }
  }
}

上のようにたくさんの繰り返しを持つfor文の外側にanalogRead()関数があるとします。ここで、for文の実行中に外部から何かしらの信号(センサーの信号など)を入力してもanalogRead()関数を通らないため入力は受け取られません。

次のスケッチもanalogRead()などの関数がうまく動作しない例です。

void loop() {
  value = analogRead(PIN);
  delay(5000);
}

delay()中は処理が停止するのでanalogRead()関数を通らないため入力を受け取ることができません。

このようなコードを修正するにはなかなかトリッキーなコードを書く必要があるのですが、外部割込みを使うことでシンプルなコードで改善できることがあります。

外部割込みは初めてだと使いどころが分かりにくい処理だと思います。(ソフトウェアからハードウェアに入った身としてはなぜ必要なのか最初はよくわかりませんでした)
そんな中、外部割込みの練習にちょうどいいセンサーを見つけたので次回はそのセンサーを使って外部割込みの実装をしていこうと思います。

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to top