周波数カウンタを作る 1

周波数を測定するには周波数カウンタを使います。
簡単な物ならデジタル・マルチメータやオシロスコープにも内蔵されていますが、専用品にはかないませんね。

実は、マルチメータと周波数カウンタだけは、比較的場所を取らないので、ジャンク計測器を大量に処分した後も作業部屋の壁面書庫の棚の中に保存していました。

また、自作の簡易型周波数カウンタも健在です。
この「簡易型周波数カウンタ」は、自分で設計した物ではなくネットの情報から製作したものですが、残念ながら現在はその情報は見られません。

製作者の方が MicroChip 社のアプリケーション・ノート AN592 を解析して、内蔵プリスケーラのゲート閉鎖後に追加パルスを使用すると分解能を落とさずに周波数測定を行えることを発見して応用したものです。

PIC16F84 という18ピンの「いわゆる入門用の MCU」単体で 60 MHz まで測定出来ます。
基準信号には時計用(?)で高安定度の 12.8 MHz TCXO が使われています。
オリジナルの回路図ではプリスケラ IC に MB506 を使用していて、手のひらサイズながら 2.4 GHz まで測定できます。
また、プリスケラの有無に関わらず分解能は 1 Hz まで対応しているというトンデモナイ性能です。
(自作の周波数カウンタはプリスケラの MB506 が手に入らなかったので最大周波数は 1.3 GHz です。)

あれから沢山の月日は流れましたが、私の電子工作の能力も少しは向上したのでしょうか?
ブログで1人で愚痴を言ってもしょうがないので、現在の進化した「マイコン」とほんの少し進化した現在の私のスキルで「簡易型周波数カウンタ」に近い性能の携帯型周波数カウンタを製作することを目標にします。

周波数カウンタの原理

後で説明する「レシプロカル方式」の簡単な構成は下図のようになります。
・アンプ部:入力信号を検出できる大きさまで増幅します。
・波形整形部:信号をカウントするのはデジタル回路なので、信号を処理できる波形に整形します。
・基準信号発生部:ゲート部へ基準信号を送ります。ここの安定度がカウンタの性能を左右します。
・ゲート部:成形された波形と基準信号を合成します。
・デジタル処理部:カウンタとディスプレイなどで構成されます。

周波数カウンタの種類

周波数カウンタには動作方法の分類で2種類あります。

ダイレクトカウント方式

一定のゲート時間内の周期を直接カウントして周波数として表示する方式です。比較的単純な回路で構成することが可能で基準となるゲート時間を長くすることで容易に測定分解能を増やすことが出来ますが、測定する周波数が低い場合は、測定時間が長くなってしまいます。

レシプロカル方式

周波数は周期時間の逆数であることから入力信号の周期を測定して周波数に換算する方式です。入力信号の周期内に収まる基準信号の数をカウントすることで周期時間を測定し周波数として表示することが出来ます。
高速な基準信号が必要になるため回路は複雑になりますが、低い周波数でも高速で測定することが出来ます。

(説明文は「株式会社 計測技術研究所」の HP より引用)

周波数カウンタの情報収集

「簡易型周波数カウンタ」が公開されてからかなりの年数が経過した為、MCU(いわゆるマイコン)の状況は大きく変化しました。
当時の電子工作で良く使われていた PIC や H8 は使用される例が減り、現在では Arduino UNO や Raspberry Pi、M5Stack、ESP32 など色々な MCU が利用されています。

その中でもArduino UNO と ESP32 で高周波用の周波数カウンタを作るのは難しそうです。
その他の MCU の情報を調べているとお世話になっている siliconvalley4066 さんのブログに STM32 を使った周波数カウンタの製作例を発見しました。

STM32 で周波数カウンタ

siliconvalley4066 さんのブログの記事は「STM32F103C8T6で192MHz周波数カウンタ」です。
元ネタは4年前(2020年)のロシアの方のブログのようです。
(下のリンクをご覧ください。別窓で開きます。言語は自動で日本語に翻訳されるのでロシア語に堪能でなくとも記事を読むことが出来ます。)

ロシアのオリジナルは STM32F103C8T6 を使用して 24MHz まで測れるそうですが、siliconvalley4066 さんは色々なバージョンに改造して 「使用したライブラリで設定できる上限の225MHzでもどうにか測れることを確認」されたそうです。

それじゃ、この STM32 を使った周波数カウンタの製作をやってみよう!

STM32F103 を Arduino で使う

今回使用する MCU は、STマイクロエレクトロニクス社の STM32F103 です。
(毎回使用する MCU が違っていて節操がない事は自分でもわかっています。)

