秋月で 120 円で購入した STM32G031J6M6(SOP8)で作ったレシプロカル周波数カウンターです。
8ピンという制約のなかで何ができるのかを考えるのはパズルのような面白さがありました。
・外観

・上面
10MHz を測定しているところです。
基板は 38 x 38 です。
信号入力 BNC、5V 電源コネクター、電源 SW、入力 SW 2個、
LCD 接続コネクター、ST-LINK コネクターがあります。
LCD とは i2c で接続しています。

・裏面
変換基板にのった STM32G031J6M6( SOP8 ) が見えます。
他は、TCXO(26MHz)、入力アンプ、3.3Vレギュレーターなどです。
ハードウェアはできるだけ簡略化してみました。
LCD には i2c 変換基板 ( PCF8574 ) がついています。
i2c 変換基板は Amazon や Aliexpress で購入できます。
PCF8574 ( DIP ) は秋月でも購入できるようです。
・操作方法
2 個の SW の短押し、長押しに、いろいろな動作を割り当てています。

・通常動作モード
LCD 1行目は周波数表示、
2行目にプリスケーラー倍率、温度、ゲート時間が表示されます。
SW 短押しで、ゲート時間を +/- します。
ゲート時間は、0.1s, 0.2s, 0.5s, 1s, 2s, 5s, 10s が選べます。
左右どちらかの SW 長押しで、メニューモードに入ります。
左右どちらかの SW 長押しでメニュー ↓ ↑ 左 SW 長押しで戻る

・メニューモード
LCD 1行目は周波数表示、2行目に項目名が表示されます。
SW 短押しで、項目を +/- します。
左 SW 長押しで、通常動作モードに戻ります。
右 SW 長押しで、項目を選択/実行します。
右 SW 長押しで選択 ↓ ↑ 左 SW 長押しで戻る

