【Python】外部短絡試験の抵抗値、電源の直並列数を自動計算

Pythonモジュール「Pandas」で外部短絡試験の抵抗値、電源の直並列数を自動で計算する方法についてまとめました。

【外部短絡試験】抵抗値、電源の直並列数を自動計算

概要
外部短絡試験とは 電化製品が外部短絡を起こしてしまったときにどの程度耐えられるか調べる試験。
【詳細】【リチウムイオン電池】外部短絡試験とは?シャント抵抗など
Pythonとは 短くて読みやすいコードを書くことができるため初心者に扱いやすく、ライブラリも豊富で、数値計算や機械学習を中心に幅広い用途で利用されている人気のプログラミング言語です。
【詳細】【Python入門】サンプル集・使い方
Pandasとは Python向けデータ分析用ライブラリです。大きな特徴は「R言語のデータフレームのような型」を持たせることができる点です。
【詳細】【Pandas入門】データ分析のサンプル集
#-*- coding:utf-8 -*-
import numpy as np
import pandas as pd

# https://colab.research.google.com/drive/1e82yrx4YhI1rPnl0gTdaZXmYYxHTfYyf

# 合成抵抗の計算
def calc_rx(r, series_N, parallel_N):
    # 直列分の計算
    series_r = np.repeat(r*series_N, parallel_N)
    # 並列分の計算
    return 1. /np.sum(1. /series_r)

# インピーダンスの一覧表を作成
def make_table(Rm, series_N, parallel_N, R_test, R_exts, R_line, Vmax, Vmin):
    # 電源の内部抵抗を計算(直並列のパターンごと)
    Rms = {}
    # 直並列数のパターンを列に追加
    series_Ns = []
    parallel_Ns = []

    for j in range(series_N):
        list_r = []
        for i in range(parallel_N):
           if((j+1) * (i+1) < 9):
               # 合成抵抗の計算
               Rms[str(j+1)+"s" + str(i+1) + "p"] = calc_rx(Rm, j+1, i+1)
               # 直列数を記録
               series_Ns.append(j + 1)
               # 並列数を記録
               parallel_Ns.append(i + 1)

    # データフレームを作成し、電源の内部抵抗を追加
    df = pd.DataFrame(pd.Series(data=Rms, name="Rm"))
    df.index.name = "Pattern"
    
    # データフレームに直並列数を追加
    df["series_N"] = series_Ns
    df["Parallel_N"] = parallel_Ns

    # 直列数に応じて電源の総電圧(最大値、最小値)を計算して追加
    df["Vmax"] = df["series_N"] * Vmax
    df["Vmin"] = df["series_N"] * Vmin

    # 外部抵抗値に応じて回路全体の抵抗、電流(最大値、最小値)を計算
    for R_ext in R_exts:
        # 回路全体の抵抗を計算(電源の内部抵抗 + 外部短絡装置の抵抗 + 配線抵抗)を計算し、列に追加
        df["R_ext" + str(R_ext)] = df["Rm"] + R_ext + R_line + R_test

        # 電流の最大値を計算(電源の組合せパターン毎)
        df["Imax_ext" + str(R_ext)] = df["Vmax"]/df["R_ext" + str(R_ext)] * 1000

        # 電流の最小値を計算(電源の組合せパターン毎)
        df["Imin_ext" + str(R_ext)] = df["Vmin"]/df["R_ext" + str(R_ext)] * 1000

    return df

