« ブールバール通り | メイン | TS850 スピーカー出力小(低域出ず) »

2018年1月 1日 (月)

DDS VFOの実験(AD9833) 1

<カテゴリー:DDS

Dds_ic

QRHの無い、安定した高周波発振器用として、DDSのICが最近安く手に入るようになってきました。ICと基準周波数発振器を表面実装した基板状態の商品がアマゾンで売られています。 DDSは性能的になにもケチをつける事はないのですが、その周波数の可変に大きな不満がありました。 それは、同調操作という純アナログ的な周波数選択操作です。 DDS周波数は数値で制御されるため、その数値を増減しながら周波数を目的の値に設定する訳ですが、SSBモードでも実用可能な10Hzステップ可変でハムバンドの下限から上限まで移動するのは簡単ではありません。 これを少しでもスムースに行う為に、1回転で1000パルスを発生させ、10回転で100KHzをカバーさせるようなロータリーエンコーダーが使われていました。このようなロータリーエンコーダーは精密機械に属し、その価格は非常に高価で、かつ物理的に大型つまみでしか実現できませんでした。 せっかくDDSのICが安くなっても、この周波数可変の部分がネックとなり、アンテナアナライザやVFOの原発振器としては利用しにくく、今まで避けてきたところです。

最近の普及価格帯のSSBトランシーバーはこの辺の使いにくさを、周波数ステップの異なるふたつのロータリーエンコーダーでカバーさせ、10HZステップのエンコーダーが高価になるのを回避していますが、それでも10Hzステップのエンコーダーは、1回転100パルスを発生出来、私が簡単に手をだせる価格やサイズでは有りません。

RSで手に入る、安いけど品質は問題なしの、ALPS製1回転24パルスの機械式ロータリーエンコーダーにて、この使いにくさをどれくらい改善出来るかの実験記です。

まずは実験回路図です。7MHzDDS180101.pdfをダウンロード

DDSをコントロールするマイコンはPIC24FV32KA302です。周波数表示は99円のLCD。そして、2個のロータリーエンコーダーを実装できるようにしました。

目標とする発振周波数は7MHzから7.2MHzでこの200KHzの範囲を10Hzステップで可変させます。 SSB受信機で7MHzを受信しようとした場合、実際のVFO周波数は受信周波数±IF周波数になりますが、IF周波数が決まっていませんので、IF周波数はゼロとして実験します。 IF周波数がいくらになろうがカバーが必要な帯域200KHzは変わりません。 1回転24パルスのエンコーダーの場合、833回転でやっとカバーしますので、2度と触りたくないというVFOです。

Dds_pcb

Dds_lcd

左上はPICとDDSを実装した実験基板、右上はテストで2MHzを発振させている時のLCD表示で、最下位は10Hzです。

Idds_2mhz

Dds_7mhz

左上は2MHzの出力波形、右上は7MHzの出力波形です。いずれもDACの出力をそのまま表示していますので、綺麗ではありません。実際に使う時は7MHzのBPFを挿入しますが、今回の実験ではこのままです。

Dds_spi

左は、PICとDDSを結ぶSPIラインのFSYNCとSCLKの波形です。周波数設定は28bitを14bitに分割し、2回に分けて送信しますが、この実験機では、LSB,MSBを両方セットしたとき、周波数が変更されるモードで使用しています。

当初、SPI通信がうまくいかず、クロックの極性がアクテイブ LOWであるという事に気付くまで足かけ2年(12月31日から1月1日の昼まで)悩みました。

DDSとの通信クロックは約1MHzで行っています。ちょっと早い感じがしますが、RF混入で問題が有る場合、フィルターを強化する度合いによりクロックレートは下げる予定です。

AD9833が動作するまでの、XC16によるソフトを説明します。

SPIの初期設定です。 メインのイニシャル関数initMain()のなかで処理しています。

SPI1CON1 = 0b0000011101110010;//
SPI1CON2 = 0b0000000000000000;//
SPI1STATbits.SPIROV = 0;
SPI1STATbits.SPIEN = 1;//SPI1有効化

