まじめにコードを追ってみる事に。arduinoの
MsTimer2の件。
まずはarduinoコアの元々のタイマー関係処理について
どうなっているのかを整理。コードを追ってみた結果
はこんな感じです。
[TIMER0関係の処理]
・初期化処理にて、高速PWMに設定(ここ注意)
・オーバーフロー割り込み処理は1024us(16Mhz時)もしくは
2048us(8Mhz時)ごとに1回発生に設定
・オーバーフロー割り込みをオン
とした上で、
16MHZの場合
・割り込み発生ごとに「ミリ秒」を1カウントアップ…(a)
・併せて、24usの誤差を蓄積
・誤差がミリ秒単位に達している場合、(a)に加えて
1カウントアップ
→1ミリ秒より少し長い時間ごとに「ミリ秒」がカウント
アップされていくが、蓄積誤差が1ミリ秒に達した時
にはいっぺんに2ミリ秒カウントされる
(およそ41~42回のオーバーフロー割り込みごとに
2ミリ秒カウントされるケースが発生する)
8MHZの場合
・オーバーフロー割り込み処理自体は2048usごとに1回発生
・割り込み発生ごとに「ミリ秒」を2カウントアップ…(b)
・併せて48usの誤差を蓄積
・誤差がミリ秒単位に達している場合、(b)に加えて
1カウントアップ
→2ミリ秒より少し長い時間ごとに「ミリ秒」がカウント
アップされていくが、蓄積誤差が1ミリ秒に達したとき
はいっぺんに3ミリ秒カウントされる
(およそ20~21回のオーバーフロー割り込み毎に3ミリ秒
カウントされるケースが発生する)
16MHZ、8MHZどちらも、長時間に渡って誤差は1クロック
単位で累積しないまた、PWM(アナログ出力)とタイマー
割り込みが両立する様に設定されている
[TIMER1関係の処理]
・位相補償PWMを使用(ここ注意)
・割り込みは使用しない
・プリスケーラ値64でフリーラン
・入出力ピンはノーマル動作状態(PWMの出力が未接続)
(注)TCCRxAの値はイニシャル値=0のため、初期化の
直後は入出力ピンにはPWMの出力が取り出されて
おらず、普通のデジタルI/Oになっている
ということで、タイマー0についてはアナログ出力用の
設定を行いつつミリ秒ごとに経過時間を計測している
けど、瞬間的には最大で1ミリ秒(8Mhz機の場合2ミリ秒)
ほどの誤差が生じている可能性がある…ということに
なります。ただ、誤差は蓄積していかず、こまめに補正
されています。
仮にタイマー0のミリ秒計測…millis() 関数…を使って
時計を作るとしたら、理論上は1ミリ秒の誤差が瞬間的
に生じるけど、蓄積誤差は水晶発振の1クロック単位で
ゼロということになります。
なお、タイマー2も初期化時にPWM(アナログ出力)の設定を
行いつつ、I/Oは通常のデジタルI/Oのままとなっています。
さてこれらを踏まえ、MsTimer2ライブラリを取り込むと
どういうことになるのか…
[MsTimer2の処理]
・プリスケーラは16Mhz時8Mhz時とも64に設定(変化無し)
・位相補償PWMに設定(変化無し)
としてから、MsTimer2::start() にて
・オーバーフロー割り込みを許可
・割り込の都度TCNT2をプログラム上でクリア(※要注意)
・指定したミリ秒経ったか判断して、経過していれば
指定の関数を呼び出し
という感じです。オーバーフロー割り込みが発生してから
TCNT2のクリア処理を行うまでに64クロック以上経過
している場合、やはり遅延を生じることとなり、この
遅延は時間経過にしたがって蓄積していきます。
(長くなってきたので次の記事に続きます)
(追記:MsTimer2は位相補償PWMじゃなくて、ノーマル
タイマーですね…訂正してお詫びします)
|