Monologue-ひとりごと

日々の考えたこと

ESP32で簡単に作る、ダイオードのI-V特性評価装置

酷暑、電気代上昇、AIサーバーによる大量の電力消費など、太陽電池への注目は日に日に増しているように感じます。 最近は、ペロブスカイト太陽電池が実用間近というニュースも聞くようになりました。

学生時代に太陽電池の研究をしていたため、このようなニュースは非常に興味があります。 最近は以下の本を読んで、研究室時代の記憶を思い出しています。

太陽電池の評価では、光学的な物性の評価に加えて、電気特性の測定も行います。中でも重要なのはI-V特性(実際には電流を受光面積で割ったJ-V特性)の評価です。 疑似太陽光照射時のI-V特性を測定することで、光電変換効率と呼ばれる太陽電池の重要な指標を取得することができます。

この評価には、ソースメーターと呼ばれる電圧を印加・電流を供給しながら、その応答を測定できる装置が用いられています。 Keithley(現在はテクトロニクス)の2400シリーズと聞くとピンとくる方も多いかもしれません。

ソースメーターは研究用の設備であることもあり、100万円以上もするため個人で所有するのは現実的ではありません。 そこまで高い測定精度は求めないので、素人でも家庭で太陽電池の評価が行えないかと色々調べていたところ、マイコンボードでの工作例を見つけました。

太陽電池の特性を測定するのは一工夫要りそうですが、通常のダイオードの特性ぐらいはマイコンボードのDAC, ADCを用いれば簡単に測定できそうだ。 太陽電池特性評価を最終的なゴールとしつつ、その前段階として、通常のダイオード特性の測定を行うシステムを試作してみました。

 原理

大体のマイコンボードにはアナログ電圧出力機能としてPWM出力を備えています。

LPFを用いて脈動を除去することでPWMを疑似的なアナログ電圧源として利用することもできます。 一方、一部ボードではDAC機能を有するものもあり、アナログ電圧を直接出力することができます。 今回使用するESP32も、8bitの分解能ですが2チャンネルのDACを装備しています。

このDACを用いて、ダイオードにバイアスを印加し、流れた電流をADCで測定することI-V特性を取得しようという目算です。

回路図

以下に回路図を示します。 マイコンボードとして、ESP32-DevKitC-32Eを使用しました。

測定対象となるダイオードに抵抗を直列に接続し、DACを通して電圧を印加します。 DACの出力電圧とダイオードの印加電圧をADCで測定し、その差から抵抗の両端の電位差を求めます。この電圧を抵抗値で割ることで、ダイオードに流れる電流値を求めることができます。

最終的に、ダイオードの印加電圧と流れた電流値をプロットしてI-Vプロットを取得することができるはずです。

DACの出力電圧は計算で求められますが、ChatGPTによると実測した方がよいとのことなので今回はこのような回路にしてみました。

プログラム

以下に、書き込んだスケッチを示します。

シリアルにヘッダ行を出力した後、以下のデータを1行ずつシリアルに出力する仕様です。

  1. DAC[V]: DACの電圧出力値(設定値)
  2. DAC output[V]: DACの電圧出力値(ADCでの読み取り値)
  3. Diode voltage[V]: ダイオードに印加した電圧(ADCでの読み取り値)
  4. Current[mA]: 2と3の電圧を差し引き、抵抗の両端の電位差を求めた後、抵抗値で割って算出
const int DAC_PIN = 25;
const int ADC_OUTPUT_VOLTAGE = 34;
const int ADC_DIODE_VOLTAGE = 35;

const float VREF = 3.30;
const float R_SHUNT = 1000.0;  // Ω

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  analogReadResolution(12);
  analogSetAttenuation(ADC_11db);

  Serial.println("DAC[V],DAC output[V],Diode voltage[V],Current[mA]");
}

float readADC(int pin)
{
  // average ADC read values
  long sum = 0;

  for(int i=0; i < 16; i++)
  {
    sum += analogRead(pin);
  }

  return sum / 16.0;
}

void loop() {
  // put your main code here, to run repeatedly:

  for(int dac=0; dac<=255; dac++)
  {
    // Output Analog Voltage
    dacWrite(DAC_PIN, dac);
    delay(10);

    // Output Voltage[V]
    float dacVoltage = (VREF / 255.0) * dac;

    // Read Voltage[V]
    float adcOutputVoltage = readADC(ADC_OUTPUT_VOLTAGE);
    float adcDiodeVoltage = readADC(ADC_DIODE_VOLTAGE);

    float outputVoltage = adcOutputVoltage * VREF / 4095.0;
    float diodeVoltage = adcDiodeVoltage * VREF / 4095.0;

    // Calculate Current[mA]
    float current = (outputVoltage - diodeVoltage) / R_SHUNT * 1000;

    // Display Values
    Serial.print(dacVoltage, 3);
    Serial.print(",");

    Serial.print(outputVoltage, 3);
    Serial.print(",");

    Serial.print(diodeVoltage, 3);
    Serial.print(",");

    Serial.println(current, 6);

  }

  Serial.println("END");
  while(true);
}

測定・データ処理

スケッチとは別で以下のPythonスクリプトを作成し、シリアルの出力をCSVファイルとして出力するようにしました。

