• トップ
  • ブログ一覧
  • Pythonでオシロスコープの波形データを自動転送してみた!
  • Pythonでオシロスコープの波形データを自動転送してみた!

    広告メディア事業部広告メディア事業部
    2021.02.16

    IT技術

    Python + PyVISA でオシロスコープの波形データを自動転送してみよう!

    前回は、PyVISA でオシロスコープを制御したり、画面キャプチャをPCに転送する方法を紹介しました。

    しかし、PyVISA でできることはこれだけではありません。

    オシロスコープでできる基本操作は、PyVISA を使えば全てカバーできるんです。

    今回は、PyVISA のさらなる活用例として、波形データを PC に自動転送する方法をご紹介します!

    前回の記事はこちら!

    Pythonを使ってオシロスコープを遠隔操作したり、画面キャプチャをしてみよう2021.02.08Pythonを使ってオシロスコープを遠隔操作したり、画面キャプチャをしてみようpython でオシロスコープを操作しよう!オシロスコープなどの計測器は「NI-VISA」という通信規格に対応していま...

    Python で波形データを取得するメリット

    オシロスコープで視覚化された電気信号は、一般的に「波形(データ)」と呼ばれます。

    この波形品質を確認するには、オシロスコープ内蔵の画面カーソルや、測定機能を使用するのが一般的なのですが…。

    オシロスコープで波形データを確認するのは面倒?

    以下のように、オシロスコープの機能だけでは不便なところも多いのです。

    1. 測定値の取り込みには別の手段が必要
    2. 波形の積分など、一般的な測定値を超えた値は未対応
    3. 波形データから区間を分割し、範囲ごとに測定するには煩雑すぎる

    こんな時は、波形データを直接解析するのがベストです。

    Python ならデータの取得と解析が一括でできる

    そこで役立つのが Python です。

    Python を使えば、波形データの取得と解析を一括で行うことができます。

    もともと Python は数値解析や大量データの処理に強いので、こういう用途にはうってつけと言えるでしょう。

    環境構築

    インストールが必要なもの

    1. Python の開発環境
    2. PyVISA モジュール
    3. NI-VISA

    筆者の実行環境

    1. Python (3.6)
    2. Spyder(3.2.6)
    3. PyVISA(1.9.1)
    4. オシロスコープ(Tektronix 社 MSO58シリーズ)

    前提

    あらかじめ、オシロスコープ上に転送したい波形を表示させておきましょう。

    表示するチャンネルはどこでも構いません。

    Python で波形データを取得する流れ

    1. PyVISA でオシロスコープを接続
    2. 波形データを保存
    3. 保存した波形データの転送

    ①PyVISA でオシロスコープを接続

    前回同様、オシロスコープのアドレスをResourceManager を使って取得し、接続まで進めてください。

    1import pyvisa
    2import time
    3from datetime import datetime
    4
    5VISAAddr = "USB0::___::____::INSTR" #rm.list_resources()にて得られる接続先のアドレス
    6
    7#リソースマネージャを実体化し、オシロスコープと接続を行う
    8rm = pyvisa.ResourceManager()
    9inst = rm.open_resource(VISAAddr)
    10
    11#接続先のオシロスコープの情報を表示(表示できない場合はエラーで終了)
    12print(inst.query('*IDN?'))

    ②波形データの保存

    接続がすんだら、ここからがいよいよ本題です!

    チャンネルを指定して、波形データをオシロスコープの内蔵 HD に保存する処理を行います。

    その前に、取得したいチャンネルがアクティブ状態(画面に表示されているか)かを確認してみましょう。

    指定したチャンネルがアクティブ状態か確認してみる

    1print(inst.query('DISplay:GLObal:CH'+str(****)+':STATE?'))

    ****にチャンネル数(1~4)を入力してコードを実行すると、1か0が表示されるはずです。

    1であればアクティブ状態で、0であれば非アクティブということになります。

    VISA のコマンド構造について

    VISA のコマンドは「画面表示」「波形属性」「ファイル操作」などの大きな項目から、それぞれの構成要素に下っていく構造になっています。

    例えばチャンネル1の場合、DISplay:GLObal:CH1:STATE? を送ることになりますね。

    構成要素ごとに「:」で区切るのは、C++のクラス変数や構造体のメンバ変数をイメージすれば良いでしょう。

    最後の「STATE」は状態を表しているため、前項の「CH1」の画面表示有無を示しています。

    波形データの保存

    次に、波形データを保存していきましょう。

    1#チャンネル1の波形データを内蔵HDにcsv形式で保存する
    2inst.write('SAVE:WAVEform CH1, \"C:Temp.csv\"')
    3
    4#波形データの保存処理が終了するまで待つ
    5while inst.query('*OPC?')[0]!="1":
    6    print("Waiting")
    7    time.sleep(1)

    画面キャプチャの時と同様に、SAVE コマンドを使い、今回は WAVEform で波形データを保存しました。

    また、コマンドOPC? を使って、処理が終了するまでウェイトを行っています。

    波形データは容量が大きいことが多いので、ここできちんとウェイトを行っておきましょう!

    ③保存した波形データの転送

    最後に、波形データを PC へ転送します。

    やることは画面キャプチャの時とほぼ同じですが、ファイル名には「csv」を指定します。

    1#保存された画像ファイルをPC側へ読み出す
    2inst.write('FILESystem:READFile \"C:/Temp.csv\"')
    3wave_data = inst.read_raw()
    4
    5#PC側に保存する際にdatetimeモジュールを使い、日付+時間のファイル名で保存する
    6dt=datetime.now()
    7filename = dt.strftime("WAVECH1_%Y%m%d_%H%M%S.csv")
    8file = open(filename,"wb")
    9file.write(wave_data)
    10file.close()
    11
    12#オシロスコープ側のテンポラリ画像ファイルを削除
    13inst.write('FILESystem:DELEte \"C:/Temp.csv\"')
    14
    15inst.close()
    16rm.close()

    VISA のFILESystem:READFile と PyVISA のread_raw は、バイナリデータとして読み出す挙動となっているため、ファイル形式は全く関係ありません。

    例えるなら、Windows でファイルのコピー・ペーストを行っているだけ、という感じですね。

    オシロスコープの接続を切る

    続いて、テンポラリファイルを削除し、オシロスコープとの接続を切れば完了です。

    これで PC 上に csv 形式の波形データが転送されたので、excel で開くも、Python でデータ解析をするも、自由にできるようになりました。

    応用例:アクティブなチャンネルを自動検出し、波形データを転送

    ただし、これではチャンネル1つ分しか転送できません。

    複数のチャンネルを転送する場合は必然的に上記の作業を繰り返すわけですが、コードをいちいち変えるのも、csv ファイルが増えていくのも面倒ですよね?

    そこで、今回は応用例として、以下のようなコードをご紹介します。

    1. アクティブなチャンネルを自動検出して、波形データを自動転送
    2. 生成されたチャンネル個別の csv ファイルを結合し、単一ファイルへ

    これを使えば、オシロスコープに表示するチャンネルがいくつあっても自動で転送し、1つのコンパクトな csv ファイルに変換してくれます。

    使用するモジュールは、2次元データ処理に特化した「Pandas」です。

    コード

    1import pyvisa
    2import time
    3from datetime import datetime
    4import pandas as pd
    5
    6
    7VISAAddr = "USB0::___::____::INSTR" #rm.list_resources()にて得られる接続先のアドレス
    8MAX_CH = 4     #オシロスコープの最大チャンネル数
    9ch_en=[]
    10IsFirstCh = False
    11
    12#リソースマネージャを実体化し、オシロスコープと接続を行う
    13rm = pyvisa.ResourceManager()
    14inst = rm.open_resource(VISAAddr)
    15
    16#接続先のオシロスコープの情報を表示(表示できない場合はエラーで終了)
    17print(inst.query('*IDN?'))
    18
    19####################
    20##波形データの取得処理###
    21####################
    22
    23#アクティブ状態のチャンネルを検出する(同時に最も若い番号のチャンネル番号も取得)
    24for i in range(MAX_CH):
    25    ch_en.append(int(inst.query('DISplay:GLObal:CH'+str(i+1)+':STATE?')))
    26    if ch_en[i] == 1 and IsFirstCh:
    27        first_ch = i
    28        IsFirstCh = False
    29        
    30#チャンネルごとに波形データ取得処理
    31csv_lst = [ 0 for i in range(MAX_CH)]
    32
    33for n in range(MAX_CH):
    34    #チャンネルがアクティブなら波形取得処理開始
    35    if ch_en[n]==1:
    36        #チャンネル番号を生成し、PyVISAでオシロスコープの内蔵HDに波形データを保存させる
    37        ch_no = "CH" + str(i+1)
    38        inst.write('SAVE:WAVEform '+ch_no +', \"C:Temp.csv\"')
    39        
    40        #PC側へ保存する個別波形データの名前を定義
    41        filename = "temp_" + ch_no +".csv"
    42        csv_lst [n] = filename
    43        
    44        #波形データの保存処理が終了するまで待つ
    45        while inst.query('*OPC?')[0]!="1":
    46            print("Waiting")
    47            time.sleep(1)
    48            
    49        #オシロスコープ上の波形データを読み出す
    50        inst.write('FILESystem:READFile \"C:/Temp.csv\"')
    51        wave_data = inst.read_raw()
    52        
    53        #読み出した波形データを指定したファイル名でPCに保存
    54        file = open(filename,"wb")
    55        file.write(wave_data)
    56        file.close()
    57        
    58        #オシロスコープ側のテンポラリ画像ファイルを削除
    59        inst.write('FILESystem:DELEte \"C:/Temp.csv\"')
    60        
    61        #処理終了を示すメッセージ
    62        print("Channel "+ str(ch_no) + " Done")
    63
    64#測定終了後にオシロスコープとの通信を切断する
    65inst.close()
    66rm.close()
    67
    68####################
    69##波形データの統合処理###
    70####################
    71CSV_HEADER_ROWS = 7
    72CSV_SKIP_ROWS = 9
    73
    74#アクティブチャンネルを検出した数だけ波形データの格納リストを作る
    75ch_wave =[[] for i in range(sum(ch_en))]
    76
    77#最も若いチャンネル番号のcsv波形データファイルからヘッダデータと時間軸データを取得
    78header = pd.read_csv(csv_lst[first_ch],header = None, nrows = CSV_HEADER_ROWS)
    79time_dt = pd.read_csv(csv_lst[first_ch],header = None, usecols=[0],skiprows=CSV_SKIP_ROWS)
    80
    81#最大チャンネル数まで波形データが保存されているかをチェックし、あれば格納リストにcsvデータを格納
    82wave_cnt = 0
    83for i in range(MAX_CH):
    84    if csv_lst[i]!=0:
    85        ch_wave[wave_cnt] = pd.read_csv(csv_lst[first_ch],header = None, usecols=[1],skiprows=CSV_SKIP_ROWS)
    86        ch_wave[wave_cnt].columns =["CH" +str(i+1)]
    87        wave_cnt +=1
    88        
    89#取得したチャンネルごとの波形データを1つのDataFrameに統合(最初の列は時間軸にする)
    90out_dt = time_dt
    91for i in range(sum(ch_en)):
    92    out_dt = pd.concat([out_dt,ch_wave[i]],axis=1)
    93    
    94#PC側に保存する際にdatetimeモジュールを使い、日付+時間のファイル名生成
    95dt=datetime.now()
    96wave_filename = dt.strftime("Wave_%Y%m%d_%H%M%S.csv")
    97
    98#Pandasの機能を使って、DataFrameをcsvに変換。このとき個別のcsvとヘッダデータ部分は共通にする
    99header.to_csv(wave_filename,header= False, index = False)
    100out_dt.to_csv(wave_filename,header= True, index = False,mode = 'a')
    101print("Wave File Output Complete")

    注意!

    CSV_HEADER_ROWS = 7はcsv ファイルのヘッダ情報が含まれている行数、CSV_SKIP_ROWS = 9はデータの格納が始まっている行数です。

    アドレスやチャンネル数と同じく、オシロスコープによって違う場合があるので、適宜調整してください。

    さいごに

    今回は、PyVISA を使って、Python でオシロスコープの波形データを PC に自動転送する方法を紹介しました。

    今回はデータの取得までですが、次回はいよいよ「データ解析」について解説していきます。

    次回もがんばっていきましょう!

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
    featureImg2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...

    広告メディア事業部

    広告メディア事業部

    おすすめ記事