Этот пример использует Simulink Design Optimization™, чтобы оценить неизвестную емкость и начальное напряжение символически выведенной алгебраической модели простой схемы конденсатора резистора (RC). Пример решает ту же задачу и использует те же экспериментальные данные в качестве Оценочных Параметров модели и начальных состояний, но использует решение закрытой формы в схеме RC вместо дифференциальной формы.
Этот пример использует возможности Symbolic Math Toolbox™ для:
Решите обыкновенные дифференциальные уравнения (ODE) с помощью dsolve
Преобразуйте аналитический результат в блок Simulink с помощью matlabFunctionBlock
Вы выполняете оптимизацию проекта, чтобы оценить емкость и начальные значения напряжения аналитической схемы RC. В частности, вы совпадаете с экспериментальными значениями выходного напряжения симулированным значениям.
Задайте и решите следующее дифференциальное уравнение для схемы RC.
Здесь, v2(t)
выходное напряжение через конденсаторный C1
, v1
постоянное напряжение через резистор R1
, и v20
начальное напряжение через конденсатор. Используйте dsolve
решить уравнение.
syms C1 R1 v1 v20 real syms v2(t) deq = (v1 - v2)/R1 - C1*diff(v2,t); v2sol = dsolve(deq, v2(0) == v20)
v2sol =
Используйте subs
оценивать решение для R1
значение 10 кОм и v1
значение 5 В.
v2sol = vpa(subs(v2sol,[R1,v1],[10e3,5]))
v2sol =
Во-первых, создайте новую модель Simulink.
myModel = 'rcSymbolic';
new_system(myModel);
load_system(myModel);
Используйте matlabFunctionBlock
преобразовывать символьный результат для выходного напряжения к блоку Simulink, представляющему модель объекта управления RC. matlabFunctionBlock
добавляет этот новый блок к модели.
blockName = 'closedFormRC_block'; rcBlock = strcat(myModel,'/',blockName); myVars = [C1,v20,t]; matlabFunctionBlock(rcBlock,v2sol,... 'vars',myVars,... 'functionName','myRC',... 'outputs',{'v2'});
Добавьте и расположите другие блоки с положениями и размерами относительно блока RC.
rcBlockPosition = get_param(rcBlock,'position'); rcBlockWidth = rcBlockPosition(3)-rcBlockPosition(1); rcBlockHeight = rcBlockPosition(4)-rcBlockPosition(2); constantBlock = 'built-in/Constant'; timeBlock = 'simulink/Sources/Ramp'; outputBlock = 'built-in/Outport';
C1
и v20
параметры должны оценить. Во-первых, введите и инициализируйте эти параметры в рабочем пространстве MATLAB, с помощью начальных значений 460 и 1 В, соответственно. Затем создайте постоянные блоки для обоих параметров.
C1val = 460e-6; v20val = 1.0; posX = rcBlockPosition(1)-rcBlockWidth*2; posY = rcBlockPosition(2)-rcBlockHeight*3/4; pos = [posX,posY,posX+rcBlockWidth/2,posY+rcBlockHeight/2]; add_block(constantBlock,strcat(myModel,'/C1'),'Value','C1val',... 'Position',pos); pos = pos + [0 rcBlockHeight 0 rcBlockHeight]; add_block(constantBlock,strcat(myModel,'/v20'),'Value','v20val',... 'Position',pos);
Добавьте пандус в течение времени.
pos = pos + [0 rcBlockHeight 0 rcBlockHeight]; add_block(timeBlock,strcat(myModel,'/t'),'Slope','1','Position',pos);
Добавьте выходной порт.
pos = [rcBlockPosition(1)+2*rcBlockWidth,... rcBlockPosition(2)+rcBlockHeight/4,... rcBlockPosition(1)+2*rcBlockWidth+rcBlockWidth/2,... rcBlockPosition(2)+rcBlockHeight/4+rcBlockHeight/2]; add_block(outputBlock,strcat(myModel,'/v2'),'Port','1','Position',pos);
Теперь соедините блоки в модели. Модель готова к Simulink Design Optimization.
myAddLine = @(k) add_line(myModel,... strcat(char(myVars(k)),'/1'),... strcat(blockName,'/',num2str(k)),... 'autorouting','on'); arrayfun(myAddLine,(1:numel(myVars))); add_line(myModel,strcat(blockName,'/1'),'v2/1','autorouting','on'); open_system(myModel);
Получите результаты измерений.
load sdoRCCircuit_ExperimentData
Переменные time
и data
загружаются в рабочую область. data
измеренное конденсаторное напряжение в течение многих времен time
.
Создайте sdo.Experiment
объект хранить экспериментальные данные о напряжении.
Exp = sdo.Experiment(myModel);
Создайте объект сохранить измеренное конденсаторное напряжение выход.
Voltage = Simulink.SimulationData.Signal; Voltage.Name = 'Voltage'; Voltage.BlockPath = rcBlock; Voltage.PortType = 'outport'; Voltage.PortIndex = 1; Voltage.Values = timeseries(data,time);
Добавьте измеренные конденсаторные данные в эксперимент как ожидаемые выходные данные.
Exp.OutputData = Voltage;
Получите параметры. Установите минимальное значение для C1
. Обратите внимание на то, что вы уже задали исходные предположения.
c1param = sdo.getParameterFromModel(myModel,'C1val'); c1param.Minimum = 0; v20param = sdo.getParameterFromModel(myModel,'v20val');
Задайте целевую функцию для оценки. Код для sdoRCSymbolic_Objective
используемый в этом примере дан в разделе Helper Functions в конце примера.
estFcn = @(v) sdoRCSymbolic_Objective(v,Exp,myModel);
Соберите параметры модели, которые будут оценены.
v = [c1param;v20param];
Поскольку модель является совершенно алгебраической, выключите предупреждающие сообщения, которые дают вам команду выбирать дискретный решатель.
set_param(myModel,'SolverPrmCheckMsg','none');
Оцените параметры.
opt = sdo.OptimizeOptions;
opt.Method = 'lsqnonlin';
vOpt = sdo.optimize(estFcn,v,opt);
Optimization started 14-Feb-2020 21:35:34 First-order Iter F-count f(x) Step-size optimality 0 5 27.7093 1 1 10 2.86889 1.919 2.94 2 15 1.53851 0.3832 0.523 3 20 1.35137 0.3347 0.505 4 25 1.34473 0.01374 0.00842 5 30 1.34472 0.002686 0.00141 Local minimum possible. lsqnonlin stopped because the final change in the sum of squares relative to its initial value is less than the value of the function tolerance.
Покажите ориентировочные стоимости.
fprintf('C1 = %e v20 = %e\n',vOpt(1).Value, vOpt(2).Value);
C1 = 2.261442e-04 v20 = 2.359446e+00
Обновите эксперимент с предполагаемой емкостью и конденсаторными начальными значениями напряжения.
Exp = setEstimatedValues(Exp,vOpt);
Симулируйте модель с предполагаемыми значениями параметров и сравните симулированный выход с экспериментальными данными.
Simulator = createSimulator(Exp); Simulator = sim(Simulator); SimLog = find(Simulator.LoggedData,get_param(myModel,'SignalLoggingName')); Voltage = find(SimLog,'Voltage'); plot(time,data,'ro',Voltage.Values.Time,Voltage.Values.Data,'b') title('Simulated and Measured Responses') legend('Measured Voltage','Simulated Voltage','Location','Best')
close_system(myModel,0);
function vals = sdoRCSymbolic_Objective(v,Exp,myModel) r = sdo.requirements.SignalTracking; r.Type = '=='; r.Method = 'Residuals'; r.Normalize = 'off'; Exp = setEstimatedValues(Exp,v); Simulator = createSimulator(Exp); Simulator = sim(Simulator); SimLog = find(Simulator.LoggedData,get_param(myModel,'SignalLoggingName')); Voltage = find(SimLog,'Voltage'); VoltageError = evalRequirement(r,Voltage.Values,Exp.OutputData(1).Values); vals.F = VoltageError(:); end