スクリプトを走らせた後、ESP32をリセットし測定を開始、測定が完了したら"END"の文字列を受け取り終了する仕様となっています。

import serial
import csv
from pathlib import Path
from datetime import datetime

PORT = "COM11"
BAUDRATE = 115200

filename = datetime.now().strftime("IV_%Y%m%d_%H%M%S.csv")
filepath = Path(f"./data/{filename}")

ser = serial.Serial(PORT, BAUDRATE)
write_flag = False

with open(filepath, "w", newline="") as f:
    writer = csv.writer(f)
    
    while True:
        readline = ser.readline().decode().strip()
        print(readline)
        
        if not write_flag:
            if readline.startswith("DAC[V]"):
                writer.writerow(readline.split(","))
                write_flag = True
        
        else:
            if readline == "END":
                break
            else:
                writer.writerow(readline.split(","))
            
ser.close()
print(f"Saved as {filename}") 

結果

得られた測定結果をMatplotlibを用いてプロットしてみました。

測定したのは、通常のSiダイオード(1N4148), 赤色のダイオードと白色ダイオード(品番などは不明)。

マイコン内蔵のDAC機能では流せる電流量が小さいため、立ち上がり初期しか測定できていませんが、順方向電圧の違いが明確に確認できます。

一方で、Siダイオードの順方向電圧の値が少し小さすぎる印象も受けるため、DACとADCの精度について検証する必要がありそうです。 ESP32のDAC・ADCにはオフセット誤差や非線形性があることが知られているため、それが原因なのかもしれません。

まとめ

ESP32に搭載されているDACとADCだけでも、簡易的なダイオードのI-V特性測定システムを構築できました。 測定可能な電流には制約がありますが、ダイオードごとの順方向電圧の違いは十分に確認できます。

今後はDAC出力をオペアンプでバッファし、より大きな電流を流せるよう改良した上で、最終目標である太陽電池のI-V特性測定にも挑戦したいと思います。

Quantum Espressoで第一原理計算#5 スーパーセルの計算-2

前回の記事では、Siのスーパーセルを作成し、DOSの計算を行いました。 今回は不純物(B, P)でスーパーセル内の原子を置換し、計算結果がどう変化するかを確認しました。

入力ファイルは全てB置換時のものを示しますが、Pの入力ファイルも同様の方法で作成したので、ほとんど違いはありません。

原子の置換

pymatgenを用いて、置換を行いました。 前回のスクリプトを流用、一部追記し、以下のようにしました。

import pymatgen
from pymatgen.core import Structure

# read cif file
structure =  Structure.from_file("Si.cif")
structure.remove_oxidation_states()
print(f"This Structure is consisted of {len(structure)} atoms")

# make supercell 
supercell = structure.copy()
supercell.make_supercell([2, 2, 2])

# substitute atom
supercell[0].species = "B"
print(f"Supercell is consisted of {len(supercell)} atoms")
supercell.to("Si_B_supercell.cif", "cif")

# print parameters
print("CELL_PARAMETERS")
lattice = supercell.lattice.matrix
for vec in lattice:
    print(f"{vec[0]:12.8f} {vec[1]:12.8f} {vec[2]:12.8f}")

print("ATOMIC_POSITIONS")
for site in supercell:
    element = site.species_string
    x, y, z = site.frac_coords
    print(f"{element} {x:.8f} {y:.8f} {z:.8f}")

cifファイルを読み込んだ後、スーパーセルに展開し、最初の原子をBに置換しています。 やっていることとしては、"ATOMIC_POSITIONS"の最初の元素をSiからBに置き換えるだけなので、エディタで編集するだけでも問題ないと思います。

SCF計算

出力された原子位置を元に以下の入力ファイルを作成し、SCF計算を行いました。 前回計算した純粋なSiと異なり、フェルミ準位が一部占有された状態(完全な絶縁体ではない状態)となるため、smearingを指定する必要がある点に注意します。 計算時間は、1時間20分程度掛かりました。

入力ファイル(クリックで展開)

&CONTROL
    calculation = 'scf',
    prefix = 'Si_B',
    outdir = './tmp',
    pseudo_dir = './pseudo'
/

&SYSTEM
    ibrav = 0,
    nat = 64,
    ntyp = 2,
    ecutwfc = 40.0,
    ecutrho = 320.0,
    occupations = 'smearing',
    smearing = 'mp',
    degauss = 0.02
/

&ELECTRONS
    conv_thr = 1.0d-6
/

CELL_PARAMETERS {angstrom}
    10.88740474   0.00000000   0.00000000
    0.00000000  10.88740474   0.00000000
    0.00000000   0.00000000  10.88740474
ATOMIC_SPECIES
    B 10.811 B.pbe-n-kjpaw_psl.1.0.0.UPF
    Si 28.08500 Si.pbe-n-kjpaw_psl.1.0.0.UPF