・例えば、1.AUTO F.ADJ を実行した場合は左画面のようになります
SW 短押しで、設定値を +/- します。
左 SW 長押しで、メニューモードに戻ります(設定は保存しません)。
右 SW 長押しで、設定を保存して通常動作モードに戻ります。
ここで保存した設定は起動時に読み込まれます。
この他の項目でも同様の操作になります。
| 項目 |
説明 |
| 1.AUTO F.ADJ |
測定周波数が、1, 10, 100, 1k, 10k, 100k, 1MHz から 1Mステップで 100MHz まで、のとき周波数自動調整をします。 調整値は 10ppb(0.01ppm) 単位です。 上の例では -1237 なので -12370ppb(-12.37ppm) に調整しています。 自動調整後、調整値を追加で +/- できます。 周波数表示は測定のたびに調整された値になります。 GPS の 1PPS でも自動調整できます。 |
| 2.FREQ ADJ |
周波数調整値を +/- します。 |
| 3.DIGITS |
周波数表示桁数を± 1 増減します。 +1 または -1 のときは、通常動作モード時 LCD 2 行目右端に +、- マークがつきます。 |
| 4.PSC DIV |
外部にプリスケーラーをつないだ場合、x64、x128、x256、に設定します。 通常動作モード時、LCD 2 行目左端に倍率を表示します。 |
| 5.COMMA |
3 桁ごとの区切りカンマを 10 種類から選択します。 設定は周波数表示に反映されますので好みのものを選びます。 |
| 6.DISP HOLD |
測定信号がなくなった場合、表示を消すか、前の測定値をホールドして表示するか選択できます。 ホールドにした場合、周波数表示の左端に H がつきます。 |
| 7.XTAL |
TCXO の周波数を表示します。 TCXO は、10MHz, 13MHz, 20MHz, 26MHz が使用でき、起動時に周波数を自動判別します。 自動判別に失敗した場合は 0 を表示します。 |
| 8.VERSION |
ソフトウェアバージョンを表示します。
|
起動時にどちらかの SW を押していると設定を読み込まずデフォールト設定になります。
・STM32G031J6M6
使用した STM32G031J6M6(SOP8)には、まるで周波数カウンターを作ってくださいと言わんばかりの以下の特徴があります。
1. LPTIM は CPU とは非同期のカウンターとして使え、実測 400MHz までカウント可能
2. TIM1 は 128MHz まで使用可能 ( 他の TIM は CPU クロック周波数まで )
3. マルチボンディングで複数パッドが同一の端子につながっている
( ①、④、⑤、⑧ピンそれぞれに 4 本ずつマルチボンディングされているようです )
分周器 ( PRE-DIV ) として LPTIM を使い、高速 Timer として TIM1 を使えば高性能なレシプロカルカウンターがつくれそうです。
STM32G031J6M6(SOP8)のピン配列です。
8 ピンの中で、①OSC_IN、②電源、③GND は完全に固定、⑦SWDIO、⑧SWCLK は固定ですが ST-LINK を邪魔しなければ共用可能です。
つまり自由に使えるのは ④~⑥ の 3 本しかなく、⑦ ⑧ の共用可能ピンを合わせても 5 本しか使えません。
一方、レシプロカル周波数カウンターを作るには、
- 信号入力 ( LPTIM 入力 )
- LPTIM 出力
- 高速 TIM1 入力
- 低速 TIMx ( できれば 32bit の TIM2 ) 入力
- SW 入力用 ADC 入力
- i2c 接続用 SDA, SCL の 2 本
の、計 7 本が必要です。
できれば、デバッグ用シリアル通信ポートや LED ポートも欲しいところですが、それどころじゃありません、諦めます。
・まず LPTIM 入力ですが、これは PB5 にして ⑧SWCLK と共用にします。
・LPTIM 出力は⑤ピン PB0 にします。
高速 TIM1 入力は PA8 が⑤ピンにマルチボンディングされているのでこれを使います。
低速 TIMx 入力は同様に⑤ピンにマルチボンディングされている PB1 TIM3(16bit) を使います。
本当は低速 TIMx には 32bit の TIM2 を使いたかったのですが仕方ありません。 ソフトウェアで頑張ります。
・SW 入力用 ADC は⑦SWDIO と共用にします。
( ハイインピーダンスの ADC 入力と⑧高速デジタル信号線を隣り合わせにするのは良くないのですが...)
・i2c の 2 本は④ピン、⑥ピンに割り当てソフトウェア i2c にします。
マルチボンディングを駆使し、ST-LINK とピンを共有にしてやっとすべてのピンが割り当てられました。
仕様書を見ながらどのピンのどの機能を使うか、本当にパズルのようでした。
・レシプロカルカウンターの周波数計算方法
ピンのアサインと使用する TIM が決まりましたので、次はこれを使ってどうやって周波数を測定するのかソフトウェアを考えます。
・カウンターブロック図
信号は最初に BF862 の PRE-AMP で約 5 倍増幅します。
増幅した信号は⑧ LPTIM1 に入り、100Hz 程度になるように分周します。
分周出力は⑤に出力され、同時に TIM1 と TIM3 で capture します
高速 Timer ( TIM1 ) は 130MHz、低速 Timer ( TIM3 ) は 31.738kHz ( = 130MHz / 4096 ) でカウントアップしています。
PRE-DIV ( LPTIM1 ) の分周比を P とします。
高速 Timer ( TIM1 ) の オーバーフロー回数を X とします(未知数です)。
高速 Timer ( TIM1 ) での前回 capture とのカウント差を N とします。
低速 Timer ( TIM3 ) での前回 capture とのカウント差を M とします。
高速 Timer から得られる⑤ピンの周期
T1 = ( N + 65536 * X ) / 130MHz
低速 Timer から得られる⑤ピンの周期
T2 = ( 4096 * M ) / 130MHz
ここで T1 ≒ T2 なので、これを X について解くと
X = ( 4096 * M - N + 32768 ) / 65536 (注) 32768 足しているのは四捨五入して整数にするため
⑤ピンの周波数 = 1 / T1 なので、
⑧ピンの周波数は、
Freq = P * 1 / T1
= P * 130MHz / ( N + ( ( 4096 * M - N + 32768 ) & 0xFFFF0000 ) ) (注) & 0xFFFF0000 は / 65536 * 65536 と同じ
と計算できます。
周波数カウンターとしてまとめるには、P をどうやって決めるか、途中で周波数が変わったときどうするかなどを考慮する必要があります。
また、低速 Timer が 16bit なのでこちらもオーバーフローカウントが必要になりました( 約 2 秒でオーバーフローする )。
振り返ってみると、デバッグ用シリアル通信ポートや LED ポートがないので机上デバッグするしかなく、大変でした。 RFC-4 で作ったプログラムの移植だったのでなんとかなりましたがスクラッチからだと不可能だと思います。
2022/11/17 追記
レシプロカル周波数カウンターは周期を測定して、周期の逆数に分周比を掛けて周波数を計算します。
RFC-5 では測定信号を分周して約100Hzにしていますが、測定する周期はさらにソフトで分周してだいたいゲート時間になるようにしています。
周期の測定はTIM1のキャプチャーで行われ、ここでの誤差は±1カウントです。
TIM1のクロックが130MHzなので±1カウントの周期測定誤差は±8nsになります。
周期≒ゲート時間なので、たとえばゲート時間が0.1sならば、カウント測定誤差≒±8ns÷0.1s=80e-9(80ppb) になります。
測定誤差は、ゲート時間によって変化し以下のようになります。
| ゲート時間(s) |
カウント測定誤差 |
| 0.1 |
80ppb |
| 0.2 |
40ppb |
| 0.5 |
16ppb |
| 1 |
8ppb |
| 2 |
4ppb |
| 5 |
1.6ppb |
| 10 |
0.8ppb |
このように、レシプロカル周波数カウンターではカウント測定誤差はゲート時間だけで決まり、ゲート方式周波数カウンターのように測定周波数で変化しません。
PULSE GENERATOR ( 以下、PG と表記 ) 機能を追加しました。
とは言っても周波数カウンターと同時動作できないので、あくまでおまけにすぎません。
ちょっと信号が欲しくなった時に便利に使えたらと思っています。
PG 出力は⑤ピンです。 使う場合はバッファを外付けするか、適当な抵抗を直列に入れてください。
・PG 操作方法

