最終更新時間:2009年07月22日 18時04分01秒
[公開:any]
[電子工作/ラジオの製作]
[電子工作/AVR]
[AVR,ATmega88,DDS,LA1600,4046B,74HCU04,短波ラジオ,ラジオ,PLL]
「AVR-DDSでPLL-VFOの実験」を短波ラジオのVFOとして使ってみようと色々と試しました。短波ラジオの回路は、DBM-IC(ダブルバランスドミキサー)のNE612を使ったダイレクトコンバージョン受信機を試してみましたが・・・・・・どうもノイズ交じりで歪んだ受信音となります。PLL-VFOの代わりに信号発生器から純度の高い正弦波を局発信号として加えるとクリアな受信音が得られます。
・・ということで、ダイレクトコンバージョン受信機には、発振波形に歪みの無い純度の高い信号が必要だと思われます。(・・・AFフィルタを単純なCRフィルタとしたのがいけないかもしれません。)
で・・結局、短波ラジオの回路をLA1600を使ったオーソドックスな形式に変更しました。中間周波数455KHzのシングルスーパーヘテロダインです。この回路では、ブレッドボード上のPLL-VFOを使っても、ある程度は、まともに受信できます。ただ、やはりクリアな受信音ではなく、ノイズが耳につきます。信号発生器の信号を局発として注入するとクリアな受信音なので、やはりVFOからの信号が良くないようです。
PLL-VFOの周波数範囲を5〜15MHz程度を目標として、良質な局発信号を提供できるようにVCOを色々と試してみました。
はじめにPLL-ICを4046Bから74HC4046に変更して、内蔵のVCOを使用してみました。このVCOは20MHzを超える周波数まで発振します。しかし、受信してみるとノイズがひどい状態です。発振波形も方形波に近く直接使用するのはムツカシイと思われます。12MHzカットオフのLPFを挿入してスペクトラムをGigaStで確認しました。高調波も出ていますが、それよりも基本波に近接する雑音が大きくて問題アリです。この近接雑音信号はフィルタで取れません。
つぎにインバータを使ったフランクリン発振回路を試してみました。LCメーターを作ったときにオシロで確認した波形がきれいな正弦波に見えたので使えそうな気がしていました。
発振波形も、発振周波数範囲も問題ありません。スペクトラムを確認すると74HC4046のVCOよりは、良さそうです。・・が受信してみるとノイズがあります。それほどひどくは無いので使えないことはないと思いますが、ビート音が気になって長時間、聞くには厳しい状況です。ループフィルタを調整したり、高調波をLPFで落としても受信音が改善しないということは、基本波の質が悪いのが原因かと思われます。
で、・・結局、普通のハートレー発振回路に戻しました。発振周波数範囲は多少狭くなりますが、受信音が一番まともです。多少のノイズもありますが、夜間などはまったく気にならなくなります。スペクトラムを見てみると、前の74HCU04のものと大差ありません。GigaStの性能では判別できないようですが、VCO自体の位相ノイズ等の何かが影響しているのでしょう。
最終的な回路図です。位相比較器は、4046Bを使用します。・・74HC4046は、高価なので気軽には使用できません。^^;
LA1600の前段にFETのGGアンプを入れました。本来、LA1600の前段には、プリセレクタが必要です。・・が、受信帯域が広いため色々と試してもいいものが出来ませんでした。LA1600に直接アンテナをつないでもある程度は受信できますが、インピーダンスマッチングが取れないのか、今ひとつ感度が上がりません。・・・ということで、苦肉の策として広帯域アンプを入れました。なるべく低雑音で歪まないものがいいと思い書籍を参考にFETのJ310をゲート接地で使用します。NFも低いのでノイズの増加はあまり気になりません。2m程度のワイヤーアンテナなら、夜間の強力な入電でも飽和することは無いようです。
いつもの基板実装図です。PCBEで作成しました。高周波部とPLLコントロール部で2枚の基盤に分けました。高周波部は、サンハヤトの高周波対応メッシュアース付きのICB-88SEGを使用しました。メッシュアースがあるので高密度実装が可能です。
完成した高周波基板です。メッシュアースでどこでもアースに落とせるので便利ですが、あまりに高密度にしてしまったのでちょっと苦労しました。
PLL基板も作成してバラックでテストします。ブレッドボードでテストしたときよりもノイズが少なく安定した受信状態です。74HC4046のVCOも74HCU04のVCOもちゃんと基板で作成すれば実用可能かもしれません。ロータリーエンコーダは、秋月電子のクリック付をクリックなしに改造して使用しています。改造が悪いのか、ブレッドボードでテストしたときに使用したアルプスのエンコーダと比べてチャタリングが多くお勧めできません。
ケースは、タカチのYM-180を使用しました。電源もトランスと3端子レギュレータを使用して内蔵しました。 イヤホン端子をつけるのを忘れましたが、前面パネルには取り付けるスペースがありません。
アンテナしだいですが、室内の2m程度のワイヤーアンテナで日中でもラジオ日経は受信することが出来ます。背面アンテナ端子(BNCコネクタ)に秋月電子で購入したBNC付きロッドアンテナ(全長50cm程度)をつないだ状態だと日中はかなり厳しいものがあります。夜間は全く問題なく外国の主要な放送が十分な感度で受信できます。
受信機を窓際に持っていったところ、秋月電子のBNC付ロッドアンテナで十分な感度で受信できました。日中でも韓国や中国の主要な放送は受信できました。通常は、このアンテナで十分かもしれません。(2009-07-25)
ロータリーエンコーダを回すとノイズが大きいのが気になります。ロータリーエンコーダそのもものノイズと言うよりPLLのロックのタイミングによって発生していると思われます。ループフィルタが最適化できていないかもしれません。そもそも位相比較する基準周波数が変動する場合のループフィルタの最適設計値ってあるのでしょうか?
ノイズの原因がわかりました。→ロータリーエンコーダの処理は、ピン割り込みを使用していますが、この割り込み内での処理中にTimer1の波形出力割り込みができないため、一時的に周波数が変動(低下)して発生したノイズでした。AVRのデフォルトでは、割り込み中は、他の割り込みを強制的に禁止し、多重割り込みできないようになっているようです。ロータリーエンコーダ処理の割り込みルーチンの先頭で強制的に割り込みを許可する命令をいれて多重割り込みを許可したところ、ノイズは完全に消滅しました。(2009-08-04)
AVRで使用したプログラムです。AVR-Studio4.16とWinAVR-20090313で作成しました。基本的に以前実験した「AVR-DDSでPLL-VFOの実験」と同じものです。AVR-DDSは、方形波出力バージョンです。実験続編の正弦波バージョンと比較してみましたが、耳で聞く限りはどちらも同じような状況でした。せっかくマイコンで制御するので今回は、EEPROMを使った周波数メモリーを20チャンネル確保しました。プッシュボタンで、メモリモードとVFOモードを切替し、VFOモードで長押ししたときにメモリー保存、メモリーモードで長押ししたときにメモリ周波数をVFOに読み出しするようにしてあります。もうひとつのプッシュボタンは、周波数ステップを1KHzと20KHzの切替となっています。
1 |
#include <avr/io.h> #include <util/delay.h> #include <avr/eeprom.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #include <stdio.h> #include "lcd.h" #define cbi(addr,bit) addr &= ~(1<<bit) #define sbi(addr,bit) addr |= (1<<bit) #define SF 160000 // Sampling Frequency #define ACCU 65536 // Accumulator FILE *fp; // for LCD volatile unsigned long freq; // DDS出力周波数[Hz] unsigned long ftmp; unsigned int delta; // 増分 unsigned int phe; // フェーズ unsigned int pos; // 波形配列のポジション unsigned int mem; // Memory number unsigned char diff; // 周波数の増減量[Hz] unsigned char mode; // VFO mode or Memory mode volatile unsigned char renc_now, renc_old; // エンコーダ値 static unsigned int fm[21] __attribute__((section(".eeprom"))); void delay_ms(unsigned int count) {while(count--) { _delay_ms(1); }} //---------------------------------------------------------------- // Timer1 Compare match interrupt // サンプリング周期で割り込み。波形のポジションを計算して出力。 // 方形波のみなので、波形データを使用せず、任意の1bitのみに出力。 // --------------------------------------------------------------- ISR(TIMER1_COMPA_vect) { phe += delta; if(phe >> 15) // >>8(/256) and >>7(/128) sbi(PORTD, PD0); else cbi(PORTD, PD0); } //---------------------------------------------------------------- // Pin changed interrupt // ロータリーエンコーダからの信号で割り込み。 // 右回りか左回りかを判別してDDS周波数を増減 //---------------------------------------------------------------- ISR(SIG_PIN_CHANGE1) { sei(); // 多重割り込みの許可 if(bit_is_set(PINC, PC3)){ if(bit_is_clear(PINC, PC4)) renc_now = 0; else renc_now = 1; } else { if(bit_is_set(PINC, PC4)) renc_now = 2; else renc_now = 3; } if((renc_now + 3 + 1) % 3 == renc_old) { if(mode == 0) { if(freq > 400) freq -= diff; } else { if(mem > 0) mem -= 1; } } if((renc_now + 3 - 1) % 3 == renc_old) { if(mode == 0) { if(freq < 20000) freq += diff; } else { if(mem < 20) mem += 1; } } renc_old = renc_now; if(mode == 1) { eeprom_busy_wait(); freq = eeprom_read_word(&fm[mem]); if(freq > 20000 || freq < 400) freq = 8000; } delta = freq * ACCU / SF; } int main() { unsigned char sw0_state, sw1_state; unsigned int tim; DDRB = 0b11111111; // LCD Output DDRC = 0b00000100; // SW input DDRD = 0b11111111; // DDS Output PORTD = 0b00000000; // PORTC = 0b00111011; // pull up lcd_init(); lcd_cls(); fp = fdevopen(lcd_putch, NULL); // LCD出力ファイルディスクプリタ sw0_state = sw1_state = 0; PCICR = _BV(PCIE1); PCMSK1 = _BV(PCINT12)|_BV(PCINT13); TCCR1B = 0b01001001; // Timer1 プリスケーラ 1/1 TIMSK1 = _BV(OCIE1A); // Timer1 compare match A interrupt OCR1A = 124; // 20MHz sampling 200kHz phe = 0; diff = 1; // DDS Frequency Up Down default 1Hz freq = 6358; // 6358 * 1024 - 455,000 = 6055KHz(Radio Nikkei) mode = 0; mem = 0; tim = 0; delta = freq * ACCU / SF; sei(); while(1) { if(bit_is_clear(PINC, PC0)) { sw0_state = 1; delay_ms(10); } if(sw0_state && bit_is_set(PINC, PC0)) { sw0_state = 0; if(diff == 1) { diff = 20; // DDS 20Hz step ... VFO 20KHz step sbi(PORTC, PC2); } else { diff = 1; // DDS 1Hz step ... VFO 1KHz step cbi(PORTC, PC2); } } if(bit_is_clear(PINC, PC1)) { sw1_state = 1; delay_ms(10); tim++; } if(sw1_state && bit_is_set(PINC, PC1)) { sw1_state = 0; tim = 0; if(mode == 0) { mode = 1; ftmp = freq; eeprom_busy_wait(); freq = eeprom_read_word(&fm[mem]); if(freq > 20000 || freq < 400) freq = 8000; delta = freq * ACCU / SF; } else { mode = 0; freq = ftmp; delta = freq * ACCU / SF; } } if(tim > 60) { // スイッチ長押し(600mS)時の処理 sw1_state = 0; tim = 0; if(mode == 0) { // VFO周波数をメモリに格納 eeprom_busy_wait(); eeprom_write_word(&fm[mem], freq); lcd_goto(0, 0); fprintf(fp, "VFO->MEM"); } else { // メモリ周波数をVFOにセット eeprom_busy_wait(); freq = eeprom_read_word(&fm[mem]); if(freq > 20000 || freq < 400) freq = 8000; lcd_goto(0, 0); fprintf(fp, "MEM->VFO"); mode = 0; delta = freq * ACCU / SF; } loop_until_bit_is_set(PINC, PC1); } lcd_goto(0, 0); if(mode == 0) { fprintf(fp, "VFO M:%02d", mem); } else { fprintf(fp, "MEM M:%02d", mem); } lcd_goto(1, 0); fprintf(fp, "%5.0fKHz", (freq - 1) * 1.024 - 455.0); } } |
LA1600のフロントエンドにアンテナ同調回路を使用しないで広帯域プリアンプを使用しました。これは、受信周波数範囲の5〜12MHzに同調する回路がうまく出来なかったためです。受信周波数範囲が狭ければ、コイルとコンデンサ(バリキャップダイオード)を使った通常の同調回路で対応可能と思われます。・・・・・・ということで、ブレッドボードで試してみました。
発振回路は、アンバッファ・インバータの74HCU04を使用したフランクリン発振回路です。コイルにトロイダルコイルを使って作成したものを利用すると広範囲で発振します。今回は周波数範囲が狭くなりますが、使いやすい7MHzのFCZコイルを利用しました。この実験回路の発振範囲は、5MHz〜9MHzまでとなりました。
LA1600前段のアンテナ同調回路に、局部発振回路と同じようにFCZコイルとバリキャップダイオードによる同調回路を設けて受信してみました。多少、受信範囲の上端で感度が低下する感じがしますが、良好に動作します。フロントエンドに広帯域プリアンプを利用したものと比べると、全体的に感度が悪いのですが、AFにはざわついたノイズが少なく聞きやすく感じます。
広帯域プリアンプ仕様と比較して夜間の「混信」が少なくなるのを期待したのですが、あまり効果は感じられません。これは、受信機の選択度の問題であって、フロントエンドの問題ではなさそうです。
周波数範囲が、多少狭くなりますが、ロングワイヤーアンテナを使って遠距離の放送を聴くにはアンテナ同調回路を採用したものが良いと思われます。
実験に利用した回路図です。