ATOMIC_POSITIONS {crystal}
    B 0.37500000 0.37500000 0.12500000
    Si 0.37500000 0.37500000 0.62500000
    Si 0.37500000 0.87500000 0.12500000
    Si 0.37500000 0.87500000 0.62500000
    Si 0.87500000 0.37500000 0.12500000
    Si 0.87500000 0.37500000 0.62500000
    Si 0.87500000 0.87500000 0.12500000
    Si 0.87500000 0.87500000 0.62500000
    Si 0.00000000 0.25000000 0.25000000
    Si 0.00000000 0.25000000 0.75000000
    Si 0.00000000 0.75000000 0.25000000
    Si 0.00000000 0.75000000 0.75000000
    Si 0.50000000 0.25000000 0.25000000
    Si 0.50000000 0.25000000 0.75000000
    Si 0.50000000 0.75000000 0.25000000
    Si 0.50000000 0.75000000 0.75000000
    Si 0.37500000 0.12500000 0.37500000
    Si 0.37500000 0.12500000 0.87500000
    Si 0.37500000 0.62500000 0.37500000
    Si 0.37500000 0.62500000 0.87500000
    Si 0.87500000 0.12500000 0.37500000
    Si 0.87500000 0.12500000 0.87500000
    Si 0.87500000 0.62500000 0.37500000
    Si 0.87500000 0.62500000 0.87500000
    Si 0.00000000 0.00000000 0.00000000
    Si 0.00000000 0.00000000 0.50000000
    Si 0.00000000 0.50000000 0.00000000
    Si 0.00000000 0.50000000 0.50000000
    Si 0.50000000 0.00000000 0.00000000
    Si 0.50000000 0.00000000 0.50000000
    Si 0.50000000 0.50000000 0.00000000
    Si 0.50000000 0.50000000 0.50000000
    Si 0.12500000 0.37500000 0.37500000
    Si 0.12500000 0.37500000 0.87500000
    Si 0.12500000 0.87500000 0.37500000
    Si 0.12500000 0.87500000 0.87500000
    Si 0.62500000 0.37500000 0.37500000
    Si 0.62500000 0.37500000 0.87500000
    Si 0.62500000 0.87500000 0.37500000
    Si 0.62500000 0.87500000 0.87500000
    Si 0.25000000 0.25000000 0.00000000
    Si 0.25000000 0.25000000 0.50000000
    Si 0.25000000 0.75000000 0.00000000
    Si 0.25000000 0.75000000 0.50000000
    Si 0.75000000 0.25000000 0.00000000
    Si 0.75000000 0.25000000 0.50000000
    Si 0.75000000 0.75000000 0.00000000
    Si 0.75000000 0.75000000 0.50000000
    Si 0.12500000 0.12500000 0.12500000
    Si 0.12500000 0.12500000 0.62500000
    Si 0.12500000 0.62500000 0.12500000
    Si 0.12500000 0.62500000 0.62500000
    Si 0.62500000 0.12500000 0.12500000
    Si 0.62500000 0.12500000 0.62500000
    Si 0.62500000 0.62500000 0.12500000
    Si 0.62500000 0.62500000 0.62500000
    Si 0.25000000 0.00000000 0.25000000
    Si 0.25000000 0.00000000 0.75000000
    Si 0.25000000 0.50000000 0.25000000
    Si 0.25000000 0.50000000 0.75000000
    Si 0.75000000 0.00000000 0.25000000
    Si 0.75000000 0.00000000 0.75000000
    Si 0.75000000 0.50000000 0.25000000
    Si 0.75000000 0.50000000 0.75000000
K_POINTS {automatic}
    4 4 4 0 0 0

NSCF計算

純粋なSiと同様に計算を行います。 DOSの計算結果において、不純物準位が確認できることを期待し、k点の分割数を多めにしています。 その結果、計算完了まで4時間半近くかかりました。。。

入力ファイル(クリックで展開)

&CONTROL
    calculation = 'nscf',
    prefix = 'Si_B',
    outdir = './tmp',
    pseudo_dir = './pseudo'
/

&SYSTEM
    ibrav = 0,
    nat = 64,
    ntyp = 2,
    ecutwfc = 40.0,
    ecutrho = 320.0,
    occupations = 'smearing',
    smearing = 'mp',
    degauss = 0.005,
    nbnd = 160
/

&ELECTRONS
    conv_thr = 1.0d-6
/

CELL_PARAMETERS {angstrom}
    10.88740474   0.00000000   0.00000000
    0.00000000  10.88740474   0.00000000
    0.00000000   0.00000000  10.88740474
ATOMIC_SPECIES
    B 10.811 B.pbe-n-kjpaw_psl.1.0.0.UPF
    Si 28.08500 Si.pbe-n-kjpaw_psl.1.0.0.UPF
