IoTで使うPython入門 Step5-Python3 VISA③DMM Keithley 2000 電圧測定(その2)

 前回、サンプル・プログラムをベースに、連続する電圧測定のプログラムを作りました。ここでは、それぞれのSCPIコマンドの動きを見ながら、プログラムを作っていきます。

測定の設定と読み取り

 DMMは1台です。*RST;*CLSで初期化後、MEAS?で計測します。このコマンドは、CONFコマンド(または SENSコマンド) + READ?コマンドをまとめて実行できます。

import visa
from time import sleep

Keithley2000_1_Addr = "GPIB0::6"

r = visa.ResourceManager()
keithley2000_1 = r.open_resource(Keithley2000_1_Addr)

keithley2000_1.write('*RST;*CLS')
keithley2000_1.write('MEAS:VOLT:DC?')
data = keithley2000_1.read()
print(data)
print(float(data))

  read()したdataは文字列です。float()で実数へ変換します。プログラム名はkeithley30.pyとしました。

>py keithley30.py
+2.49222515E+00
2.49222515

 この動作を、100回繰り返します。

import visa
from time import sleep

Keithley2000_1_Addr = "GPIB0::6"

r = visa.ResourceManager()
keithley2000_1 = r.open_resource(Keithley2000_1_Addr)

keithley2000_1.write('*RST;*CLS')
data = []
i = 0
print('\n---start---')
while i <100:
    i += 1
    keithley2000_1.write('MEAS:VOLT:DC?')
    d = float(keithley2000_1.read())
    data.append(d)
print(len(data), data)

 実行結果です。

>py keithley31.py

---start---
100 [2.49223014, 2.49222719, 2.49222755, 2.4922297, 2.49222894, 2.49222954, 2.49
22934, 2.49223351, 2.49222607, 2.49222627, 2.49222998, 2.49223007, 2.49222545, 2
49222545, 2.49222926, 2.49222998, 2.49223, 2.49222878, 2.49222739, 2.49223068, 2
9223169, 2.4922283, 2.49222659, 2.49223173, 2.49222563, 2.49222849, 2.49223093,
.49222705, 2.49222979, 2.49222741, 2.4922295, 2.4922321, 2.49222509, 2.49222684,
2.49223226, 2.49222634, 2.49222598, 2.49222963, 2.49222677, 2.49222943, 2.492225
3, 2.49222918, 2.4922268, 2.49223178, 2.49222871, 2.49222902, 2.49222814, 2.4922
35, 2.49222981, 2.4922294, 2.49223362, 2.49222874, 2.49222972, 2.49223116, 2.492
2721, 2.49222684, 2.49222988, 2.49222805, 2.49222894, 2.49223127, 2.49223144, 2.
9223057, 2.49222878, 2.49223445, 2.49223173, 2.49223255, 2.49223054, 2.49223166,
.49223112, 2.49222952, 2.49223146, 2.49222636, 2.49222972, 2.49222782, 2.4922333
2.49223239, 2.4922289, 2.49222853]

まとめて測定

 上記のプログラムでは、「1回の測定とPCへの転送」が100回繰り返されるので、GPIBバスは大変混雑しています。ここでは、100回の測定を指示し、データが用意できたらPCに読み込むプログラムを作ります。

  「Model 2000 Multimeter User’s Manual、2000-900-01 Rev. J / August 2010」

のサンプル・プログラムを参照します。

  • 測定のための準備;初期化、電圧測定、レンジの設定、測定数の設定、準備ができたら直ちに測定開始
  • 測定開始;INITで測定開始。測定終了のステータスを監視
  • 読み出し;データをPCへ転送

 測定終了のステータスを監視するのは、STATus:MEASurement?です。戻ってくる値を見ると、最初に160、そのあと32が続き、288が出てまた32が続き、544が出ます。500を超えると、準備完了と判断しました。

 STAT:MEAS:ENABは、:STATus:MEASurement:ENABle で、Measurement
