データからのバッテリー パラメーターの抽出
この例では、さまざまな温度にわたって定義されたデータを近似するための、Battery ブロックのパラメーターの最適化を示します。MATLAB® 最適化関数 fminsearch
を使用します。Simscape™ Electrical™ モデルに対するこの種のパラメーター近似の実行に使用可能なその他の製品には、Optimization Toolbox™ や Simulink® Design Optimization™ があります。これらの製品は、GUI またはコマンド ライン アプローチを使用してブロックの操作と解析を行うための、事前定義された関数を提供します。
手法
4 ステップの手順を使用して、Battery の出力電圧曲線をデータに近似します。
Battery の [メイン] ダイアログ タブのパラメーターを最適化します。
Battery の [ダイナミクス] ダイアログ タブのパラメーターを最適化します。
Battery の [温度依存性] ダイアログ タブで、定格電圧と内部抵抗を最適化します。
Battery の [温度依存性] ダイアログ タブで、温度依存の電荷ダイナミクスのパラメーターを最適化します。
データとブロックのセットアップ
Battery データは、MATLAB データ ファイル ee_battery_data.mat に構造体の配列として保存されています。各構造体には、v (電圧)、i (電流)、t (時間)、SOC0 (最初の SOC) および T (温度) の 5 つのフィールドが含まれています。スコープは、出力電圧を構造体データ out.Vo.signals.values として保存します。
% Load Battery data load ee_battery_data.mat assignin('base','T1',battery_data(find([battery_data(1:2).T]==25)).T); assignin('base','T2',battery_data(find([battery_data(1:2).T]~=25)).T); % Display the Battery model Model = 'ee_battery'; open_system(Model)
close_system(Model, 0);
初期パラメーター指定
fminsearch
の開始値は、Battery ブロックの既定値とデータシートの値の組み合わせを使用して推定できます。
最適化前のパラメーターと初期値のリスト
ParsListMain = {'Vnom', 'R1', 'AH', 'V1', 'AH1'}; InitGuessMain = [3.6, 0.045, 2.7, 3.4, 1.4]; ParsListDyn = {'Rp1', 'tau1'}; InitGuessDyn = [0.006, 200]; ParsListTemp = {'Vnom_T2', 'R1_T2', 'V1_T2','Rp1_T2','tau1_T2'}; InitGuessTemp = [3.8, 0.055, 3.6, 0.006, 200 ]; Pars0 = reshape([[ParsListMain ParsListDyn ParsListTemp]; cellstr(num2str([InitGuessMain InitGuessDyn InitGuessTemp]'))'],1,[]); fprintf('\t%5s = %s\n', Pars0{:}); clear Pars0
Vnom = 3.6 R1 = 0.045 AH = 2.7 V1 = 3.4 AH1 = 1.4 Rp1 = 0.006 tau1 = 200 Vnom_T2 = 3.8 R1_T2 = 0.055 V1_T2 = 3.6 Rp1_T2 = 0.006 tau1_T2 = 200
fminsearch
は関数の局所的最小値を特定する、制約なしの非線形オプティマイザーであるため、初期推定値を変更すると解のセットが変わります。
初期パラメーターを使用した、Battery の出力に対するデータのプロット
単一のセルの Battery モデルを読み込み、パラメーターを設定します。
load_system(Model); % Enable Fast Restart to speedup the simulation set_param(Model,'FastRestart','on') Pars = reshape([ParsListMain; cellstr(num2str(InitGuessMain'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end Pars = reshape([ParsListDyn; cellstr(num2str(InitGuessDyn'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end Pars = reshape([ParsListTemp; cellstr(num2str(InitGuessTemp'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end % Generate preliminary model curves and plot against data num_lines = length(battery_data)-1; v_model = cell(1, num_lines); t_model = cell(1, num_lines); legend_info_data = cell(1, num_lines); legend_info_model = cell(1, num_lines); for idx_data = 1:num_lines assignin('base','t_data',battery_data(idx_data).t); assignin('base','i_data',battery_data(idx_data).i); assignin('base','T_data',battery_data(idx_data).T*ones(length(t_data),1)); assignin('base','T0',battery_data(idx_data).T); assignin('base','Ts',t_data(2)-t_data(1)); assignin('base','AH0',AH*battery_data(idx_data).SOC0); out = sim(Model); v_model{idx_data} = out.Vo.signals.values; t_model{idx_data} = out.Vo.time; legend_info_data{idx_data} = [ 'Temp = ' ... num2str(battery_data(idx_data).T) '\circC, Data']; legend_info_model{idx_data} = [ 'Temp = ' ... num2str(battery_data(idx_data).T) '\circC, Model']; end plot([battery_data(1:num_lines).t]/3600, [battery_data(1:num_lines).v], 'o', [t_model{:}]/3600, [v_model{:}]) xlabel('Time (hours)'); ylabel('Battery voltage (V)'); legend([legend_info_data legend_info_model], 'Location', 'Best'); title('Model with Initial Parameter Values');
誤差の二乗和の計算
ee_battery_lse
は、fminsearch
で最小化される関数です。この関数は、Battery の出力電圧とデータの差に対する誤差の二乗和を返します。fminsearch
によって無効なパラメーター値が供給された場合、catch
ステートメントは、誤差として大きな値を返します。
電荷ダイナミクスなしの [メイン] タブ ダイアログのパラメーターの最適化 (手順 1)
% Find ambient temperature data index idx_data = find([battery_data(1:num_lines).T]==25); assignin('base','t_data',battery_data(idx_data).t); assignin('base','i_data',battery_data(idx_data).i); assignin('base','T_data',battery_data(idx_data).T*ones(length(t_data),1)); assignin('base','T0',battery_data(idx_data).T); assignin('base','Ts',t_data(2)-t_data(1)); assignin('base','v_data',battery_data(idx_data).v); % Optimize parameters in main dialog tab of Battery assignin('base','ParsList',ParsListMain(1:4)); InitGuess = InitGuessMain(1:4); OptPars = fminsearch(@ee_battery_lse, InitGuess, ... optimset('TolX', 1e-3)); OptParsMain = [OptPars(1:4) InitGuessMain(5)]; % Update Battery block with optimized parameters Pars = reshape([ParsListMain; cellstr(num2str(OptParsMain'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end % Display optimized parameters fprintf(['Optimized parameters for the battery main ' ... 'dialog tab are:\n']); fprintf('\t%5s = %s\n', Pars{:}); clear i_data v_data t_data T_data Ts clear k InitGuess
Optimized parameters for the battery main dialog tab are: Vnom = 3.6999 R1 = 0.050299 AH = 2.6033 V1 = 3.5265 AH1 = 1.4
電荷ダイナミクス パラメーターの最適化 (手順 2)
% Use only one current pulse for optimizing the charge dynamics i_pos=battery_data(1).i.*(battery_data(1).i>=0); a=find(diff(i_pos)>0,2); b = find(diff(battery_data(1).i)); c = fix((b(find(b<a(1),1,'last'))+a(1))/2); assignin('base','i_data',battery_data(idx_data).i(c+1:a(2))); assignin('base','v_data',battery_data(1).v(c+1:a(2))); assignin('base','t_data',battery_data(idx_data).t(1:length(i_data))); assignin('base','T_data',battery_data(idx_data).T*ones(length(t_data),1)); assignin('base','T0',battery_data(idx_data).T); assignin('base','Ts',t_data(2)-t_data(1)); % Find Battery initial charge before optimizing charge dynamics parameters assignin('base','ParsList',{'charge'}); InitGuessCharge = OptParsMain(3); OptCharge = fminsearch(@ee_battery_lse, InitGuessCharge, ... optimset('TolX', 1e-3)); assignin('base','AH0',OptCharge); % Optimize Battery charge dynamics parameters assignin('base','ParsList',[ParsListMain(2) ParsListDyn]); InitGuessDyn = [OptPars(2) InitGuessDyn]; OptParsDyn = fminsearch(@ee_battery_lse, InitGuessDyn, ... optimset('TolX', 1e-3)); % Update Battery block with optimized charge dynamics parameters ParsListMainDyn = [ParsListMain ParsListDyn]; OptParsMainDyn = [OptPars(1) OptParsDyn(1) OptPars(3:4) InitGuessMain(5) OptParsDyn(2:3)]; Pars = reshape([ParsListMainDyn; cellstr(num2str(OptParsMainDyn'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end assignin('base','AH0',AH*battery_data(idx_data).SOC0); % Display optimized parameters fprintf(['Optimized parameters for the Battery, ' ... 'including charge dynamics, are:\n']); fprintf('\t%5s = %s\n', Pars{:}); clear i_data v_data t_data T_data Ts clear i_pos a b c clear k clear OptPars OptParsDyn ParsListMainDyn InitGuessMain InitGuessDyn ParsListDyn ParsListMain
Optimized parameters for the Battery, including charge dynamics, are: Vnom = 3.699931 R1 = 0.05019736 AH = 2.603326 V1 = 3.526493 AH1 = 1.4 Rp1 = 0.005029392 tau1 = 109.691
温度依存のパラメーターの最適化 (手順 3)
idx_data = find([battery_data(1:num_lines).T]~=25); assignin('base','t_data',battery_data(idx_data).t); assignin('base','i_data',battery_data(idx_data).i); assignin('base','T_data',battery_data(idx_data).T*ones(length(t_data),1)); assignin('base','T0',battery_data(idx_data).T); assignin('base','Ts',t_data(2)-t_data(1)) assignin('base','v_data', battery_data(2).v); % Use parameters for T1 as initial guess for T2 parameters InitGuessTemp = [OptParsMainDyn(1:2) OptParsMainDyn(4) OptParsMainDyn(6:7)]; Pars = reshape([ParsListTemp; cellstr(num2str(InitGuessTemp'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end % Optimize Battery temperature dependent parameters assignin('base','ParsList',ParsListTemp(1:3)); OptParsTemp = fminsearch(@ee_battery_lse, InitGuessTemp(1:3), ... optimset('TolX', 1e-3)); % Update Battery block with optimized parameters Pars = reshape([ParsListTemp(1:3); cellstr(num2str(OptParsTemp'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end assignin('base','AH0',AH*battery_data(idx_data).SOC0); % Display optimized parameters fprintf(['Optimized temperature dependent parameters for the Battery ' ... 'are:\n']); fprintf('\t%5s = %s\n', Pars{:}); clear i_data v_data t_data T_data Ts clear k clear OptParsMainDyn
Optimized temperature dependent parameters for the Battery are: Vnom_T2 = 3.9003 R1_T2 = 0.081404 V1_T2 = 3.8133
2 つ目の温度用の電荷ダイナミクス パラメーターの最適化 (手順 4)
% Find index into data for non-room temperatures % Use only one current pulse for optimizing the charge dynamics i_pos=battery_data(idx_data).i.*(battery_data(idx_data).i>=0); a=find(diff(i_pos)>0,2); b = find(diff(battery_data(idx_data).i)); c = fix((b(find(b<a(1),1,'last'))+a(1))/2); assignin('base','i_data',battery_data(idx_data).i(c+1:a(2))); assignin('base','v_data',battery_data(idx_data).v(c+1:a(2))); assignin('base','t_data',battery_data(idx_data).t(1:length(i_data))); assignin('base','T_data',battery_data(idx_data).T*ones(length(t_data),1)); assignin('base','T0',battery_data(idx_data).T); assignin('base','Ts',t_data(2)-t_data(1)) % Find Battery initial charge before optimizing charge dynamics parameters assignin('base','ParsList',{'charge'}); InitGuessCharge = OptParsMain(3); OptCharge = fminsearch(@ee_battery_lse, InitGuessCharge, ... optimset('TolX', 1e-3)); assignin('base','AH0',OptCharge); % Optimize Battery charge dynamics parameters assignin('base','ParsList', [ParsListTemp(2) ParsListTemp(4:5)]); InitGuessTempDyn = [OptParsTemp(2) InitGuessTemp(4:5)]; OptParsTempDyn = fminsearch(@ee_battery_lse, InitGuessTempDyn, ... optimset('TolX', 1e-3)); % Update Battery block with optimized parameters OptParsTempDyn = [OptParsTemp(1) OptParsTempDyn(1) OptParsTemp(3) OptParsTempDyn(2:3)]; Pars = reshape([ParsListTemp; cellstr(num2str(OptParsTempDyn'))'],1,[]); for k=1:2:length(Pars) evalin('base',[Pars{k} '=' Pars{k+1} ';']) end assignin('base','AH0',AH*battery_data(idx_data).SOC0); % Display optimized parameters fprintf(['Optimized temperature dependent parameters for the Battery, ' ... 'including charge dynamics, are:\n']); fprintf('\t%5s = %s\n', Pars{:}); clear i_data v_data t_data T_data Ts clear i_pos a b c clear k clear OptCharge OptParsMain OptParsTemp OptParsTempDyn clear Pars ParsList ParsListTemp InitGuessCharge InitGuessTemp InitGuessTempDyn
Optimized temperature dependent parameters for the Battery, including charge dynamics, are: Vnom_T2 = 3.900266 R1_T2 = 0.07979468 V1_T2 = 3.813256 Rp1_T2 = 0.007920818 tau1_T2 = 160.2999
最適化された曲線の表示
for idx_data = 1:num_lines assignin('base','t_data',battery_data(idx_data).t); assignin('base','i_data',battery_data(idx_data).i); assignin('base','T_data',battery_data(idx_data).T*ones(length(t_data),1)); assignin('base','T0',battery_data(idx_data).T); assignin('base','Ts',t_data(2)-t_data(1)); out = sim(Model); v_model{idx_data} = out.Vo.signals.values; t_model{idx_data} = out.Vo.time; end plot([battery_data(1:num_lines).t]/3600, [battery_data(1:num_lines).v], 'o', [t_model{:}]/3600, [v_model{:}]) xlabel('Time (hours)'); ylabel('Battery voltage (V)'); legend([legend_info_data legend_info_model], 'Location', 'Best'); title('Model with Optimized Parameter Values');
動的電流サイクルを使用した検証
idx_data = 3; assignin('base','t_data',battery_data(idx_data).t); assignin('base','i_data',battery_data(idx_data).i); assignin('base','T_data',battery_data(idx_data).T); assignin('base','T0',battery_data(idx_data).T(1)); assignin('base','Ts',t_data(2)-t_data(1)); assignin('base','AH0',AH*battery_data(idx_data).SOC0) out = sim(Model); subplot(3,1,1) plot(t_data, battery_data(3).v, 'o', out.Vo.time, out.Vo.signals.values) xlabel('Time (s)'); ylabel('Battery voltage (V)'); legend('Data','Model', 'Location', 'Best'); subplot(3,1,2) plot(t_data,i_data) xlabel('Time (s)'); ylabel('Current requirement (A)'); subplot(3,1,3) plot(t_data,T_data) xlabel('Time (s)'); ylabel('Temperature (^oC)'); title('Model validation');
bdclose(Model) clear num_lines legend_info_data legend_info_model out v_model t_model clear battery_data idx_data Ts Model