ATOMIC_POSITIONS {crystal}
    B 0.37500000 0.37500000 0.12500000
    Si 0.37500000 0.37500000 0.62500000
    Si 0.37500000 0.87500000 0.12500000
    Si 0.37500000 0.87500000 0.62500000
    Si 0.87500000 0.37500000 0.12500000
    Si 0.87500000 0.37500000 0.62500000
    Si 0.87500000 0.87500000 0.12500000
    Si 0.87500000 0.87500000 0.62500000
    Si 0.00000000 0.25000000 0.25000000
    Si 0.00000000 0.25000000 0.75000000
    Si 0.00000000 0.75000000 0.25000000
    Si 0.00000000 0.75000000 0.75000000
    Si 0.50000000 0.25000000 0.25000000
    Si 0.50000000 0.25000000 0.75000000
    Si 0.50000000 0.75000000 0.25000000
    Si 0.50000000 0.75000000 0.75000000
    Si 0.37500000 0.12500000 0.37500000
    Si 0.37500000 0.12500000 0.87500000
    Si 0.37500000 0.62500000 0.37500000
    Si 0.37500000 0.62500000 0.87500000
    Si 0.87500000 0.12500000 0.37500000
    Si 0.87500000 0.12500000 0.87500000
    Si 0.87500000 0.62500000 0.37500000
    Si 0.87500000 0.62500000 0.87500000
    Si 0.00000000 0.00000000 0.00000000
    Si 0.00000000 0.00000000 0.50000000
    Si 0.00000000 0.50000000 0.00000000
    Si 0.00000000 0.50000000 0.50000000
    Si 0.50000000 0.00000000 0.00000000
    Si 0.50000000 0.00000000 0.50000000
    Si 0.50000000 0.50000000 0.00000000
    Si 0.50000000 0.50000000 0.50000000
    Si 0.12500000 0.37500000 0.37500000
    Si 0.12500000 0.37500000 0.87500000
    Si 0.12500000 0.87500000 0.37500000
    Si 0.12500000 0.87500000 0.87500000
    Si 0.62500000 0.37500000 0.37500000
    Si 0.62500000 0.37500000 0.87500000
    Si 0.62500000 0.87500000 0.37500000
    Si 0.62500000 0.87500000 0.87500000
    Si 0.25000000 0.25000000 0.00000000
    Si 0.25000000 0.25000000 0.50000000
    Si 0.25000000 0.75000000 0.00000000
    Si 0.25000000 0.75000000 0.50000000
    Si 0.75000000 0.25000000 0.00000000
    Si 0.75000000 0.25000000 0.50000000
    Si 0.75000000 0.75000000 0.00000000
    Si 0.75000000 0.75000000 0.50000000
    Si 0.12500000 0.12500000 0.12500000
    Si 0.12500000 0.12500000 0.62500000
    Si 0.12500000 0.62500000 0.12500000
    Si 0.12500000 0.62500000 0.62500000
    Si 0.62500000 0.12500000 0.12500000
    Si 0.62500000 0.12500000 0.62500000
    Si 0.62500000 0.62500000 0.12500000
    Si 0.62500000 0.62500000 0.62500000
    Si 0.25000000 0.00000000 0.25000000
    Si 0.25000000 0.00000000 0.75000000
    Si 0.25000000 0.50000000 0.25000000
    Si 0.25000000 0.50000000 0.75000000
    Si 0.75000000 0.00000000 0.25000000
    Si 0.75000000 0.00000000 0.75000000
    Si 0.75000000 0.50000000 0.25000000
    Si 0.75000000 0.50000000 0.75000000
K_POINTS {automatic}
    8 8 8 0 0 0

DOS計算

以下の入力ファイルでDOSを計算した後、出力ファイルをmatplotlibでプロットしました。

入力ファイル(クリックで展開)

&DOS
    outdir = './tmp',
    prefix = 'si',
    fildos = './dos/Si_B.dos',
    Emin = -10,
    Emax = 15,
    DeltaE = 0.02
/

プロット図を以下に示します。

フェルミ準位がVBM付近に位置していることが分かります。

0Kの基底状態を計算しているはずなので、フェルミ準位より上の状態は電子が占有していない。 従って、フェルミ準位上方のDOSが、Bによるアクセプタ準位という理解で正しい…と思う。

同様に、Pで置換した場合のDOSを示します。

CBM付近にフェルミ準位が位置しています。 こちらも、基底状態では電子は励起されずドナー準位に存在するはず。 従って、フェルミ準位の下方のDOSがPによるアクセプタ準位という理解であっているのかな。

Quantum Espressoで第一原理計算#5 スーパーセルの計算-1

久しぶりに、第一原理計算の勉強を進めています。

これまでは単純な物質の計算について計算を行ってきました。 ドーパントや欠陥を含む系を計算するには、単位格子を複数繋げたスーパーセルと呼ばれる系を作成し、その中に任意の原子を配置したり、欠陥構造を再現して計算します。

今回は、SiにB(ホウ素), P(リン)をドーパントとして加えた系の計算を目標としました。 実際のドープ濃度を再現するには超巨大なスーパーセルを作成する必要がありますが、今回は家庭用のPCでも計算できるような2×2×2のスーパーセルで計算しました。 このサイズのセルでも、私のPCでは結構重かったです。なお、いずれもRyzen5 5600下で計算し、実行時はmpirun -np 6で並列計算しました。

スーパーセルの作成

まず、SiのCIFファイルを入手します。 私はMaterials Projectよりダウンロードしました。

CIFファイルが入手出来たら、pymatgenを用いて得られた構造をスーパーセルに展開します (インストールされていない場合は、pip install pymatgenなどでインストールしてください)。

以下のコードで、2×2×2のスーパーセルに展開し、入力ファイルに使用する格子定数や原子位置を得ました。

import pymatgen
from pymatgen.core import Structure

