ラベル USB-DAC の投稿を表示しています。 すべての投稿を表示
ラベル USB-DAC の投稿を表示しています。 すべての投稿を表示

2023年4月11日火曜日

Raspberry Pi Pico/Pico WからI2SでPCM5102ボードにオーディオ出力(USB-DAC)

この記事では,Raspberry Pi Picoをpico audioボードに接続して,ここにあるプログラムをRaspberry Pi Picoに書き込んで,USB-DACとして使いました.

ここでは,ここで購入できる一般のPCM5102 I2Sボードを使ってUSB-DACを作成します.

プログラムの書き込みはここと一緒です.配付されたプログラムから何も書き換えていません.

ハードウェアの結線は以下のとおりです.このDACボードは5V電源なので,以下のように接続します.


USB-DACボードの左から順に書いています.

  • GND→接続なし
  • MCLK→接続なし
  • BICK→PICO 31pin
  • DATA→PICO 34pin
  • LRCK→PICO 32pin
  • GND→PICO 38pin
  • MUTE→結線なし
  • VCC→PICO 40pin

Raspberry Pi Pico/Pico Wのピン配置はこのようになっています.

これでパソコンからUSB-DACとして認識して音が出ました.


2022年4月14日木曜日

CQ出版のBlackfin DSPセットアップとLチカ,このボードをUSB-DACとして使用する

ツールチェーンのインストール

sourceforge.netからツールチェーンをダウンロードしてインストールします.ここから最新バージョンをダウンロードします.2022年4月現在,2014R1が最新バージョンのようなので,このディレクトリの中を見ると,2つのバージョンが置いてあります.2014R1_45-RC22014R1-RC2があり,前者がgcc 4.5,後者がgcc 4.3を用いたバージョンのようです.ここでは最新版の前者をインストールしてみます.Windows用のバイナリをダウンロードします.

ファイルblackfin-toolchain-win32-2014R1_45.exeがダウンロードフォルダの中にダウンロードされるので,これをダブルクリックして実行します.


[Next]ボタンをクリックします.


[I Agree]ボタンをクリックします.


そのまま[Next >]ボタンをクリックします.


インストール先のフォルダを確認されますので,そのまま[Next >]ボタンをクリックします.ここでは「Program Files (x86)\Analog Devices\GNU ToolChain\2024R1_45」にインストールされます.


スタートメニューの場所を確認されますので,そのまま[Install]ボタンをクリックします.


インストールが開始されます.


インストールが終了しました.


コマンドプロンプトを開いて「bfin-elf-gcc --version」というコマンドを打ち込んで,上記のようにバージョンが表示されたら,PATHの設定まで正常に終了しています.うまくいかない場合は,環境変数PATHに以下のパスが追加されているか確認してください.

C:\Program Files (x86)\Analog Devices\GNU Toolchain\2014R1_45\extra-bin
C:\Program Files (x86)\Analog Devices\GNU Toolchain\2014R1_45\elf\bin
C:\Program Files (x86)\Analog Devices\GNU Toolchain\2014R1_45\uclinux\bin
C:\Program Files (x86)\Analog Devices\GNU Toolchain\2014R1_45\linux-uclibc\bin

Lチカプログラムのダウンロードとコンパイル

次に,サンプルプログラムをダウンロードしてインストールしてみます.LEDを点滅させるプログラムがCQ出版のサポートページにあるので,ダウンロードします.

ファイル「led_blink.zip」をダウンロードします.zipファイルを展開するとフォルダ「led_blink」ができるので,これを,書籍の付録CD-ROMからコピーしたフォルダ階層の中のフォルダ「effect_sample」の中にコピーします.コマンドプロンプトでここに移動してください.


makeコマンドを入力すると,次のようにファイルがコンパイルされて,ファイル「led_blink.ldr」ができます.


フラッシュROM書き込みツールのインストール

書籍付録のCD-ROMのフォルダ「miniconfig」の中にあるファイル「miniconfig-1.6.3.msi」をダブルクリックして実行します.次のようなダイアログが表示されます.


「次へ」ボタンをクリックします.


上の図のようなダイアログが表示されるので,ここでも「次へ」ボタンをクリックします.


上の図のようなバージョン情報が表示されるので,「次へ」ボタンをクリックします.


インストール先のフォルダを選択するダイアログが出ますので,そのまま「次へ」ボタンをクリックします.このときフォルダ「C:\Program Files (x86)\CuBeatSystems\Blackfin MiniConfig for IFX-49\」にツールがインストールされます.


