Arduinoのタイマーライブラリ

Arduinoでなんらかの時間的に正確な処理をしたい時、Arduinoのタイマーライブラリを利用すると簡単に出来る。ArduinoのタイマーライブラリはMsTimer2とTimerOneがあり、これらのライブラリを利用すると、一定時間ごとに関数を「割り込み(interrupt)」で呼び出す、ということがさくっと出来る。

【永久保証付き】Arduino Uno

【永久保証付き】Arduino Uno

Arduinoのタイマー

Arduinoはハードウェアの機能としてタイマーを持っている。これはArduinoで使用しているAVRというマイコンの機能で、各種ライブラリ上から使われている。Arduinoで使用している主要なAVRマイコン*1では、Timer0、Timer1、Timer2の3つのタイマーがある。これらのハードウェアのタイマーを利用し、一定時間ごとにある関数を「割り込み(interrupt)」で呼び出すことをArduinoのタイマー系ライブラリは実現している。

  • Timer0 8bitのタイマーでArduinoの時間を管理する用途で利用されている。delay(), millis(), micros()などである。UNOでは5,6番ピンのPWMで利用されている。
  • Timer1 16bitのタイマーでUNOではServoライブラリと9,10番ピンのPWMで利用されている。
  • Timer2 8bitのタイマーでUNOではtone()と3,11番ピンのPWMで利用されている。

上記のTimerの説明にある通り、AVRのタイマー機能はArduinoの各種ライブラリによって利用されていて、タイマーライブラリを使う際は、利用されていないタイマーを使うなど競合を避けないければならない。PWMもまた、タイマーを利用しているため、同時に使用することは出来ない。

タイマーライブラリ

今回紹介するライブラリは、Arduinoソフトウェア(v1.6.3)の下記階層に行くと、Library Managerが起動し、そこからインストールすることが出来る。

スケッチ > Include Library > Manage Libraries...

MsTimer2

Arduino Playground - MsTimer2
最も利用されるTimer2を利用したシンプルなライブラリ。まずはこれの利用を検討するとよい。
100ms毎に呼びだすサンプル。

#include <MsTimer2.h>

void timerFire() {
  //100ms毎にここが呼び出される
}

void setup() {
   //100ms毎にtimer発火
  MsTimer2::set(100, timerFire);
  MsTimer2::start();
}

void loop() {

}

TimerOne, TimerThree

TimerOne & TimerThree Arduino Libraries
Timer2以外のTimerを利用したライブラリ。Timer2が使えなかったり、複数個のタイマーを使いたいときに。また、MsTimer2に比べてより細かく設定が可能。TimerOneとTimerThreeの利用の仕方はまったく同じだが、TimerThreeはTimer3以上が実装されたArduino MEGA等でないと当然使えない。MsTimer2ではミリ秒で設定するが、TimerOneとTImerThreeはマイクロ秒単位で設定することに注意。*2
同じく100ms毎に呼び出すサンプル。

#include <TimerOne.h>

void timerFire() {
  //100ms(=100000us)毎にここが呼び出される
}

void setup() {
  Timer1.initialize(100000); //マイクロ秒単位で設定
  Timer1.attachInterrupt(timerFire);
}

void loop() {

}

割り込み(interrupt)

割り込みもまたマイコンの機能のひとつで、割り込みはある事柄が発生した時に、処理を割りこませるという機能である。今回はTimerがある一定時間経つと割り込みを発生させるということになる。割り込みの発生源としては、他に外部入力などがある。割り込みが発生するとソフトウェア上では、あらかじめ指定された関数のところに処理が飛ばされる。今回のサンプルプログラムではtimerFireという関数を呼び出している。

利用時のソフトウェア面での注意

割り込みしたときと、メインループ(Arduinoではloop()の中とそこから呼び出している関数)の時とで、共有して使いたい変数がある場合、volatile属性をつけないと値が共有されないので注意する必要がある。

volatile int value;

*1:Arduino毎に利用しているAVRマイコン自体が異なることがある

*2:とみっくすさんのコメントで気づきました。ありがとうございます。