ダイオードI-V特性測定器作成:3-4. PC側ソフト設計 – openpyxlでグラフ描画と最小二乗法の指数関数近似

2025年8月31日

Google Ad

本記事の主旨

ダイオードI-V特性測定器(カーブトレーサ)作成のPC側ソフト上におけるopenpyxlでグラフ描画と最小二乗法の指数関数近似について記す。

本記事の目的

本記事の目的を以下に記す。

  • openpyxlでグラフ描画と最小二乗法の指数関数近似のソースについての解説を記すこと

本記事の背景

ダイオードI-V特性測定器(カーブトレーサ)作成の中でPC側ソフトを作成したため、本記事でその部分的な解説をする。

本記事の位置づけ

以下の流れで作業説明と解説を行った。

記事に対応したリンクを添付した。

概要説明:ダイオードI-V特性測定器作成:0. 概要 | 工事中.com

  1. 取扱説明
  2. 回路設計
    1. ダイオードのI-V特性を手作業で確認
    2. 回路の実装
      1. 回路の実装(PWM平滑化)
      2. 回路の実装(PWM平滑化以外)
  3. PC側ソフト設計
    1. pySerialでUSBシリアル通信
    2. Matplotlibでのグラフ表示
    3. Pythonで最小二乗法の指数関数近似
    4. openpyxlでグラフ描画と最小二乗法の指数関数近似★現在のページ
  4. マイコン側ソフト設計
    1. Arduino Uno Rev3 / R4 Minima
    2. Raspberry Pi Pico / Pico 2
  5. 実験
    1. 1N4148の測定でマイコンとソースの組み合わせを比較
    2. 種々のダイオードを測定
    3. 種々の高精度ゲルマニウムダイオードを測定
  6. まとめと補足

コードの全体

今回解説するコードの全体は、以下にアップロードした。

excel.py

計算用ソースファイル。

コードの解説

以下のようなExcelファイルを生成するのに必要なコードを解説する。

筆者はExcelをインストールしていないため、代わりにLibreOfficeで開いた。

Excelファイルの処理

以下のExcelクラス内で実装した。

全体処理

openpyxlのopenpyxl.workbook.workbook.Workbookオブジェクトで、ワークブックを作成する。

openpyxlのopenpyxl.workbook.workbook.Workbook.activeでワークブックのアクティブなシートを選択する。

このとき、アクティブなワークシートは最初に存在するシート一つしかないため、それが選択される。

セルのフォントは、openpyxlのopenpyxl.styles.fonts.Font()関数で指定する。

図中のフォントは、openpyxlのopenpyxl.drawing.text.Font()関数で指定する。

openpyxlのopenpyxl.worksheet.worksheet.Worksheet.cell()関数で、メモリを確保する。

ここでは、10000行100列分のセルが入るメモリを確保している。

openpyxlのopenpyxl.cell.cell.Cell.fontに、セルのフォントを設定する。

        wb = xl.Workbook()
        ws = wb.active
        xl_font = xl.styles.Font(name='BIZ UDP明朝 Medium', size=10)        # セルのフォント指定
        xl_chart_font = xl.drawing.text.Font(typeface='BIZ UDP明朝 Medium') # 図中のフォント指定

        # メモリ上にセルを配置。ワークシートを作成時、セルは存在しない。
        # https://openpyxl.readthedocs.io/en/stable/tutorial.html#accessing-one-cell
        for xl_x in range(1,10001):
            for xl_y in range(1,101):
                ws.cell(row=xl_x, column=xl_y)
                ws.cell(row=xl_x, column=xl_y).font = xl_font

セルに値入力

openpyxlのopenpyxl.cell.cell.Cell.valueに値を入力することで、セルに値を入力する。

        # 値を入力
        ws.cell(row=1, column=1).value = "ダイオード"
        ws.cell(row=1, column=2).value = "ダイオード"
        ws.cell(row=2, column=1).value = "電圧[V]"
        ws.cell(row=2, column=2).value = "電流[mA]"
        for xl_row in range(3, len(x) + 3):
            ws.cell(row=xl_row, column=1).value = x[xl_row - 3]
            ws.cell(row=xl_row, column=2).value = y[xl_row - 3]

グラフ作成

openpyxlのopenpyxl.chart.scatter_chart.ScatterChartオブジェクトで、散布図の設定をする。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.widthに、幅を[cm]単位で入れる。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.heightに、高さを[cm]単位で入れる。

        # グラフ作成
        xl_chart = xl.chart.scatter_chart.ScatterChart(scatterStyle='marker')
        xl_chart.width = 32
        xl_chart.height = 18

グラフタイトル指定

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.titleに、散布図のタイトルを入れる。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.x_axis.titleに、x軸のラベルを入れる。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.y_axis.titleに、y軸のラベルを入れる。

        ## タイトル作成
        xl_chart.title = "可変・固定抵抗を用いて測定した1N4148のI-V特性"
        xl_chart.x_axis.title = "電圧[V]"
        xl_chart.y_axis.title = "電流[mA]"

グラフフォント指定

グラフのフォント指定は、タイトルやテキストに直接文字列でフォントを設定することができない。

例として、openpyxl.chart.title.TitleオブジェクトのtxPrプロパティは存在するが、そこでは指定できない。

openpyxlのopenpyxl.drawing.text.CharacterProperties()関数で、言語ごとのフォントをプロパティとして指定する。

言語ごとのフォントは、以下のように4つに分かれているといわれている

  • latin:アルファベット用、西洋諸言語
  • ea:東アジアの文字、アジア諸言語
  • cs:右から左に書く文字
  • sym:シンボル系文字

