LoginSignup
1
0

More than 1 year has passed since last update.

concurrent.futures.ThreadPoolExecutor を用いて2台の Keithley 2401 sourcemeter から矩形波定電圧を印加する

Last updated at Posted at 2022-03-17

はじめに

複数台の Keithley 2401 sourcemeter(以下 2401)を動かす方法を述べる。
マルチプロセスで動かした方が正確なはずだが、なぜかProcessPoolExecutor では動かず、かつ、私の理解が足りないために理由もよくわからないため、ThreadPoolExecutor で動かす方法を述べる。

例として、2台とも矩形波定電圧を印加し、1台がもう1台に対して遅れて定電圧を印加する場合を考える。
image.png

方法

事前準備

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
image.png

関連記事

PythonおよびKeithley 2401 を用いた矩形波定電圧の印加
concurrent.futures.ThreadPoolExecutor についての備忘録

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0