# read cif file
structure =  Structure.from_file("Si.cif")
structure.remove_oxidation_states()
print(f"This Structure is consisted of {len(structure)} atoms")

# make supercell 
supercell = structure.copy()
supercell.make_supercell([2, 2, 2])
print(f"Supercell is consisted of {len(supercell)} atoms")
supercell.to("Si_supercell.cif", "cif")

# print parameters
print("CELL_PARAMETERS")
lattice = supercell.lattice.matrix
for vec in lattice:
    print(f"{vec[0]:12.8f} {vec[1]:12.8f} {vec[2]:12.8f}")

print("ATOMIC_POSITIONS")
for site in supercell:
    element = site.species_string
    x, y, z = site.frac_coords
    print(f"{element} {x:.8f} {y:.8f} {z:.8f}")

スクリプトの実行結果を以下に示します。

出力結果(クリックして展開)

This Structure is consisted of 8 atoms
Supercell is consisted of 64 atoms
CELL_PARAMETERS
 10.88740474   0.00000000   0.00000000
  0.00000000  10.88740474   0.00000000
  0.00000000   0.00000000  10.88740474
ATOMIC_POSITIONS
Si 0.37500000 0.37500000 0.12500000
Si 0.37500000 0.37500000 0.62500000
Si 0.37500000 0.87500000 0.12500000
Si 0.37500000 0.87500000 0.62500000
Si 0.87500000 0.37500000 0.12500000
Si 0.87500000 0.37500000 0.62500000
Si 0.87500000 0.87500000 0.12500000
Si 0.87500000 0.87500000 0.62500000
Si 0.00000000 0.25000000 0.25000000
Si 0.00000000 0.25000000 0.75000000
Si 0.00000000 0.75000000 0.25000000
Si 0.00000000 0.75000000 0.75000000
Si 0.50000000 0.25000000 0.25000000
Si 0.50000000 0.25000000 0.75000000
Si 0.50000000 0.75000000 0.25000000
Si 0.50000000 0.75000000 0.75000000
Si 0.37500000 0.12500000 0.37500000
Si 0.37500000 0.12500000 0.87500000
Si 0.37500000 0.62500000 0.37500000
Si 0.37500000 0.62500000 0.87500000
Si 0.87500000 0.12500000 0.37500000
Si 0.87500000 0.12500000 0.87500000
Si 0.87500000 0.62500000 0.37500000
Si 0.87500000 0.62500000 0.87500000
Si 0.00000000 0.00000000 0.00000000
Si 0.00000000 0.00000000 0.50000000
Si 0.00000000 0.50000000 0.00000000
Si 0.00000000 0.50000000 0.50000000
Si 0.50000000 0.00000000 0.00000000
Si 0.50000000 0.00000000 0.50000000
Si 0.50000000 0.50000000 0.00000000
Si 0.50000000 0.50000000 0.50000000
Si 0.12500000 0.37500000 0.37500000
Si 0.12500000 0.37500000 0.87500000
Si 0.12500000 0.87500000 0.37500000
Si 0.12500000 0.87500000 0.87500000
Si 0.62500000 0.37500000 0.37500000
Si 0.62500000 0.37500000 0.87500000
Si 0.62500000 0.87500000 0.37500000
Si 0.62500000 0.87500000 0.87500000
Si 0.25000000 0.25000000 0.00000000
Si 0.25000000 0.25000000 0.50000000
Si 0.25000000 0.75000000 0.00000000
Si 0.25000000 0.75000000 0.50000000
Si 0.75000000 0.25000000 0.00000000
Si 0.75000000 0.25000000 0.50000000
Si 0.75000000 0.75000000 0.00000000
Si 0.75000000 0.75000000 0.50000000
Si 0.12500000 0.12500000 0.12500000
Si 0.12500000 0.12500000 0.62500000
Si 0.12500000 0.62500000 0.12500000
Si 0.12500000 0.62500000 0.62500000
Si 0.62500000 0.12500000 0.12500000
Si 0.62500000 0.12500000 0.62500000
Si 0.62500000 0.62500000 0.12500000
Si 0.62500000 0.62500000 0.62500000
Si 0.25000000 0.00000000 0.25000000
Si 0.25000000 0.00000000 0.75000000
Si 0.25000000 0.50000000 0.25000000
Si 0.25000000 0.50000000 0.75000000
Si 0.75000000 0.00000000 0.25000000
Si 0.75000000 0.00000000 0.75000000
Si 0.75000000 0.50000000 0.25000000
Si 0.75000000 0.50000000 0.75000000

SCF計算

得られた格子定数や原子位置を用いて、SCF計算を行いました。 スーパーセルの計算では、k点のメッシュ数は大きくしなくても精度が確保できるそうなので4×4×4と設定しました。 ただ、この分割数でも計算完了まで1時間近くかかりました。

入力ファイル(クリックして展開)

&CONTROL
    calculation = 'scf',
    prefix = 'si',
    outdir = './tmp',
    pseudo_dir = './pseudo'
/

&SYSTEM
    ibrav = 0,
    nat = 64,
    ntyp = 1,
    ecutwfc = 40.0,
    ecutrho = 320.0,
    occupations = 'fixed'
/

&ELECTRONS
    conv_thr = 1.0d-6
