時間を操作するときにdelay関数をよく使いますが、これを使うとdelayで指定した時間が経過するまで、プログラムが止まってしまいます。メインのプログラムは動かし続けた状態で、 時間を計測したい場合は、割り込みタイマーを使うと良いです。
目次
Timerの種類
Arduino Unoは、AVR ATmega328Pというマイコンを搭載しており、このマイコンにはTimer0, Timer1, Timer2の3つのタイマーがあります。このタイマーを利用して、時間を計測することが出来ます。ただし、使用する際には注意が必要です。各タイマーは、PWM波形を出力するために使用したり、delay関数などに使用します。各タイマーの割当を以下に記載します。
bit数 | 対応ピン | 対応関数 | |
Timer0 | 8bit | 5pin, 6pin (PWM) | delay, millisなど |
Timer1 | 16bit | 9pin, 10pin (PWM) | (Servoライブラリ) |
Timer2 | 8bit | 3pin, 11pin (PWM) | tone |
Timer0はdelay関数で使うので、これを使用できる機会はなかなか無いと思います。よく使われるのはTimer2です。今回はTimer2を使用したプログラムを書きます。
MsTimer2
Timerのライブラリはいくつかありますが、ここでは「MsTimer2」を紹介します。MsTimer2は、Arduino-IDEの[ツール]->[ライブラリを管理]からインストールできます。下記のウィンドウが開いたら、検索ボックスにmstimer2と入力すれば、下記のように表示されると思いますので、クリックしてインストールして下さい。
使い方は非常に簡単です。
①MsTimer2::set(unsigned long ms, void (*f)())
第一引数にタイマーの時間をミリ秒単位で入力します。第二引数は、タイマーの時間が経過したとき(割り込み)に呼び出す関数です。
②MsTimer2::start()
タイマーによる割り込みを有効にします。
③MsTimer2::stop()
タイマーによる割り込みを無効にします。
FlexiTimer2
FlexiTimer2は、マイクロ秒単位のタイマーを使いたい場合に使用します。
FlexiTimer2::set(unsigned long units, double resolution, void (*f)());
第一引数は時間を入力し、第ニ引数は分解能を入力します。例えば、 FlexiTimer2::set(1, 1/100000, INT)の場合、100us毎にINT関数を呼び出します。使用する場合には精度に注意が必要です。精度が出るのは40us~1000usの間だけで、それよりも短い領域や長い領域では誤差が大きという報告があります。短い領域については、マイコンのクロック周期に近づくので厳しいのはわかりますが、1000us以上で誤差が大きいのは意外でした。1000us以上の場合は、MsTimer2を使用したほうが良さそうです。
プログラム
サンプルプログラムは、1ms毎にtimerFire関数を呼び出して、timeCountをカウントアップします。timeCountは1000でクリアされます。これは、メインのloop関数とは別で動作を続けます。loop関数内では、シリアルプロッタ用にSerial.printを常時実行します。timeCountが500~600のときだけ、flagIntを100にセットします。
//www.stemship.com //2020.1.19 #include <MsTimer2.h> unsigned int timeCount = 0; void setup() { Serial.begin(9600); //1ms毎にtimerFire関数を呼び出す MsTimer2::set(1, timerFire); //タイマー開始 MsTimer2::start(); } void loop() { unsigned int flagInt = 0; if(timeCount>=500 && timeCount<600) { //タイマカウントが500~600の間だけフラグを立てる flagInt = 100; } Serial.print(timeCount); Serial.print(","); Serial.print(flagInt); Serial.println(); } void timerFire() { if(timeCount >= 1000){ //タイマーをゼロカウントに戻す timeCount = 0; } else { //1ms毎にタイマーをカウントアップ timeCount++; } }
上記のプログラムを実行して、シリアルプロッタ画面を開くと以下のようなグラフが表示されます。今回は画面で出力確認を行いましたが、flagIntを出力ポートに割り当てて、LEDを点灯させたり、音を鳴らしたりする応用ができます。
コメントを残す