上の図のようなダイアログが表示されるので,「次へ」ボタンをクリックするとインストールが始まります.


インストール中です.


インストールが終了しました.「閉じる」ボタンをクリックしてインストーラを終了してください.


デスクトップにコンフィグツールのアイコンが2個できています.また,スタートメニューにも登録されています.

GUIツールでのプログラムの書き込み

ここではプログラムをblackfinボードに書き込みます.デスクトップのアイコン「Blackfin MiniConfig GUI」をダブルクリックしてプログラムを起動します.


USBポートにボードが接続されていなかったり,ボードが認識されていなかったりすると,上の図のようにグレースケールでボードの絵が表示されます.


ボードをUSBケーブルでパソコンに接続すると,ボードが認識されて「ターゲット」にボードのIDが表示されます.

次に書き込むプログラムを選択します.表示されているプログラムを書き込んでみます.

ボードのジャンパーピンを接続してボードのRESETボタンを押した後,プログラムの「書き込み」ボタンをクリックします.

下のプログレスバーが表示され,プログラムが書き込まれます.プログラムの書き込みが終了すると,次のような「完了しました」というダイアログが表示されます.


Lチカプログラムの書き込み

上で作成したLチカプログラムを書き込むには,makeして出来たled_blink.ldrファイルをこのGUIツールにドラッグ&ドロップすれば良いです.
まずボードを書き込みモードにするために,ジャンパーピンを繋いでリセットボタンを押します.その後で,led_blink.ldrファイルをファイルエクスプローラーからドラッグ&ドロップします.
プログレスバーに進捗が表示され,プログラムが書き込まれます.
プログラムの書き込みが終わりました.
ボードのジャンパーピンを外してリセットボタンを押すと,プログラムが実行されます.

USB-DACとしての使用

上記のプログラムでは,書き込むプログラムがあらかじめ決まっているようです.ここでは,このボードをUSB-DACとして使用する「misc_ifx49_usbdac.ldr」をアプリケーションとして選択して書き込みボタンをクリックします.


書き込みは,ボードのジャンパーピンを繋いで,RESETボタンを押した後ソフトウェアから書き込みです.実行は,ボードのジャンパーピンを外して,RESETボタンを押します.


無事にこのボードがUSB-DACとして認識されてパソコンの音をこのボード経由で出すことができました.

このボードはエフェクターとしてのアプリを念頭に置いたDSPボードなので,このUSB-DACの出力音にいろいろとエフェクトをかけることができそうです.



2021年5月17日月曜日

Raspberry Pi PicoでUSB-DAC(I2Sボードをつけて音出し)

前の投稿でRaspberry Pi PicoをUSB-DACにするソースコードをコンパイルし,ボードに書き込んで,パソコンでUSB-DACとして認識させるところまでできたので,今回は最終的に音出しまでします.

まず,I2S-DACボードはこれを使いました.Raspberry Pi Picoに足の配置が合わせてあり,そのまま挿すことができます.ボードの裏には,Raspberry Pi Picoの絵が描いてあり,挿す向きもわかります.Raspberry Pi Picoに足をはんだ付けしますが,足が曲がって付かないように,Raspberry Pi PicoとI2S DACボードの両方にピンを挿した状態ではんだ付けします.

実際に動かすには,ソースコードの書き換えが必要でした.この製品のページ

You can use Pico Audio Pack with the I2S audio examples provided by Raspberry Pi in their experimental examples (usb_sound_card and sine_wave_i2s). You'll need to #define PICO_AUDIO_I2S_DATA_PIN and PICO_AUDIO_I2S_CLOCK_PIN_BASE to 9 and 10 respectively to tell the examples which pins are being used for the audio data.

とあります.具体的にこれらの値が定義されているファイルは

pico-extras/src/rp2_common/pico_audio_i2s/include/pico/audio_i2s.h 

です.このファイルを以下のように書き換えます.


#ifndef PICO_AUDIO_I2S_DATA_PIN
//#warning PICO_AUDIO_I2S_DATA_PIN should be defined when using AUDIO_I2S
// https://shop.pimoroni.com/products/pico-audio-pack
#define PICO_AUDIO_I2S_DATA_PIN 9 // 28
#endif