/

CELL_PARAMETERS {angstrom}
    10.88740474   0.00000000   0.00000000
    0.00000000  10.88740474   0.00000000
    0.00000000   0.00000000  10.88740474
ATOMIC_SPECIES
    Si 28.08500 Si.pbe-n-kjpaw_psl.1.0.0.UPF
ATOMIC_POSITIONS {crystal}
    Si 0.37500000 0.37500000 0.12500000
    Si 0.37500000 0.37500000 0.62500000
    Si 0.37500000 0.87500000 0.12500000
    Si 0.37500000 0.87500000 0.62500000
    Si 0.87500000 0.37500000 0.12500000
    Si 0.87500000 0.37500000 0.62500000
    Si 0.87500000 0.87500000 0.12500000
    Si 0.87500000 0.87500000 0.62500000
    Si 0.00000000 0.25000000 0.25000000
    Si 0.00000000 0.25000000 0.75000000
    Si 0.00000000 0.75000000 0.25000000
    Si 0.00000000 0.75000000 0.75000000
    Si 0.50000000 0.25000000 0.25000000
    Si 0.50000000 0.25000000 0.75000000
    Si 0.50000000 0.75000000 0.25000000
    Si 0.50000000 0.75000000 0.75000000
    Si 0.37500000 0.12500000 0.37500000
    Si 0.37500000 0.12500000 0.87500000
    Si 0.37500000 0.62500000 0.37500000
    Si 0.37500000 0.62500000 0.87500000
    Si 0.87500000 0.12500000 0.37500000
    Si 0.87500000 0.12500000 0.87500000
    Si 0.87500000 0.62500000 0.37500000
    Si 0.87500000 0.62500000 0.87500000
    Si 0.00000000 0.00000000 0.00000000
    Si 0.00000000 0.00000000 0.50000000
    Si 0.00000000 0.50000000 0.00000000
    Si 0.00000000 0.50000000 0.50000000
    Si 0.50000000 0.00000000 0.00000000
    Si 0.50000000 0.00000000 0.50000000
    Si 0.50000000 0.50000000 0.00000000
    Si 0.50000000 0.50000000 0.50000000
    Si 0.12500000 0.37500000 0.37500000
    Si 0.12500000 0.37500000 0.87500000
    Si 0.12500000 0.87500000 0.37500000
    Si 0.12500000 0.87500000 0.87500000
    Si 0.62500000 0.37500000 0.37500000
    Si 0.62500000 0.37500000 0.87500000
    Si 0.62500000 0.87500000 0.37500000
    Si 0.62500000 0.87500000 0.87500000
    Si 0.25000000 0.25000000 0.00000000
    Si 0.25000000 0.25000000 0.50000000
    Si 0.25000000 0.75000000 0.00000000
    Si 0.25000000 0.75000000 0.50000000
    Si 0.75000000 0.25000000 0.00000000
    Si 0.75000000 0.25000000 0.50000000
    Si 0.75000000 0.75000000 0.00000000
    Si 0.75000000 0.75000000 0.50000000
    Si 0.12500000 0.12500000 0.12500000
    Si 0.12500000 0.12500000 0.62500000
    Si 0.12500000 0.62500000 0.12500000
    Si 0.12500000 0.62500000 0.62500000
    Si 0.62500000 0.12500000 0.12500000
    Si 0.62500000 0.12500000 0.62500000
    Si 0.62500000 0.62500000 0.12500000
    Si 0.62500000 0.62500000 0.62500000
    Si 0.25000000 0.00000000 0.25000000
    Si 0.25000000 0.00000000 0.75000000
    Si 0.25000000 0.50000000 0.25000000
    Si 0.25000000 0.50000000 0.75000000
    Si 0.75000000 0.00000000 0.25000000
    Si 0.75000000 0.00000000 0.75000000
    Si 0.75000000 0.50000000 0.25000000
    Si 0.75000000 0.50000000 0.75000000
K_POINTS {automatic}
    4 4 4 0 0 0

NSCF計算

次に、DOS計算用のNSCF計算を行います。 以下に入力ファイルを示します。こちらは完了まで2時間程度掛かりました。。。

入力ファイル(クリックして展開)

&CONTROL
    calculation = 'nscf',
    prefix = 'si',
    outdir = './tmp',
    pseudo_dir = './pseudo'
/

&SYSTEM
    ibrav = 0,
    nat = 64,
    ntyp = 1,
    ecutwfc = 40.0,
    ecutrho = 320.0,
    occupations = 'tetrahedra',
    nbnd = 160
/

&ELECTRONS
    conv_thr = 1.0d-6
/

CELL_PARAMETERS {angstrom}
    10.88740474   0.00000000   0.00000000
    0.00000000  10.88740474   0.00000000
    0.00000000   0.00000000  10.88740474
ATOMIC_SPECIES
    Si 28.08500 Si.pbe-n-kjpaw_psl.1.0.0.UPF
