1.はじめに ジャンクオーディオの修理でいつも楽しい時間を過ごしているが全ての修理がいつもいつもうまくいく訳でもない。 修理のために高額な部品が必要となればその時点で修理を諦めることが多々ある。 CDプレーヤーやMDレコーダーなど光学系の機器の故障においては、使われているピックアップが消耗品であることから、 ピックアップを交換すれば治るケースがほとんどであるが、このピックアップの値段が非常に高いのがネックである。 ピックアップはレーザーを使用した精密部品であるだけに、購入したジャンク品本体の数倍もの値段がする。 そのためにピックアップの劣化と判った時点で修理は終わりとしている。特にその機器にこだわりでもない限りこれ以上の 投資はしない。 そんな訳で手元には使えないCDプレーヤーやMDレコーダーのジャンク品が貯まってしまう。 そこでこれらの有効活用として、電子工作のネタに使ってしまおうというのが今回の企画。 2.発振器とカウンタの製作構想 昨年夏に16ビットPICマイコンを試して見ようとマイコン基盤が付属した書籍を購入した。CQ出版のマイコン活用シリーズの 中の一冊、 「PICマイコンスタートアップ」という本だ。マイクロチップ社の16ビットマイコン「dsPIC30F2012」を搭載した基板が付属している。 開発環境は、マイクロチップ社のWebサイトから無償で手に入る。 書籍の例題に従いLEDの点滅など一通り試し、このマイコンの基本的な使い方が判ると付属基盤はそのままとなっていた。 このままこれを遊ばしておくのも勿体ないと思い、この付属マイコン基盤を使った面白い電子工作はないものかと考え、 思いついたのが波形発振器と周波数カウンタの製作だ。 手元にあるジャンクのMDレコーダー 「DMD-F101」にこのマイコン基盤を組み込み、波形発振器と周波数カウンタを 製作しようと考えた。
「DMD−F101」のフロントパネルにある操作ボタンやディスプレーはそのままに、発振器やカウンタの機能操作ボタンとして 使うことにする。またディスプレーには、発振中の波形の周波数を表示したり、カウンターで測定した測定結果を表示 させたりすることにする。 さらに、発振器では、周波数を一定速度で上昇したり下降したりする自動スィープ機能を設けてみたい。 ディスプレーのVFDは、その明るさを高級機並みに調整できる機能も付加してみたい。 「DMD-F101」のバックパネルには、アナログのLINE-OUT、LINE-INのオーディオ端子がある。発振器の出力は、LINE-OUTから出力し、 カウンターの入力信号は、LINE-INから入力するものとする。 と、まぁこんな構想の元にそれを実現すべく「DMD-F101」の回路解析ならびにPICマイコンのプログラム設計に取り掛かることにした。
3.「DMD-F101」の回路解析 3−1.ディスプレーパネル部の解析 PICマイコンでディスプレーを制御したりボタンの操作を検出させるために必要な情報を得るためにディスプレーが納まった フロントパネル部分を中心に解析を開始した。 「DMD-F101」では、本体基盤側にH8Sマイコンが搭載され、ディスプレーの制御には、専用のコントローラーIC(M66005-001FP、 フロントパネルに搭載)が使われていた。ディスプレーを制御するには、H8Sマイコンに成り代わってこのコントローラーICと通信を 行えばよいことになる。
ちなみにこのMDレコーダとセットとなるレシーバーアンプの 「DRA−F101」では、マイコンにuPD780208GFが使われている。こちらのマイコンは ディスプレーの制御も可能なマイコンであるので専用のコントローラーICは搭載されずに、このマイコンでディスプレーの制御が行なわれている。 この場合には、PICマイコンでディスプレーを制御することは困難(VFDを直接制御するのは配線とプログラミングが大変)となり改造は諦めざるを得ないことになる。
「DMD−F101」も一般的なオーディオ機器の作りがしてあり電源コンセントにプラグを差し込むと、マイコンとスタンバイ動作に必要な個所だけに 電源が供給され、MDユニットなどその他の回路には電源は供給されない。これにより待機時の消費電力を最小としている訳だ。 マイコンは初期化動作の後、フロントパネルのボタンが押されるのを監視し続け、PWRボタンが押されるとMDユニットやその他の回路へ 電源を供給するように電源回路をコントロールする。これには、リレーが使われることが多く、このレコーダーでも電源回路部分にリレー が搭載されていた。 フロントパネル内部の基盤について、パターンを追いかけて回路を解析してみた。その結果を図1に示す。またこの基盤と本体基盤を 結ぶケーブルコネクタの端子割り当ては、解析の結果、表1に示すとおりであった。 このレコーダーも操作ボタンのオン・オフの検出は、マイコンのAD入力で行っているようだ。多数のスィッチのオン・オフを デジタル入力で検出するとなるとマイコンの入力ポートを沢山必要とするが、AD入力なら少ないポート数で済む。 PICマイコンでボタンの操作を検出するプログラムを作成するにあたり、各ボタンを操作した時にAD入力に入力される電圧を調べて見た。 表2、表3に示すのがその結果である。表は、読み取った回路の抵抗値から算出した計算値であり、実際は抵抗値のバラツキにより若干異なるものと思われる。 プログラムでの検出は、ボタンを押した時にAD入力に発生する電圧の範囲を予め定めておき、その範囲内の電圧であれば該当のボタンが 押されたものと判断するようにすればよい。 表4に各ボタンが取り得る電圧の範囲を示す。AD入力の電圧を読み取り、その値が10E(16進)より小さければボタン1が押されたことになり、大きければ、 次の30A(16進)と比較し、それより小さければボタン2が押されたことになる。 30Aよりも大きければ、さらに次の値と比較するのだ。これを順次繰り返せばどのボタンが押されたか判定できる。 なお、ここでは5Vを12ビットでFFF(16進)としている。
図1の回路図からも判るとおり、2つのボタンを同時に押してもそれを判定することは出来ない。 勿論、KEY1のボタンとKEY2のボタンの同時押しは、AD入力ポートが別であるので判定できる。 古いオーディオ装置で、あるボタンを押した時に、そのボタンとは別のボタンを押したような動作を経験することがあるが、 それは経年劣化でボタンの接触抵抗が大きくなり、AD入力の電圧値が想定の電圧範囲から逸脱してマイコンが誤判定するからである。 3−3.ロータリーエンコーダーの回転検出 操作パネル右側にある回転つまみには、可変抵抗器ではなくロータリーエンコーダーが使われている。 最近のオーディオ装置のボリュームは、マイコンで音量制御を行うために可変抵抗器ではなくロータリーエンコーダーが使われることが多い。 DENONのコンポでは、このロータリーエンコーダーの経年劣化による不具合をよく耳にする。 音量を小さくしようと左に回転しているのに音量が下がらず、逆に上がったりするというのがそれだ。 ロータリーエンコーダーの回転検出は簡単だ。エンコーダーからは2つの接点が出力されている。 接点出力は、VCCに抵抗でプルアップされており、回転に応じて接点がオンオフすると出力には、GNDが0、VCCが1のパルスが発生する。 2つの接点で発生するパルスには、位相差が設けられており、どちらか一方のパルスに着目し、そのパルスの立ち上がりを検出した時に、 もう一方のパルスの状態が0であれば左(右)回転であり、1であれば右(左)回転であると判定できる。 3−4.ディスプレーコントローラーの制御 ディスプレーコントローラーに関する信号は、4つ。RESET、CS、SCLK、SDATA だ。RESETは、コントローラーICをリセットするもの。CSはこのICの選択、 SCLKは、シリアル通信のためのクロック信号、SDATAはシリアル通信で伝送するデータだ。これらの信号のタイミングや条件は、コントローラーICである 「M66005-001FP」のデーターシートに詳しく書かれている。付属基盤に搭載の「dsPIC30F2012」では、SPI通信モジュールが内蔵されているので簡単に制御 できそうだ。 FIL1、FIL2、-35Vは、ディスプレーであるVFDの駆動電源であり、これらはスタンバイ状態でも供給されており、特に改造にあたって検討すべき事はない。 DMD-F101の動作を確認してみると、RESET信号は、スタンバイ状態では、常に0であり、電源が入っている時には、常に1のままであった。PICによるRESET 信号の制御は省略できるかもしれない。 3−5.アナログ入出力回路の解析 発振器出力とカウンタ信号入力に使用するアナログ入出力回路を調べてみた。入力、出力ともOPアンプ「4510」が使われており、 OPアンプの電源は、スタンバイ状態では供給されていない。
メイン基盤とMDユニットを接続するコネクタには、MDユニットへのANALOG-INと、MDユニットからのANALOG-OUTの端子がある。 アナログの入力信号は、背面のLINE-IN端子からOPアンプ回路を通ってコネクタのANALOG-IN端子に出力されてくる。 その逆に、MDユニットからのアナログ出力信号は、コネクタのANALOG-OUTからOPアンプ回路を通って背面のLINE-OUTに出力される。 PICマイコンで作成した発振器出力は、このコネクタ端子のANALOG-OUTに接続し、カウンターの入力は、ANALOG-INに接続すればよいわけだ。 LINE-OUT手前には、トランジスタによるミューティング回路が組み込まれていた。MDを再生していない時は、ミュート状態であった。 今回の改造では、MDユニットを取り外してしまうのでH8Sマイコンがミュート状態を解除することはない。このため、常時ミュートを オフの状態にする改造が必要だ。あるいはトランジスタ回路を取り去ってしまっても良い。 これらの解析結果を図2アナログ入出力回路に示す。 4.PICマイコン基盤の回路設計 4−1.DDS方式の発振器
PICマイコンで方形波を発生させるのは簡単だ。インターバルタイマーによってデジタル出力ポートに1と0を交互に出力すれば良い。 ところが今回は正弦波や三角波を発振させたいと思うのでこの方法では無理だ。そこでDDS(Direct Digital Synthesizer)方式で 発振器を作成することにした。これならD/A変換器さえあれば簡単に実現できる。 今回使用する「dsPIC30F2012」には、12ビットのA/Dコンバーターは内蔵されているが、生憎とD/Aコンバーターは内蔵されていない。 そこで簡単にR-2Rラダー抵抗によるD/Aコンバーターを外付けで作成することとした。PICのRB0からRB7までの8ビットを使った D/Aコンバータとした。なお、RB8とRB9の2ビットを追加して10ビットのD/Aコンバーターとすることも可能であるが、ポートに余裕がないので 8ビットで我慢することにした。 予め計算された正弦波や三角波の波形データ128サンプル分をメモリに蓄積しておき、インターバルタイマーで波形データを順次読み出してRBポートに 出力すれば、D/Aコンバーターからは正弦波や三角波が出力される。タイマーの周期を変化させれば出力周波数を変化させることも出来る。タイマーの 分解能次第では、低周波から高周波まで正確に1Hzステップでの周波数変更も可能となるはずだ。 4−2.カウンター入力回路 周波数カウンターは、dsPICに内蔵の入力キャプチャーモジュールを使えば簡単に実現できる。入力信号の立ち上がりから 次の立ち上がりまでの時間を計測し、逆数を取れば周波数が判る。信号波形を直接計数するのではなく、波形の周期を 測定する、いわゆるレシプロカル方式でのカウンターだ。 PICへの入力信号がデジタルパルスなら、直接マイコンに接続しても問題はないが、アナログ信号の場合には、マイコンの入力の手前で 信号を1、0のデジタルレベルに変換してやる必要がある。そこで、OPアンプによるコンパレーター回路を設けることにした。 OPアンプは、+5Vの単電源にて動作させることにする。 OPアンプの非反転入力、反転入力ともに抵抗分圧にて+2.5Vのバイアスをかけ、非反転入力側に被測定信号を入力することにした。 カウンターの入力となるメイン基盤のANALGO-INから出てくる入力信号は、直前のコンデンサで直流カットされているので、入力信号の 0クロス点でコンパレーターが働くことになる。コンパレーター出力のチャタリングを防止するために、1kと100kによる正帰還をかけ、 若干のヒステリシスを持たせておいた。 4−3.キーの入力とディスプレー制御 キーの入力やディスプレー制御はデジタル入出力処理であり、PICマイコンのポートに信号を直結できるため、特に外付け部品などは 不要だ。本体基盤側の配線パターンを修正すれば良い。 操作パネルの電源LEDの制御や電源の入切処理、ディスプレーコントローラーのRESET処理は、PICマイコンではなく、 本体側のH8Sマイコンで行わせることにした。全てPICマイコンで制御することも不可能ではないが、今回は、PICのポートが足らないので 2つのマイコンで機能分担させることにした。KEY1に含まれるPWRボタンは、回路から切り離してH8Sマイコンに直接入力できるようパターン 修正が必要だ。 5.PICマイコンのプログラム設計 5−1.DDS発振器 インターバルタイマーの周期割り込みにより波形データを出力させるわけだが、この割り込み周期の最小値は75命令サイクルとした。 このPICのタイマーは1命令サイクル毎にカウントアップするので、割り込みの最小周期を、1命令サイクルは極端としても数命令サイクルに 設定することは可能であるが、割り込みの中で行う波形データ出力処理に要する命令サイクル数よりも小さくは出来ない。 また、キー入力監視やディスプレー制御にもCPUリソースを割り当てなければならないので、ここでは、取り合えず75命令サイクルとした。 なお、波形データの出力に要する命令サイクル数は、30サイクル未満と想定している。
このPICの命令クロックは30Mhzなので、75命令サイクルによる最小の割り込み周期は400Khzとなる。1波あたり128サンプルとすると、 発振可能な最高周波数は、400Khz/128=3125hzとなってしまう。これでは使い物にならないので、発振する周波数帯に応じてサンプル数を 変化させることにした。プログラム上では、表5のとおりに設定することにした。 3本あるインターバルタイマーの内、発振器には、2番目のタイマーT2を使用する。T2の周期レジスタであるPR2レジスタに75を設定すると 75命令サイクル毎にタイマーT2の割り込みが発生する。割り込み毎に、波形のサンプルデータをRBレジスタに順々に書きだすと3125hzの正弦波が 出力される。 5khzの周波数を発振させるには、命令クロック30Mhzを、5khzを生成するサンプリング周波数 320khz(5khz x 64) で割った値である 94 を T2の周期レジスタであるPR2レジスタに設定すれば良いことになる。なお、5khzの時のサンプル数は表5に示したとおり64とする。 5−1−2.DDS発振器のプログラム設計 DDS発振器のプログラムは次のように設計した。 まずは、波形データをunsigned char型の配列に準備する。R-2RラダーによるD/A変換器は8ビットなので、 char型の配列とした。正弦波、三角波、鋸波の128サンプル分の波形データを、sin_wave[128], triangle_wave[128], saw_wave[128]とする。これらは、グローバル変数としてソースプログラム内で初期化宣言しておく。 // sin wave data table 正弦波の波形データ 128サンプル unsigned char sin_wave[128] = { 0x80, 0x86, 0x8c, 0x93, 0x99, 0x9f, 0xa5, 0xab, 0xb1, 0xb6, 0xbc, 0xc1, 0xc7, 0xcc, 0xd1, 0xd5, 0xda, 0xde, 0xe2, 0xe6, 0xea, 0xed, 0xf0, 0xf3, 0xf5, 0xf8, 0xfa, 0xfb, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfd, 0xfb, 0xfa, 0xf8, 0xf5, 0xf3, 0xf0, 0xed, 0xea, 0xe6, 0xe2, 0xde, 0xda, 0xd5, 0xd1, 0xcc, 0xc7, 0xc1, 0xbc, 0xb6, 0xb1, 0xab, 0xa5, 0x9f, 0x99, 0x93, 0x8c, 0x86, 0x80, 0x7a, 0x74, 0x6d, 0x67, 0x61, 0x5b, 0x55, 0x4f, 0x4a, 0x44, 0x3f, 0x39, 0x34, 0x2f, 0x2b, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x13, 0x10, 0x0d, 0x0b, 0x08, 0x06, 0x05, 0x03, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0b, 0x0d, 0x10, 0x13, 0x16, 0x1a, 0x1e, 0x22, 0x26, 0x2b, 0x2f, 0x34, 0x39, 0x3f, 0x44, 0x4a, 0x4f, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x74, 0x7a, }; // triangle wave data table 三角波の波形データ 128サンプル unsigned char triangle_wave[128] = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, ....... . . }; // saw tooth wave data table 鋸波の波形データ 128サンプル unsigned char saw_wave[128] = { 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, ....... . . };D/A変換器への出力は、RBポートへの書き込みとなるが、この処理は、タイマーT2の割り込み処理により実施する。 T2タイマーの割り込み処理ルーチンは次のとおり。 // T2 Interrupt routine (wave out) unsigned char *wave; // データテーブル unsinged int wvidx; // データテーブル内データ参照インデックス unsigned int wvstp; // サンプリング数に応じたデータ参照ステップ void __attribute__ ((__interrupt__, __shadow__, no_auto_psv)) _AltT2Interrupt(void) { IFS0bits.T2IF = 0; // clear interrupt flag PORTB = wave[wvidx]; wvidx += wvstp; wvidx &= 0x7f; }5000Hzの正弦波を発振する場合、割り込みルーチンが使用する変数を次のように設定する。 wave = sine_wave; wvidx = 0; wvstp = 2; // 5000hzを64サンプルで出力する。128/64=2三角波を発振する場合には、 wave = triangle_wave; と設定し、鋸波を発振する場合には、wave = saw_wave;と設定する。 次にタイマーT2を次のように設定する。 #define SYSTEM_CLOCK 29378621L // 実際の命令クロック30Mhzを設定。この値を変更すれば周波数を微調整できる。 T2CON = 0; // prescale は使わない。 PR2 = SYSTEM_CLOCK / (5000 * 64); // 5000hz を出力するサンプリング周波数でクロックを割る以上の準備の後、T2CONbits.TON = 1; としてT2タイマーを起動すれば、 320khz間隔で割り込み処理が実行されて、D/A変換器からは、5000hzの正弦波が出力される。 周期レジスタPR2の値を一定時間間隔で増大、あるいは減少すれば、発振周波数を上下にスィープすることが出来る。 5−2.周波数カウンター 周波数カウンターを実現するための入力キャプチャモジュールは、16ビットタイマーのタイマー値を入力信号の立ち上がりエッジで キャプチャするため、その最大値は、FFFF(16進)となる。最初の立ち上がりエッジによるキャプチャ値をTsとし、次の立ち上がりエッジに よるキャプチャ値をTeとすると、その差、Te-Tsの最大値もFFFF(16進)となる。 タイマーは1命令サイクル毎にカウントアップしているので、FFFFが1周期となる周波数は、30Mhz/FFFF(16進)=457hzと なり、457Hz未満の信号は、正確にカウント出来ないことになる。 そこで、457hz未満の周波数測定の場合には、タイマークロックのプリスケール値を1:64に設定することとする。これで、7hz までの低周波数をカウント出来るようになる。更に低周波数を測定するには、プリスケール値を1:256にすれば良いが、 今回の製作では、7hzまでの測定としておく。 5−2−1.周波数カウンターのプログラム設計 2つある入力キャプチャモジュールのうち、今回は、2つ目のIC2を使うこととする。エッジ検出によるキャプチャー動作2回毎に 割り込みを発生させ、割り込み処理の中で、キャプチャーされたタイマー値の差を計算することとする。 その割り込み処理は次のとおり。 // IC2 Interrupt routine unsigned int CapData; void __attribute__ ((__interrupt__, __shadow__, no_auto_psv)) _AltIC2Interrupt(void) { unsigned int capd1, capd2; IFS0bits.IC2IF = 0; // clear interrupt flag capd1 = IC2BUF; capd2 = IC2BUF; CapData = capd2 - capd1; }カウンターの初期化手順は次のとおりに行う。 TRISDbits.TRISD9 = 1; // RD9 を入力ポートに設定 IC2CON = 0x0023; // T3を使用。キャプチャ2回で割り込み。立ち上がりエッジ毎回キャプチャー。 T3CON = 0; // T3タイマー停止 PR3 = 0xffff; // T3タイマーの周期を最大に設定IC2の入力となるRD9ピンを入力に設定し、IC2をセットするとともに、IC2がキャプチャーに使用するT3タイマーを停止しておく。 次に、 T3CONbits.TON = 1;と設定してT3タイマーを起動する。RD9に信号を入力すると、信号の2回の立ち上がりエッジ毎に、割り込み処理により入力信号の 周期が計算される。具体的な計測処理は次のように行う。 CapData = 0; while(!Capdata); freq = SYSTEM_CLOCK / CapData; // freq が計測された周波数となる。CapDataをクリアした後、割り込み処理によりCapDataが設定されるのを待ち、値が設定されたら周波数を計算して求める。 複数回の測定により平均値を求める場合には、少し手直しが必要だ。なお、高周波を測定する場合には、立ち上がりエッジ毎回毎に キャプチャするとTe-Tsの値が小さくなり測定誤差が大きくなってしまう。そこで、25Khz以上の周波数測定の場合には、立ち上がり4回毎に キャプチャするようにした。 5−3.キーの機能割り当て 「DMD-F101」のフロントパネルにあるキーには、表6のように、波形発振器や周波数カウンターを操作する機能を割り当てることにした。
EDITキーを押した時のメニュー処理には次のような処理を設けることにした。 波形発振器の時は、「発振周波数の設定」、「スィープ時の増減周波数の設定」、「ディスプレーの輝度設定」の3つ。周波数カウンターの時は、「測定帯域の選択」とした。 メニュー処理が起動された後、EDITキーを押す毎にディスプレーにこれらの処理を順次表示し、ENTERキーが押されると当該処理を行うものである。 周波数カウンターの「測定帯域の選択」では、"10 - 500Hz?", " 500 - 25kHz?", " 25k -100kHz?" の3帯域の選択とした。前述したように、427hz未満の低周波数の測定の 場合には、"10 - 500hz?" を選択し、タイマーのプリスケール値を1:1から1:64に変更することとなる。 完成したプログラムの波形発振器部分と周波数カウンター部分のソースファイルを公開しておく。何らかの参考になれば幸いである。 6.ブレッドボードによる試作と動作確認 以上の解析・設計をもとに、ブレッドボードに回路を試作し、必要なプログラムをPICに書き込んで動作テストを行った。 「DMD-F101」は、基盤内の各点の電圧や信号レベルを容易に確認できるよう全て分解した状態で実施した。一応、電源トランスなどは、 絶縁テープを巻いて電気トラブルが発生しないよう留意していたのだが、 うっかりとオシロスコープのGND側クリップが、メイン基盤の+5V配線に触れて電源ショートを起こしてしまう。 この後、完全に動作しなくなる。調べてみたら、電源回路部分に使われていた小型のICプロテクターが断線していた。代替部品もなく、プロテクターが挿入されていた部分を ワイヤーで接続しなんとか元通り動かすことができる。 このようなアクシデントはあったが、期待どおりの動作に満足し、本格的な製作に移ることにした。
7.マイコン基盤の製作とMDレコーダー基盤の改造 マイコン基盤は、ユニバーサル基盤で作成した。ICソケットの取り付けと抵抗によるD/A変換器の作成と、簡単な工作である。 「DMD-F101」の基盤改造は、主にディスプレーへの信号の横取りである。H8Sマイコンからの信号ラインを調べ、基盤上のジャンパー の箇所で切り離し、PICマイコンとの接続ピンを基盤側に取り付けた。ディスプレーのPWRボタンは、H8Sマイコンで検出させる必要があり、 こちらは、パターンカットを行い、フラットケーブルとは別配線で接続を行った。 LINE-OUTのミュートの解除は、トランジスタが常時オフとなるようトランジスタのベース端子をGNDに落としておく。またLINE-INから ANALOG-INまでのトータルの増幅度が小さかったので、OPアンプ回路を少し修正した。
8.発振器の出力波形 製作した発振器の出力波形を次に示す。最終的に5種類の波形を発生できるようにした。いずれも1000Hzで発振させている。D/A変換器の出力点で観測している。 今回製作した発振器では、周波数が高くなるとサンプル数を小さくしているため、D/A変換器の出力では、綺麗な正弦波が出力されない。しかし、 LINE-OUTでは、「DMD-F101」のアナログ回路が一種の高調波フィルターとして働き、綺麗な正弦波が出力されている。ただし、出力レベルが小さくなるのは 致し方ないところ。
|