このボードの CPU には ARM コアの 32-bit Cortex-M3 が使用されています。
手持ちの部品は AliExpress で数年前に購入して部品箱に眠っていた「STM32F103C8T6」互換機です。

この型番が表しているのは、
・C:48 Pin
・8:メモリ容量 Flash:64 k、SRAM:20 k
・T:LQFP パッケージ
・6:動作温度 -40 ℃ ~ +85 ℃
です。

とりあえず、久々に使う「STM32F103C8T6」を使い慣れた Arduino IDE で使用できるようにセットアップします。
国内では STM32 を Arduino IDE で使う情報は 1.8 系が多かったのですが、今回は使い慣れた Arduino IDE 2 系で解説します。

Arduino IDE へ STM322F103 を追加

Arduino IDE を立ち上げて「ファイル」「基本設定」を開き「追加のボードマネージャのURL」の右側にある緑のアイコンを押します。

「追加のボードマネージャのURL」の窓が開いたら、ボードを追加するための URL を記載します。
今回は、siliconvalley4066 さん指定の URL を使用します。(他の設定ではエラーが出ます。)
http://dan.drown.org/stm32duino/package_STM32duino_index.json
です。

ボードマネージャの URL を追加したら「OK」を押して窓を閉じます。

ボードマネージャで「STM32」で検索して「STM32F1xx・・・」ボードのサポートをインストールします。
「インストール」の緑のボタンを押すと数秒で処理が終了します。

今回は USB シリアル変換器でプログラムを書き込むので、設定はここで終了です。
(もしブートローダの書き込みを行う場合は他のサイトをご覧ください。)

今回は、書き込む回数が少ないので手間のかかるブートローダの書き込みの解説は行いません。
(実は今回使用した STM32 が安価な互換品を使用した為か Windows と Linux 環境で色々試してみましたが、ブートローダを書き込んでも動作しません。)
ブートローダを書き込まなくても、Arduino IDE からスケッチを USB シリアル変換機経由で書き込めばプログラムは正常に動作します。

周波数カウンタ用スケッチの入手

siliconvalley4066 さんのブログへ行きます。下のリンクを使ってください。(別窓で開きます。)

種類別に圧縮ファイルが上がっていますが、今回は OLED 表示バージョンを使用します。

「ライブラリ版」(ダイレクトカウント方式)なら「frequency_meter110.zip」を使用します。
「周期カウンタ版」(レシプロカル方式)なら「frequency_reciprocal101.zip」又は「frequency_capture101.zip」を使用します。

周波数カウンタ回路の組み立て

ブレッドボード上に周波数カウンタの回路を組み立てます。
通常は USB シリアル変換機で STM32 へプログラムを書き込んでから回路を組んで動作を確認すると思いますが、書き込み回路と周波数カウンタを同一のブレッドボード上に配置しても正常に動作します。
(USB シリアル変換機は型番指定はありません。使い慣れた物で問題なく動作します。)

ただし、この回路は 3.3 V で動作するので、USB シリアル変換機の電源(VCC +5 V)は、STM32 の 5 V ピン(18 Pin)へ接続してください。

接続先

STM32F103C8T6入出力他OLEDUSB変換機
3Gate Time SW
4Prescaler SW
6RX
7TX
10Input
14SCL
15SDA
17Test Out
18+5V
38VCC
39GNDGNDGND

STM32 の接続

ブレッドボードに回路が組み上がったら、パソコンに USB シリアル変換機を中継して STM32 へ接続します。
Arduino IDE を立ち上げて、siliconvalley4066 さんのブログから落としてきたスケッチを書き込みます。

あ、STM32 は書き込む時にボード上のジャンパ設定が必要でした。
プログラムを書き込む時は、上側のジャンパを右側に付け替えてください。

Arduino IDE のボードの設定は下を参考にしてください。
ちなみに、最低でも下の設定を変更しないと動作しません。
・ボード:”Generic STM32F103C series”
・ポート:USB シリアル変換機をつないだ USB ポートの番号(USB Device Tree Viewer などのソフトを使用すると USB ポートの確認が楽です。)
・Upload method:”Serial”

スケッチの書き込み

ブレッドボードの回路に間違いがなく、Arduino IDE の設定が正しければ、パソコンを USB シリアル変換機に接続して「書き込み」ボタンを押すと下の画面が出て正常に書き込みが終了します。
通常はこの時点で STM32 に自動でリセットがかかって、OLED に周波数カウンタの画面が表示されます。

プログラムを書き込み終わったら、USB ケーブルを外して STM32 のジャンパを元に戻します。
通常の動作時にはジャンパはこの位置で使ってください。

動作確認