・周波数カウンター通常動作モード
左 SW 長押しで、 PG モードに入ります。(変更点)
右 SW 長押しは、 以前と同じく周波数カウンターのメニューモードに入ります。
左 SW 長押しで PG モード ↓ ↑ 左 SW 長押しで戻る

・PG モード
LCD 1行目は PG と周波数表示、
2行目に周波数ステップ、duty が表示されます。
SW 短押しで、選択された項目 ( ▶ ) を +/- します。
左 SW 長押しで、周波数カウンター通常動作モードに戻ります。
右 SW 長押しで、周波数 → 周波数ステップ → duty を順に選択します。
・周波数は 1Hz ~ 50MHz( 実際は65MHzを出力 ) まで設定できます。
・周波数ステップは 123..、1-2-5、1-10 モードが選べます。
・duty は 5%、10%、25%、50%、75%、90%、95% が選べます。
TIM1(130MHz) の PWM モードを使用しているので、出力できない周波数、duty の時は、近い値で出力します。
SW 短押しで項目を +/- したときは設定値を表示しますが、1秒後、実際に出力している周波数、duty の表示になります。
左画面では、20MHz, duty=25% に設定しましたが、
実際には 21.666MHz, duty=33% を出力していることを示しています。
これは 1/130MHz の整数倍のパルス幅しか出力できないためで、
周波数が高いほど設定値と実際の出力値とのずれが大きくなります
20MHz 設定では 6 分周になるので 130MHz/6=21.666MHz、
6 クロックのうち 2 クロックを H にして duty=2/6=33% になります。
外付けの 20dB アンプをつくりました。
周波数カウンターの感度が低め(ゲイン 5 倍)なので、もうちょっとゲインがあれば、という時につないで使えます。
約 300MHz と広帯域、低雑音なので、何か実験している時にプリアンプが欲しい、といった時にも便利に使えます。
・回路
回路は、BF862 のアンプに 2SC3356S のベース接地、エミフォロを組み合わせたものです。
BF862 のドレイン電圧が固定されるため広帯域になります。
周波数特性は、上図 R1 と Q1 2SC3356S のコレクタ容量 + Q4 のコレクタ容量 + C1(浮遊容量)で決まります。
ゲインは、(BF862 の gm) * R1 になります。 ゲインを大きくしようと R1 を大きくすると周波数特性が落ちることになります。
試作するときは J2 BF862 の IDSS のばらつきで動作点が動くので、BF862 のドレインが 2V 程度、Q1 2SC3356S のコレクタが 3.5V 程度であることを確認します。
大きくずれている場合は、R11 を増減して合わせます。
・
NanoVNA-V2(S-A-A-2) でゲイン周波数特性測定
P1 から ATT20dB を通してアンプ入力に繋ぎます。
アンプ入力を 50Ω にするため 49.9Ωの抵抗を付け、
「 1k + 51Ωで分圧するプローブ」で P2 に繋いで THRU CAL を取ります。
出力から「 1k + 51Ωで分圧するプローブ」で P2 に繋ぎ S21 を測定します。
測定結果
10MHz 19.26dB
100MHz 18.71dB
200MHz 17.50dB
300MHz 16.29dB
400MHz 14.34dB
500MHz 10.48dB
-3dB 帯域は約 300MHz となりました。
外付け 20dB アンプの周波数特性を改善したものを試作してみました。
こんな回路が正常に動くか心配だったのですが、発振もせず意外と安定動作しています。
シミュレーションでは少ししか改善しなかったのですが実測では大幅に良くなり約 500MHz となりました。
・回路
追加したのは回路図の赤で囲ったところです。
周波数特性は、R1 と Q1 のコレクタ容量 + Q4 のコレクタ容量 + C1(浮遊容量)でほぼ決まります。
今回の回路では Q4 のコレクターに L1、Q3 とその周辺回路を追加して、Q4 のコレクターの交流電圧をベースと同相・同電圧にすることで、
Q4 のコレクタ容量をキャンセルして周波数特性を改善しています。
コレクター交流電圧がベースと同相・同電圧のときコレクター容量が見かけ上キャンセルされることを使っています。
コレクター交流電圧がベースと逆相の時はコレクター容量が見かけ上大きくなり、これを
ミラー効果といいます。
今回の回路は逆ミラー効果回路といったところでしょうか。
実際には L1 はインダクターではなくフェライトビーズ(120@100MHz)を使いました。 数百Ωのフェライトビーズなら使えると思います。
R5、R7 は発振止めです(発振したわけではないのですが...)。
・
NanoVNA-V2(S-A-A-2) でゲイン周波数特性測定
出力に「 1k + 51Ωで分圧するプローブ」をつないで測定しました。
-3dB 帯域は約 500MHz となりました。
シミュレーションより大幅に良くなったのは浮遊容量が想定より小さかったのかな
と思っています。
あとはシミュレーションモデルが良くないとかでしょうか。
なんにせよ高周波回路は実測して確認しないといけないですね。
上記のように 1kΩ 負荷のときは周波数特性が良いのですが、50Ω 負荷のときは 292MHz と大幅に落ちました。
2SC3356 は ft=7GHz なので高周波では hfe=7000/freq( たとえば 350MHz では 20 )に低下します。
エミフォローの出力インピーダンス = 入力抵抗/hfe + re なので、周波数が高くなると出力インピーダンスが大きくなります。
周波数が高くなるにつれ Q4 エミフォローの出力インピーダンスが大きくなるので、50Ω 負荷のときはエミッターの交流電圧が落ち、
つられてコレクターの交流電圧も落ちるので、コレクター容量キャンセルが効かなくなってくるのではないかと推測しています。
周波数カウンターのようなハイインピーダンス入力につなぐことを想定したアンプなので、
50Ω 負荷で周波数特性が落ちても問題はないのですが、ここまで変化するのは予想外でした。
・500MHz 低雑音アンプのノイズ特性測定 2023/11/13 追記
アンプのノイズを測る前に、まずはローノイズ電源を用意しないといけません。
このアンプは PSRR( 電源の影響の受けにくさ )が 10dB ぐらいしかなく、電源のノイズが -10dB(0.3倍)されてアンプ出力に出てきてしまいます。
測定しようとしているアンプのノイズ密度が 1nV/√Hz ぐらいと想定されるので、電源にも 1nV/√Hz 以下のローノイズ電源が必要です。
普通の電源( 安定化電源やレギュレーター IC )の出力はだいたい 100nV/√Hz 以上のノイズがありますので、
この電源出力をリップルフィルター( ノイズフィルター )に通してローノイズ電源を作ります。
一般的なリップルフィルターは Tr のベースに RC フィルターを入れ、エミッターから出力する回路ですが、電圧ドロップが 0.8 ~ 1V 程度と大きい欠点があります。 できれば 5V 電源を昇圧したりせずそのまま使いたいので、電圧ドロップの小さい回路にします。
これが今回採用したリップルフィルターです。
負荷 46mA( 500MHz アンプを接続 )時の電圧ドロップが実測 0.19V と小さく、今回の用途には最適です。
このリップルフィルターでは入力ノイズを反転増幅し、元のノイズから引き算してキャンセルしています。
反転した電圧が同じでないとキャンセルされないので、hfe のばらつきに敏感です。
hfe が 2 倍ばらつくと最悪 20dB 程度しかノイズを落とすことができません。( 低周波から落とせるので 20dB でも良いという用途はありそうですが...)
そこで試作では回路図の R10 100kΩ を半固定抵抗 200kΩ に変えて調整しました。
C3 が 120uF と変な値なのは手持ちの部品都合です。 100uF でも 220uF でもかまいません。
Q4 2SC2412R は 2SC1815GR と同じような特性の小信号用汎用 Tr です( これも手持ち部品都合で採用 )。