event enable registerの各値をセットします。ビット操作をしなくて済むように、8ビットの値には重み付けが行われて、ふたつの、BFL (bit B9) =512、RAV (bit B5) =32をセットするには、合計の544にします。 
 ステータス・レジスタの内容は、それぞれの項目の役割をわかってうえで利用すると、もっと確実な判断ができるかもしれません。

 TRIGger:SOURce IMMediateとTrigger:Delay:AUTOは、トリガ条件をすぐに実行という意味合いで記述しましたが、間違っているかもしれません。

 NPLC 1は積分時間を設定しています。0.01~10が設定できます。 60Hzで使っている機器の場合、1 PLCは16.67msです。数字が小さいほど高速ですが、読み取りノイズが増加し、使用可能な桁が少なくなります。

 TRAC:CLEは、バッファからの読みをクリアにするという意味で使っていますが、不要かもしれません。

 TRACe:FEED:CONTrol NEXTは、すぐに測定を開始し、バッファがいっぱいになったときに停止します。TRACe:FEED SENSe1;CONTrol NEXTとした場合は、未処理の読み取り値を保存しますが、その違いがよくわかりません。

import visa
from time import sleep

Keithley2000_1_Addr = "GPIB0::6"

r = visa.ResourceManager()
keithley2000_1 = r.open_resource(Keithley2000_1_Addr)

keithley2000_1.write('*RST;SYSTem:PRESet;*CLS')
keithley2000_1.write(':CONF:CONF:VOLT:DC')
keithley2000_1.write(':STAT:MEAS:ENAB 544')
keithley2000_1.write('*SRE 1')  # buffer full
data = []
print('\n---start---')
keithley2000_1.write(':TRIGger:SOURce IMMediate')
keithley2000_1.write(':Trigger:Delay:AUTO')
keithley2000_1.write(':SENS:RES:NPLC 1')
keithley2000_1.write(':TRAC:CLE')
keithley2000_1.write(':TRIGger:COUNt 10')
keithley2000_1.write(':SAMPle:COUNt 10')
keithley2000_1.write(':TRACe:POINts 380')
keithley2000_1.write(':TRACe:FEED:CONTrol NEXT')

keithley2000_1.write(':INITiate')
sleep(1)
keithley2000_1.write(':STATus:MEASurement?')
k = keithley2000_1.read()
#print(type(k), k)

while int(k) < 500:
    keithley2000_1.write(':STATus:MEASurement?')
    k = keithley2000_1.read()
    #print(k)
    #sleep(0.1)
print(k)
sleep(1)
d = keithley2000_1.query_ascii_values(':TRAC:DATA?')
print(len(d))
f = [float(f) for f in d]
print(f)

 測定は、TRACe:POINts 380で380回分行ってバッファに入れるのが限界のようでした。INITiateまでは、設定項目です。INITiateが発行されると、それらが実行されます。

380回の測定を繰り返す

 上記のプログラムを繰り返せば、ずっと測定が続きます。測定した380個のデータで最頻度のグラフを描きます。380回がエラーとなるときは、200回ぐらいに減らして実行すると、timeoutのエラーが出ないこともあります。

import visa
from time import sleep
import matplotlib.pyplot as plt
import matplotlib.animation as animation

Keithley2000_1_Addr = "GPIB0::6"

r = visa.ResourceManager()
keithley2000_1 = r.open_resource(Keithley2000_1_Addr)

keithley2000_1.write('*RST;SYSTem:PRESet;*CLS')
keithley2000_1.write(':CONF:CONF:VOLT:DC')
keithley2000_1.write(':STAT:MEAS:ENAB 544')
keithley2000_1.write('*SRE 1')  # buffer full
data = []
print('\n---start---')
keithley2000_1.write(':TRIGger:SOURce IMMediate')
keithley2000_1.write(':Trigger:Delay:AUTO')
keithley2000_1.write(':SENS:RES:NPLC 1')
keithley2000_1.write(':TRAC:CLE')
keithley2000_1.write(':TRIGger:COUNt 10')
keithley2000_1.write(':SAMPle:COUNt 10')
keithley2000_1.write(':TRACe:POINts 380')

while 1:
    keithley2000_1.write(':TRACe:FEED:CONTrol NEXT')
    keithley2000_1.write(':INITiate')
    #print('\n---init---')
    sleep(1)
    keithley2000_1.write(':STATus:MEASurement?')
    k = keithley2000_1.read()

    while int(k) < 500:
        keithley2000_1.write(':STATus:MEASurement?')
        k = keithley2000_1.read()
        #print(k)
    print('find', k)
    sleep(1)
    d = keithley2000_1.query_ascii_values(':TRAC:DATA?')
    print('data is', len(d))
    data = [float(f) for f in d]
    print(data)
    print('---repeat')

    plt.hist(data, rwidth=0.7)
    plt.pause(1)

 実行例です。