def search_pattern(path, df, R_exts, I_target, V_target):
    # 目標電流を満たす電源・外部短絡抵抗の組合せを検索(結果をマスクで出力)
    df_imin = df.loc[:, 'Imin_ext' + str(R_exts[0]):'Imin_ext' + str(R_exts[-1])]
    df_imax = df.loc[:, 'Imax_ext' + str(R_exts[0]):'Imax_ext' + str(R_exts[-1])]
    df_imin_mask = (df_imin <= I_target)
    df_imax_mask = (I_target <= df_imax)

    # 目標電圧を満たす電源・外部短絡抵抗の組合せを検索(結果をマスクで出力)
    df_vmin = df.loc[:, 'Vmin']
    df_vmax = df.loc[:, 'Vmax']
    df_vmin_mask = (df_vmin <= V_target)
    df_vmax_mask = (V_target <= df_vmax)

    # 目標値用のデータフレーム作成
    df_target = df_imin.copy()

    # 目標電圧・電流を満たす電源と外部短絡抵抗を検索(結果をマスクで出力)
    for R_ext in R_exts:       
        df_target['ext' + str(R_ext)] = df_imin_mask['Imin_ext' + str(R_ext)] & df_imax_mask['Imax_ext' + str(R_ext)] & df_vmin_mask  & df_vmax_mask
    
    # 外部短絡抵抗値
    df_target = df_target.loc[:, "ext" + str(R_exts[0]):"ext" + str(R_exts[-1])]
    patterns = df_target.index.tolist()

    # データフレームを転置
    df_target = df_target.transpose()
    
    result_ext_dict = {}

    # 目標電圧・目標電流を電源・両方満たす外部短絡抵抗の組合せを取得
    for pattern in patterns:
        result = df_target[df_target[pattern] == True].index.tolist()
        if result:
            result_ext_dict[pattern] = df_target[df_target[pattern] == True].index.tolist()

    df_result = pd.DataFrame(columns=['Imin', 'Imax', 'Vmin', 'Vmax', 'I[A](' + str(V_target) +'V)', 'V[V](' + str(I_target) +'A)'] )

    for key, value in result_ext_dict.items():
        for i in range(len(value)):
            # 試験条件を満たす電流、電圧の最小値、最大値
            Imin = df.loc[key, "Imin_" + value[i]]
            Imax = df.loc[key, "Imax_" + value[i]]
            Vmax = df.loc[key, "Vmax"]
            Vmin = df.loc[key, "Vmin"]
            # 電源電圧を目標電圧に固定したときの電流値を計算
            I = Imax - (Imax - Imin) * ((Vmax - V_target) / (Vmax - Vmin))
            # 電源電流を目標電流に固定したときの電圧を計算
            V = Vmax - (Vmax - Vmin) * ((Imax - I_target) / (Imax - Imin))
            # データフレームに追加
            df_result.loc[key + "-" + str(value[i])] = [Imin, Imax, Vmax, Vmin, I, V]      

    # 目標電流値と理論電流値との絶対誤差を計算(電源電圧を目標値に固定した場合)
    df_result["I_error"] = (df_result['I[A](' + str(V_target) +'V)'] - I_target).abs()

    # 目標電圧値と電源電圧値との絶対誤差を計算(電源電流を目標値に固定した場合)
    df_result["V_error"] = (df_result['V[V](' + str(I_target) +'A)'] - V_target).abs()

    # インデックス名を「Pattern」に設定
    df_result.index.name ='Pattern'

    # データフレームが空の場合(試験条件を満たす構成が無い)
    if df_result.empty:
        print("試験条件を満たす構成は存在しません。") 
        return -1

    # コンソール表示する数値の桁数(小数点以下2位まで)
    pd.options.display.float_format = '{:.2f}'.format

    # 試験条件を表示  
    print('----------------------------------------')
    print('●試験条件を満たす構成一覧')
    print(df_result)

    # 目標電流値と理論電流値との絶対誤差が最小になるときの装置構成を表示
    print('\n----------------------------------------')
    print('●電源電圧を目標値に固定、目標電流値と理論電流値の絶対誤差が最小となる装置構成')
    ss_ierror_min = df_result.loc[df_result['I_error'].idxmin()]
    print(ss_ierror_min)
    
    # 目標電圧値と電源電圧値との絶対誤差が最小になるときの装置構成を表示
    print('\n----------------------------------------')
    print('●電源電圧を目標値に固定、目標電圧値と電源電圧値の絶対誤差が最小となる装置構成')
    ss_verror_min = df_result.loc[df_result['V_error'].idxmin()]
    print(ss_verror_min)
    
    # 結果をCSVファイルに出力
    df_result.to_csv(path + '/result.csv')
    ss_ierror_min.to_csv(path + '/result_ierror_min.csv', header=False)
    ss_verror_min.to_csv(path + '/result_verror_min.csv', header=False)
    df.to_csv(path + '/table.csv')

    return df_result