#ifndef PICO_AUDIO_I2S_CLOCK_PIN_BASE
//#warning PICO_AUDIO_I2S_CLOCK_PIN_BASE should be defined when using AUDIO_I2S
// https://shop.pimoroni.com/products/pico-audio-pack
#define PICO_AUDIO_I2S_CLOCK_PIN_BASE 10 // 26
#endif


実際に使っているピン番号は12, 14, 15なので,なぜこの番号なのかは謎です.この後,pico-extrasをbuildしなおします.その上で,pico-playgroundをbuildしなおします.

pico-playground/build/usb_sound_card/usb_sound_card.uf2をRaspberry Pi Picoに書き込むと,ボードが再起動して,音がこのボード経由で出せるようになります.

I2Sボードの方はPCM5100Aで32bit, 384kHzまで出力できるのに,Raspberry Pi PicoがXMOSと違いソフトウェアで処理を実行しているので,16bit, 44.1kHz/48kHzしか出力できないのは残念です.

ただ,ソフトウェアでUSBから入力した信号をI2Sに出力しているので,ここで信号処理が色々できると面白いと思います.ソースコードの公開されているUSB-DACって,物がないので,自分でいじるには貴重はハードウェアではないでしょうか.

2021年5月15日土曜日

Raspberry Pi PicoでUSB-DAC(I2Sボード無しでbuild,installまで)

Raspberry Pi PicoでLチカの続きです.

Raspberry Pi PicoからI2S信号をI2S-DACに出力すると,Raspberry Pi PicoのUSBがパソコンに対してslave側なので,パソコンのUSBに外付けしてUSB-DACとして使えるのでは?という話です.



この商品の記述に,「カスタムUSBサウンドカード」って書いてあるので,いろいろ探してみた所,こういうソースコードを見つけました.ざっと眺めてみると,どうもUSBとI2Sを両方使っているので,USBオーディオデバイスとしてパソコンから認識されて,I2Sに信号を流し込めるっぽいです.

このページをみると,pico-playgroundはpico-extras内のライブラリを使っていると書いてあります.

まず,pico-sdkやpico-exampleディレクトリのあるディレクトリで以下ようにライブラリとexampleを取得します.

git clone -b master https://github.com/raspberrypi/pico-extras.git
git clone -b master https://github.com/raspberrypi/pico-playground.git

ここの,pico-playground/apps/usb_sound_card/がそれっぽいです.


まずは,pico-extrasからbuildします.

cd pico-extras
git submodule update --init
mkdir build
cd build
export PICO_SDK_PATH=../../pico-sdk
cmake ..
make

これでpico-extras以下が全てコンパイルできした.


次にpico-playgroundをbuildします.

cd ../../pico-playground
mkdir build
cd build
export PICO_SDK_PATH=../../pico-sdk
export PICO_EXTRAS_PATH=../../pico-extras
cmake ..
make

これでpico-extrasが全てコンパイルできました.


Raspberry Pi PicoのBOOTSELボタンを押しながらUSBケーブルでMacに接続すると,RPi-RP2という外付けストレージとして認識されます.

pico-playground/buildの中のファイルapps/usb_sound_card/usb_sound_card.uf2をRPi-RP2の中にコピーすると,RPi-RP2がアンマウントされ,Raspberry Pi Picoが再起動してプログラムが動きます.このとき,Raspberry Pi Picoは外付けUSBストレージとして認識されません.画面の一番上のオーディオボリュームをクリックしてみると,無事にオーディオ出力デバイスとして認識されているようです.


また,/アプリケーションズ/ユーティリティ/Audio MIDI設定.appを起動してみると,48kHzと44.1kHzが使えて,初期値が48kHzのオーディオデバイスとして認識されていることがわかります.



Raspberry Pi Picoに足をはんだづけするのを忘れたのと,I2S DACボードを家に持って帰ってくるのを忘れたので,とりあえず今日はここまでです.

続きはここで.

2014年6月4日水曜日

エレキットUSB-DACにVUメーターの追加

先日作ったエレキットのUSB-DACにVUメーターを追加してみました.

VUメーターとVUメーターへの出力基板はヤフオクで落札.メーターは中古品だったのでだいぶ安く本物を手に入れる事が出来ました.メーターのブツはComponexの2LXとかいう物で,出品者の方によると,TASCAMのオープンリールデッキから外した中古品だそうです.4個がバラバラで出品されていたので,そのうち2個だけ入札して手に入れました.

