MATLABを使ってみませんか?

第1回:アナログ信号の入出力

設備・情報技術室 AI・メカトロニクス班
木庭 洋介

はじめに

皆様はMATLABというソフトウェアをご存知でしょうか。MATLABはアルゴリズム開発、データ解析、可視化、数値計算のための統合開発環境です。様々な分野に対応したToolbox(アドオン製品)があり、これらを利用することで、複雑な処理を簡潔なコードで実現できます。

> MathWorks社 MATLAB紹介ページ

九州大学情報統括本部は、「MATLAB Campus-Wide License(包括ライセンス契約)」の運用を2023年1月4日から開始しました。これにより、MATLAB/Simulinkおよび100以上のToolbox(アドオン製品)の他オンラインツールやサービスを、教職員は有償ですが、学生は無償(!!)で利用できるようになりました。

私は音響制御シミュレーション、空間の音響特性測定、画像処理、機械学習、アプリ作製などでMATLABを使用しています。これらで利用したToolboxは10程度ですのでMATLABを熟知しているとは言えませんが、私の知りうる範囲で「MATLABでこういう事ができます」ということを少しご紹介したいと思います。

第1回のテーマは「アナログ信号の入出力」です。Data Acquisition ToolboxSignal Processing Toolboxを使ってWindows PCと接続したデータ収集(DAQ)デバイスを制御し、PCへのデータ取り込み、任意波形の出力を行います。このData Acquisition ToolboxはWindows OSにしか対応していませんのでWindowsがインストールしてあるPCをご用意ください。また、DAQデバイスはToolboxがサポートしている製品しか使えません。以下のリンク先にData Acquisition ToolboxがサポートしているDAQデバイスについて紹介されていますので、ご参考にしてください。

> Hardware Support from Data Acquisition Toolbox

ちなみに本記事では、DAQデバイスに以下のものを使用します。あらかじめPCにデバイスドライバをインストールしてDAQデバイスを認識させておきます。

  • CompactDAQ​シャー​シ:NI cDAQ-9178(NATIONAL INSTRUMENTS)
  • アナログ入力モジュール(4ch):NI 9215(NATIONAL INSTRUMENTS)
  • アナログ出力モジュール(4ch):NI 9263(NATIONAL INSTRUMENTS)

MATLABは、自分がやりたいことをMATLABコマンドや関数で記述したスクリプトファイルを作って実行させるのが基本ですが、スクリプトを書くことなく処理を実行してくれるアプリも多く提供されています。まずはそれを使ってみます。

アプリを使って入出力

アナログ入出力用のアプリとして、Analog Input RecorderAnalog Output Generatorがあります。また、取得したデータの分析用アプリとして、Signal Analyzerがあります。

Analog Input Recorderを起動すると以下のような画面が表示されます。サンプリングレート、取得するサンプル数などの測定条件と使用するチャンネルを設定し、測定開始ボタンを押すとMATLABのワークスペースへ測定した電圧値が保存されます。

Signal Analyzerでは、取得したデータの時系列波形、パワースペクトル、スペクトログラムなどを表示し、比較することができます。また、信号の平滑化、ローパスやハイパスなどのフィルタ処理、包絡線を求めるなどのデータ処理も行えます。

Analog Output Generatorは、電圧出力を行なうアプリです。出力信号はDC出力、テスト信号(10Hzのサイン波)、任意の波形出力から選択できます。下図はあらかじめ作成しておいた線形チャープ信号を読み込ませたときのものです。サンプリングレート、出力チャンネルを設定し、出力開始ボタンを押すと出力モジュールから電圧出力します。

このようにアプリを利用すれば、スクリプトを書くことなくアナログ信号の入出力や取得したデータの簡単な解析が可能です。