def main():
    # 試験条件
    I_target = 200 # 目標電流値[A]
    V_target = 50 # 目標電圧値[V]
    R_test = 0 # 試験体の抵抗[mΩ]
    R_other = 0 # その他の抵抗値(端子台など)

    # 保存先パス
    # 例:C:/prog/python/test
    path = "C:/prog/python/pandas"

    # 配線抵抗[mΩ]
    R_line = 5 

    # 電源のパラメータ
    Rm = 5 # 電源1つ(1直1並)あたりの内部抵抗[mΩ]
    series_N = 4 # 電源の最大直列数
    parallel_N = 4 # 電源の最大並列数
    V_power_min = 20.0 # 電源1つ(1直1並)あたりの最小電圧[V]
    V_power_max = 30.0 # 電源1つ(1直1並)あたりの最大電圧[V]

    # 外部短絡装置の可変抵抗組み合わせパターン(昇順に並べる)
    R_exts = [100, 200]

    print('----------------------------------------')
    print('●以下の試験条件で、最適な装置構成を計算...')
    print("目標電流:" + str(I_target) + "[A]")
    print("目標電圧:" + str(V_target) + "[V]")
    print("試験体抵抗:" + str(R_test) + "[mΩ]")
    print("その他の抵抗:" + str(R_other) + "[mΩ]")
    print('----------------------------------------')
    print('●例')
    print('2s1p-ext200 → 2直列1並列で外部短絡抵抗は200[mΩ]')

    # 一覧表を作成・保存
    df = make_table(Rm, series_N, parallel_N, R_test + R_other, R_exts, R_line, V_power_max, V_power_min)

    # 試験条件を満たす電源・外部短絡抵抗の組合せを探索し、保存
    df_result = search_pattern(path, df, R_exts, I_target, V_target)


if __name__ == "__main__":
    main()

"""
----------------------------------------
●以下の試験条件で、最適な装置構成を計算...
目標電流:200[A]
目標電圧:50[V]
試験体抵抗:0[mΩ]
その他の抵抗:0[mΩ]
----------------------------------------
●例
2s1p-ext200 → 2直列1並列で外部短絡抵抗は200[mΩ]
----------------------------------------
●試験条件を満たす構成一覧
                   Imin        Imax  Vmin  Vmax   I[A](50V)  V[V](200A)    I_error   V_error
Pattern
2s1p-ext200  186.046512  279.069767  60.0  40.0  232.558140   43.000000  32.558140  7.000000
2s2p-ext200  190.476190  285.714286  60.0  40.0  238.095238   42.000000  38.095238  8.000000
2s3p-ext200  192.000000  288.000000  60.0  40.0  240.000000   41.666667  40.000000  8.333333
2s4p-ext200  192.771084  289.156627  60.0  40.0  240.963855   41.500000  40.963855  8.500000

----------------------------------------
●電源電圧を目標値に固定、目標電流値と理論電流値の絶対誤差が最小となる装置構成
Imin          186.046512
Imax          279.069767
Vmin           60.000000
Vmax           40.000000
I[A](50V)     232.558140
V[V](200A)     43.000000
I_error        32.558140
V_error         7.000000
Name: 2s1p-ext200, dtype: float64

----------------------------------------
●電源電圧を目標値に固定、目標電圧値と電源電圧値の絶対誤差が最小となる装置構成
Imin          186.046512
Imax          279.069767
Vmin           60.000000
Vmax           40.000000
I[A](50V)     232.558140
V[V](200A)     43.000000
I_error        32.558140
V_error         7.000000
Name: 2s1p-ext200, dtype: float64
"""
- 関連記事
1 【Pandas入門】データ分析のサンプル集
2 【Python入門】サンプル集・使い方
Python
技術雑記

コメント

タイトルとURLをコピーしました