実際の製作は,基板に部品のハンダ付けが済んでいるものだったので,ケーブルをつなげて終わり.エレキットのUSB-DACは出力がライン出力とヘッドホン出力の2つあり,両方に同時に出力できるので,ヘッドホン出力を真空管アンプに出して,ラインアウトから信号をもらってVUメーター用の基板に入力しました.


ただ,VUメーターの振れ幅は適当に調節しています.本物のVUメーターのレベルはWikipediaによると
インピーダンス600Ωの負荷回路へ1kHzの正弦波を加えて1mWの電力を消費したときの出力電圧を0dBmとし、+4dBmを0VUとする
となっており,0dBmの電圧は
$$\frac{\{E (V)\}^2}{600 (\Omega)} = 1 \times 10^{-3}(W)$$
より$E = \sqrt{0.6} = 0.775 (V)$ (よって0VUの電圧が1.228V)なのですが,Mac側でUSB出力をボリューム調整できるんで,適正なラインレベルが出てるのかよく分からないし,インピーダンスもよく分からないので,結局適当です.この基板を使っていると,入力が30mVから10Vまで調節できるとの事なので,適当に針がよく振れるように調整してみました...どうも左右の針の振れ幅が違うみたい.中古品だからか?

ともかく,真空管とVUメーターで,見た目だけはアナログチックになってきました.ただ,基板むき出しのままで置いてあるので,いい加減ケース買って来て入れなきゃ.

2014年5月29日木曜日

エレキットUSB-DACの製作

真空管アンプを買った日に寄り道して買っておいた,エレキットのUSB-DACを作ってみました.

セルフパワーにするための追加部品は全て手元にあったので,初めからセルフパワーで作製.最初電源をつないでも,パソコンから認識されない!パイロットランプも無いので,電源が来ているかも不明!最初はキット通りに作るべきだったかと,あせりました.

テスターを持ち出してセルフパワーの電源周りを確認してみたところ,DCジャックの配線を間違っていました.DCプラグを差し込むと−側でつながっている2つの端子って離れて,片方だけが−になるのね.久しぶりなので,すっかり忘れていました.

ハンダ付けをやり直したところ,今度は大丈夫.

秋月のUSB-DACと2台,両方とも動きました.


このキットはオペアンプの交換ができたりするので,もう少しいじくれそうです.

2014年5月28日水曜日

秋月電子USB-DACおよびローパスフィルタの製作

秋月電子のUSB-DACキットローパスフィルタを組み込んで,実際に作ってみました.

ローパスフィルタは,ぺるけさんのページにある数値を参考にし,手元にあった部品で自分で再計算(ローパスフィルタのみの場合と,その前段のハイパス(DCカット)フィルタも含めた場合)してシミュレーションしています.ローパスフィルタの効きが分かるように,フィルタなしの回路とフィルタありの回路を切り替えられるようにしました.

あまり配置を考えずに配線してしまいましたが,とりあえず音が出ました.


次のオシロの写真は無音入力時の波形(上の黄色)とFFT(下の赤色)です.波形は縦軸が1ブロックあたり10mV,横軸は4msです.FFTの横軸は1ブロックあたり12.5kHz,縦軸は10dBVです.

次のオシロの写真は,ローパスフィルタを挟んだときの波形(青色)とFFT(赤色)です.

FFTでざっと-10dBVぐらいの差が出ています.電圧比で$1/\sqrt{10}$倍に減ったことになります.波形を見ても明らかにノイズは減っているようなので,ローパスフィルタの効き目はあったようです.

現在のところ,裸のままでタミヤのプラスチック基板にねじ止めしているだけなので,そのうち,ちゃんとしたケースに入れようと思います.


2014年5月25日日曜日

秋月電子USB-DAC用ローパスフィルタの設計(その2)

秋月電子USB-DAC用ローパスフィルタの設計」で,外付けのローパスフィルタに使う抵抗の抵抗値,コンデンサの容量を確認したのですが,元のページでは,さらに回路の出口のすぐ外に10kΩが追加されており,これが回路の出口に直列で付いている47μFの電解コンデンサにたまった電荷を放出するためとの事です.

その結果,電解コンデンサから先の回路は下記の回路のようになっています.
ここで,オレンジで囲まれている部分が,元々のキットに含まれている部分です.この部分まで含めて回路図を描くと
  • ハイパスフィルタ(47μF + 10kΩ)
  • ローパスフィルタ(100Ω + 0.022μF)
  • ローパスフィルタ(330Ω + 0.0047μF)
