IoTで使うPython入門 Step5-Python3 VISA④DMM Keithley 2000 +電源E3631A 設置

 実験用の電源を追加します。AgilentのE3631Aです。6V/5A、±25V/1Aの三つの出力が利用できる80Wの実験用電源です。デフォルトで、GPIBとRS-232インターフェースが用意されています。今回、GPIBを使います。

GPIBアドレス

 マニュアルによれば、デフォルトは5に設定されています。

 パネルにあるI/O Configボタンを押します。HPIB / 488の表示が出ます。もう一度I/O Configボタンを押します。ADDR Xの表示が出るので、ダイヤルを回して、10にしました。I/O Configボタンを押すと、CHANGE SAVEDの表示が出た後、初期メッセージOUTPUT OFFが表示されます。

接続

 DMMのGPIBコネクタにGPIBケーブルで電源E3631Aを数珠つなぎしていけばよいのですが、ここでは、GPIB-USB変換ケーブル(Agilentの82357B)をもう1本使ってPCのUSBポートにつなぎました。

 Keysight Connection Expert 2020を起動します。

 GPIBのバス1アドレス10に見つけてきました。DMMはGPIBバス0にいました。

 このソフトの中にあるInteractive IOをボタンを押して起動します。デフォルトで機器名問い合わせの*IDN?がCommand欄に記述されているので、Send & Readボタンを押しました。

 製品のパネルではAgilentですが、さらに古い会社名が出てきました。

動作確認のプログラム

 3台のGPIB機器に対して測定器のIDの問い合わせをします。

import visa

Keithley2000_1_Addr = "GPIB0::6"
Keithley2000_2_Addr = "GPIB0::18"
AgilentE3631A_Addr  = "GPIB1::10"

r = visa.ResourceManager()
keithley2000_1 = r.open_resource(Keithley2000_1_Addr)
keithley2000_2 = r.open_resource(Keithley2000_2_Addr)
agilentE3631A  = r.open_resource(AgilentE3631A_Addr)

keithley2000_1.write('*IDN?')
keithley2000_2.write('*IDN?')
agilentE3631A.write('*IDN?')

print(keithley2000_1.read())
print(keithley2000_2.read())
print(agilentE3631A.read())

 実行結果です。

>py keithley40.py
KEITHLEY INSTRUMENTS INC.,MODEL 2000,0801917,A13 /A02

KEITHLEY INSTRUMENTS INC.,MODEL 2000,0638990,A06 /A02

HEWLETT-PACKARD,E3631A,0,2.1-5.0-1.0

電流を測る

 DMMではデフォルトの電圧測定をしていました。GPIBアドレス6のDMMで電流を測ります。電源は手動で約10Vを出力します。負荷に2kΩの抵抗をつなぎ、電流を測定します。

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("SENSe:FUNCtion 'CURRent'; DC:RANG AUTO")
#keithley2000_1.write("CONF:CURR; DC:RANG AUTO") 

while 1:
    data = keithley2000_1.query(":READ?") 
    sleep(1)
    print("I: ", float(data))

 *RST;*CLSは初期化です。*RSTは測定器をリセットします。*CLSはステータス・レジスタをクリアします。Keithley 2000では、イベント・レジスタをクリアします。

  keithley2000_1.write("SENSe:FUNCtion 'CURRent'; DC:RANG AUTO")
と、
  keithley2000_1.write("CONF:CURR; DC:RANG AUTO")

は、同じ電流設定です。DCの前にスペースが必要です。113 Undefined header(コマンドの綴りが不正であるか、無効なコマンドが入力された)というエラーが出ますが、電流モードに変更されました。

抵抗の両端に電圧をかけ、電圧と電流を測る

 電源を約10Vに設定し、+25V端子に2kΩの抵抗をつなぎます。その両端の電圧を1台のDMMで、もう1台のDMMで電流を測ります。

import visa
from time import sleep

Keithley2000_6_Addr  = "GPIB0::6"
Keithley2000_18_Addr = "GPIB0::18"

r = visa.ResourceManager()
keithley2000_6  = r.open_resource(Keithley2000_6_Addr)
keithley2000_18 = r.open_resource(Keithley2000_18_Addr)

keithley2000_6.write("*RST;*CLS")
keithley2000_18.write("*RST;*CLS")
keithley2000_6.write("CONF:CURR; DC:RANG AUTO")
keithley2000_18.write("CONF:VOLT:DC:RANG 10")

