Этот пример показывает оптимизацию параметров блока Battery, чтобы соответствовать данным, заданным для различных температур. Он использует оптимизационную функцию MATLAB ® fminsearch
. Другими продуктами, доступными для выполнения этого типа подгонки параметров с Simscape™ моделями Electrical™, являются Optimization Toolbox™ и Simulink ® Design Optimization™. Эти продукты обеспечивают предопределенные функции для манипулирования и анализа блоков с помощью графические интерфейсы пользователя или подхода командной строки.
Подгонка кривых выходного напряжения для батареи к данным с помощью процедуры 4 шага:
Оптимизируйте параметры в диалоговом окне Battery Main вкладки.
Оптимизируйте параметры в диалоговом окне Battery Dynamics вкладки.
Оптимизируйте номинальное напряжение и внутреннее сопротивление в диалоговом окне Battery Temperature Dependence вкладки.
Оптимизируйте параметры динамики заряда, зависящего от температуры, в диалоговой вкладке Battery Temperature Dependence.
Файл данных MATLAB, ee_battery_data.mat, сохраняет данные Battery как массив структур. Каждая структура содержит 5 полей: v (напряжение), i (ток), t (время), SOC0 (начальное состояние заряда) и T (температура). Возможности сохраняют выходное напряжение как структурные данные, 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
является нелинейным оптимизатором без ограничений, который находит локальный минимум функции, изменение начальной оценки приведет к другому набору решений.
Загрузите одну камеру Модель батареи и установите параметры
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
. Эта функция возвращает сумму квадратов ошибки для различия между выходным напряжением Батареи и данными. Если недопустимое значение параметров задано как fminsearch
, а catch
оператор возвращает большое значение ошибки.
% 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
% 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
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
% 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