おお、10Mhzまでなら楽々測定できる。10Mhzがほぼ測定限界で、11Mhzではかえって周波数が落ちる。計算を楽にするため切りの良い時間を作るのに良いタイマーの設定が見つかった。CPUクロック20Mhzで、8bitタイマーのプリスケールを64にしてTickを3.2μsにすると、122回(256×122×3.2=99.9424ms)まわした端数が18(0.0032×18=0.0576ms)できっちり、0.100秒になる。クロックが正確ならどこまでも0.1秒である。オシロとの周波数の誤差は全くなかった。普及品なのに立派なものである。少なくともオシロの表示する数字とは完全に一致している。1桁ほどこちらのほうが細かい。前にも書いたように、あくまでも周波数測定ではなく、シグナルジェネレーターの周波数表示用のために作っている。早いタイミングで計測をしたい。すると分解能を上げるためには、前に作ったレシプロカル方式のロジックを併用する必要がある。どのあたりでこの直接計測に切り替えるか、レシプロカル方式の測定期間をどの程度にするか、調べなければならないことが沢山でてきた。レシプロカル方式は、どれだけ細かい時間まで計測できるかが、有効桁数を上げる決め手になるので、CPUのタイマーをプリスケールなしの最高速で動かすことにする。有効桁数を上げるため大きな数字を取り扱おうとすると、計測時の変数は簡単に2バイトの上限(65535)を超えてしまう。4バイトデータのやりとりは2バイトのときよりはるかにステップを喰うので使うわけにはいかない。測定期間や最大測定カウント数が決まってきた。プログラムロジックは最初のプログラムとほぼ同じで、パラメーターを変えるだけだったので、プログラムはすぐ動き始めた。バイトどまりでLCDに切り替えても何とか入りそうである。UARTに直接計測で出した周波数と、新しいレシプロカル方式で出した周波数を並べて表示し、テストに入った。測定範囲が5Hz(レシプロカル方式の測定期間による下限)から、500Khz(I/Oポート入力を繰り返すループロジックの上限)ととんでもなく広いので、チェックしていくのに時間がかかる。最初にでてきたデータは、あっているところが少しある程度で、どこも全部違っていた。計測の方は、10Hzの分解能ながら見事に10Mから低周波まで、オシロが出す周波数と一致している。それに対して、レシプロカルは不安定極まりない。同じ周波数でも測るたびに違うし、第一合っていない。バグをつぶしていこう。分かったのは、タイマーオーバーフローのキャリーフラグ上げと測定時とのタイミングの違いによるミスである。タイマーをCPUのクロックと同じ最速(0.05μs)で動かしている。測ったときとタイムアウトしたときのキャリーを一致させるため、やりたくなかったが、ループの中に時間記録と同時にキャリーも保存するステップを加える。不正確になる現象である。これは、UARTに途中経過の変数を逐一表示させ、数字をチェックして、4バイトのデータの桁あふれを見つけた。4バイトは10進数で9桁あるのだが、計算の段階の、ある変数の範囲で10桁になることが分かった。マイクロセカンドの世界なので通常の数が6桁、除算は乗算より桁を取らないとはいえ、うまく分割して計算しないと、32ビット(4バイト)でも難しい。周波数を出すのに一回の計算ではできないので、始め3回分けて計算していたのを工夫して2回に減らしていたがその配分がまずかった。WINAVRで64ビット変数が使えることを発見し、喜び勇んで入れてみたら、フラッシュサイズがいきなり5Kを超えて唖然とする。ロジアナさまさま(11/01/08)細かいバグを追いこんで、段々レシプロカル方式も精度が上がってきた。キャリーの食い違いによる誤った周波数表示は稀にだが起きるし、周波数が低くなると全く不正確になる。一回分パルスをミスしているようである。2回に分けた計算法も自信がない。Webに助けを求めるが、出てくる記事は、大掛かりな多倍長演算の手法ばかりで、こうしたちょっとした多数桁の計算のヒントになるようなものはない。低周波が不正確なのは痛い。計測では1秒測らないと最小桁が出ないので、このあたりはレシプロカルに頼るしかないのだが、これが安定しない。こんな低い周波数のところで、1周期見逃すはずがないのだが、結果は見逃した形になっている。キャリーの食い違いは、どうしても起きることがあるので、とうとう計測ループの中に割込み禁止命令を挿入して対処した。これで最大測定周波数は500Khz以下に下がってしまったが背に腹はかえられない。低周波の方は万策がつきた。ロジックアナライザーの登板をあおいだ。ソースの上では数命令先だが、もしかしたら意外な時間をとっているのかもしれない。割り込みがかかって別のところにいくのかもしれない。実際に確かめてみようと言うのである。要所、要所に、ピンをドライブするsbi(PORT,PIN)などの命令を挿入し、そのピンにロジアナのプローブを接続して動かしてみた。机上には、オシロ、シグナルジェネレーター、ブレッドボード、アッテネータ、ロジアナなど所狭しと機材が並ぶ。いくつか挿入ポイントを変えてテストするうち驚くべき事実が明らかになった。測定期間にはいったあと、最初のパルスを確かに一回見逃しているタイミングチャートがでてきたのである。ほんとだ、タイムアウトのときに何かおかしくなると予想していたが、最初でまるまる1パルスをとっていない。