実際にlatinとeaを設定してExcelファイルを作成すると、latinは西洋諸言語、eaはアジア諸言語が変更されていることは確認できた。

シンボル文字は、Windowsのフォントに存在するSimbol font family等の記号であるのかもしれない。

openpyxlのopenpyxl.drawing.text.ParagraphProperties()関数で、段落のプロパティに言語ごとのフォントを関連付ける。

openpyxlのopenpyxl.drawing.text.Paragraph()で、段落に段落のプロパティと言語ごとのフォントのプロパティを関連付ける。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.text.RichText()関数で、図のリッチテキストとして段落の設定を設定する。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.legend.txPrにリッチテキストのオブジェクトを入れることで、凡例のフォントを設定する。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.x_axis.txPrにリッチテキストのオブジェクトを入れることで、x軸に書かれた数値のフォントを設定する。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.y_axis.txPrにリッチテキストのオブジェクトを入れることで、y軸に書かれた数値のフォントを設定する。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.title.tx.rich.p[0].pPrにリッチテキストのオブジェクトを入れることで、図のタイトルのフォントを設定する。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.x_axis.title.tx.rich.p[0].pPrに段落のプロパティのオブジェクトを入れることで、x軸ラベルのフォントを設定する。

openpyxlのopenpyxl.chart.scatter_chart.ScatterChart.y_axis.title.tx.rich.p[0].pPrに段落のプロパティのオブジェクトを入れることで、y軸ラベルのフォントを設定する。

        ## フォント指定
        cp = xl.drawing.text.CharacterProperties(latin=xl_chart_font, ea=xl_chart_font)
        pp = xl.drawing.text.ParagraphProperties(defRPr=cp)
        rtp = xl.chart.text.RichText(p=[xl.drawing.text.Paragraph(pPr=pp, endParaRPr=cp)])
        xl_chart.legend.txPr = rtp  # 凡例のフォント
        xl_chart.x_axis.txPr = rtp  # x軸に書かれた数値のフォント
        xl_chart.y_axis.txPr = rtp  # y軸に書かれた数値のフォント
        xl_chart.title.tx.rich.p[0].pPr = pp    # 図のタイトルのフォント
        xl_chart.x_axis.title.tx.rich.p[0].pPr = pp # x軸ラベルのフォント
        xl_chart.y_axis.title.tx.rich.p[0].pPr = pp # y軸ラベルのフォント

グラフのデータ入力範囲指定

openpyxlのopenpyxl.chart.reference.Referenceオブジェクトで、データの入力範囲を作成する。

        ## データ
        xl_chart_data_xvalues = xl.chart.Reference(ws, min_row=3, max_row=len(x) + 2, min_col=1, max_col=1)
        xl_chart_data_values = xl.chart.Reference(ws, min_row=2, max_row=len(x) + 2, min_col=2, max_col=2)

散布図にするための処理

openpyxlのopenpyxl.chart.series.Seriesオブジェクトに、データの情報を指定する。

openpyxlのopenpyxl.chart.series.Series.graphicalProperties.line.noFillをTrueにして、グラフの枠を消す。

openpyxlのopenpyxl.chart.series.Series.marker.symbolを'circle'にして、観測値を丸い点で表す。

openpyxlのopenpyxl.chart.series.Series.marker.spPr.solidFillに、観測値の色を指定する。

ここで、グラフの色はMatplotlibの中で一番よく使われる、下記に引用したTableau Paletteを用いた。

List of named colors — Matplotlib 3.10.5 documentation

Matplotlibのmatplotlib.colors.TABLEAU_COLORSに、TABLEAUカラーの一覧が入っている。

        ## 散布図にするデータのリスト
        xl_chart_ser = xl.chart.Series(xl_chart_data_values, xl_chart_data_xvalues, title_from_data=True)
        xl_chart_ser.graphicalProperties.line.noFill = True
        xl_chart_ser.marker.symbol = 'circle'
        xl_chart_ser.marker.spPr.solidFill = (list((mcolors.TABLEAU_COLORS).items()))[0][1][1:]

指数関数近似処理

openpyxlのopenpyxl.chart.trendline.Trendline()関数で、関数近似を行う。

ここで行った指数関数近似により求められた近似曲線は、Pythonのみで行った最小二乗法による指数関数近似の結果と一致する。

また、以下の東北学院大学のページでも、根拠が不明だがExcelの指数関数近似が最小二乗法で求められていることを前提としている。

ipc.tohoku-gakuin.ac.jp/mech/tools/lsm2/index.html

        ## 指数関数近似
        xl_chart_ser.trendline = xl.chart.trendline.Trendline(dispEq=True, dispRSqr=True, trendlineType='exp')

ワークシートにグラフを乗せる処理

openpyxlのopenpyxl.chart.series.append()関数で、グラフに観測値を乗せる。

openpyxlのopenpyxl.worksheet.worksheet.Worksheet.add_chart()関数で、ワークシートにグラフを乗せる。

        ## 図に散布図データを乗せる
        xl_chart.series.append(xl_chart_ser)

        ## ワークシートに図を乗せる
        ws.add_chart(xl_chart, 'F3')

保存処理

openpyxlのopenpyxl.workbook.workbook.Workbook.save()関数で、ワークブックをExcelファイルとして保存する。

        # 保存
        wb.save("IV特性.xlsx")

前回(3-3. PC側ソフト設計 - Pythonで最小二乗法の指数関数近似)

次回(4-1. マイコン側ソフト設計 - Arduino Uno Rev3 / R4 Minima)

他の回

「ダイオードI-V特性測定器作成 連載記事」でタグ付けを行っている。

広告

PythonでExcelを操作するのによさそうな本。

広告