topmenu

トップコンピュータカメラ雑記プロフィールこのページについて

2018/12/04

Arduino ライブラリ MsTimer2 を見る

Arduino で周辺機器のタイマを使うため(特に Nano)、ライブラリ MsTimer2 を見ていく。
Arduino では、タイマのライブラリがない(と思われる)ので、自分で記述するか、ライブラリをインストールする必要がある。
ほかにもよさそうなタイマがあるのかもしれないが、
公式サイト(http://playground.arduino.cc/Main/MsTimer2)で紹介されていたので MsTimer2 とした。
なお、オリジナルの MsTimer2 は、Javier Valencia氏によって書かれている(https://www.pjrc.com/teensy/td_libs_MsTimer2.html)。

このライブラリを使うには、先に割り込みについて知る必要があるので、かんたんにまとめる。

割り込み(Interrupt)とは

割り込みとは、その字の通りで、コンピュータが何かの処理をしているときに
その処理を中断して、別の処理が割り込んで処理を行うことである。その別の処理は、「割り込み処理」と呼ばれる。
また、割り込み処理は、さまざまな種類があり、その1つ1つを「割り込み要因」と呼ばれることがある。
なお、割り込み処理は、英語で Interrupt Service Routine (ISR) と呼ばれ、プログラムでも ISR と表現されることがある。
また、日本語では、「割り込み関数」や「割込みハンドラ」などと呼ばれることがある。

ある周辺機器で、割り込みを発生するように設定する。
設定した割り込み要因の割り込みが発生すると、それまで行っていた処理を中断し、ISR に飛んで割込み処理が行われる。
ISR が終了すると、もともと行っていた処理に戻る。

(ISR を呼び出すには、前もってプログラムで割り込みベクタテーブルと呼ばれるメモリアドレスに ISR を登録する必要があるが、
ライブラリを使うだけなら関係ないので省略。コンパイラごとに記述方法が違うのでとりあげない。)


割り込みの注意事項

割り込みが発生し続けると、その処理に CPU の演算時間がとられ、通常の処理ができなくなる。
また、ISR の処理時間が長いと通常の処理(とほかのISR)ができなくなるので、ISR は短時間で終了させなければならない。

ISR の中で、何らかの変数を使った時、メイン側の処理でその変数を参照するときには、注意することがある。
もし、メイン側で変数を読み取っているときに、割り込みが発生し、ISR 側でその変数が書き換わることがあったときには、正常に読み取れないことがある。
理由は、変数のビット数が多い(複数バイト)場合には、変数を読み取るという処理が、CPU では命令の実行が 1 サイクルで終えられないことになるからである
(ここでは、1サイクルを CPU が実行できる最小の命令時間単位する)。

変数の読み取りに 2 サイクルかかってしまうと、1サイクル目でコピーしたときに割り込みが発生したら、割り込みで変数が書き換わって
通常の処理にもどり、2サイクル目から実行される。もし、1サイクル目の値が書き換わっていたら、本来とは違う値となる。
変数の読み取りとしたが、もちろん、書き込みのときも同じことが言える。

ではどうするかというと、メイン側で割り込みに使う変数にアクセスするときには、割り込みを「禁止」する。
プログラムを言葉で表現すると、以下のようになる。

割り込み禁止命令;
割り込みのリソース(変数)へのアクセス
割り込み許可命令;

つまり、割り込み禁止命令と割込み許可命令の間に、行いたい処理を記述する。
この2つの命令は、アセンブラ言語であるが、C言語の場合には、 define 文などで定義されており、それを使うことになる。

具体的に AVR では avr/Interrupt.h の中に定義され、割り込み禁止 sei()、割り込み許可 cli()
sei(), cli()は、それぞれ SE(se-)t I(i)nterrupt flag, CL(cl-)ear I(i)nterrupt flag からであると考えられる。
AVR 以外では、seiではなく、stiと呼ぶこともあるようだ。

なお、 Arduino IDE では以下のディレクトリに存在する(zip 版を使っているので exe とは違うかも)。
(Arduino IDE インストールフォルダ)arduino-x.x.x\hardware\tools\avr\avr\include\avr

* 変数は、最適化したときに勝手に消されないように不揮発性(volatile)と明示すること。
   

ライブラリ MsTimer2

このライブラリは、タイマ2 の割り込み機能を使って、指定したミリ秒ごとに割り込みを発生させる。発生時には、指定した関数が実行される。

License: LGPL

対応するハードウェアは以下の通りである(2018.12 現在)
・works on ATmega1280 (thanks to Manuel Negri).
・works on ATmega328 (thanks Jerome Despatis).
・works on ATmega48/88/168 and ATmega128/8.

ライブラリの使い方

1.設定した時間で実行させる関数を書く。
2.タイマに時間と関数を設定する。
3.タイマをスタートさせる。

1.
実行させたい関数を記述する(戻り値と引数は void 型)。
void fuction_name(void) { 何かの処理 }

この関数は、ISR で実行されることに注意(上の注意事項を参照)。

2.
タイマに周期的に実行させたい時間(ms)と関数をセットする。set()
MsTimer2::set(10, function_name);

これで、10 ms(ミリ秒)ごとに、function_name 関数が設定される。

3.
タイマをスタートさせる。start()
MsTimer2::start();

EX. タイマを止める。stop()
MsTimer2::stop();


サンプルプログラム(Official site より)
// Pin 13 の LED を 500 ms ごとに点灯と消灯を繰り返すプログラム
#include <MsTimer2.h>

void flash() {
  static boolean output = HIGH;
  digitalWrite(13, output);
  output = !output;
}
 
 void setup() {
  pinMode(13, OUTPUT);
  MsTimer2::set(500, flash); // 500ms period
  MsTimer2::start();
}
 
void loop() {

}
割り込み処理(タイマ)を使えば、loop()内で delay する(待つ)必要がなくなり、CPU の処理時間を別の処理に使える。


ライブラリがインストールされる場所
C:\Users\(ユーザ名)\Documents\Arduino\libraries\MsTimer2

Ref.
MsTimer2 github
https://github.com/PaulStoffregen/MsTimer2

より柔軟にタイマの設定ができる MsTimer2 からフォークした FlexiTimer2 がある。
https://github.com/PaulStoffregen/FlexiTimer2