の3段のフィルタになります.以下では,1段目のハイパスフィルタの周波数特性,3段まとめてのフィルタの特性を計算してみます.

まず,1段目だけのハイパスフィルタの周波数特性を計算します.下図のように変数を定義します.抵抗の抵抗値を$R_0$,コンデンサの容量を$C_0$,入力電圧を$v_i(t)$,出力電圧を$v_2(t)$,コンデンサに流れる電流を$i_1(t)$,コンデンサにかかる電圧を$v_{C_0}(t)$とします.
すると,抵抗に関する式
$$v_2(t) = R_0 i_1(t)$$
コンデンサに関する式
$$\frac{d v_{C_0}(t)}{dt} = \frac{1}{C_0}i_0(t)$$
電圧に関する式
$$v_i(t) = v_{C_0}(t) + v_2(t)$$
が成立します.これらの式から$i_0(t)$と$v_{C_0}(t)$を消すと
$$\frac{d^2}{dt^2}v_i(t) + \frac{1}{C_0R_0}\frac{dv_2(t)}{dt} + \frac{d^2}{dt^2}v_2(t)$$
となります.これをラプラス変換すると
$$V_i(s)s^2 = \frac{1}{C_0R_0}V_2(s)s + V_2(s)s^2$$
となるので,伝達関数は
$$G(s) = \frac{V_2(s)}{V_i(s)} = \frac{C_0R_0 s}{1 + C_0R_0 s}$$
となります.周波数特性は$s = j\omega$,$\omega = 2\pi f$を入れて絶対値を取る事で
$$|G(j\omega)| = \frac{C_0R_02\pi f}{\sqrt{1 + (C_0R_02\pi f)^2}}$$
となるので,dBに直すと
$$g = 20\log_{10}|G(j\omega)| = 20\log_{10}\frac{C_0R_02\pi f}{\sqrt{1 + (C_0R_02\pi f)^2}}$$
となります.

次に,3段まとめたフィルタの周波数特性を計算します.下図のように変数を定義します.抵抗の抵抗値をそれぞれ$R_0$,$R_1$,$R_2$,コンデンサの容量をそれぞれ$C_0$,$C_1$,$C_2$,コンデンサ$C_0$に流れる電流を$i_1(t)$,抵抗$R_0$に流れる電流を$i_r(t)$,抵抗$R_1$に流れる電流を$i_2(t)$,コンデンサ$C_1$に流れる電流を$i_c(t)$,抵抗$R_2$に流れる電流を$i_3(t)$,入力電圧を$v_i(t)$,抵抗$R_1$の手前の電位を$v_2(t)$,コンデンサ$C_0$にかかる電圧を$v_{C_0}(t)$,コンデンサ$C_1$にかかる電圧を$v_{C_1}(t)$,出力電圧を$v_o(t)$とします.


すると,電圧に関する式
$$v_i(t) = v_{C_0}(t) + v_2(t)$$
$$v_2(t) = R_0 i_r(t)$$
$$v_2(t) = R_1 i_2(t) + v_{C_1}(t)$$
$$v_{C_1}(t) = R_2 i_3(t) + v_o(t)$$
電流に関する式
$$i_1(t) = i_2(t) + i_r(t), \quad i_2(t) = i_3(t) + i_c(t),$$
コンデンサの充電に関する式
$$i_1(t) = C_0 \frac{dv_{C_0}(t)}{dt}, \quad i_c(t) = C_1 \frac{dv_{C_1}(t)}{dt}, \quad i_3(t) = C_2 \frac{dv_o(t)}{dt}$$
が得られます.

まず,$v_2(t)$から右だけを見ると,これは$v_2(t)$より左には依存しないので前回の計算と同じ形になり,この部分の伝達関数の逆数は
$$\frac{V_2(s)}{V_o(s)} = (R_1C_1s + 1)(R_2C_2s+1) + R_1C_2s$$
となります.

$v_2(t)$より左については,上のハイパスフィルタとは微妙に式が違う($i_1(t)$が$i_2(t)$と$i_r(t)$に分かれて,電流$i_2(t)$が$v_2(t)$以降の回路に流れ込む)ので,上の式からうまく$i_2(t)$を消して$v_2(t)$を残すようにすると,

