« 300kHzのセラミック発振子:Tele Auto FX-1 修理 | トップページ | ArduinoのanalogWrite 1/255なの? »

2020年2月 4日 (火)

Arduinoのタイマー OCRレジスタは「n」じゃなく「n - 1」の値を設定せよ

ミスが広まる 1/1023 vs 1/1024は、Arduino-UNO(ATmega328pマイコン)
のA/Dコンバータ・スケーリングのお話しでしたが、今回はタイマーのコンペアマッチ
レジスタのお話しです。

Arduinoのタイマーを直接操作する時(例えばMsTimer2などのタイマー
ライブラリーを使わずにタイマー割り込みを使いたい時など)、CTCモードで
アウトプットコンペアレジスタにタイマーの最大カウント値を設定します。
Arduinoから「タイマー0」を取り上げる(ユーザーが使う) では
「1m秒」割り込みを例にしました。
1msつまり1kHzの割り込み周期を得るには、
 ・CTCモードに。 (コンペアマッチでカウンタゼロクリアー)
 ・16MHzのクロックをプリスケーラーで1/64して250kHzに。
 ・それを1/250して1kHzに。
この1/250するのがアウトプットコンペアレジスタへの設定です。
↑の例では
   OCR0A = 250 - 1;    // 250カウントで1kHzを
の所。
1/250なんで「250 - 1」を設定しています。
これをミスして「-1していない」プログラム例や解説を見かけるのです。

なぜ「n - 1」なのかは、このタイミング図を見れば分かるかと。
A1_20200204115801
TOP値がOCR:コンペアレジスタへの設定値。
そして、CTCモードだとBOTTOM値はゼロになります。
TOP値を検出した次のサイクルがゼロとなるわけです。

例えば「1/4」したい時、TOP値つまりコンペアレジスタの値を
「4」にしてしまうと・・・
0 1 2 3 4  0 1 2 3 4  0・・・」と繰り返しが「5」になってしまいます。
TOP値としてOCRに設定するのは「カウント周期 - 1」でなければいけません。
「-1」しないと、「1/4」が欲しいのに「1/5」になってしまうという
スカタンが発生します。

これに気付かない原因の推測ですが、
・とりあえず、それらしい動きをしてるから。
・16ビットタイマーであるタイマー1に対して、大きな値をセットしてる。
 そのままの値と-1した場合とで、タイマー周期にほとんど違いが出ない
 から気がつかない。
・8ビットタイマーでも、ミスを測定する手段を持ってない、あるいは
  積極的に結果を計ろうとしていない。
   ※周波数カウンタやオシロスコープなどの測定器をつなぎ
    テストパルスを出せばすぐに気がつくはず。
・ハードウェアの非同期カウンタを思い浮かべている。
   ※1/10カウンタなら、7→8→9→[10=0]→1→2→
    と、10検出で直ちにリセットされて0になるので。

こんなところかと。

※見かけたミスの例
ArduinoのTimerを初心者が1からなんとなくわかるためのメモ - Qiita
  16MHzクロックを1/256し、「OCR1A = 62500;」として「1秒」としている。
Arduinoでtimerを使った割込み処理の方法 ? 自作のいろいろ
  「OCR2A=100; //100カウントごと(50μs)毎」と。。。
Timer1 - FreeStyleWiki
  ちょっと違う。
タイマー割り込みを使う - arduino始めました
  惜しいような。。。
Timer0 & 1
  アセンブラでもミス。

多くの正しい解説もありますが、ミスしたのが目立っちゃいます。

そして、もうひとつ気になるのが割り込み処理内で走らせるプログラム。
「呼んですぐに戻ってくる関数」が基本。
そして、それがメインの処理とぶつからないこと。
他の割り込み処理に影響(長い時間待たせる)を与えてもダメ。
割り込みの中で「Serial.println(xxx)」を使ってる例を見かけるのですが、
これはいかがなものかと・・・。


|

« 300kHzのセラミック発振子:Tele Auto FX-1 修理 | トップページ | ArduinoのanalogWrite 1/255なの? »

Arduino」カテゴリの記事

コメント

注目されてます。
PIC AVR 工作室 ブログ:あぁ、タイマーの設定値、-1するの忘れがちなんだ
よなぁ。
https://brown.ap.teacup.com/nekosan0/4150.html

投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年2月 9日 (日) 21時57分

コメントを書く



(ウェブ上には掲載しません)




« 300kHzのセラミック発振子:Tele Auto FX-1 修理 | トップページ | ArduinoのanalogWrite 1/255なの? »