SPI1CON1にてマスターモード 16bit、プライマリ1/4、セカンダリ1/4、クロックactive_Lを設定します。

DDSへの書き込み関数です。

// DDS 書き込み
void DDSwrite(unsigned int data) {
    SPIFlg = 0; //DDS FSYNC 0(CEをL) 
    __delay_us(1);
 SPI1BUF = data;
    while(!SPI1STATbits.SPITBF);
    __delay_us(20);
 SPIFlg = 1; // CEをH
}

20usの遅延時間は16bitの送信が終わるまでをオシロで確認しながら決めました。

マイクロチップが公開しているSPIのリファレンスマニュアルによると、16bitのデータ送信が完了すると、SPI1IFというフラグがセットされるらしいのですが、いくらやってもこのフラグがセットせず、やむなく遅延時間を入れてCEの信号を作成しました。 また、SPITBFフラグも役立たずで、このwhile文も削除しても動作に影響は有りませんでした。

DDSのイニシャライズです。

void initDDS() {
 DDSwrite(0x2100);//DDS reset
 DDSwrite(0xC000);//PHASE0 0
 DDSwrite(0xE000);//PHASE1 0
 DDSwrite(0x2000);//16bit連続2回送信にて周波数確定
 Freqwrite(Freset,0);//reg0に1MHz書き込み
 Freqwrite(Freset,1);//reg1に1MHz書き込み

DDSにリセットをかけますが、位相、周波数レジスタともにクリアされません。 従い、初期値が存在してはならないデータになっている可能性が有り、何が起こるか判りませんので、それぞれのレジスタにダミーデータを書き込んでいます。 最初の行でセットしたRESETビットは4行目の0x2000のコントロールコマンドでRESETビットも落とし、RESET終了としています。

このAD9833のイニシャル設定は、アナデバが公表している資料によると、ここで示した各コマンドの送出順序と異なる事がわかりました。 もし、この順序でうまく動作しない場合、アナデバが公表しているこの資料を参照して下さい。

周波数の設定

FREQREGの値はAD9833の仕様書から周波数x(2^28/25MHz)で計算されますので、(2^28/25MHz)部分をKdと置き、値は10.73741824という実数になります。 しかし、この発振器の周波数は10Hz単位の表示ですので、実際に計算する場合、Kd=107.3741824という数値に定義し直しています。

void Freqwrite(unsigned long int FQ, unsigned char ML) {
 unsigned long int Freg;
 unsigned int MLset,MFreg,LFreg;
 double DFreg;
 if (ML == 0) {MLset = 0x4000;} else {MLset = 0x8000;}
    DFreg = FQ;
 Freg = (double) (DFreg * kd); 
 MFreg = (Freg >> 14) + MLset;
 LFreg = (Freg & 0x00003FFF) + MLset;
 DDSwrite(LFreg);
    __delay_us(20);
 DDSwrite(MFreg);
}

この関数の中で引数MLは周波数レジスター0か1を指定するものです。

ロータリーエンコーダーによる周波数のアップ、ダウンは、A,B 2bitを定期的に監視して、基本パルスの4倍の分解能(1回転96パルス)を得る手法が一般的ですが、この方法ではエンコーダーの回転速度を検出できないので、今回はINT1と2からの割込みで割込み周期を計数するとともに回転方向を検出する方法にしています。 エンコーダーの回転速度を検出する必要が有る理由は後述します。 従い、1回転24パルスが基本となります。 ソフトの内容は添付ソースファイルを参照下さい。


周波数可変の設定は、ロータリーエンコーダーRE1は10Hzステップ、RE2は1KHzステップ可変です。 200KHzをカバーするのに、RE1だけなら、833回転ですが、RE2だけの場合、8.33回転で済みます。

このチューニング感覚はYAESUのFT450とかFT991と同じで、コンテストのときなどに多用しますが、さすがに10Hzステップのダイヤル操作は同じ感覚とは言えません。ここら付近が改善のポイントと思われます。

現時点でのソースファイルです。 DDS_7MHz180101.cをダウンロード

ファイルの中に、EEPROMのアクセス関数がありますが、この実験では使用していません。

ここまでは、何の工夫も加えられていません。 そこで、いつかは実験しようと考えていた、2個のエンコーダーを1個にして、同様な効果が得られないかトライする事にします。 ヒントは20年くらい前に聞いたKENWOODが保有していた特許です。 

この特許のアイデアは非常にわかり易く、ゆっくりエンコーダーを回転させた場合、周波数もゆっくり変化するが、早く回転させた場合、周波数変化ステップが大きくなり、回転速度以上の速さで周波数が変化すると言うものでした。 具体的には、ゆっくり回転している場合のアップダウンステップは10Hzですが、早く回転させると、アップダウンステップが100Hzに自動的に変わるというものです。

この話を聞いて、すぐにSSBトランシーバーのダイヤル機構を思い浮かべたのですが、私の知る限り、このような機能を設けたトランシーバーは有りませんでした。 理屈は正しいけど、実際に使用した場合、問題があり、実用化されなかったのか、私の知らない所ですでに実用化済みなのか、あるいは、この話の出所が、KENWOODのオーディオ製品を扱う関係者からの話でしたので、トランシーバーを扱う関係者へは、周知されていなかったのでは?と勝手に想像しながら、過去20年間ずっと疑問のままでした。 

そこで、この実験機の10Hzステップのエンコーダー側に、エンコーダーのパルス間隔が50msec以下になったら、ステップを100Hzに変更するプログラムを仕込んでみました。 結果は考えた通りの動作を行い、ゆっくりの場合1回転で240Hzしか変化しないのに早く回すと2KHzくらい変化します。 ただし、LCDの数値変化を見ているだけなので、実際にSSB信号を聞きながら操作した訳ではありません。 従いチューニング操作のフィーリングは判りません。

理屈的にはスピード判定を2段階で行い、最少ステップ10Hz、中間ステップ100Hz、最高ステップ1KHzで操作できれば、百数十円のエンコーダー1個でかなり経済的なVFOができそうです。 ソフト的には簡単に実現でき、10Hzの分解能を得ながら、簡単に200KHzの幅の可変が出来ます。 しかし、これでダイヤル操作のフィーリングがHFトランシーバーと同等なのかは判りません。 LCDの表示を見ていると、数KHz飛んだりと、スムースに変化はしていないようです。 

DDS_7MHz180102.cをダウンロード

例えば、7100KHzから7150KHzに周波数を変えようと、エンコーダーを回します。 7145KHzくらいまでは、スムースに素早く変更されますが、その後、回転速度を落とし、後2KHz以内くらいになったので、さらに回転速度を落としますが、意に反して周波数は7150KHzを飛び越えてしまいます。 仕方がないので、回転を反転しますが、ゆっくりやると10Hzステップでしか、変化しないので、少し早く回したくなります。 すると、またも行き過ぎて、周波数は7150KHz以下になってしまいます。 この現象は何回操作しても同じように繰り返されます。 

しばらく、時間をおいて原因を考察した所、割込み処理時、CNTをクリアーしていますが、このタイミングが悪そうです。 割込み発生から、しばらくは次の割込みを禁止していますが、CNTクリアーはこのディレー設定の前で行わなければ、意味が無い事がわかりました。 このアイデアに対応したソースファイルは以下です。

DDS_7MHz180104.cをダウンロード

CNTクリアーの位置を変更し、いくつかのパラメーターを調整すると、かなりスムースに目的の周波数に合わせ込む事が出来るようになりました。 しかし、まだ、時々、目標周波数の500Hzくらい手前で1KHzくらいジャンプする事があります。 しばらくは、パラメーターを微調整してみる事にします。

正月休みの最終日の夜、風呂に入っていたら、改善アイデアが浮かびました。 エンコーダーのパルス間隔を1msec単位でカウントしていますが、この時のタイマー1の割込み優先度より、エンコーダーの回転検出のINT1,2からの割込みの方が優先度が高く、INT1,2からの割込み処理中はタイマー1からの割込みがブロックされている可能性がありました。 また、INT1,2からの割込み処理が済んでから、タイマー1による割込みによるカウンターをクリアーしていましたので、正確にエンコーダーのパルス周期をカウントしていない可能性もありました。 

そこで、まず、エンコーダーからの割込みよりタイマー1からの優先順位を上げる事にしました。 そして、タイマー1によるカウント値CNTもエンコーダーから割込みが有った直後にiCNTという変数に退避させた後クリアーする事にしました。 さらに、1KHzステップで変化する場合、最初のインクリメントまたはデクリメント時、100Hz及び10Hzの値は00に丸める事にしました。 例えば、7100,57という周波数でインクリメントした場合、最初は7101.00となり以降1KHzステップでアップしていきます。 デクリメントの最初は7100.00となり、以降1KHzでステップダウンしていきます。

同様に100Hzステップの場合も10HZの数値を最初0に丸めてからアップ、またはダウンさせるように変更しました。

この状態のソースファイルです。DDS_7MHz180106.cをダウンロード

1KHz、100HzのiCNTしきい値も微調整した事で、かなり素早く目標周波数に合わせこむ事が出来るようになりました。 ただし、まだ完全ではなく、行き過ぎも頻度は少なくなりましたが発生します。 

DDSに連続して書き込むと、近傍のスプリアスが増え、ビート音が濁って聞こえます。 従い、周波数に変更が無い時はDDSに書き込まないようにしました。 しかし、それでもビートの濁りは消えません。 原因はこの表面実装の基板の中で、DGNDとAGNDをつないである事かも知れません。 ICの足も、インターフェース用の出力ピンもわざわざ独立しているのに、基板内でショートしてあります。 ICの足を浮かし、AGNDを独立させる事を試みましたが、作業の途中で銅箔がはがれてしまい、動作不能に。 

Dds_add_475k

やむなく、予備の基板に交換し、DDS ICの周りに付けられているVCCとGND間のチップコンデンサにパラに4.7uFのチップコンデンサを3個追加しました。 少しは改善しました。S/Nが悪い時はあまり濁りは気になりませんが、S9くらいの強度の信号の場合、まだ濁りが気になります。 この濁りの程度は、以前PLLの7MHz VFOを実験しましたが、それよりかなり悪い状態です。 フィルター前の波形はかなり汚いので、オシロで見てもかなり綺麗に見える2MHzくらいを出力し、TS-930で聞いてみましたが、濁りの程度は変わりません。 もしかしたら、ICそのものの性能かも知れません。 アナデバのDDSを使ったKEM設計の7MHz CWトランシーバーを持っていますが、この受信音は、濁りを全く気にする事が有りません。 チャンスがあれば、両者のスペクトルをスペアナで確認してみる事にします。 

本来の実験テーマである、安いロータリーエンコーダーによる操作性改善は、ソフトの改善アイデアも手詰まりになりましたので、新しいアイデアが出るまで、ソフトやハードの更新は休止します。

Dds_71mhz

DDSのAD出力端子に7MHzのBPFを追加し、1石アンプで増幅しました。 左の波形はRF OUTの出力コネクター部分の波形で、1.5Vppのレベルです。

この状態での配線図です。

7MHzDDS180106.pdfをダウンロード

この基板で信号純度の改善検討を行っていましたが、その途中で、5Vの3端子レギュレーターが入出力ショートモードで壊れてしまい、その結果5Vラインに12Vが流れ込み、PICkit3とLCDそれにLCDがつながれていたPICのI/O3ピンが壊れてしまいました。 3端子レギュレーターはNJM2845といICでしたが、このICは出力をGNDへ短絡すると、入出力ショートモードで破壊するようです。 この破壊モードは今回が初めてではなく、AM送信機検討中も同様な破壊モードになり、多くのICを壊してしまいました。 7805タイプの3端子レギュレーターは電流リミッターが働き、ショートモードで壊れる事は有りませんが、このICは違うようです。 2度と使わない事にします。

PICkit3が壊れるまでの間に変更を加えたソフトの最終状態は以下でした。

DDS_7MHz180210.cをダウンロード

 DDS VFOの実験(AD9833) 2へ続く。

このPICkit3はなんとか修理完了し、また現役に復帰しました。

PICkit3 の修理 を参照下さい。(2018年8月)

INDEXに戻る