ところで、入出力のできるモジュールがそろっているならば、それらを同時に動かしてみたいと思いませんか?例えば、出力をスピーカーへ、入力をマイクロホンへ繋げれば空間の音響特性を求められそうです。または、出力を加振器へ、入力を加速度センサやレーザー変位計に繋げれば構造物の振動試験を行えそうです。
このように、入力モジュールと出力モジュールを同時に制御すればできることの幅が広がるのですが、アプリではそれができません。しかし、スクリプトを書けば両モジュールを同時に制御することが可能です。そこで次では、スクリプトを使ったアナログ信号の入出力についてご紹介します。

スクリプトを使って入出力

エディタの起動

スクリプトを作るには、MATLABコードエディタ(.mファイル)にコードを書いていくのが一般的です。

MATLABコードエディタにはブレークポイントの設定、ステップ実行、命令ごとの実行時間の計測など、デバッグ作業によく使う機能が備わっていますし、実行途中の変数や配列の値はワークスペースで簡単に確認できます。また、MATLABはPythonのようなインタプリタ方式の言語ですので、コンパイルの必要がなく迅速にデバッグ作業を行うことができます。

以下で紹介するコードはMATLABコードエディタに記述して実行します。

DataAcquisitionオブジェクトの作成

まずは、DAQデバイスの設定・操作を行うために、daq関数によりDataAcquisitionオブジェクトを作成します。入力引数の”ni”でNATIONAL INSTRUMENTS製デバイスを指定しています。

dq = daq("ni")
dq = 

DataAcquisition using National Instruments(TM) hardware:

                     Running: 0
                        Rate: 1000
           NumScansAvailable: 0
            NumScansAcquired: 0
              NumScansQueued: 0
    NumScansOutputByHardware: 0
                   RateLimit: []

daqlist関数は使用可能なDAQデバイス一覧を表示させる関数です。”Description”列を見ると、今回使用する出力モジュールのNI 9263と入力モジュールのNI 9215が認識されていることがわかります。それぞれ”DeviceID”として”cDAQ1Mod1″と”cDAQ1Mod2″が割り当てられており、このIDを用いて各デバイスを制御します。

dqlist = daqlist
dqlist =

  2×5 table

    VendorID     DeviceID                    Description                        Model                  DeviceInfo          
    ________    ___________    ________________________________________    _______________    _____________________________

      "ni"      "cDAQ1Mod1"    "National Instruments(TM) NI 9263"          "NI 9263"          [1×1 daq.ni.CompactDAQModule]
      "ni"      "cDAQ1Mod2"    "National Instruments(TM) NI 9215 (BNC)"    "NI 9215 (BNC)"    [1×1 daq.ni.CompactDAQModule]

アナログ入出力チャンネルをオブジェクトに追加する

addoutput関数でアナログ出力チャンネル”ao0″を、addinput関数でアナログ入力チャンネル”ai0″を追加します。

addoutput(dq, "cDAQ1Mod1", "ao0", "Voltage")
addinput(dq, "cDAQ1Mod2", "ai0", "Voltage")

それでは、最初に作成したDataAcquisitionオブジェクトの中身を確認してみます。オブジェクトの内容のうち、”RateLimit”(設定可能なサンプリング周波数の上下限値(Hz))が追加したモジュール固有の値に変更されていることがわかります。

dq
dq = 

DataAcquisition using National Instruments(TM) hardware:

                     Running: 0
                        Rate: 1000
           NumScansAvailable: 0
            NumScansAcquired: 0
              NumScansQueued: 0
    NumScansOutputByHardware: 0
                   RateLimit: [0.1000 100000]

Show channels
Show properties and methods

サンプリング周波数を変更する

現在、サンプリング周波数は”Rate: 1000″(1kHz)、に設定されています。例えばこれを100kHzサンプリングに変えるには、オブジェクト内の変数”Rate”を直接変更すればよいです。

dq.Rate = 100000
dq = 

DataAcquisition using National Instruments(TM) hardware:

                     Running: 0
                        Rate: 100000
           NumScansAvailable: 0
            NumScansAcquired: 0
              NumScansQueued: 0
    NumScansOutputByHardware: 0
                   RateLimit: []

