正月気分も程々にAD9850とAD9851を使った安価なDDSモジュールでDDS-VFOのテストをしている。昨年から懸案になっていた実験だ。 VFOのプログラムは「AD9834を使ったDDS-VFO」のものを移植している。 同じようにうまく動いてくれた。何とか正月の休み中に終わってホッとしている。
プログラムのおもな相違点はDDSへのデータ転送の部分である。VFOとしての機能に関わる部分はほとんど変えていない。回路もDDSモジュールの接続部分を除き共通だ。もしDDS-VFOの機能について再確認したいなら前のBlog(←リンク:DDS-ICにはAD9834を使っている)を参照してもらえたらと思う。 ここではマイコンにATmega328P-PUと言う比較的新しいチップを使ってテストしている。 このあたりの事情は文末のあたりで触れたいと思う。
機能の違いはないが発生可能な上限周波数はアップした。 前のBlogのAD9834-DDSよりもDDS-ICに与えるクロック周波数がアップしているためだ。AD9850/125MHzクロックで約40MHzあたりまで、AD9851/180MHzクロックで約55MHzあたりまでである。 また、このテストで使用したDDSモジュールはDDS出力がDC結合になっているので極端な話し、1Hz以下まで発生可能だ。(オシロスコープで確認済み・笑) もちろん通信機のVFOとしては意味がないのでプログラム的に下限も制限している。 通信機の発振器(VFO)ではなくて、低周波を含む広範囲な発振器の製作も可能だ。汎用発振器としてVFOのプログラムを簡略化したものも作りたいと思っている。
(注)以下の話しでは、三種類の「クロック」が登場する。1つはマイコン自身が動作するためのクロックで、マイコン内部の発振器で作っているもの。1MHzあるいは8MHzである。2つ目は、DDS-ICが出力信号を作るために使うクロックで、AD9850では125MHz、AD9851では180MHzである。AD9851では30MHzのクロックオシレータを使い内部で6逓倍している。3つ目はマイコンからDDS-ICへデータを送る時に歩調を合わせるためにつかうクロックである。(シリアル)シフト・クロックとも言う。これらの三種類を混同するとワケが解らなくなるかもしれない。なるべくわかり易く書いているが意識して読んでいただけたら幸いだ。
のちほど説明するプログラムを走らせるためのテスト用回路である。 マイコンにはATMEL社のAVRマイコンから、ATmegaX8シリーズを使う。 このテストの目的ならATmega8、ATmega48(P)、ATmega88(P)、ATmega168(P)、ATmega328(P)のいずれでも良い。 作業手順であるが、基板を作成したらプログラミングのために、BASCOM-AVRコンパイラの初期設定を行なう。(初期設定の方法は→こちら)その後、下記で説明のプログラムを書込むことになる。
マイコンのクロックはマイコン自体に内蔵のRCオシレータを使う。下記のプログラムを走らせるだけのテスト目的に限れば、ヒューズビットの書き換えは不要である。初期値である1MHzのクロックで十分だ。 従ってこのあとのテスト・プログラムを書込むだけで良い。 なお上の写真の様にDDS-VFOにするならヒューズビットを書き換えてクロックを8MHzにアップする必要がある。これはダイヤルやスイッチの状態を逐次監視し連続処理する必要があるからだ。 具体的には、ヒューズバイト:Lowを、ATmega8なら「E1」から「E4」へ、他のATmega48〜ATmega328Pでは「62」から「E2」に書き換える。それで8MHzクロックに切り替わる。(ヒューズビット/バイトの書き換えに関しては→こちら)
DDSモジュールへの配線方法は、手元の2種類の基板について纏めて書いておいた。 これは、次の写真のような2種類を同じプログラムでテストするためだ。 従って、自分が入手した方のモジュールに合わせた配線をすれば良い。マイコンからはDDSデータ、シフト・クロック、Fq_UDの各信号を配線する。また電源+5Vも供給する。従ってDDSモジュールへはGNDを含めて5本の配線で済む。
プログラムを走らせてDDSモジュールから信号が出てくればテストの目的は達成だが、マイコン部分はDDS-VFO化したり他の目的にも使える。マイコンの回りは余裕を持たせて場所を開けておく方が良いかもしれない。
アナログ・デバイセス社製のDDS-ICを使い、使い易くモジュール化したものが多数販売されている。 いずれも中国製のようだ。 おそらく何か簡易な測定器あるいは通信機などの電子機器を製造する目的で開発したモジュールであろう。 写真の形状以外にも何種類か目にした。
左は、既に紹介済みのものだ。AD9850版なら秋葉原でも手に入る。写真はAD9851版だが基板の見かけはまったく同じである。搭載されるクロック・オシレータの周波数とDDS-ICだけが異なっている。 AD9850版もAD9851版も基板の機能は互換である。(制御も殆ど同じなのでほぼ共通のプログラムで行ける)
右はさらにローコストなモジュールとして売られていたものだ。今のところAD9850版だけらしい。左の基板よりも簡略化されているが同様に使えることがわかった。 こうした物は「数割」があるので自作好きの皆さんと共同購入している。今回は私が買う番で、少々海外通販のスリルを感じつつも纏め買いしてみた。(幸い問題なし・笑) なお、このDDSモジュールに関しては別のBlog(←リンク)で詳しく扱っている。注:数割=数量割引。いっぱい買うと安くしてくれる。
プログラム言語はBASCOM-AVRである。DDS-ICのテストプログラムとはなっているが、上記のDDSモジュールが対象だ。 前のAD9834のときと同じように基本的なことを確認するためのものだ。プログラムを走らせてDDS基板から7MHzが出てくればテストは完了である。
しかし、DDS-ICを使うためのエッセンスはすべて詰まっている。この短いプログラムが動作しないようでは以後どんなプログラムでも旨く行かないだろう。 DDS-VFOなり汎用オシレータなりを開発するにあたっては、真っ先にこうした基本的な動きを確認しておきたいものだ。手に入れたDDSモジュールに異常はないか基本的な確認にもなる訳だ。
周波数データは純2進数の32ビットで与える。DDS-ICに与えるクロック周波数と関連するので送るべき2進データ値を求めるには計算が必要だ。 リストの300番台の行にその方法を書いておいた。 同じ周波数を発生させるにも、AD9850とAD9851ではクロック周波数が異なるので送るべきデータ値は異なってくる。それぞれの計算方法を示しておいた。
WindowsあるいはMacintoshに備えられた電卓を使うと簡単に純2進データを作ることが出来る。 何か試してみて欲しい。そうすればプログラム・リストの例(7MHz)とは異なった周波数が発生できる。 まずは電卓を起動したら関数電卓に切換え、それを使い式の通り十進演算で答えを求める。続いてそのまま2進電卓のモードに切り替えればそこに現れる数字が2進表現の「答え」なので2進変換はごく簡単である。(笑) なお、DDS-VFOではもちろんこうした演算はマイコン内蔵のプログラムで行なっている。もしもこうして発生した周波数に実測で誤差が認められるなら、DDSクロック・オシレータに周波数誤差があるのだ。計算するときに、ちょうど125MHzや180MHzではなく、実際のクロック周波数で計算すれば良く合うようになる。クロックと得られた周波数は比例関係なので、実測した周波数の誤差分を使って換算すればクロックの正確な周波数が求められる。クロックその物を実測する必要などない。
上記の計算で得られた純2進データをDDS-ICに転送する部分はAD9834との違いが大きい。但し、転送方法そのものはむしろ易しい感じだ。 周波数データの列を分割して2回に分けて送る・・と言うような細工は必要ない。 単純に32ビットの周波数データを送ればよい。 さらに続けてDDSチップへのコマンド列:8bit(1バイト)を送って終了だ。 合計で40bitデータを送ることになる。
最初に書くべきだったが、電源を与えたら真っ先にDDS-ICを初期化してシリアル(直列)データモードにする必要がある。周波数の設定などはその後だ。AD9850/51は、パワーオンの初期値は8bit単位のパラレル・データモードになっている。シリアル形式でデータを送るためにはモードを切り替えなくてはならない。リストの「Init_dds」と言うサブルーチンがその切換え部分だ。電源投入後の初期に一回だけ行なえば良い。 詳細は次項を参照。
DDS-ICの初期化の部分である。 メーカーの資料に詳しく書いてあるが、説明はやや難解に思えたので自身の備忘として書いておこう。
8bitのデータバスからコマンドで行なうことが出来るが、そもそもパラレルモードで使っていなければモードの切換えはできない。 そこで、左記のような方法がとれるようになっている。
AD9850/51から引き出されているデータバス:D0〜D7の下位3ビット、即ちD0、D1、D2を図のように配線しておく。 そのうえで、1発だけシフト・クロック(Wclk)与える。そのあとで直ちにFq_UDパルスを1発与えるとシリアル・モードに切り替わる。
なお、説明を読んでいてReset端子の操作が必要そうに感じた。試したらReset端子はLow、即ちGNDレベルに固定したままでも良いことがわかった。 電源を加えたあとで、上記のシーケンスさえ行なえばシリアル・モードに入ってくれる。 従って、DDS-ICとマイコンの間はデータと制御の配線3本の他、+5V電源とGNDを合わせても5本の配線でインターフェースできる。
シリアルモードに切り替わったら、直ちに32ビットの周波数データと、8ビットのDDSコマンドを送ってやる。 周波数データとDDSコマンドの与え方は次項を参照。
一旦シリアル・モードに入れば,あとは32bitの周波数データと8ビットのコマンドデータ、合計で40bitのデータを送ってやれば良い。 Fq_UDパルス(周波数のアップデートパルス)を送ると、送ったデータが直ちに反映され新しい周波数が出力される。
ここで注意すべきなのは、ビット列の送出順序である。 AD9834ではビット列の上位側、即ちMSB側から送出していた。 しかし、AD9850/AD9851ではビット列の下位側(LSB)を先頭にして送る必要がある。 これは8ビットのDDSコマンド(位相情報を含む)も同じである。
一見難しそうであるが、BASCOM-AVRではShiftoutコマンドの後のパラメータでLSBファーストにもMSBファーストにも簡単に切換えできるから心配いらない。 パラメータの詳細はBASCOM-AVRのshiftoutコマンドの説明に丁寧に書いてあるので参照を。
なお、AD9851には、外部から与えたDDSクロックを6逓倍する機能がある。その機能のON/OFFがDds_cmdのLSBにあって、「1」でON、「0」でOFFである。 OFFの場合はAD9850と同じように動作する。 AD9851を使った基板では30MHzのクロック・オシレータが載っていた。 従って6逓倍をONすれば180MHzのクロックで動作し、より高い周波数まで発生可能になる。 但し、逓倍に起因するらしいジッターがやや多くなるので、高級な通信機の局発にはイマイチかも知れない。 もちろんテスト・オシレータや周波数特性測定装置などの信号源には不安なく使える。
AD9851は本質的にAD9850よりも高いクロック周波数を許容すると思われる。従って、内部6逓倍ではなく、外部から直接180MHzを与えてやれば出力信号品質を維持しつつ、より高い周波数の発生が可能なる筈だ。高次オーバートーンで180MHz付近を直接得てクロックとして与えたら面白そうだと思っている。
電源は+5Vを与える。 DDSモジュールの消費電流は実測の平均で110mAくらいであった。 +5Vの3端子レギュレータは放熱なしでも何とかなる範囲であるが、他への供給を考えて簡単なヒートシンクを付けておこう。 この程度のヒートシンクでは300mAくらいまでと思った方が良い。 いくら1Aタイプのレギュレータを使っていても、放熱が悪ければ遥かに少ない電流までしか許容できない。
DDS基板には約70MHzをカットオフ周波数とするLPF(低域濾波器)が実装されている。 しかし、AD9851/180MHzならともかく、AD9850/125MHzクロックにはカットオフ周波数が高過ぎる。40MHzあたりが適当な所だ。 チップ部品の載せ換えでカットオフの変更も可能だが少量のチップ部品入手は難しいかもしれない。従って、DDSモジュールの外で増幅+フィルタを行なう方が良さそうだ。 簡単な実験程度なら、このままでも良いが実用にするならもっと目的に適したフィルタを外付けしないと旨くないと思う。 もしスペアナが利用できるなら良くスペクトラムを観測しておこう。
搭載されているこうしたクロック・オシレータには周波数誤差があることを前に書いた。このDDSモジュールでも例外ではなく最大では+13ppmくらいの誤差があった。 初期周波数の誤差はプログラムによってソフト的に補正してしまうので何ら支障はない。 問題になるのは温度による周波数変動の方である。室温の変化から様子を見ていたら1〜2ppm/℃程度なのでまずまず安定と言えそうである。 もちろん自励発振器やVXOなど目ではない。 安価なDDSモジュールとは言え、周波数シンセサイザの威力を十分に発揮してくれる。
☆ ☆ ☆ ☆ ☆
あらかじめ書いておくが、このBlogに掲載した簡単なテスト・プログラム(上記)ならまったく問題なく動作するから以下のことは心配はいらない。問題ない用途へなら古いチップもどんどん使うべきだ。
実は、AD9850/51 DDS-VFOのプログラム開発作業で半日トラブった。 もともとAD9834用に開発したDDS-VFOプログラムをベースに開発していた。 ところが、手を加えてもいない部分でコンパイラのエラーが続出したのであった。 具体的にはTimer割り込みと内蔵のA/Dコンバータの部分である。 それぞれ割り込みコマンドやA/D変換のステートメントが未定義であると言うエラーが出たのだ。
結論から言えば、BASCOM-AVRが少し古いチップをサポートしていないのが原因であった。写真奥のATmega168は既に5年以上前のチップだ。いま出ているのはサフィックスにPの付いた、ATmega168P-PUである。 ATmega168Pならエラーなくコンパイルできるのに、Pなしの旧型チップは不完全なチップ定義ファイルらしく未定義エラーが続発するのであった。結局、写真手前の新型チップ、ATmega328Pに変えたらコンパイル一発でノーエラーである。あっけなくAD9850版のDDS-VFOが完成した。(笑)
もちろん、単純なポート操作程度のプログラムなら問題なかったのだろう。しかし、割り込みと言った少し高級な処理をともなうと古いチップに対するBASCOMの対応は不完全なようである。 原因がわかったから良かったようなものだが、エラーに悩んでお正月の半日分を損した気分である。(-_-)
結局、こうしたマイコンのような部品は買い溜めたらダメである。 少々割高でも必要な分をその都度購入するに限る。そして余分に買ったら早めに使い切ろう。 BASCOMのエラーから教えられた教訓であった。(いつものことだ・笑) de JA9TTT/1
(終わり)
☆ ☆ ☆ ☆ ☆
【追記】ATmega168(8,48,88のPナシ含む)への対処方法:(備忘:2012.1.9)
まずはBASCOMのフォルダを開いてみよう。BASCOM-AVRをアップデートすると、以前のチップ定義ファイル(例えば:m168def.dat)は「BACKUP」と言う名前のフォルダに保存される。(自動的に保存されている) このBASCOMフォルダのトップレベルには同名の新しいチップ定義ファイル:(この例では:m168def.dat)が置いてあって、コンパイル時にはこちらの新しい方が使用されるようになっている。
上記の問題はこの新しい方のチップ定義ファイルに問題があるのは明らかだ。従って、新しい方のチップ定義ファイルをどこかに一旦退避させた上で、「BACKUP」フォルダ内にある前のチップ定義ファイルをトップレベルに持ってくることで解消できる。 これでPなしのATmega168,etcでも問題なくコンパイルでき、正常な動作が確認できた。従って、現在はATmega168-20PIで動作させている。もちろん快調である。(BASCOM-AVRも一旦、Ver.1.12.0.0に戻している)
そもそも、それほど新しい機能を使っている訳でもないので古いバージョンのBASCOMのままでも良かった訳だ。 無闇にバージョンアップしないと言うのも教訓かもしれない。これで買い置きのATmega168-20PI,etcを無駄にせずに済む。 コンパイルできて書込みさえ出来れば別段P付きの新チップでなくても何ら支障はない。 もしも同じ問題に遭遇してしまい、旨く行かないならメールでも頂ければと思う。遠慮なくどうぞ。
(めでたし、めでたし)
12 件のコメント:
こんばんは。
お正月の成果拝見させて頂きました^^
BASCOMのバージョンによる違いにはいつも泣かされますが、
今回のは特にわかりにくいですね。
手持ちにPタイプがなければ確認のしようもありません。Hi
やはりマイコンは必要なときに最新の物を必要なだけ購入しないとダメですね。Hi
JE6LVE/3 高橋さん、こんばんは。 こちら明日からまた仕事です。 正月休みは短いですねえ。hi hi
さっそくのコメント有難うございます。
> 今回のは特にわかりにくいですね。
トラブる筈のない部分が旨くないんですから悩みましたね。 たまたま間違ってP付きチップのdefファイルでコンパイルしたらノーエラーになったのでBASCOMの問題なのが発覚しました。(笑)
古いチップは早々に何か簡単なことに使ってしまいましょう。(汗)
どうぞ今年も宜しく。
連休最後の日となってしまいましたが、成果がまとまりましたね!
丁寧に解説されているのに、いつも関心させられます。
この記事で、DDSはどこから調達できるの?と、質問が増えそうですね!
当局も、このボードちょっとだけ実験しました。
JN3XBY 岩永さん、こんばんは。 北関東は今夜も寒いです。 明朝の出勤が億劫になりますね。hi hi
コメント有難うございます。
> 成果がまとまりましたね!
有難うございます。 昨晩までにおおよそプログラムも終わったので、今日はBlogに纏めておりました。意外に手間がかかりましたね。(笑)
> DDSはどこから調達できるの?と、質問が・・
この後のBlogで廉価版のDDSモジュールについてやる予定です。 そこである程度詳しく書きたいと思いますが・・・。待ってもらえるかなあ??(笑)
岩永さんのDDS-VFOも拝見して来ました。いきなり実用品が出来上がりますね。すばらしい!
どうぞ本年もよろしく。
こんにちは、
ROMばかりですが今年もよろしくお願いいたします。
いつも会社の昼休みに観させていただいています。
AD9800ファミリーはだいぶ以前に9844(だっけかな?)であまりよい結果が出せなかったものですから、
「相性が悪い」ことにして手つかずでおりまして、今回の加藤さんのブログ続編を楽しみにしておりました。
また時折書き込みさせていただきたくよろしくお願いいたします。
JA8CZX 矢北さん、こんばんは。 新年おめでとうございます。
コメント有難うございます。
> 9844(だっけかな?)であまりよい結果が・・・
今度はAD9850/51でお試しになって下さい。 こうしたDDSモジュールになっているとずっと手軽だと感じました。 使い方はBlogの通りで良い様ですので、今度は旨く行くでしょう。
こちらこそ今年もよろしくお願いします。
こんばんは、
ローカルクラブ(横浜みどりクラブJH1YMC)のものづくり仲間で、昨年アリババから共同購入しました。PICで色々とテストしているところです。
本年もよろしくお願いいたします。
JG1CCL 内田さん、おはようございます、 こちらへのコメントは初めて頂いたでしょうか? 有難うございます。
コメント有難うございます。
> (横浜みどりクラブJH1YMC)のものづくり仲間で・・
みどりクラブのサイトを拝見しました。CCLさんをはじめ皆さんの力作が揃っていますね。
> PICで色々とテストしているところです。
制御するうえで必要なことは単純です。たぶんPICでもほとんど同じように出来ると思います。 皆さんと楽しまれるのはVY-FBですね。
こちらこそ本年も宜しくおねがいします。
こんにちは、毎日寒いですね。
やはりLPFは外部に置くのが無難なようですね。
シリアルモードへの移行ですが、D0,D1のハードワイヤー接続のみで、特に移行シーケンスをしなくてもシリアル制御できています。
したほうがいいのでしょうか?
JA2NKD/1 松浦さん、こんばんは。 寒いですねえ。
コメント有難うございます。
> 特に移行シーケンスをしなくてもシリアル制御・・
特別な手順を経なくても、シリアル通信のコマンドを連続するとそのモードに自然に移行するようです。 但し、初回の一回だけミスすることがあるようなので移行するための手順を入れた方が確実なようでした。 連続してロータリエンコーダを読んで周波数を更新して行くような使い方では初回のミスは感じられないかも知れませんね。 確実のために私の例では正規の手順を入れることにしています。
JA9/TTT加藤さん
ありがとうございます。
確かにミスすることがあるようですね。
基本に忠実なのが、成功の秘訣かもしれませんね。
JA2NKD/1 松浦さん、こんばんは。
コメント有難うございます。
> 確かにミスすることがあるようですね。
Power-ONしたら、予めメモリされた周波数を発生させたい・・と言うような用途では、確実性が求められるので必ず初期化ルーチンを入れないと旨くないと思います。 用途によって要・不要は変わって来ますね。
コメントを投稿