while 1:
    dataI = keithley2000_6.query(":READ?")
    dataE = keithley2000_18.query(":READ?") 
    sleep(1)
    print("I: ", float(dataI), "E: ", float(dataE))

 実行結果です。

>py keithley43.py
I: 0.00498658355 E: 9.95433082
I: 0.00498560093 E: 9.95438632
I: 0.00498557851 E: 9.95436033

電源の設定

 +25Vの出力を制御します。最初に10.06Vの電圧を設定(中古品を入手したので少し電圧がずれているので補正)、すぐにトリガをかけ、出力をONする設定をし、INITで実行に移します。その後、電圧を1Vずつ上げます。

import visa
from time import sleep

AgilentE3631A_Addr   = "GPIB1::10"

r = visa.ResourceManager()
agilentE3631A   = r.open_resource(AgilentE3631A_Addr)

agilentE3631A.write("*RST;*CLS")
agilentE3631A.write("INST:SEL P25V")
agilentE3631A.write("VOLT:TRIG 10.06")
agilentE3631A.write("TRIG:SOUR IMM")
agilentE3631A.write("OUTP ON")
agilentE3631A.write("INIT")
print('10V')
sleep(5)
agilentE3631A.write("VOLT:TRIG 11.06")
agilentE3631A.write("INIT")
print('11V')
sleep(5)
agilentE3631A.write("VOLT:TRIG 12.06")
agilentE3631A.write("INIT")
print('12V')

 ループで電圧を、0から15Vに1Vステップで上げるように変更しました。

import visa
from time import sleep

AgilentE3631A_Addr   = "GPIB1::10"

r = visa.ResourceManager()
agilentE3631A   = r.open_resource(AgilentE3631A_Addr)

agilentE3631A.write("*RST;*CLS")
agilentE3631A.write("INST:SEL P25V")
agilentE3631A.write("TRIG:SOUR IMM")
agilentE3631A.write("OUTP ON")

for outVolt in range(16):
    agilentE3631A.write("VOLT:TRIG " + str(outVolt+0.06))
    agilentE3631A.write("INIT")
    print(outVolt)
    sleep(3)

抵抗の両端に電圧をかけ、電圧と電流を測ってグラフにする

 forループの中では、電圧を指定し、INITコマンドを発行し、100ms待つという動作を繰り返しています。この流れがよいかどうかは不明ですが、正しく動いているように見えます。電圧の設定は90ms以下の内部の時間が必要なので100msを待たしています。

 出力される抵抗値は、いずれの値もほぼ2kΩなので、測定が正しいことがわかります。

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

Keithley2000_6_Addr  = "GPIB0::6"
Keithley2000_18_Addr = "GPIB0::18"
AgilentE3631A_Addr   = "GPIB1::10"

r = visa.ResourceManager()
agilentE3631A   = r.open_resource(AgilentE3631A_Addr)
keithley2000_6  = r.open_resource(Keithley2000_6_Addr)
keithley2000_18 = r.open_resource(Keithley2000_18_Addr)

dataI = []
dataE = []
agilentE3631A.write("*RST;*CLS")
agilentE3631A.write("INST:SEL P25V")
agilentE3631A.write("TRIG:SOUR IMM")
agilentE3631A.write("OUTP ON")

keithley2000_6.write("*RST;*CLS")
keithley2000_18.write("*RST;*CLS")
keithley2000_6.write("CONF:CURR; DC:RANG AUTO")
keithley2000_18.write("CONF:VOLT:DC:RANG 10")
sleep(1)

for outVolt in range(1,16):
    agilentE3631A.write("VOLT:TRIG " + str(outVolt+0.06))
    agilentE3631A.write("INIT")
    print(outVolt)
    sleep(0.1)
    dI = keithley2000_6.query(":READ?")
    dataI.append(dI)
    
    dE = keithley2000_18.query(":READ?")
    dataE.append(dE)
    
    print("  E: ", float(dE), "I: ", float(dI) , "R=", float(dE)/float(dI))

dataCurrent = [float(f)*1000 for f in dataI]
dataVoltage = [float(f) for f in dataE]
print(dataCurrent, dataVoltage)
plt.plot(dataVoltage, dataCurrent, label="R 2k")
plt.xlabel("Volt [V]")
plt.ylabel("Current [mA]")
plt.show()

 実行結果です。抵抗は線形素子なので、まっすぐなグラフが得られます。