酷暑、電気代上昇、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行ずつシリアルに出力する仕様です。
- DAC[V]: DACの電圧出力値(設定値)
- DAC output[V]: DACの電圧出力値(ADCでの読み取り値)
- Diode voltage[V]: ダイオードに印加した電圧(ADCでの読み取り値)
- 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特性測定にも挑戦したいと思います。