$$\frac{d^2}{dt^2}v_i(t) = \frac{C_1 + C_2}{C_0} \frac{d^2}{dt^2} v_o(t) + \frac{C_1C_2R_2}{C_0} \frac{d^3}{dt^3} v_o(t) + \frac{1}{C_0R_0} \frac{d}{dt}v_2(t) + \frac{d^2}{dt^2} v_2(t)$$
が得られます.ラプラス変換すると
$$V_i(s)s^2 = \frac{C_1 + C_2}{C_0} V_o(s)s^2 + \frac{C_1C_2R_2}{C_0} V_o(s)s^3 + \frac{1}{C_0R_0} V_2(s)s + V_2(s)s^2$$
となります.すると,全体の伝達関数の逆数は
$$\frac{V_i(s)}{V_o(s)} = \frac{C_1 + C_2}{C_0} + \frac{C_1C_2R_2}{C_0}s + (\frac{1}{C_0R_0s} + 1)\frac{V_2(s)}{V_o(s)} = \frac{C_1 + C_2}{C_0} + \frac{C_1C_2R_2}{C_0}s + (\frac{1}{C_0R_0s} + 1)\{ (C_1R_1s + 1)(C_2R_2s + 1) + R_1C_2 s\}$$
となります.$s = j\omega$を代入し,複素数としての絶対値を取り,さらに$\omega = 2\pi f$を代入すると,最終的な周波数特性は
$$g = 20\log_{10} |G(j\omega)| = 20\log_{10} \frac{C_0R_02\pi f}{\sqrt{(C_1R_0 + C_2R_0 + C_1R_1 + C_2R_2 + C_2R_1 + C_0R_0 - C_0C_1C_2R_0R_1R_2(2\pi f)^2)^2 (2\pi f)^2 + \{ 1 - ( C_1C_2R_1R_2 + C_1C_2R_0R_2 + C_0C_1R_0R_1 + C_0C_2R_0R_2 + C_0C_2R_1R_2)(2\pi f)^2\}^2}}$$
となります.

以上の2つの式に以下のパラメータを代入してgnuplotでプロットします.
  • $C_0 = 47 \times 10^{-6}$,$R_0 = 10 \times 10^3$
  • $R_1 = 100$,$C_1 = 0.022 \times 10^{-6}$
  • $R_2 = 330$,$C_2 = 0.0047 \times 10^{-6}$

gnuplotに食わせるスクリプトは以下のようになります.
set logscale x
set xrange [0.1:1000000]
set xlabel 'Hz'
set ylabel 'dB'

f(r0, c0, f) = 20 * log10(c0 * r0 * 2 * 3.1415 * f) - 10 * log10((2 * 3.1415 * r0 * c0 * f)**2 + 1)

g(r0, c0, r1, c1, r2, c2, f) = 20 * log10(c0 * r0 * 2 * 3.1415 * f) - 10 * log10((c1*r0 + c2*r0 + c1*r1 + c2*r2 + c2*r1 + c0*r0 - c0*c1*c2*r0*r1*r2*(2 * 3.1415 * f)**2)**2 * (2 * 3.1415 * f)**2 + (1 - (c1*c2*r1*r2 + c1*c2*r0*r2 + c0*c1*r0*r1 + c0*c2*r0*r2 + c0*c2*r1*r2)*(2 * 3.1415 * f)**2)**2  )

set term pdf
set output 'HighPass-47uF-10kohm-0.1Hz-1MHz.pdf'

plot f(10e3, 47e-6, x) title '47uF, 10kohm'

set term png
set output 'HighPass-47uF-10kohm-0.1Hz-1MHz.png'
replot

set term pdf
set output 'HighPass-47uF-10kohm+LowPass-100ohm-0.022uF-330ohm-0.0047uF-0.1Hz-1MHz.pdf'

plot g(10e3, 47e-6, 100, 0.022e-6, 330, 0.0047e-6, x) title '47uf, 10kohm + 100ohm, 0.022uF + 330ohm, 0.0047uF'

set term png
set output 'HighPass-47uF-10kohm+LowPass-100ohm-0.022uF-330ohm-0.0047uF-0.1Hz-1MHz.png'
replot

結果のグラフは以下のようになりました. まず,最初のハイパスフィルタだけの周波数特性です.
次がハイパスフィルタと2段のローパスフィルタ全体の周波数特性です.

ちょっとすごい式になりましたが,プロットしてみると,きちんと計算できてそうに見えます.

2014年5月24日土曜日