ATOMIC_POSITIONS {crystal}
    Si 0.37500000 0.37500000 0.12500000
    Si 0.37500000 0.37500000 0.62500000
    Si 0.37500000 0.87500000 0.12500000
    Si 0.37500000 0.87500000 0.62500000
    Si 0.87500000 0.37500000 0.12500000
    Si 0.87500000 0.37500000 0.62500000
    Si 0.87500000 0.87500000 0.12500000
    Si 0.87500000 0.87500000 0.62500000
    Si 0.00000000 0.25000000 0.25000000
    Si 0.00000000 0.25000000 0.75000000
    Si 0.00000000 0.75000000 0.25000000
    Si 0.00000000 0.75000000 0.75000000
    Si 0.50000000 0.25000000 0.25000000
    Si 0.50000000 0.25000000 0.75000000
    Si 0.50000000 0.75000000 0.25000000
    Si 0.50000000 0.75000000 0.75000000
    Si 0.37500000 0.12500000 0.37500000
    Si 0.37500000 0.12500000 0.87500000
    Si 0.37500000 0.62500000 0.37500000
    Si 0.37500000 0.62500000 0.87500000
    Si 0.87500000 0.12500000 0.37500000
    Si 0.87500000 0.12500000 0.87500000
    Si 0.87500000 0.62500000 0.37500000
    Si 0.87500000 0.62500000 0.87500000
    Si 0.00000000 0.00000000 0.00000000
    Si 0.00000000 0.00000000 0.50000000
    Si 0.00000000 0.50000000 0.00000000
    Si 0.00000000 0.50000000 0.50000000
    Si 0.50000000 0.00000000 0.00000000
    Si 0.50000000 0.00000000 0.50000000
    Si 0.50000000 0.50000000 0.00000000
    Si 0.50000000 0.50000000 0.50000000
    Si 0.12500000 0.37500000 0.37500000
    Si 0.12500000 0.37500000 0.87500000
    Si 0.12500000 0.87500000 0.37500000
    Si 0.12500000 0.87500000 0.87500000
    Si 0.62500000 0.37500000 0.37500000
    Si 0.62500000 0.37500000 0.87500000
    Si 0.62500000 0.87500000 0.37500000
    Si 0.62500000 0.87500000 0.87500000
    Si 0.25000000 0.25000000 0.00000000
    Si 0.25000000 0.25000000 0.50000000
    Si 0.25000000 0.75000000 0.00000000
    Si 0.25000000 0.75000000 0.50000000
    Si 0.75000000 0.25000000 0.00000000
    Si 0.75000000 0.25000000 0.50000000
    Si 0.75000000 0.75000000 0.00000000
    Si 0.75000000 0.75000000 0.50000000
    Si 0.12500000 0.12500000 0.12500000
    Si 0.12500000 0.12500000 0.62500000
    Si 0.12500000 0.62500000 0.12500000
    Si 0.12500000 0.62500000 0.62500000
    Si 0.62500000 0.12500000 0.12500000
    Si 0.62500000 0.12500000 0.62500000
    Si 0.62500000 0.62500000 0.12500000
    Si 0.62500000 0.62500000 0.62500000
    Si 0.25000000 0.00000000 0.25000000
    Si 0.25000000 0.00000000 0.75000000
    Si 0.25000000 0.50000000 0.25000000
    Si 0.25000000 0.50000000 0.75000000
    Si 0.75000000 0.00000000 0.25000000
    Si 0.75000000 0.00000000 0.75000000
    Si 0.75000000 0.50000000 0.25000000
    Si 0.75000000 0.50000000 0.75000000
K_POINTS {automatic}
    6 6 6 0 0 0

DOSのプロット

NSCF計算が完了後、DOSの計算を行います。

入力ファイル(クリックして展開)

&DOS
    outdir = './tmp',
    prefix = 'si',
    fildos = './dos/si.dos',
    Emin = -10,
    Emax = 15,
    DeltaE = 0.02
/

出力されたDOSをプロットしました。 参考として、ユニットセルでの計算結果と比較してみました。 なお、いずれもDOS計算の出力ファイルに記載されていたフェルミ準位(と記載されているがVBM?)を0としてプロットしています。

なんとなくの傾向は一致してそうですが、スーパーセルの計算結果はジャギーな感じになっています。 完全に一致するものと思っていましたが、精度が足りていないのでしょうか。

取り急ぎ計算自体はうまくできてそうなので、次回は不純物で置換して計算を行います。

ラズパイPico + MicroPythonでのプログラミング-4

前回の記事から少し間が空きましたが、ラズパイPico+MicroPythonを用いた電子工作入門を再開していきます

tamurata435.hatenablog.com

今回からシリアル通信を試していきたいと思います。初めにUARTによる通信を試していきます。

UARTの概要

UART は I2C、SPI と並んで、マイコンで最も一般的に利用されるシリアル通信方式です。 シリアル通信は、1 本の信号線を用いて(双方向通信の場合は 2 本)、データを 1 ビットずつ送受信する方式です。送信側が 1 ビットを送り、受信側がそれを受け取るという単純な動作を繰り返すことでデータを伝送します。 このような通信を行うには、受信側・送信側ともに共通の信号(クロック)に従って動作する必要があります。 クロック信号を送受信側で共有する方式を同期通信、共有しない方式を非同期通信と呼び、UART は名称の “Universal Asynchronous Receiver Transmitter” の通り非同期通信に分類されます。

UARTのメリット

