ファンクションジェネレータつくりました
かなり以前に0.5mmの壁として作り始めて放置していたファンクションジェネレータですが、ようやく完成したのでここにまとめておきます。
概略
前々から何かとファンクションジェネレータがあれば・・・と思う場面があって、機会があれば作ってみたいと思っていました。とはいえこういう「地味な」工作は途中で投げ出すことも多いので、次のような方針で作ることにしました。
- できるだけ手持ちの部品のみで作る (際限無い機能追加を防ぐ)
- 「ケースに入れるまでが電子工作」 (実用する)
それに伴って
最低限の機能に絞って、〜1MHzは綺麗な波形、〜20MHzまで減衰ありでなんとか出せる、周波数精度はそれなりに重視する。
という仕様を決めました。
そこで手元にはCPLD(XC2C256)があったので、DDS*1方式にして、R-2R DACを通した後、振幅とオフセット調整はアナログ的に行う、ということにしました。
DDSの動作
仕組みについてはChaN氏のところ*2などが参考になります。
まずはクロックを決める必要があります。最低でも20MHzの2倍の40MHzなので、秋月で売ってる2^26Hz(≒67MHz)の水晶発振器を使うことにしました。SRAMには運良く転がっていたCY7C1041DV33(リードサイクルが10ns)を使います。
DACは8bitのR-2R*3にすることにして、5%誤差のカーボン抵抗を選別して0.1%に抑えた物を使います。各bitはまともなDAC ICではカレントミラーになっていることが多いですが、今回はSRAMのデータ線直結で特に電圧降下もなく正常に動作したようです。
生成する波形、特に正弦波の傾きを考えると波形メモリは1024サンプル分あれば充分、クロックには10mHz単位で設定したいということでごにょごにょ計算すると34bit分のレジスタが必要ということになります。AVRから34bitパラレルで接続するわけにはいかないので、FFが最低でも68個必要で、XC2C256の場合だとアドレスの生成のみに絞らないと無理でした。
で、結局は図の構成に落ち着きました。SRAMのリードはアドレスを変えるだけでできることと、波形書き換え時に出力が変動するのを許容したのが簡略化において重要な感じです。
波形の書き換えはμCからアドレスをシフトレジスタに書き込み->SRAMにデータ転送を1024回繰り返すので100ms程度かかってるようです。
振幅・オフセット
上記の設計で、周波数変更時(Δレジスタの更新)には出力(の位相)は連続です。あとは振幅とオフセットの変更時ですが、これもできる限り連続にしたい。ということでAVRの出力をLPFに通して、残りはアナログ的に・・・と考えていたのですが、FETでの変調で予想外に非線形性が大きく、あまり幅をとれなかったため、仕方なくレンジ切り替え式にしました。
この部分はオペアンプ(LM7171)のオフセット電圧のドリフトが大きかったりで、設定値と10%程度ずれたりとあまり性能が出なかった部分ではあります。
UI
出力は20文字×4行のキャラクタLCD、入力はスイッチ×4+ロータリエンコーダというシンプルな構成にしました。
もっともよく使うのが周波数の変更なので(そもそも今回の設計ではそれ以外の数字は当てにならない)、それが快適に変更出来れば十分です。
とはいえまともに作るなら波形設定は専用のボタンを用意したりした方が快適性は向上するでしょう。
μC
マイコンが行うべき処理は:
なので速度は要りませんがそれなりにピン数が必要です。今回はATmega64を内蔵の8MHz発振器で動かすことにしました。
注意する事があるとすれば、ロータリエンコーダは結構頻繁(数ms)に値を読まないと回転を取り逃すことがあって、これが非常に不快だということでしょうか。
電源
測定器でスイッチング電源を使うのはノイズの点からみてご法度なのですが、既に加工済みのケースに収めるために仕方なく使用しています。
1kHz程度の信号を生成させて、波形を見る感じではSNRは30dBぐらいはありそうですが、聞いてみると10kHzぐらいの甲高い音が入っているのでオーディオ帯で使うにはシールドするなりの対策が必要なようです
実装
以上のことを踏まえて設計するとこの回路図のようになります。(ちなみにこの画像はcircsketchで書いています)
実装はいつも通りに、ユニバーサル基板+カプトンテープです。0.5mmのQFPは1ピンごとに持ち上げると*4、ブリッジの修復中に足が折れたり、ピン番号を数えられないといった問題を回避できるようです。これは個人的には大きなブレークスルー(笑)なので、今後も使いたいテクニックですね。
上の写真ではヒートシンクが付いていますが、ケース組込時には適当なアルミ片と熱伝導シートでケースと結合させています。
完成
蓋を閉じる前と後でそれぞれこんな感じになります。
残念ながら手元にあるオシロスコープは20MHzのものなので高周波については実際に出力されているのか確認することはできませんが、数MHzの信号はまったく問題なく出力されているようです。
ソースコードその他一式は http://www.xanxys.net/public/SimpleFG.tar.bz2 に上げておきます。
まとめ
- 50MHz程のデジタル回路では高周波特有の問題は発生しない (気づいてないだけという可能性はある)
- せっかくDDSにするなら振幅の設定を含めてできるだけデジタル処理した方が設計が楽
- CPLDの限界動作周波数に当たるとタイミングレポートを見ながらの設計になって面倒 (これが普通)
- 手間さえかければケースは綺麗に仕上げられる
- ATmega64のJTAGは不安定
といったところでしょうか。いろいろと欠陥はありますが今後の活躍が期待されるところです。
*1:参考: wikipedia:ダイレクト・デジタル・シンセサイザ
*2:ELM - DDSファンクション・ジェネレータ http://elm-chan.org/works/asg/report_j.html
*3:参考: http://en.wikipedia.org/wiki/Resistor_ladder
*4:参考写真: http://twitpic.com/1nxsc3