秋月電子USB-DAC用ローパスフィルタの設計

真空管アンプにはMac miniのヘッドフォン端子から音を入れているのですが,最近USB-DACが流行っているみたいなので,一番安い秋月電子のUSB-DACを買いました.

エレキットのUSB-DACだと,出力にオペアンプが入っていたりするのですが,秋月電子のキットはD/A変換した信号がそのまま出力されているので,色々と回路を追加した改造例があるようです.その中で,ぺるけさんのページhttp://www.op316.com/tubes/lpcd/aki-dac.htmに,ローパスフィルタを付ける話があったので,やってみることにしました.

ここで一つ問題が.ここに載っていた抵抗値は100Ωと390Ωまたは82Ωと330Ωだったのですが,手元にあった抵抗が100Ωと330Ωなので,どっちの組み合わせでもありません.

折角なので,100Ωと330Ωの組み合わせでも問題ないかどうか自分で計算してみました.あと,100Ω-0.022uFと330Ω-0.0047uFのそれぞれ単体で,どの程度のフィルタ特性になるかも確認します.計算をフォローするWebページが無かったので,教科書「演習で学ぶ基礎制御工学」を取り出して,改めて問題を解いてみます.

まず以下のような1段だけの場合,入力電圧を$v_i(t)$,出力電圧を$v_o(t)$,抵抗値を$R_1$,コンデンサの容量を$C_1$,抵抗に流れる電流を$i_1(t)$とします.
すると,電圧の式として
$$R_1 i_1(t) + v_o(t) = v_i(t)$$
が出ます.また,コンデンサの充電の式として
$$v_o(t) = \frac{1}{C_1} \int_0^t i_1(\tau)\, d\tau$$
が出ます.2番目の式を$t$で微分すると
$$\frac{d v_o(t)}{dt} = \frac{1}{C_1} i_1(t)$$
となるので,これを最初の式に代入すると
$$R_1C_1\frac{d v_o(t)}{dt} + v_o(t) = v_i(t)$$
となります.電圧の初期値を$0$としてラプラス変換すると
$$R_1C_1 s V_o(s) + V_o(s) = V_i(s)$$
となるので,この回路の伝達関数は
$$G(s) = \frac{V_o(s)}{V_i(s)} = \frac{1}{R_1C_1 s + 1}$$
となります.ゲインは
$$|G(j\omega)| = \frac{1}{\sqrt{(R_1C_1\omega)^2 + 1}}$$
となるので,$\omega = 2\pi f$を代入すると,結局周波数特性は
$$g = 20\log_{10} |G(j \omega)| = 10 \log_{10}\frac{1}{(2\pi R_1C_1 f)^2 + 1}$$
となります.

次に,以下のように2段重ねた場合に,入力電圧を$v_i(t)$,1個目のコンデンサにかかる電圧を$v_c(t)$,出力電圧を$v_o(t)$,抵抗の抵抗値を$R_1$と$R_2$,コンデンサの容量を$C_1$と$C_2$,抵抗に流れる電流を$i_1(t)$と$i_2(t)$,$C_1$に流れる電流を$i_c(t)$とします.
コンデンサの充電の式が2個,
$$ i_c(t) = C_1 \frac{d v_c(t)}{dt}, \quad i_2(t) = C_2 \frac{d v_o(t)}{dt} $$
電流の式が1個,
$$i_1(t) = i_c(t) + i_2(t)$$
電圧の式が2個,
$$ R_1 i_1(t) + v_c(t) = v_i(t), \quad R_2 i_2(t) + v_o(t) = v_c(t)$$
出ます.
これらから電流を消すと
$$R_1( C_1\frac{d v_c(t)}{dt} + C_2 \frac{d v_o(t)}{dt} ) + v_c(t) = v_i(t)$$
および
$$ R_2 C_2 \frac{d v_o(t)}{dt} + v_o(t) = v_c(t)$$
が出ますので,全ての初期値を$0$にしてラプラス変換すると
$$R_1( C_1 V_c(s) s+ C_2 V_c(s) s) + V_c(s) = V_i(s)$$
および
$$R_2 C_2 V_o(s) s + V_o(s) = V_c(s)$$
が出ます.この2式から$V_c(s)$を消すと,結局
$$(R_1 C_1 s + 1)(R_2 C_2 s + 1)V_o(s) + R_1 C_2 s V_o(s) = V_i(s)$$
となり,伝達関数は
$$G(s) = \frac{V_o(s)}{V_i(s)} = \frac{1}{(R_1 C_1 s + 1)(R_2 C_2 s + 1) + R_1 C_2 s}$$
となります.ゲインは
$$|G(j\omega)| = \frac{1}{\sqrt{(R_1C_1+R_2C_2+R_1C_2)^2\omega^2 + (1-R_1C_1R_2C_2\omega^2)^2}}$$
となるので,$\omega = 2\pi f$を入れると,周波数特性は
\begin{align*}
g &= 20 \log_{10} |G(j\omega)|
\\
&= 10 \log_{10} \frac{1}{(R_1C_1+R_2C_2+R_1C_2)^2(2\pi f)^2 + (1-R_1C_1R_2C_2(2\pi f)^2)^2}
\end{align*}
となります.