非同期通信である UART ではクロック信号を共有しないため、送受信間の配線は信号線と GND のみで済みます。 実装がシンプルで、クロック同期を気にする必要がないため長距離通信にも向いています。 I2C や SPI と比べると通信速度は遅いものの、扱いやすさから産業用の計測機器などで未だに使用する場面があります。

UARTの通信方式

クロックを共有しないため、送受信側であらかじめ1ビットの時間幅(ボーレート)やデータ長を一致させておく必要があります。 また、通信の開始と終了を示すために、データにスタートビットとストップビットを付与する必要があり、オーバーヘッドが大きく効率はあまり良くありません。 一般的には、スタートビット 1bit、データビット 8bit(パリティを含む場合は 7bit)、ストップビット 1〜2bit といった構成がよく使われます。

一般的に無信号区間は"1"の状態を維持するため、スタートビットは"0", ストップビットは"1"で固定となります。

ラズパイPicoによるUART

ラズパイPicoに搭載されたマイコンRP2040は2個のUARTコントローラーを持ち、以下のGPIOピンにマッピングすることが出来ます。

id TX RX
0 GPIO 0, 12, 16 GPIO 1, 13, 17
1 GPIO 4, 8 GPIO 5, 9

UARTのid番号、ボーレート、TX, RXとして使用するPinオブジェクトなどを引数にしてUARTオブジェクトを作成して通信を開始します。

uart1 = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))

サンプルプログラム

2 台の Pico を使って送受信を確認するのが分かりやすいのですが、今回は都合により 1 台の Pico 内で通信を行います。uart0 と uart1 の 2 つの UART オブジェクトを作成し、uart0 から送信したデータを uart1 で受信します。 例として、Pico 内蔵の CPU 温度センサの値を読み取り、その値を UART で送受信してみます。 ジャンパピンの接続は、2 つの UART 間で TX と RX がクロスするように接続します(2 台の Pico を使う場合は GND を共通にする必要があります)。

# Raspberry Pi PicoのCPU温度を読み込み、UARTで送信/受信する

import time, utime
from machine import Pin, ADC, UART

temp_sensor = ADC(4)
led = Pin("LED", Pin.OUT, value=0)
uart0 = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))


def send_temp():
    read_value = temp_sensor.read_u16() * (3.3 / 65535)
    temp = 27 - (read_value - 0.706) / 0.001721
    message = f"temperature: {temp:.1f} degree\n"
    uart0.write(message)
    time.sleep(1)


def receive_temp():
    if uart1.any():
        led.value(1)
        print(uart1.readline())
        utime.sleep_ms(50)
        led.value(0)
    else:
        utime.sleep_ms(50)


while True:
    send_temp()
    receive_temp()

1秒ごとに温度が受信できればOKです!

Quantum Espressoで第一原理計算#4 スピン軌道相互作用

今回は、スピン軌道相互作用(Spin Orbit Coupling: SOC)を考慮した計算を行ってみます。

スピン軌道相互作用(SOC)について

原子核の周囲を回る電子について、電子が静止した座標系を考えてみます。 この座標系では、電子の周囲を原子核が回転しているように見なすことができます。 正に帯電した原子核の回転による環状電流により、原子核周囲には磁場が生じます。

この磁場と電子スピンが相互作用する現象がスピン軌道相互作用です。 一般に重元素ほど効果が大きく、軽元素での効果は無視できる場合が多いとされています。

SOCを考慮した計算

SOCを考慮した計算を行うには、相対論的な効果が含まれた(full relativisticな)擬ポテンシャルを使用する必要があります。 適切な擬ポテンシャルを用意した上で、&SYSTEMブロックに以下のパラメータを追記します。

&SYSTEM
    noncolin = .TRUE.
    lspinorb = .TRUE.

"lspinorb"を.TRUE.にすることで、スピン軌道相互作用を考慮した計算が行えます。

"noncolin"を.TRUE.にすることで、任意の方向のスピンを取ることができるようになります。 ただ、このパラメータの物理的な意味についてはまだあまり理解できていません……。 非磁性な物質ではスピンの向きはランダムで全体として打ち消し合った状態となるため、そのような状況を扱うための設定なのでしょうか。

バンド分散図の計算

今回はSi, GaAsについてSOCを考慮したバンド分散図の計算を行い、SOCなしの場合と比較しました。 SOCなしの結果は、過去の計算結果を流用しています。

tamurata435.hatenablog.com

まず、SiのSOC有無での分散図を比較してみます。 大きな変化は見られず、SOCの効果が小さいことが分かります。 実際にはVBM付近のバンドに数十meVの分裂が生じるようですが、実用上の影響はほぼ無視できると言えそうです。

Siのバンド分散図

次に、GaAsについて見ていきましょう。 こちらは明確に変化が見られます。 VBMに注目すると、SOC無しでは縮退していたバンドが分裂しています。 また伝導帯についても同様に分裂が生じています。 以上より、重元素におけるSOCの効果が確認できました。

GaAsのバンド分散図

計算メモ

GaAsのバンド分散図計算において、nscf計算がなかなか収束せず苦労しました。 conv_thrの値を緩和することで(1.0d-8→1.0d-6)、なんとか計算を完了させることができました。