こちらの記事について、内容・翻訳・視点・長さなど、皆様のご意見をお送りください。今後の記事製作の参考にしたいと思います。
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
こちらの記事の感想をお聞かせください。
多機能な測定機器とRaspberry Pi 4を使って、スタンドアロンで、プログラマブルなオーディオアンプ評価測定装置を作ってみます。
この連載のパート1では、アンプ評価測定装置の基本的な動作を概説し、AD 2(以下AD2)とそれに提供されているソフトウェアについて、使用する予定のハードウェア構成部品とともに調べました。今回の投稿では、さらに詳しく、どのようにカスタマイズしたテスト機能を開発するのか、ソフトウェアの面から簡単な例を使って実際に見ていきます。
AVアンプ評価測定の典型的なシチュエーション
オーディオアンプを評価測定する際、典型的な測定項目として、以下のものが挙げられます。
- ゲイン
- 周波数特性
- 全高調波歪(THD: Total Harmonic Distortion)
- 2チャンネル以上でのクロストーク
- 位相
- DCレベル
このような、すべてのアンプ機器に共通する一般的な測定項目に加えて、特定のアンプ向けに、サービス手順の一環として行われるテストが存在します。これは、構成部品や回路が、部分的に正しく機能していないことを確かめるためや、バイアス等のアライメント手順の一環として、特定の信号を入力し、希望する信号が出力されているか観察する、といったものです。
こういったことから、素早くTHDなどの計算を行うことが可能であり、アンプ入力のために適切な信号を発生する際の設定作業を自動化できるといった、オーディオ専用のテスト機器から受けられる恩恵は明らかでしょう。
ハードウェアのセットアップ
この投稿の目的や、後の簡単なテストケース例を開発する際に便利だと考えたため、AD2を、Ubuntu 20.04を搭載したノートパソコンに接続することにしました。今後の投稿では、他の構成部品と共にエンクロージャー内に組み込まれたRaspberry Pi 4に切り替える予定です。
上の図は、AD2のピンアサインです。ここでは、この後実験する簡単なサンプル用に、波形発生器1(Waveform Generator 1)の出力をスコープチャンネル1の正入力(Scope Ch.1 Positive)に接続しようと思います。スコープチャンネルは差動であるため、チャンネル1の負入力(Scope Ch.1 Negative)は、グランド(Ground)に接続します。
波形
パート1ですでに述べたように、AD2のソフトウェアサポートは、WaveForms virtual instrument suiteにおいて無料で提供されています。今回私たちは、「Getting Started Guide for Linux (Linux用スタートガイド)」に沿って準備を行いましたが、MacやWindowsもサポートされています。
最初にAdept 2ランタイムを、続いて、WaveForms自体をダウンロードする必要があります。ダウンロード後に以下のコマンドを入力することでインストールできました。
$ sudo dpkg -i digilent.adept.runtime_2.21.3-amd64.deb
$ sudo dpkg -i digilent.waveforms_3.16.3_amd64.deb
2つ目のコマンドを実行すると、エラーが表示されました。libqt5scripttools5がシステムにインストールされていなかったことが原因でしたが、こういった依存関係のエラーは、以下のコマンドで簡単に解決できます。
$ sudo apt -f install
次のコマンドを入力することで、WaveFormsを起動することができました。
$ waveforms
アプリケーションの読み込みが終わると、Welcomeタブが表示され、ここから最近のワークスペースを開くことができ、さらに、左側のボタンからいくつかのバーチャル機器を読み込むことが可能になります。スタートガイドには、WavegenとScope機能を使った、初めて測定を行うまでの手順がひと通り説明されています。
このガイドに沿って、1kHzの正弦波を生成し、スコープ上に信号を表示してみます。
次に、オーディオアンプをテストする、性能を測定するといった、今回の用途に応用できそうな、少し高度な機能について見ていきます。
Digilentのウェブサイトには、信号の高調波を測定する方法を説明したサンプルが示されています。
再びWavegenを使用しましたが、今回はCustomモードを選択し、Mathタブへと進んで、その後、下に示すコードを追加しました。
var amp = [1,0,0,0,0,0,0,0,0,0]; //amplitude values from 0 to 1 (0-100%)
var ph = [0,0,0,0,0,0,0,0,0,0]; //phase values from 0 to 1 (0-360 degrees)
Y = amp[0] * sin((1 * 2*PI*X) + 2*PI*ph[0])
+ amp[1] * sin((2 * 2*PI*X) + 2*PI*ph[1])
+ amp[2] * sin((3 * 2*PI*X) + 2*PI*ph[2])
+ amp[3] * sin((4 * 2*PI*X) + 2*PI*ph[3])
+ amp[4] * sin((5 * 2*PI*X) + 2*PI*ph[4])
+ amp[5] * sin((6 * 2*PI*X) + 2*PI*ph[5])
+ amp[6] * sin((7 * 2*PI*X) + 2*PI*ph[6])
+ amp[7] * sin((8 * 2*PI*X) + 2*PI*ph[7])
+ amp[8] * sin((9 * 2*PI*X) + 2*PI*ph[8])
+ amp[9] * sin((10 * 2*PI*X) + 2*PI*ph[9]);
Generateを選択することで再び正弦波が出力されますが、振幅や位相値を変更することで、歪んだ波形を生成することも可能です。
var amp = [1,1,0,0,0,0,1,0,0,0];
例えば、このようにampを変更すると、下の図のようなWavegenの出力とスコープのプロットが得られます
提供されている高調波のサンプルを参考にして、下のようにベクトルを設定しました。
var amp = [1,0,0.33,0,0.2,0,0.14,0,0.11,0];
次は、スコープとFFTの機能を正しく設定し、プロットを、下の図のような時間、周波数領域において表示させました。
ここでは基本周波数と高調波がはっきりと示されており、基本周波数に対する高調波の振幅が測定可能になります。
カスタマイズしたWavegenの設定を、このバーチャル機器内に保存できます。また、Welcomeタブからワークスペースごと保存することも可能です。このように、一般的なものから、ある特定のアンプに対するテストや、そのサービス手順特化したものなど、様々なテストを実施するための設定の作成や再現が容易に行えるのです。さらにもう1歩進んで、スクリプトエディタを用いた機能の自動化の例を、この記事で紹介しています。
ですがここで、先にSDKについて詳しく調べ、最低限必要な機能を備えたカスタムアプリケーションを作成する際に、どのように使用するのか見ていきましょう。
WaveForms SDK
WaveFormsアプリケーションは、ランタイムを用いてAD 2と通信しますが、これによってカスタムアプリケーションのためのパブリックAPIが提供されます。 これを用いたコードのサンプルはPython、C、C#、Visual Basicのものが配布されており、私たちはPythonを使用することにしました。上のスクリーンショットから、プログラムを製作する際のサンプルコードがたっぷりあるのがおわかりでしょう。なんと、全部で76個もあります!
これらを実行した際、Pythonの依存関係が足りない場合にエラーが表示されることがあります。例えば、AnalogOut_Sweep.pyを実行にしてみると、Matplotlibモジュールが必要だということがわかりました。Ubuntu 20.04上では、このプログラムに対するパッケージが、既定のPython 2.7向けにはインストールされておらず、Python 3向けのものはすでにインストールされていました。幸い、このサンプルは、両方のPythonバージョンで使用できるように書かれていたので、代わりにPython3で実行することでエラーは解決しました。
もちろん、Python 2.7用のMatplotlibをPyPy(pip)経由でインストールすることもできましたが、何にせよ、Python 3を使用すべきだと思います。
Python 3でサンプルを実行するところまで話を戻すと、上の図のようなプロットが生成されました。
ターミナルの出力は上のようになります。では、次にコードの中身を見ていきましょう。
hzStart = 1e3
hzStop = 20e3
hzMid = (hzStart+hzStop)/2
secSweep = 5e-3
channel = c_int(0)
dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeCarrier, c_bool(True))
dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeCarrier, funcSine)
dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeCarrier, c_double(hzMid))
dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeCarrier, c_double(1))
dwf.FDwfAnalogOutNodeOffsetSet(hdwf, channel, AnalogOutNodeCarrier, c_double(1))
dwf.FDwfAnalogOutNodeEnableSet(hdwf, channel, AnalogOutNodeFM, c_bool(True))
dwf.FDwfAnalogOutNodeFunctionSet(hdwf, channel, AnalogOutNodeFM, funcRampUp)
dwf.FDwfAnalogOutNodeFrequencySet(hdwf, channel, AnalogOutNodeFM, c_double(1.0/secSweep))
dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, channel, AnalogOutNodeFM, c_double(100.0*(hzStop-hzMid)/hzMid))
dwf.FDwfAnalogOutNodeSymmetrySet(hdwf, channel, AnalogOutNodeFM, c_double(100))
dwf.FDwfAnalogOutRunSet(hdwf, channel, c_double(secSweep))
dwf.FDwfAnalogOutRepeatSet(hdwf, channel, c_int(1))
モジュールのインポートや、装置のオープン処理をしている部分は省きます。上記から、いくつかの変数が宣言されていることと、アナログ出力(任意波形発生器の部分)が、これらの変数により設定されたことがわかります。関数とパラメータが何を示すのか、これだけで一目瞭然ですね。
hzRate = 1e6
cSamples = 8*1024
rgdSamples1 = (c_double*cSamples)()
rgdSamples2 = (c_double*cSamples)()
sts = c_int()
print("Configure analog in")
dwf.FDwfAnalogInFrequencySet(hdwf, c_double(hzRate))
dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(-1), c_double(4))
dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(cSamples))
dwf.FDwfAnalogInTriggerSourceSet(hdwf, trigsrcAnalogOut1)
dwf.FDwfAnalogInTriggerPositionSet(hdwf, c_double(0.3*cSamples/hzRate)) # trigger position at 20%, 0.5-0.3
print("Starting acquisition...")
dwf.FDwfAnalogInConfigure(hdwf, c_int(1), c_int(1))
以降のコードは、たとえ今回がアナログの入力に関する設定であっても、ほぼ同じようなコードです。その後、データの取得が開始され、完了するとデータをバッファにコピーし、デバイスをクローズして結果がプロットされるといった流れになっています。
これは、最初に行ったWavegenとScopeのバーチャル機器を、WaveFormアプリケーションで使用したサンプルによく似ていますね。
私たちがズルをしていないことを証明するために、上に、波形発生器1とスコープチャンネル1に接続している黄色のワイヤーを切断した際のプロットの様子を示します。得られたのはノイズだけです。
また、SDK Reference Manualも用意されており、こちらでは、サンプルとAPI関数を少し理解しやすいかたちで説明しています。このマニュアルにはAPIの基礎が取り上げられており、例えば、接続された機器を検出するための正しい手順や、接続を開く、機器を設定するといった動作に関するプラグインについて記載されているかもしれません。
API関数は、以下のグループに分けられ、詳細に文書に整理されています。
- デバイスの列挙
- デバイスの制御
- アナログ入力(オシロスコープ)
- アナログ出力(任意波形発生器)
- アナログI/O(様々なアナログ信号の取得・駆動)
- デジタル入力(ロジックアナライザ)
- デジタル出力(バターン発生器)
- デジタルI/O(デジタル信号の取得・駆動)
- システム(システム基本情報の取得)
まとめ
ベンダーによるシンプルなSDKのサンプルに触れることで、オーディオアンプ入力に対して信号を生成し、試験用機器からの信号をプロットすることで、信号の特徴を観察できるようなカスタマイズアプリケーションが、どれほど容易に作成できるかわかりました。私たちが作るアプリケーションでは追加の機能として、対象の機器固有のテストをシーケンス化し、簡単な合格・不合格表示をできるようにします。さらに、結果をログとしてファイルで残し、ものによってはシリアル番号を記録することもできるでしょう。テストをスピードアップするなど、開発可能な機能はたくさんあり、また、テスト機器の設定ミスから生じるエラーを低減できるかもしれません。
次回の投稿では、アンプテスト装置のハードウェアプラットフォームを組み立てます。これには、Raspberry PiタッチスクリーンディスプレイとあわせてRaspberry Pi 4をホストコンピュータとして使用し、さらに、ダミーロードも取り付けます。また、使い勝手向上のために、いくつかの簡単な物理スイッチを用意しようと思います。