本題に入る前に少しお話があります。
以前、一定周期で処理を実行するためのスケッチ(ソースコード)を掲載したことがありますが、あのスケッチはやっつけなのでかなり問題があります。
delayを使用して時間調整を行なっていたため周期の精度が悪かったり、オーバーフローが発生するとおかしな挙動が発生したりします。
オーバーフローの方は簡単な演算で解決可能なのですが、精度の悪さはどうにも解決できませんでした。
フィードバックをかけて誤差を少なくしようと色々やってみたのですが、誤差を20マイクロ秒以下に抑えることができませんでした。
タイマ割り込みを使用せずに頑張った理由としては、外部のライブラリを使用せず、Arduinoの開発環境に標準で付いている機能のみでやってやろうという発想からでした。
ふと気が付いてみたら時間調整を行う処理だけで、それなりに行数を食ってしまいなんとも微妙な状態になってしまいました。
そこで、Arduinoの公式サイトにも掲載されているタイマ割り込みライブラリを使用して、タイマ割り込みを利用した周期処理を行うことにしました。
MsTimer2というライブラリで、以下のリンクに詳細が載っています。
ダウンロードしてArduinoの"libraries"フォルダに突っ込めば準備完了です。
サンプルコード(FlashLed")も付いているので、開発環境を立ち上げ早速実行してみます。
500msec毎にLEDが付いたり消えたりするはずです。。。はずでした。
試してみると分かりますが、ATmega2560が搭載された新しいArduino MegaではMsTimer2は使えません(2012/02/03現在)。
何故なのかというと、MsTimer2のソースコード"MsTimer2.cpp"の中で、CPU毎に処理が書かれているのですが、悲しいことにArmega2560の処理が無いからです。
しかし、ちょっといじるだけで使えるようになります。
"MsTimer2.cpp"の
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__) || (__AVR_ATmega2560__) |
と書き換えるだけです。
見にくいので、変更する場所だけを言うと
|| (__AVR_ATmega2560__)
を追記するだけです。
これで、Armega2560が搭載されたArduino Megaでもタイマ割り込みの処理が実行されます。
何故これだけで良いかというと、Armega2560はATmega1280のメモリが増えただけなので、レジスタの変更などは有りません。したがって、処理の内容はATmega1280のままで良いことになります。
再度、サンプルコードを実行してみると、今度はちゃんとLEDが付いたり消えたりするのが確認できると思います。
周期の精度はタイマ割り込みなので、言うこと無しです。
一定間隔で処理をする時は、こんな感じで書きます。
周期の精度はタイマ割り込みなので、言うこと無しです。
一定間隔で処理をする時は、こんな感じで書きます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <MsTimer2.h> | |
/* タイマ割り込み間隔 */ | |
#define TIMER2_INTERVAL (unsigned long)500 | |
/* タイマ割り込み */ | |
void timer2interrupt() { | |
/* 何か処理 */ | |
} | |
void setup() { | |
Serial.begin(115200); | |
MsTimer2::set(TIMER2_INTERVAL, timer2interrupt); | |
MsTimer2::start(); | |
} | |
void loop() { | |
/* 何もしない */ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <MsTimer2.h> | |
/* タイマ割り込み間隔 */ | |
#define TIMER2_INTERVAL (unsigned long)500 | |
#define LOCK 1 | |
#define UNLOCK 0 | |
volatile int lock = 0; | |
/* タイマ割り込み */ | |
void timer2interrupt() { | |
lock = UNLOCK; /* ロック開放 */ | |
} | |
void setup() { | |
Serial.begin(115200); | |
MsTimer2::set(TIMER2_INTERVAL, timer2interrupt); | |
MsTimer2::start(); | |
} | |
void loop() { | |
if( lock == UNLOCK ){ | |
/* 何か処理 */ | |
lock = LOCK; | |
} | |
} |
タイマー割り込みが使えなく、困っていたところ偶然見つけました。
返信削除おかげさまでMEGAでも動作するようになり、助かりました。
本当にありがとうございます。
分かりやすかったです。
返信削除ありがとうございます。