以上の2つの式に下記のパラメータを代入してgnuplotでプロットしてみます.

  • 1段のフィルタ回路で$R_1 = 330$,$C_1 = 0.0047\times 10^{-6}$
  • 1段のフィルタ回路で$R_1 = 100$,$C_1 = 0.022\times 10^{-6}$
  • 2段のフィルタ回路で$R_1 = 82$,$C_1 = 0.022\times 10^{-6}$,$R_2 = 330$,$C_2 = 0.0047\times 10^{-6}$
  • 2段のフィルタ回路で$R_1 = 100$,$C_1 = 0.022\times 10^{-6}$,$R_2 = 330$,$C_2 = 0.0047\times 10^{-6}$
  • 2段のフィルタ回路で$R_1 = 100$,$C_1 = 0.022\times 10^{-6}$,$R_2 = 390$,$C_2 = 0.0047\times 10^{-6}$
  • 2段のフィルタ回路で$R_1 = 100$,$C_1 = 0.022\times 10^{-6}$,$R_2 = 430$,$C_2 = 0.0047\times 10^{-6}$

gnuplotに食わせるスクリプトはこんなかんじ.


set term pdf
set output 'LowPassFilter-100ohm-0.022uF-330ohm-0.0047uF-10Hz-1MHz.pdf'

set logscale x
set xrange [10:1000000]
set xlabel 'Hz'
set ylabel 'dB'

f(r1, c1, f) = 10 * log10(1/((2 * 3.1415 * r1 * c1 * f)**2 + 1))
g(r1, c1, r2, c2, f) = 10 * log10(1/( (r1*c1 + r2*c2 + r1 * c1)**2 * (2*3.1415 * f)**2 + (1 - r1*c1*r2*c2*(2*3.1415 * f)**2) ))

plot \
     f(330, 0.0047e-6, x) title '330ohm, 0.0047uF', \
     f(100, 0.022e-6, x) title '100ohm, 0.022uF', \
     g(82, 0.022e-6, 330, 0.0047e-6, x) title '82ohm, 0.022uF + 330ohm, 0.0047uF', \
     g(100, 0.022e-6, 330, 0.0047e-6, x) title '100ohm, 0.022uF + 330ohm, 0.0047uF', \
     g(100, 0.022e-6, 390, 0.0047e-6, x) title '100ohm, 0.022uF + 390ohm, 0.0047uF', \
     g(100, 0.022e-6, 430, 0.0047e-6, x) title '100ohm, 0.022uF + 430ohm, 0.0047uF'

set term png
set output 'LowPassFilter-100ohm-0.022uF-330ohm-0.0047uF-10Hz-1MHz.png'
replot

set xrange [1000:1000000]
set term pdf
set output 'LowPassFilter-100ohm-0.022uF-330ohm-0.0047uF-1kHz-1MHz.pdf'
replot

set term png
set output 'LowPassFilter-100ohm-0.022uF-330ohm-0.0047uF-1kHz-1MHz.png'
replot

  1. 10Hzから1MHzまでプロットした場合は以下のグラフになりました.
  2. 1kHzから1MHzまでプロットした場合は以下のグラフになりました.

結局,1段と2段ではローパスフィルタの効き目は結構違うこと,また,1段目の抵抗値を100Ωにしておけば,2段目の抵抗値 は330Ωでも390Ωでも430Ωでもあまり変わらないことが分かったので,手元にある100Ωと330Ωで下記のようなローパスフィルタ回路を組んでみる事にしました.


続きは「秋月電子USB-DAC用ローパスフィルタの設計(その2)」で.