Show channels
Show properties and methods

出力信号を作製する

線形チャープ信号を出力する例を示します。Signal Processing Toolboxのchirp関数で、0Hzから1kHzまで10秒で線形に掃引する信号データを作製します。ちなみに、chirp関数はスイープ手法として線形チャープ、2次チャープ、対数チャープが選択できます。
下記コードではチャープ信号作製後に、その時系列波形とスペクトログラムを表示させます。各グラフを見ると、振幅1Vで周波数が10秒間で0から1kHzに変化する線形チャープ信号ができていることがわかります。

Fs = dq.Rate; % サンプリング周波数(Hz)
t = 0:1/Fs:10; % 時間配列(s)

output = chirp(t,0,10,1000); % チャープ信号の作製

% 確認のためにグラフ表示
% 時系列データの表示
nexttile
plot(t,output);
title('時系列波形')
xlim([t(1) t(end)]) % 横軸表示は範囲の設定
xlabel('時間 (s)')
ylabel('振幅 (V)')
% スペクトログラムの表示
nexttile
pspectrum(output,Fs,...
    'spectrogram',...
    'FrequencyLimits',[0 2000],...
    'FrequencyResolution',10)
title('スペクトログラム')

アナログ入出力の同時実行

readwrite関数でアナログ入出力を同時に行います。第1入力引数にDataAcquisitionオブジェクトを指定し、第2入力引数に出力信号ベクトルを与えます。入力デバイスから取得したデータは、出力引数で指定した名前でワークスペースに保存されます。下記コードではアナログ入出力後に、各信号の時系列波形とスペクトログラムを表示させます。

今回は出力チャンネルと入力チャンネルを直接ケーブルでつないで実行しました。時系列波形を見ると、AD/DA変換に時間がかかるため、出力波形に対し入力波形に時間遅れがあるのが確認できます。また、スペクトログラムを見ると、周波数が10秒間で0から1kHzに変化する線形チャープ信号を取得できているものの、取得した信号(入力信号)にはわずかですが高調波が見られ、全体に-100dB程度のランダムノイズがのっているのが確認できます。この高調波はAD/DA変換の際の量子化によるものです。また、全体にのっているランダムノイズも同様に量子化誤差によるもので、使用した入力モジュール(±10V入力、16bit分解能)を考えると妥当な値です。

toutput = output'; % 出力信号ベクトルを転置
input = readwrite(dq, toutput); % デバイスチャンネルデータの入出力の同時実行

% 確認のためにグラフ表示
figure(2)
% 最後の1msの時系列データ表示
nexttile([1 2])
plot(t,output,t,input.cDAQ1Mod2_ai0);
title('時系列波形')
xlim([t(end-100) t(end)]) % 横軸表示は範囲の設定
ylim([-1.1 1.1])
xlabel('時間 (s)')
ylabel('振幅 (V)')
legend('出力信号', '入力信号')
% スペクトログラムの表示
nexttile
pspectrum(toutput,Fs,...
    'spectrogram',...
    'FrequencyLimits',[0 2000],...
    'FrequencyResolution',10)
title('出力信号のスペクトログラム')
nexttile
pspectrum(input.cDAQ1Mod2_ai0,Fs,...
    'spectrogram',...
    'FrequencyLimits',[0 2000],...
    'FrequencyResolution',10)
title('入力信号のスペクトログラム')

おわりに

今回はアプリとスクリプトを使ったアナログ信号の入出力について簡単にご紹介しました。このほかにも、様々なMATLAB関数があり、またスクリプトを関数化して再利用することも可能です。スクリプトを使えば、MATLABだけで測定、データ解析、可視化、グラフ保存まで行えるので、実験の自動化・省力化が期待できます。

最後までお読みいただきありがとうございました。本記事ではご理解できない点が多々あるかと思いますので、ご遠慮なく技術部までご相談いただきますようよろしくお願い申し上げます。