はじめに
複数台の Keithley 2401 sourcemeter(以下 2401)を動かす方法を述べる。
マルチプロセスで動かした方が正確なはずだが、なぜかProcessPoolExecutor では動かず、かつ、私の理解が足りないために理由もよくわからないため、ThreadPoolExecutor で動かす方法を述べる。
例として、2台とも矩形波定電圧を印加し、1台がもう1台に対して遅れて定電圧を印加する場合を考える。
方法
事前準備
2台の2401本体を操作する。「MENU」→「COMMUNICATION」→「GPIB」から、2台の2401のGPIBアドレスをそれぞれ23および24に設定する(コード内で指定しているGPIBアドレスと一致させる)。
コード
サンプルコード
# coding: UTF-8
import openpyxl
import time
from pymeasure.instruments.keithley import Keithley2400
from datetime import datetime
import concurrent.futures
### common settings ###
date = int(datetime.now().strftime("%Y%m%d"))-20000000 # 日付。2020年9月10日なら「200910」
keithley1 = Keithley2400("GPIB::23")
keithley2 = Keithley2400("GPIB::24")
def initial_settings():
sheet.cell(row = 1, column = 1).value = 't1 (sec)'
sheet.cell(row = 1, column = 2).value = 'I1(A)'
sheet.cell(row = 1, column = 3).value = 't2(sec)'
sheet.cell(row = 1, column = 4).value = 'I2 (A)'
sheet.cell(row = 1, column = 5).value = datetime.now()
### keithley settings ###
keithley1.reset()
keithley1.disable_buffer()
keithley1.use_front_terminals()
keithley1.apply_voltage()
keithley1.source_voltage_range = 0.3
keithley1.source_voltage = 0
keithley1.enable_source()
keithley1.measure_current()
keithley1.compliance_current = 1
keithley2.reset()
keithley2.disable_buffer()
keithley2.use_front_terminals()
keithley2.apply_voltage()
keithley2.source_voltage_range = 0.3
keithley2.source_voltage = 0
keithley2.enable_source()
keithley2.measure_current()
keithley2.compliance_current = 1
# ペルチェセルに電流を印加する
def v_1(voltage):
target_time = interval
current_time = current_interval
time_accuracy = 0.2
rest_direction = time.time() - base_time - target_time
for step in range(steps):
keithley1.ramp_to_voltage(voltage,steps=3)
while rest_direction < 0 : # 電圧の向き不変
rest_current = time.time()-base_time - current_time
while rest_current < 0 and rest_direction<0: # 電流測定しない、かつ、電圧の向き不変
time.sleep(time_accuracy)
rest_current = time.time()-base_time - current_time
rest_direction = time.time() - base_time - target_time
# 電流測定する、かつ、電圧の向き不変
sheet.cell(row = int(current_time/current_interval)+1, column = 1).value = time.time()-base_time
sheet.cell(row = int(current_time/current_interval)+1, column = 2).value = keithley1.current # 電圧記録の予定時間が来たらエクセルへ記録。
current_time = current_time + current_interval # 電圧記録時間を再設定。
#電圧の向き変更
target_time = target_time + interval
rest_direction = time.time() - base_time - target_time
#電圧 0 にする(後の電圧の向き反転のため、voltageに0を代入していない)
keithley1.ramp_to_voltage(0,steps=3)
while rest_direction < 0 : # 電圧の向き不変
rest_current = time.time()-base_time - current_time
while rest_current < 0 and rest_direction<0: # 電流測定しない、かつ、電圧の向き不変
time.sleep(time_accuracy)
rest_current = time.time()-base_time - current_time
rest_direction = time.time() - base_time - target_time
# 電流測定する、かつ、電圧の向き不変
sheet.cell(row = int(current_time/current_interval)+1, column = 1).value = time.time()-base_time
sheet.cell(row = int(current_time/current_interval)+1, column = 2).value = keithley1.current # 電圧記録の予定時間が来たらエクセルへ記録。
current_time = current_time + current_interval # 電圧記録時間を再設定。
#電圧の向き変更
voltage = voltage*(-1) # 電圧の向き反転
print(voltage)
target_time = target_time + interval
rest_direction = time.time() - base_time - target_time
keithley1.shutdown()
print('v_1_done.')
def v_2(voltage):
# print("v_2 is running")
target_time = interval
current_time = current_interval
time_accuracy = 0.01
while time.time() - base_time - delay_time < 0:
time.sleep(time_accuracy)
print("delayed")
base_time_2 = time.time() #delayの時間はノーカウント
rest_direction = time.time() - base_time_2 - target_time
# rest_direction = time.time() - base_time - target_time
for step in range(steps):
keithley2.ramp_to_voltage(voltage,steps=3)
while rest_direction < 0 : # 電圧の向き不変
rest_current = time.time()-base_time_2 - current_time
while rest_current < 0 and rest_direction<0: # 電流測定しない、かつ、電圧の向き不変
time.sleep(time_accuracy)
rest_current = time.time()-base_time_2 - current_time
rest_direction = time.time() - base_time_2 - target_time
# 電流測定する、かつ、電圧の向き不変
sheet.cell(row = int(current_time/current_interval)+1, column = 3).value = time.time()-base_time
sheet.cell(row = int(current_time/current_interval)+1, column = 4).value = keithley2.current # 電圧記録の予定時間が来たらエクセルへ記録。
current_time = current_time + current_interval # 電圧記録時間を再設定。
#電圧の向き変更
target_time = target_time + interval
rest_direction = time.time() - base_time_2 - target_time
#電圧 0 にする(後の電圧の向き反転のため、voltageに0を代入していない)
keithley2.ramp_to_voltage(0,steps=3)
while rest_direction < 0 : # 電圧の向き不変
rest_current = time.time()-base_time_2 - current_time
while rest_current < 0 and rest_direction<0: # 電流測定しない、かつ、電圧の向き不変
time.sleep(time_accuracy)
rest_current = time.time()-base_time_2 - current_time
rest_direction = time.time() - base_time_2 - target_time
# 電流測定する、かつ、電圧の向き不変
sheet.cell(row = int(current_time/current_interval)+1, column = 3).value = time.time()-base_time
sheet.cell(row = int(current_time/current_interval)+1, column = 4).value = keithley2.current # 電圧記録の予定時間が来たらエクセルへ記録。
current_time = current_time + current_interval # 電圧記録時間を再設定。
#電圧の向き変更
voltage = voltage*(-1) # 電圧の向き反転
print(voltage)
target_time = target_time + interval
rest_direction = time.time() - base_time_2 - target_time
print('v_2_done.')
keithley2.shutdown()
### conducting functions ###
if __name__ == "__main__":
sample_name = "test"
V1 = 0.1
V2 = 0.1
steps = 2
interval = 2 #(sec)
delay_time = 2 #v_2がv_1に遅れる時間
current_interval = 0.5 # 電流測定間隔
Username = '***'
filename = "{0}_{1}_{2}V_{3}V_{4}sec_{5}.xlsx".format(date, sample_name, V1, V2, interval, steps)
path = "C:\\Users\\{0}\\Desktop\\".format(Username)
print(datetime.now())
book = openpyxl.Workbook() # エクセルファイルを作成
sheet = book.worksheets[0]
initial_settings() #ソースメータの電源を入れる
base_time = time.time()
executor = concurrent.futures.ThreadPoolExecutor(max_workers=2) # サーミスタと電流引加をマルチスレッドで実行。マルチプロセスだとなぜか上手く動かない。
executor.submit(v_1,V1) #この形式で引数入れる。v_1(V1)だと駄目。
executor.submit(v_2,V2)
executor.shutdown() #両方の操作が終わったら次の操作へ。
book.save(path + filename)
print('finished.')
結果
V1=V2=0.1 V をinterval=2secごとに向きが入れ替わるように2サイクル印加した。
今回はintervalについて、V1およびV2で同じ値を用いた。
ファイル名:220315_test_0.1V_0.1V_2sec_2
関連記事
PythonおよびKeithley 2401 を用いた矩形波定電圧の印加
concurrent.futures.ThreadPoolExecutor についての備忘録