Pythonでオシロスコープを制御する(PyVISA)

Pythonでオシロスコープを制御する(PyVISA)

2023/01/07

今回は、Pythonでオシロスコープ等の測定機器を制御できるパッケージの紹介です。

動作環境

  • Cygwin

※Cygwinなのは、他のアプリとの兼ね合い上、そうせざるを得なかったからです。

インストール

Pythonはインストール済の想定です。

pip install pyvisa

サンプルコード

計測器のアドレス一覧表示

import pyvisa

rm = pyvisa.ResourceManager()
inst_list = rm.list_resources() #接続されている機器のアドレス一覧
## 上でエラーが出る場合は、以下のように設定するとうまくできる場合があります。

import pyvisa

visa32_path = "C:\\Program Files (x86)\\IVI Foundation\\VISA\\WinNT\\agvisa\\agbin\\visa32.dll"
rm = pyvisa.ResourceManager(visa32_path)
inst_list = rm.list_resources() #接続されている機器のアドレス一覧

機器情報読み出し

import pyvisa

address = "USB0::0x****::0x****::MY********::0::INSTR" #USB接続の場合

rm = pyvisa.ResourceManager()
inst = rm.open_resource(address)
inst.timeout = 20000 # 適当にタイムアウトの時間を設定しておく
inst.write("*IDN?") # "*IDN?"コマンドを機器に送信
result = inst.read() # 先程のコマンドの結果を読み出し
inst.write("*IDN?")
result = inst.read()

# 上の2行は下のプログラムで代替可能です。
result = inst.query("*IDN?")

実装例

プログラム例は、各機器のプログラミングガイドを参考にしてください。

また、sleep関数などを用いて、測定機器が短期間に複数の処理をしないようにするほうがいいと思います。

電源ユニット例

import pyvisa

address = "USB0::0x****::0x****::MY********::0::INSTR"

rm = pyvisa.ResourceManager()
inst = rm.open_resource(address)
inst.timeout = 20000

ch = 1
inst.write(f"VOLTage 1.0, (@{ch})") #ch1の電圧を1.0Vにする
inst.write(f"OUTPut 1, (@ch)") #ch1の電源をONにする
inst.query(f"VOLTage? (@{ch})") #ch1の電圧を取得する

オシロスコープ例

波形データを取得する方法が意外と難しかったりするので、参考にしてみてください。

なお、”:WAVeform:FORMat” を指定しないと、8bit(=256階調)で量子化されるため、ここでは16bit(=65536階調)で量子化するようにしています。

import pyvisa

address = "USB0::0x****::0x****::MY********::0::INSTR"

rm = pyvisa.ResourceManager()
inst = rm.open_resource(address)
inst.timeout = 20000

ch = 1
inst.query(f"MEASure:Vpp? CHANnel{ch}") #ch1のpeak-to-peak電圧を測定する

## 以下は波形データを取得する
### 波形データは標本化・量子化されている
inst.write(f":WAVeform:SOURce CHANnel{ch}") #対象chをch1に
inst.write(":WAVeform:FORMat WORD") #1データあたり16bitに
inst.write(":WAVeform:STReaming OFF")
inst.write(":WAVeform:VIEW MAIN")
inst.write(":WAVeform:BYTeorder LSBFirst") #データの順番を指定

x_increment = float(inst.query("WAVeform:XINCrement?")) #時間サンプリング間隔
x_origin = float(inst.query("WAVeform:XORigin?")) #サンプリング開始時間
y_increment = float(inst.query("WAVeform:YINCrement?")) #信号強度サンプリング間隔
y_origin = float(inst.query("WAVeform:YORigin?")) #信号強度基準
st_data = query_ieee(":WAVeform:DATA?") #波形生データ

values = struct.unpack("%dh" % (len(st_data)/2), st_data) #生データを扱える形にする
np_time = np.array(range(len(values))) * x_increment + x_origin #時間データ
np_value = np.array(values) * y_increment + y_origin #信号強度データ
print(np.stack[np_time,np_value])

def query_ieee(self, query):
    return inst.query_binary_values("%s" % query, datatype="s", container=bytes)