siliconvalley4066 さんのブログでは、この周波数カウンタは(3.3 Vpp のデジタル信号なら)「192MHzまで測れることを確認しました。」とのことですが我が家にある信号発生器をつないでも上限は 10 MHz 位までしか計れません。
そこで、ブレッドボード上に同じく siliconvalley4066 さんのブログで公開されている「Raspberry Pi Picoオシロ」を再現して信号発生器として使います。(信号発生器替わりとは、なんという贅沢)

入力回路を作らなかったので、すぐに出来ました。

このオシロスコープが備えている信号発生器の機能を使います。
とりあえず、この基板をクロックアップなどを行わない状態で、出力できるテスト信号の上限周波数は 62.5 MHz です。

あれ?10 ~ 20 MHz 程度までしかカウント出来ませんね。
何度かスケッチを書き直したり、Pi Pico オシロの配線を再確認しますが、どうやっても 22 MHz が上限です。

原因究明

siliconvalley4066 さんのブログのゲストブックで質問をしてみました。
(すぐに詳細な回答を頂き、ありがとうございます。)

一晩たって(頭を冷やして)から、部品箱をひっくり返して4個の STM32 の在庫を確認しました。
これに「A」「B」「C」「D」と名前を付けて、1つづつ確認します。

A:最初から使用していた物です。ブートローダを書き込んでいます。(ブートローダの動作は確認できません。)上限は 22 MHz でした。
B:比較のためにこれもブートローダを書き込みました。上限は 66 MHz です!(これ以上行けるかもしれませんが、現在の所、確認していません。)

C:ブートローダは面倒なので書き込んでいません。上殿は 44 MHz でした。
D:同じくブートローダなしです。上限は 66 MHz でした。

どうやら、見た目は同じ「STM32F103C8T6」互換機ですが、入力部には「個体差」(性能差)があるようです。

おまけ

siliconvalley4066 さんのブログの Pi Pico オシロスコープには TFT ディスプレイでタッチ操作対応というゴージャス版が存在します。
簡単に出来るので、これは動作させてみるべきでしょう!

やってみました。
あれ?画面が90度回転しています。

TFT 画面の拡大です。

これには、siliconvalley4066 さんから、「display.setRotation(3)の3を2に変えてみたらどうでしょうか。」とアドバイスを頂いたので、やってみました。

だめですね。
90度回転していたのと同じところが「灰色ノイズ」画面になっています。

一応、画面の向きが正常になったので、タッチセンサの機能を確認してみました。
表示出来ていない部分が 1/4 程あるので完璧ではありませんが、タッチして値を変更できるようです。

その後、さらに「Setup60a_RP2040_ILI9341.hの中でSPIクロックを下げてみる」とアドバイスを頂いたので、70 MHz 設定の所を 40 MHz ~ 20 MHz まで段階的に下げてみましたが症状は改善しませんでした。

これ以上やると、周波数カウンタの製作からどんどん話がそれていくので、Pi Pico TFT オシロの話はここまでです。

次回の予定

今後やりたいことが2つあります。

1 プリアンプの製作
現在は、主にデジタル信号しか高い周波数は測れないので、何かしらのプリアンプを作りたいです。
一応、高周波で使用できる部品も在庫にあるので、プリアンプ的な物が出来ないかガンバってみます。

2 プリスケラ
現在も 24 MHz 以上の周波数の測定には STM32 の機能で8倍のプリスケラ使用して行っていますが、さらに上の周波数を分解能を下げずに測定できるか確認したいです。

その為には、ハード的なプリスケラが必要です。
部品箱にある部品などで実現できないか考えてみます。

コメント

  1. ちょっと試して頂きたいことがあります。次の行(最大2行)をコメントアウトして下さい。
    afio_remap(AFIO_REMAP_TIM2_PARTIAL_1);
    そうするとA15ではなくA0が入力になるはずです。こちらの方が普通なので良くなるかもしれません。
    何故かA0を別の目的に使うシステムのためにピン割り当てをRemapしたと思われます。

    • パオさん より:

      ご連絡ありがとうございます。
      何でA15を使用しているのか不思議に思っていましたが、オリジナルがA0を別の目的で使っていたのですね。

      「PeriodCount_STM.cpp」の指定箇所をコメントアウトしたら、A0が入力になりました。

      手持ちのSTM32を全てA0入力にしたら、デジタル信号で10〜20MHzまでしか計測できなかった物も66MHzまで計測できるようになりました。

      • 気になっても確認できなくて、モヤモヤしていました。
        たとえコピー品でも普通の使い方をすればOKかもしれないということでしょう。
        御確認をありがとうございました。すっきりしました。