計測器制御：周波数特性の計測にオシロとファンクションジェネレータを利用する

# 概要
ExcelVBAからVISAライブラリを経由してファンクションジェネレーターとオシロスコープの制御を行い、テスト対象のアンプの周波数特性を計測します。

![F得.dio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/9dc5c6db-b507-9e3c-b7dc-42d303b2e723.png)

# 計測構成

試験の条件となる入力周波数の設定値をEXCELに予め記入しておきます。この入力周波数をファンクションジェネレーターに送った後にオシロスコープの振幅計測値を読み取ってエクセルのセルに記録します。
EXCELの機能を用いてグラフ化します。


# 機材

- オシロスコープ：HDO4404（RIGOL社）
- ファンクションジェネレーター：WF1968（エヌエフ回路ブロック）
- パソコン：Windows10 , ExcelVBA, (VISAドライバインストール済)

# 前提
- 「VISAとはなんぞや？」という説明は割愛いたします。
- 計測機のコマンドリファレンスマニュアルの読み方の説明も割愛いたします。

# ソースコード

- USBの機器IDは計測器の固有値になりますので、利用の環境に応じて編集してください
- オシロの諸々の設定（入力インピーダンス、レンジ等）は予め手動で設定しているものとします

```VB
'スリープ関数の定義
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As Long)

Dim RM As New VisaComLib.ResourceManager
Dim OSC As New VisaComLib.FormattedIO488
Dim FG As New VisaComLib.FormattedIO488

'-------------------------------------------------------------------------------------------------
' ファンクションジェネレータの周波数を変化させながらオシロの振幅をロギングして周波数特性をグラフ化
'-------------------------------------------------------------------------------------------------
Sub 周波数特性()
    '計測器オープン（USBの機器IDは各自の環境によって変更してください）
    Set OSC.IO = RM.Open("USB0::0x1AB1::0x0610::HDO4A243800220::INSTR")
    Set FG.IO = RM.Open("USB0::0x0D4A::0x003A::9399147::INSTR")
    
    '計測器通信用イベントレジスタをクリアしておく
    OSC.WriteString ("*CLS")
    FG.WriteString ("*CLS")
            
    '--------------------
    'オシロの設定
    '--------------------
    '計測アイテムをクリア
    OSC.WriteString (":MEASure:Clear")
    'CH2の信号の振幅Vp-pを計測するモードを有効にする
    OSC.WriteString (":MEASure:STATistic:Item VPP,CHANnel2")
        
    '---------------------------------------
    'Excelの表に従って計測を繰り返すループ
    '---------------------------------------
    Dim ofs As Integer
    Dim cmd As String
    ofs = 0
    
    With Range("A2")
        Do
            'セルから周波数の値を拾ってくる
            Frq = .Offset(ofs, 0)
            'セルに書いてある周波数MHzを計測器に送る設定値のHzにする
            Frq = Frq * 1000000
            
            'FGに周波数設定を送る
            FG.WriteString (":SOURce1:FREQ " & Frq)
            
            '周波数に合わせてオシロの時間レンジを設定する
            TimeScale = 1 / Frq
            OSC.WriteString (":TIMebase:MAIN:SCALe " + CStr(TimeScale))
            
            '安定するまでちょっと待つ
            Sleep 500
            
            'アベレージに結果を与える古い計測値をクリア
            OSC.WriteString (":MEASure:STATistic:Reset")
            
            '１秒待ってアベレージを掛ける
            Sleep 1000
            
            'オシロから振幅の計測値を取得すしてセルに転記する
            .Offset(ofs, 1) = Query(OSC, ":MEASure:STATistic:ITEM? AVERages,VPP")
            
            '１つしたの行へ移動
            ofs = ofs + 1
            
            .Offset(ofs, 0).Select: DoEvents
        Loop While (.Offset(ofs, 0) <> "")
    End With
    
    '計測器クローズ
    OSC.IO.Close
    FG.IO.Close
End Sub

'---------------------------------------------------------------------
'ライト＆リード動作をまとめて関数化
'---------------------------------------------------------------------
Function Query(inst As VisaComLib.FormattedIO488, cmd As String)
    Dim rtn
    inst.WriteString (cmd)
    rtn = inst.ReadString
    Query = Val(rtn)
End Function
```

# プログラムする上でのポイント

## オシロの時間レンジ
レンジが不適切な場合は計測結果も不適切になります。
オシロの画面内にSIN波が１０サイクル程度写るように、毎回レンジの設定を行っています。

例えば時間レンジが異常に短い場合、SIN波の全体が映らづに正確なピークトゥーピークの計測ができません。

## オシロのメジャー機能のカウンタクリア
入力周波数を切り替えた後に、オシロのメジャー機能のカウンタをクリアしています、
このカウンタクリアを怠ると、周波数を切り替える以前の計測結果も含めた平均値を取得してしまいます。

## ウェイトを入れる
オシロのメジャー機能でアベレージを取得しているため、条件を与えた後に１秒のウェイトを設けてアベレージ回数を稼いでいます。アベレージ回数を稼いだ方が試験結果の再現性を得やすい為です。

# 計測結果

８０ポイントの計測を約２分で完了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/eea32673-f620-be70-86d7-799b19a5eddb.png)