Python および Keithley 2401 sourcemeter を用いて CV 測定を行う(2)

#はじめに
[前回](https://qiita.com/matoarea/items/42292f27a9e669a8758a)の記事では必要なソフトのインストールなど、準備を行った。
（2）では測定に用いるプログラムの機構およびソースコードについて解説する。

#プログラムの概要
プログラムの機構について述べる。CV 測定を行うというのは、すなわち、
__0.__ scan rate, 掃引する電圧の範囲などの初期条件を入力する
__1.__ ある電圧（最初のsegmentのときは初期電圧）をWE-RE間に印可する
__2.__ そのときの電流値を測定する
__3.__ 電流値をどこかに記録する
__4.__ scan rate に応じた時間待つ
__5.__ 0.001 V だけ電圧を大きく（小さく）する
__6.__ 1~5 を掃引範囲に応じた点数だけ繰り返す（＝電圧を0.001 Vずつずらしたときの電流値を測定する）
__7.__ 1~6 を、電圧の掃引方向を変えて繰り返す
__8.__ 1~7 を、segment の数だけ繰り返す
を行うことである。
ずらす電圧の大きさを 0.001 V ごとにしたが、原理上は 0.01 V でも 0.0001 V でもよい。
ALS 電気化学アナライザーでは 0.001 V ごとに電流の値を測定しているようなので、それに倣って 0.001 V 刻みで電圧を変化させ、そのときの電流を測定するようにしてみた。
なお、__3.__ において、 openpyxl というモジュールを用いて Excel（以下、エクセル） ファイル内に電圧-電流を記録するようにした。
ソースメータで測定した結果をエクセルファイルに記録できるようになると、色々扱いやすいと思う。
グラフ作成も自動化できるが、それはまた別の話。

#ソースコード
```python:210401_CV_test_6-2.py

import openpyxl
from openpyxl import Workbook
import time
from pymeasure.instruments.keithley import Keithley2400
from datetime import datetime

date = int(datetime.now().strftime("%Y%m%d"))-20000000 # 日付。2020年9月10日なら「200910」
keithley = Keithley2400("GPIB::24") # 使用する機器に該当するGPIBアドレスを指定。
book = openpyxl.Workbook() # エクセルファイルを作成
sheet = book.worksheets[0] # エクセルファイル中の使用するブックを指定。

x = [] # voltage
y = [] # current
z = [] # time

def initial_settings():

    # エクセルファイルの作成
    sheet.cell(row = 1, column = 1).value = 'voltage (V)'
    sheet.cell(row = 1, column = 2).value = 'current (mA)'
    sheet.cell(row = 1, column = 3).value = 'time (sec)'
    sheet.cell(row = 1, column = 4).value = datetime.now()

    # ソースメータの設定
    keithley.reset() # とりあえずreset
    keithley.disable_buffer()
    keithley.use_front_terminals()
    keithley.apply_voltage() # 電圧印可モード。
    keithley.source_voltage_range = 1 # 印可する電圧のレンジ。 1.000 V のレンジで印可。
    keithley.source_voltage = 0 # ソース電圧（印可される電圧）の大きさをとりあえず0に。
    keithley.enable_source() # 印可を行う（ソース電源の印可を有効にする）。
    keithley.measure_current(nplc=0.01, current=0.000105, auto_range=True) # 電流測定。測定に用いる積分時間の長さを0.01 nplcに設定。測定される電流のレンジを
    keithley.current_range = I_sensitivity
    keithley.compliance_current = 0.01 # まず超えないが、一応設定。
    keithley.wires = 4 # 4線式で行うことが肝要。理由も説明できるようになるべし。

def voltage_apply(voltage):
    measurement_interval = 1/(scan_rate*1000) #余談だが、0.001/scan_rateにすべきではない。小数を用いると桁落ちの危険。
    meas_time = measurement_interval
    time_accuracy = 0.001

    points = int((high_V-low_V)*1000) # the number of point which should be recorded. I value is recorded at every 0.001 V.
    dV = 0.001 # 掃引電圧の粗さ 兼 （今回の場合は）電流測定間隔
    for i in range(segments):
        step = 0
        for step in range (points): 
            keithley.source_voltage = voltage
            rest_measurement = time.time() - base_time - meas_time
            while rest_measurement < 0: # 電流反転予定の時間が来るまで待つ。
                rest_measurement = time.time() - base_time - meas_time
                time.sleep(time_accuracy)
            z.append(time.time()-base_time) #時間記録
            x.append(voltage) # 電圧記録
            y.append(keithley.current) # 電流記録(A)
            voltage = voltage + dV # 印可電圧の変更（反映されるのは次のループから）
            meas_time = meas_time + measurement_interval # 次の測定点を設定
        dV = dV*(-1) # 掃引方向を変更
    keithley.shutdown()

    # エクセルにデータ記入。リストに一旦入れた値をエクセルへ。
    #この方法が毎度毎度エクセルに記録するよりも速いのかは未検証。
    for i in range(segments * points): 
        sheet.cell(row = 2+i, column = 1).value = x[i]
        sheet.cell(row = 2+i, column = 2).value = y[i]*1000 # 電流をmA単位で記入する。
        sheet.cell(row = 2+i, column = 3).value = z[i]
    print('voltage_apply_done.')

### conducting functions ###
if __name__ == "__main__": # おまじないみたいなもの。気になるならググって。
    # ファイル情報
    path = "C:\\Users\\（各自のユーザー名）\\Desktop\\" #ファイル保存場所を好きに設定。
    #とりあえずデスクトップに保存することにしてみた。
    sample_name = 'test' # ここに入力したサンプル名がファイル名に反映される。

    # 測定条件
    high_V = 0.5 # high voltage (V)
    low_V = 0.4 # low voltage (V)
    start_V = low_V # 必ずしも start_V = low_V ではないが、今回は簡単のため一致させている。
    finish_V = high_V
#    direction = n # p/nの設定で掃引方向を設定できるようにしましょう。
    scan_rate = 0.05 # scan rate(V/s)
    segments = 2 # number of segments (2 segments is equal to 1 cycle )
    I_sensitivity = 0.0001 # sensitivity of current measurement (A). 0.0001 means 0.00105 uA is maximum.

    # 保存ファイル名を生成
    filename = "{0}_{1}_{2}-{3}V_{4}Vs-1.xlsx".format(date, sample_name, low_V,high_V, scan_rate) 

    # 測定の実行
    initial_settings()
    keithley.enable_source()# なぜかここでもoutputをenableしないとoutputがenableにならない
    base_time = time.time() # 測定において0秒となる時刻を取得
    voltage_apply(start_V)
    book.save( path + filename ) # エクセルファイルを filename の名前で、path の場所に保存。
    print('finished.') 
```
自分用、かつ、研究室の新 B4・M1 向けのメモが散見されますが、ご容赦ください。

#コードの解説
### 序盤のimport
必要なモジュールを使えるようにする。
詳しくはhttps://www.tech-teacher.jp/blog/python-import/ を参照。
###initial_settingsの手前まで
・後々、保存するエクセルファイル名に自動で日付が入るようにしたい。そこで、 date=~ のところで、日付を文字列として入手する。余談だが、今回のプログラムでは datetime と time という似た見た目のモジュールを用いる。datetime / time はそれぞれ現時刻を、人の目にわかりやすいように扱うもの/ コンピュータが扱いやすい形で扱うもの だとご理解ください。
・使う keithley sourcemeter を指定。
・測定により得られた電圧値・電流値・そのときの時間を記録するためのリスト（=入れ物）を生成。
###initial_settings_voltage
エクセルについては openpyxl, keithley については pymeasure の keithley2400 モジュールを利用している。各コードの細かい意味は参考文献を参照しながら頑張って理解してください。的場が作っていてわかりにくかった/調べるのに時間がかかった点のみ共有する。

__keithley.measure_current(nplc=0.01, current=0.000105, auto_range=True)__
ソースメータが感知している電流値を取得するコードである。ここで、 nplc とは、number of power line circles の略で、1 PLC の何倍の積分時間を使って電流の値を取得するかを指定する。1 PLC は電源周波数の1周期分に相当する時間。関東では 50 Hz → 0.02 sec. したがって nplc = 0.01 の場合、0.01 * 0.02 sec = 0.0002 sec の間に得られる電流値から測定電流値を求める。無論、nplc が大きいほど 1 つの電流値取得により長い時間をかけることになるため、誤差は小さくなる。
auto_range はとりあえず設定しているが、どうせ次の行で range を指定するため、どっちでもいい。なお、ここでいうレンジは、測定電流値のオーダーのこと。これを予め指定しておけば、測定序盤で測定に要する時間を短くできる。

__keithley.wires = 4__
重要なところ。なぜ4線式にするかを理解するためには、CV で 3 つの電極を使う理由を理解している必要がある。練習実験が終わるころには、説明できるようになりましょう。

### voltage_apply(voltage)
まず入力した scan_rate から、何秒ごとに 0.001 V 動かすかを求める。
次に for 文において、電圧印可・時間の測定・電流測定・電圧の掃引 を行う。
最後に、リスト内に入れた各データを、エクセルファイル内に移す。

### if __name__ == ～～ 以下
上で定義した関数の実行をここで行う。
まず電圧測定範囲、電流感度（測定する電流値の桁）、掃引速度などを好きに設定する。次に測定を行い、測定後にエクセルファイルを保存する。

# おわりに
（2）では測定に用いるソースコードについて解説した。（3）では実際の測定のセットアップについて解説する。加えて、B4・M1向けの演習問題を課す予定である。

#参考文献
###import とは
https://www.tech-teacher.jp/blog/python-import/
その他、わからない語句があれば都度ググったり詳しそうな人に聞いてください。
###Keithley 2400 SourceMeter
https://pymeasure.readthedocs.io/en/latest/api/instruments/keithley/keithley2400.html
このモジュールを用いてソースメータを操作する。ソースメータを好きに動かしたいときに辞書的に利用できる。

### Tutorial openpyxl 3.0.7 documentation
https://openpyxl.readthedocs.io/en/stable/tutorial.html
openpyxl の使い方について。