簡易レシプロカル周波数カウンター (測定周波数1Hz〜40MHz)
私の掲示板でレシプロカル周波数カウンタが話題だったので、PSoC(CY8C29466−24)で作ってみました。
レシプロカル周波数カウンタは本来、測定周波数が変化しても分解能は一定であり、市販のレシプロカル周波数カウンタは多数波長を使用して周波数を求めているそうです。前にPIC24Fで1波長をキャプチャするレシプロカル周波数カウンタを作ったことがありますが、高周波では誤差が大きくて使えませんでした。
分周した波形の時間を計ることの1次元的原理はこうです。例えば長さが正確に0.96mmの四角い物体があって、1mmまで計れる定規があるとします。1個だと約1mmだけど100個繋げると96mmとなって1個の平均は0.96mmとわかります。これが原理です。今回は入力信号が40MHzだとすると、40Mで分周して40M個波長をつなげてから12.8MHzのクロックで総時間を求めることで1波長の周波数を逆数演算により求めています。
・PSoC内部ブロック図
説明:
単にPSoCのカウンターモジュールを繋いだだけのものです。測定信号を分周して約1秒のゲート信号を作り、それを計数カウンタのENABLEに入力します。計数カウンタは外部12.8MHzクロックにて動作させていて、ゲート時間を数えています。時計カウンタは分周が終わらないときのタイムオーバー監視用です。
計算式は以下のようになります。
測定信号(Hz)=(分周値/計数カウンタ数) × 計数カウンタクロック周波数
次回分周値 = 今回の周波数の値
例えば測定信号100Hzは100分周して「1秒のゲート時間(約1秒であれば良い)」になります。周波数=分周値なので考えか方はシンプルです。端数のある周波数、例えば10.5Hzでは整数値をとって10分周とします。これにより1秒より若干少ないゲート時間になりますが、計測カウンタはゲート制御されるので問題ありません。
しかし分周によるゲート生成には問題点があって、測定信号100Hzからいきなり10Hzに変更した場合は、分周値が100なので分周が1秒で終わりません。そこで時計カウンタで割り込みを発生させ1+α秒を超えたらタイムオーバーとします。タイムオーバーとなったら、次回の分周値を1とすればこの問題は解決します。
10Hzを1分周するとゲート時間は本来の1秒でなく1/10秒になります。ここで約10Hzというのが求まります。ゲート時間を分周値で割ったものが1波長の周期なので、分周値1の1波長でも大体の周波数は求まります。次回10分周になるので、精度が上がった周波数に戻るわけです。
逆に測定信号10Hzからいきなり100Hzに上げた場合も、ゲート時間は本来の1秒でなく1/10秒となります。分周値10でゲート時間1/10秒なので結局100Hzが得られます。次回100分周になるので、精度が上がった周波数に戻ります。
ご注意 : 周波数が大きく変化中で計数ミスした場合は、精度が戻るまで回数が増えます。
これらを繰り返し、途中で周波数を変更されても自動分周値変更を行いゲート時間約1秒を保持します。ただ、前に書いたように分周値は周波数の小数部は盛り込まないため、1.5Hzなど端数のある低周波ではゲート時間は1秒を大きく下回る場合があります。それと瞬間的に周波数の微小変動があった場合、ゲート時間は1秒を前後します。
実際は分周なのでLOW、HIGH(両方とも約1秒)があり、HIGHをゲート時間としているので2秒で1回測定となります。つまり100Hzの分周値は実際は200となります。タイムオーバーは2+α秒です。
・PSoC内部モジュール構成 (クリックすると大きくなります)
・プロパティ(赤丸は変更場所)
|
・ソフトウエア手順
1)初期値セット後、全カウンタ始動2)分周カウンタの分周終了の割り込みまたは、時間カウンタの割り込み(タイムオーバー監視用)を待つ
3)割り込みがきたら、全カウンタを止めてカウンタ値を読む
4)計数カウンタの値から演算で周波数を出し表示
5)次回分周値を計算、もしタイムオーバーしていれば次回分周値は1にする。
6)1へ戻る
・できあがり写真 (クリックすると大きくなります)
Asa工房さんのPSoC汎用基板(ASA-001-PSoC/PR232)を使用しました。
・動作結果(上の写真)
40MHzのTTLパルスを入力したところです。1Hz〜40MHzまで追従しました。
液晶の上の段は、計数カウンタ数、下の段は演算した周波数です。
下の7SEGは市販の周波数カウンタの値で、直接計測のカウンタ入力を使いました。
・感想
C言語で作成しました。
PSoCで初めてプログラムを作りましたが、ほとんど自動生成されるので楽です。カウンターの関数も用意されているのでPSoCを詳しく知らなくてもいきなり動いてしまいます。私はmain.cを作るだけでした。割り込みもC言語側の個別の割り込み先の関数を用意するだけです。
ちなみにPSoCのカウンタモジュールはこんな感じで使えます。 Counter32_1_WritePeriod(999); Counter32_1_WriteCompareValue(500); Counter32_1_Start(); Counter32_1_Stop(); Counter32_1_ReadCounter(&count); |
表示には桑野さんのprintf関数を使用させていただきました。感謝します。
・将来の改造希望点
周波数演算の計算の桁落ちが心配です。PSoCではdoubleもfloatなので有効桁が6、7桁(内部は8桁か?)になってしまいます。桁数を増やすためには64ビット浮動小数演算のルーチンが必要だとおもいます。
・プロジェクトファイル(PSoC Designer 5.0 SP5.5にて作成しました)
reciprocal_fcounter20090908.zip new 2009.09.08
|
|
●情報収集
重要情報 |
『PSoC Designer5.0 SP5にて外部クロックを設定しても、動作しない』 SP5.5でもまだ直っていません。やはりSP6まで直らないのでしょう。 |
|
『Designer5.0にてSDカードユーザーモジュールが使えない』 SDカードモジュールが削除されています。 SD card user module in System Level and Chip Level designs |
データシート |
|
お店 |
●デジタルブロックの最大周波数
CY8C29466のデータシートのTable11-22にある情報では、
カウンタ周波数は49.2MHzまで対応してる。