リップルフィルターを通す前( 安定化電源の出力ノイズ )と
通した後のノイズ密度測定結果です
ゲイン 60dB の
測定用ローノイズアンプ LNA-4 を入れていますので
0dBu/√Hz が 1nV/√Hz になります。
リップルフィルターを通す前は 100nV/√Hz 以上あったノイズが、通した後は 200Hz 以上の周波数で 1nV/√Hz 以下になっています( 測定限界が 0.35nV/√Hz で、リップルフィルターは -70dB @1kHz なので 1kHz 以上ではもっとノイズは小さくなっていると思われます )。
残念ながら 100Hz、150Hz の電源ハム成分がまだ残っています。 C3 や C4 をもっと大きくした方が良かったかもしれません。
やっとローノイズ電源が用意できたので 500MHz アンプのノイズを測ってみます。

500MHz アンプの 20dB +
測定用ローノイズアンプ LNA-4 の
60dB で合わせて 80dB のゲインになっていますので、
20dBu/√Hz がアンプ入力換算ノイズ密度 1nV/√Hz になります。
10kHz 以上の周波数では、アンプ入力換算ノイズ密度 = 0.74nV/√Hz になりました。
アンプ出力ノイズ(帯域 500MHz 時)= 0.165mV( = 10 * 0.74e-9 * √500e6 )です。
周波数カウンターにはもったいないようなローノイズアンプです。
1kHz 以下で持ち上がっているのは 1/f ノイズでコーナー周波数は約 500Hz です。 たぶん BF862 由来だと思います。
100Hz、150Hz の持ち上がりは取り切れなかった電源ハム成分です。