直線上に配置

[小ネタ]DDS方式1.5kHzサイン波発生器



 送信機調整用にレベル変動の少ない1.5kHzサイン波発生器を作りました。

AVRマイコンとR-2R抵抗ラダーによるDDS方式でサイン波を発生させていて、出力信号のレベルは主に内部の電源電圧に依存するため変動幅はごく僅かです。
周波数も水晶発振から分周した割り込みが基なので安定しています。
サイン波1サイクル当たり160ポイント、レベル分解能はP-P間255ステップです。


1 ハードウエアの構成

 MPUは1.5kHzの正弦波データを処理するため、20MHzクロック対応のATmega88P-20PUを使っています。
クロックは手持の発振器EC03 19.66MHzを使用していますが、サトー電気あたりで入手できる19.66MHzの水晶でも良いと思います。

MPUポートDの8ビットを出力とし、R-2R(実際はR/2-R)抵抗ラダーにより階段状に変化する疑似サイン波になります。
 
 疑似サイン波は[フォロワ]→[LPF]→[レベル調整兼出力アンプ] で構成構成したアナログ回路に入力されます。

アナログ回路もMPUと同じ5V電源のため、今回使用したオペアンプでは各段の出力が0〜Vcc-1.5Vという制約があるので、バイアス電圧を約1.7Vに設定しています。

初段フォロワ回路の入力側は、バイアスを与える抵抗をD/Aからの信号電圧を半減するのにも利用しています。
D/A出力が2.5Vを中心に±2.5V弱と大きいため、そのまま入力するとクリップしてしまう為です。

LPFはカットオフ周波数1.8kHz Q=0.5 12dB/Octで設定しています。

出力部は前段と直結するためとマイナスゲインにする必要から反転増幅回路になっています。
本機の目的からこの回路の半固定抵抗で出力を30mVrmsに調整しています。
定数を変更すれば、計算上は1Vrms程度の出力まで得られそうです。

(回路図はクリックで拡大↓)

2 出力信号の状態

 LPFを通すことで階段状の波形は見えなくなり、スペクトルを見ると高調波の中で2次が-53dBc程度で、3次以降は無視できるレベルでした。(負荷2kΩの状態)
歪率にすると約0.25%で十分実用レベルです。
信号レベルも安定で指針式のレベルメータでは変動が認められませんでした。

以下は出力信号の状態です
LPFによりきれいなサイン波になっています

波形とスペクトル画像はクリックすると拡大します
スペクトルはUSB-オーディオコンバータ経由でPCに取り込み、WS.exeを使って観測しました。

 ミリボルトメータを使って信号レベルを30mVrmsに設定

 左上のカウンタに周波数が表示されています
誤差-1.52Hz


3 ソフトウエア

 プログラム制作にはBASCOM-AVRコンパイラデモ版ver.2.0.7.1を使用しました。

 始めにEEPROMの内容とプログラム中のコサイン波形データを順次比較し、一致しない場合はEEPROMにデータの書込みを行います。
コサイン波データは1サイクルあたり160ポイントの1バイト(0〜254)です。

コサイン波のデータにしているのは、電圧変化の少ない+ピークで次のサイクルとつないだ方が繋ぎ目が目立たないだろうという目論見からです。

一度書き込みが行われれば故障などが無い限り一致するはずなので、通常は寿命に影響するEEPROM書込みは行われません
書込みが行われた場合はポートB.0がHレベルになります。

割込みはタイマー0を使っています。
タイマーのカウント数Nは
  クロック周波数÷N÷160=出力周波数 の関係があり
  クロック周波数19.66MHz N=82 で1498.48Hz、N=123 では 998.98Hz となります

割込みが発生する都度EEPROMから1バイトのデータを読み出してポートDにセットし、ポインタを1進めます。
コサイン波データを1サイクル分160回読み出すとポインタは初期状態に戻ります。


 * このプログラムの使用は自己責任でお願いします。
 * 利益を目的とした頒布や商用利用はできません。

'
' ***************************************
' * DDS Fullswing SinWave generator
' * 2022.05.14
' ***************************************



$regfile = "m88pdef.DAT"
$crystal = 20000000 ' Clock:Ext 19.66MHz
$hwstack = 32 ' default
$swstack = 10 ' default

Config Portd = Output
Config Portb.0 = Output
Dim Fdt As Byte ' Waveform data
Dim Wpt As Byte ' EEPROM write Pointer
Dim Rpt As Byte ' EEPROM read Pointer
Dim Eck As Byte

' ***************************
' * Eeprom Data check
' ***************************
Restore Wfdat
For Wpt = 0 To 159

Read Fdt ' Read orijinal data
Readeeprom Eck , Wpt ' Read EEPROM data

If Fdt <> Eck Then Goto Epset ' If don't match, goto EEPROM write

Next Wpt
Goto T0set ' goto Timer0 config

' ***************************
' * Eeprom write routine
' ***************************
Epset:
Restore Wfdat
For Wpt = 0 To 159 ' Data transfer to Eeprom
Read Fdt
Writeeeprom Fdt , Wpt
Next Wpt
Portb.0 = 1 ' EEPROM write indicater

' ***************************
' * Timer setting
' ***************************
T0set:
Config Timer0 = Timer , Prescale = 1 , Clear Timer = 1 , Compare A = Disconnect
Ocr0a = 81 ' Division number setting
On Oc0a Outsub Nosave ' Jump destination at the interrupt
Enable Oc0a ' Comparator 0a interrupt enable

Enable Interrupts ' All interrupt enable

' ***************************
' * Main routine
' ***************************
Main:
Do
nop
Loop

' ***********************
' * Cosin Waveform Data
' * 2.25deg.x 160points
' ***********************

Wfdat:
Data 254 , 254 , 254 , 253 , 252 , 252 , 250 , 249 , 248 , 246 '0-9
Data 244 , 242 , 240 , 238 , 235 , 233 , 230 , 227 , 224 , 220 '10-19
Data 217 , 213 , 209 , 206 , 202 , 198 , 193 , 189 , 185 , 180 '20-29
Data 176 , 171 , 166 , 161 , 157 , 152 , 147 , 142 , 137 , 132 '30-39
Data 127 , 122 , 117 , 112 , 107 , 102 , 97 , 93 , 88 , 83 '40-49
Data 78 , 74 , 69 , 65 , 61 , 56 , 52 , 48 , 45 , 41 '50-59
Data 37 , 34 , 30 , 27 , 24 , 21 , 19 , 16 , 14 , 12 '60-69
Data 10 , 8 , 6 , 5 , 4 , 2 , 2 , 1 , 0 , 0 '70-79
Data 0 , 0 , 0 , 1 , 2 , 2 , 4 , 5 , 6 , 8 '80-89
Data 10 , 12 , 14 , 16 , 19 , 21 , 24 , 27 , 30 , 34 '90-99
Data 37 , 41 , 45 , 48 , 52 , 56 , 61 , 65 , 69 , 74 '100-109
Data 78 , 83 , 88 , 93 , 97 , 102 , 107 , 112 , 117 , 122 '110-119
Data 127 , 132 , 137 , 142 , 147 , 152 , 157 , 161 , 166 , 171 '120-129
Data 176 , 180 , 185 , 189 , 193 , 198 , 202 , 206 , 209 , 213 '130-139
Data 217 , 220 , 224 , 227 , 230 , 233 , 235 , 238 , 240 , 242 '140-149
Data 244 , 246 , 248 , 249 , 250 , 252 , 252 , 253 , 254 , 254 '150-159


' **********************************
' * Waveform output subroutine
' **********************************
'
Outsub:
Readeeprom Fdt , Rpt
Portd = Fdt

Incr Rpt
If Rpt = 160 Then Rpt = 0
Return


製作過程ではAVRを使ったPWM式のAF発生器やウイーンブリッジ発振器なども実験しています。

PWM方式は周波数の自由度は高いもののサイン波に乗ってくるPWMの漏れが、簡単なフィルタでは取り切れませんでした。
ウイーンブリッジ発振器は低歪でS/Nも良好ですが振幅を安定度させるのが私には難しくてあきらめました。

DDS方式は水晶発振を基に作り出しますので周波数は安定しています。
今回の方法では細かい周波数設定ができないところが欠点です。

振幅は内部の3端子レギュレータの電圧安定度に依存しています。
変動は少ないので一度合わせておけば長期間無調整で使用できると期待しています。

MPUを使ったDDS方式と、LPFを通すことでどの程度の歪率になるかという点に関心もあって今回の製作を行いました。

【追実験】 オペアンプをCMOSタイプのLMC660CNに交換しました
 このICはGND電位付近から電源線圧付近まで出力できますので、バイアス電圧を電源電圧の50%に変更しています。
30mV出力(2kΩ負荷)での歪率が0.05%以下と交換前より大きく改善しました。
ドライブ能力が上がっていますので出力アンプの歪が減ったのかもしれません。

下図はオペアンプ交換後のスペクトラムです。


4 2号機でさらに歪改善

 2号機の回路は初号機とほぼ同じで、R-2Rラダーの抵抗値を大きくしてMPUの負荷を軽減したのと、出力部にグランドループを切るためトランスを実装しています。

R-2Rラダー用の抵抗は10kΩ1%の抵抗から±5Ωに収まるものを選別しています。
抵抗値を変更した結果、オペアンプ初段の出力波形が崩れたので入力の分圧抵抗も変更しています。

トランスを接続するとオペアンプの終段部が高周波で発振するので、対策として入力と帰還部にコンデンサを追加しました。

トランスは始めにサンスイST-71A(600:600Ω)を載せましたが、負荷の変化でレベルが少し変動するので、ST-32(CTを使い300:8Ω)に変更しています。
ST-32では多少の負荷変動ではレベルが変わりませんがST-71Aより発振しやすいため発振防止コンデンサの容量を大きくしました。

また電源オン時に一瞬発振しますが直ぐ正常な動作状態になり、不安定な様子がないので負荷によるレベル変動が無いことを優先してそのままにしています。
バイポーラのオペアンプとは様子が違いますね。
実装時にはオーディオパワーアンプのようなミューティング回路を設置するつもりです。

電源入力には高周波対策のフェライトコイル(実測10uH)を追加しています。
初号機は無くても問題なかったので、気休め程度です。

(2号機の回路図 クリックで拡大↓)

2号機の実装済基板(初期版)です。

基板中ほどの青い抵抗23本がR-2Rラダー

2号機では高調波が-80dBc近くまでさがりました。
アンプ部は変わってないのでR-2Rラダーを変更した影響だと思います。
よく見ると-80dBのラインから下の輝線がよれているのでノイズが乗っている様です。
S/Nは52dB*でイマイチですが用途としては問題ありません。
 *プログラムを直流出力のみに変更して残留分を測定

以下は参考まで菊水417A低周波発振器のスペクトラムです。
2次が見えていますが仕様の歪率0.05%に収まっていて、輝線の裾もさすがに綺麗です。

目標だった送信機調整用の周波数とレベルが安定したサイン波発生器ができました。
消費電流は12V40mA以下でした。

*ATmega88P-20PUが現在入手できません。
 ATmega328P-PUが代わりに使用できそうです。
 
                                           (C)JA1VZV 2022.5
                                          2022.06.11加筆修正


トップ アイコントップページへもどる

直線上に配置