Система управления состава топливно-воздушной смеси с данными фиксированной точки

Этот пример показывает, как сгенерировать и оптимизировать код для системы управления состава топливно-воздушной смеси фиксированной точки, разработанной с Simulink® и Stateflow®. Для подробного объяснения модели см. sldemo_fuelsys и fxpdemo_fuelsys. Пример использует Embedded Coder® (цель ERT). Концепции также применяются к Simulink® Coder™.

Соответствующие фрагменты модели

Рисунки 1-4 показывают соответствующие фрагменты модели sldemo_fuelsys, которая является системой с обратной связью, содержащей подсистему объекта и подсистему контроллера. Объект позволяет инженерам подтверждать контроллер посредством симуляции рано в рабочем цикле. В этом примере сгенерируйте код для соответствующей подсистемы контроллера, fuel_rate_control. Рисунок 1 показывает имитационную модель верхнего уровня.

% Open |sldemo_fuelsys| via |rtwdemo_fuelsys_fxp| and update the model diagram
% to view the signal data types.
rtwdemo_fuelsys_fxp;

sldemo_fuelsys([],[],[],'compile');
sldemo_fuelsys([],[],[],'term');

Рисунок 1: модель верхнего уровня объекта и контроллера

Система управления состава топливно-воздушной смеси состоит из блоков Stateflow® и Simulink®. Это - фрагмент модели, для которой можно сгенерировать код.

open_system('sldemo_fuelsys/fuel_rate_control');

Рисунок 2: подсистема контроллера состава топливно-воздушной смеси

Оценка потока воздуха потребления и система исправления замкнутого цикла содержат две интерполяционных таблицы, Качая Постоянный и Уровень Пандуса Ки.

open_system('sldemo_fuelsys/fuel_rate_control/airflow_calc');

Рисунок 3: airflow_calc подсистема

Управляющая логика является графиком Stateflow®, который задает различные режимы работы.

open_system('sldemo_fuelsys/fuel_rate_control/control_logic');

Рисунок 4: Топливный контроллер отношения логика

Удалите помеху окна.

close_system('sldemo_fuelsys/fuel_rate_control/airflow_calc');
close_system('sldemo_fuelsys/fuel_rate_control/fuel_calc');
close_system('sldemo_fuelsys/fuel_rate_control/control_logic');
hDemo.rt=sfroot;hDemo.m=hDemo.rt.find('-isa','Simulink.BlockDiagram');
hDemo.c=hDemo.m.find('-isa','Stateflow.Chart','-and','Name','control_logic');
hDemo.c.visible=false;
close_system('sldemo_fuelsys/fuel_rate_control');

Создайте систему управления состава топливно-воздушной смеси только. Если процесс генерации кода завершен, отчет HTML, детализирующий сгенерированный код, отображен. Основная часть кода расположена в fuel_rate_control.c.

rtwbuild('sldemo_fuelsys/fuel_rate_control');
### Starting build procedure for model: fuel_rate_control
### Successful completion of build procedure for model: fuel_rate_control

Рисунок 5 показывает отрывки сгенерированного кода для интерполяционной таблицы, Качающей Постоянный.

Чтобы видеть код для Нагнетания Постоянного, щелкните правой кнопкой по блоку и выберите Code Generation> Navigate к коду.

rtwtrace('sldemo_fuelsys/fuel_rate_control/airflow_calc/Pumping Constant');

Код для постоянного нагнетания содержит два поисковых запросов точки останова и 2D интерполяцию. Точка останова SpeedVect неравномерно расположена с интервалами, и в то время как точка останова PressVect равномерно расположена с интервалами, ни у одного нет интервала степени двойки. Текущий интервал приводит к дополнительному коду (ROM), включая деление, и требует, чтобы все точки останова были в памяти (RAM).

Рисунок 5: Сгенерированный код для Нагнетания Постоянного поиска (содержит неравномерно распределенные точки останова),

Оптимизируйте код с равномерно расположенными с интервалами точками останова степени двойки

Можно оптимизировать производительность сгенерированного кода при помощи равномерно расположенных с интервалами точек останова степени двойки. В этом примере повторно сопоставьте данные об интерполяционной таблице в системе управления состава топливно-воздушной смеси на основе существующих результатов измерений.

Когда вы загрузили модель, модель PostLoadFcn создала данные об интерполяционной таблице в рабочем пространстве модели. Получите исходные табличные данные через sldemo_fuelsys_data, измените его для равномерно расположенной с интервалами степени двойки и повторно присвойте его в рабочем пространстве модели.

td = sldemo_fuelsys_data('sldemo_fuelsys', 'get_table_data');

Вычислите новые табличные данные для равномерно расположенных с интервалами точек останова степени двойки.

ntd.SpeedVect   = 64 : 2^5 : 640;             % 32 rad/sec
ntd.PressVect   = 2*2^-5 : 2^-5 : 1-(2*2^-5); % 0.03 bar
ntd.ThrotVect   = 0:2^1:88;                   % 2 deg
ntd.RampRateKiX = 128:2^7:640;                % 128 rad/sec
ntd.RampRateKiY = 0:2^-2:1;                   % 0.25 bar

Повторно сопоставьте табличные данные.

ntd.PumpCon  = interp2(td.PressVect,td.SpeedVect,td.PumpCon, ntd.PressVect',ntd.SpeedVect);
ntd.PressEst = interp2(td.ThrotVect,td.SpeedVect,td.PressEst,ntd.ThrotVect',ntd.SpeedVect);
ntd.SpeedEst = interp2(td.PressVect,td.ThrotVect,td.SpeedEst,ntd.PressVect',ntd.ThrotVect);
ntd.ThrotEst = interp2(td.PressVect,td.SpeedVect,td.ThrotEst,ntd.PressVect',ntd.SpeedVect);

Повторно вычислите данные о таблице Ramp Rate.

ntd.RampRateKiZ = (1:length(ntd.RampRateKiX))' * (1:length(ntd.RampRateKiY)) * td.Ki;

Нагнетание постоянного интервала степени двойки

figure('Tag','CloseMe');
mesh(td.PressVect,td.SpeedVect,td.PumpCon), hold on
mesh(ntd.PressVect,ntd.SpeedVect,ntd.PumpCon)
xlabel('PressVect'), ylabel('SpeedVect'), zlabel('PumpCon')
title(sprintf('Pumping Constant\nOriginal Spacing (%dx%d) vs. Power of Two Spacing (%dx%d)',...
    size(td.PumpCon,1),size(td.PumpCon,2),size(ntd.PumpCon,1),size(ntd.PumpCon,2)));

Оценочный интервал степени двойки давления

clf
mesh(td.ThrotVect,td.SpeedVect,td.PressEst), hold on
mesh(ntd.ThrotVect,ntd.SpeedVect,ntd.PressEst)
xlabel('ThrotVect'), ylabel('SpeedVect'), zlabel('PressEst')
title(sprintf('Pressure Estimate\nOriginal Spacing (%dx%d) vs. Power of Two Spacing (%dx%d)',...
    size(td.PressEst,1),size(td.PressEst,2),size(ntd.PressEst,1),size(ntd.PressEst,2)));

Оценочный интервал степени двойки скорости

clf
mesh(td.PressVect,td.ThrotVect,td.SpeedEst), hold on,
mesh(ntd.PressVect,ntd.ThrotVect,ntd.SpeedEst)
xlabel('PressVect'), ylabel('ThrotVect'), zlabel('SpeedEst')
title(sprintf('Speed Estimate\nOriginal Spacing (%dx%d) vs. Power of Two Spacing (%dx%d)',...
    size(td.SpeedEst,1),size(td.SpeedEst,2),size(ntd.SpeedEst,1),size(ntd.SpeedEst,2)));

Отрегулируйте оценочный интервал степени двойки

clf
mesh(td.PressVect,td.SpeedVect,td.ThrotEst), hold on
mesh(ntd.PressVect,ntd.SpeedVect,ntd.ThrotEst)
xlabel('PressVect'), ylabel('SpeedVect'), zlabel('ThrotEst')
title(sprintf('Throttle Estimate\nOriginal Spacing (%dx%d) vs. Power of Two Spacing (%dx%d)',...
    size(td.ThrotEst,1),size(td.ThrotEst,2),size(ntd.ThrotEst,1),size(ntd.ThrotEst,2)));

Уровень пандуса интервал степени двойки Ки

clf
mesh(td.RampRateKiX,td.RampRateKiY,td.RampRateKiZ'), hold on
mesh(ntd.RampRateKiX,ntd.RampRateKiY,ntd.RampRateKiZ'), hidden off
xlabel('RampRateKiX'), ylabel('RampRateKiY'), zlabel('RampRateKiZ')
title(sprintf('Ramp Rate Ki\nOriginal Spacing (%dx%d) vs. Power of Two Spacing (%dx%d)',...
    size(td.RampRateKiZ,1),size(td.RampRateKiZ,2),size(ntd.RampRateKiZ,1),size(ntd.RampRateKiZ,2)));

Настройка по умолчанию заставляет модель регистрировать данные моделирования для сигналов верхнего уровня. Эти результаты симуляции хранятся в переменной sldemo_fuelsys_output рабочей области. Прежде, чем обновить рабочее пространство модели с новыми данными, сохраните результат симуляции в hDemo.orig_data для более позднего сравнения с равномерно расположенной с интервалами табличной симуляцией степени двойки.

set_param('sldemo_fuelsys','StopTime','8')
sim('sldemo_fuelsys')
hDemo.orig_data = sldemo_fuelsys_output;

Повторно присвойте новые табличные данные в рабочем пространстве модели.

hDemo.hWS = get_param('sldemo_fuelsys', 'ModelWorkspace');
hDemo.hWS.assignin('PressEst',   ntd.PressEst);
hDemo.hWS.assignin('PressVect',  ntd.PressVect);
hDemo.hWS.assignin('PumpCon',    ntd.PumpCon);
hDemo.hWS.assignin('SpeedEst',   ntd.SpeedEst);
hDemo.hWS.assignin('SpeedVect',  ntd.SpeedVect);
hDemo.hWS.assignin('ThrotEst',   ntd.ThrotEst);
hDemo.hWS.assignin('ThrotVect',  ntd.ThrotVect);
hDemo.hWS.assignin('RampRateKiX',ntd.RampRateKiX);
hDemo.hWS.assignin('RampRateKiY',ntd.RampRateKiY);
hDemo.hWS.assignin('RampRateKiZ',ntd.RampRateKiZ);

Реконфигурируйте интерполяционные таблицы для равномерно расположенных с интервалами данных.

hDemo.lookupTables = find_system(get_param('sldemo_fuelsys','Handle'),...
    'BlockType','Lookup_n-D');

for hDemo_blkIdx = 1 : length(hDemo.lookupTables)
    hDemo.blkH = hDemo.lookupTables(hDemo_blkIdx);
    set_param(hDemo.blkH,'IndexSearchMethod','Evenly spaced points')
    set_param(hDemo.blkH,'InterpMethod','None - Flat')
    set_param(hDemo.blkH,'ProcessOutOfRangeInput','None')
end

Повторно выполните симуляцию для равномерно расположенной с интервалами реализации степени двойки и сохраните результат симуляции в hDemo.pow2_data.

sim('sldemo_fuelsys')
hDemo.pow2_data = sldemo_fuelsys_output;

Сравните результат симуляции для топливной скорости потока и воздушного топливного отношения. Симуляция осуществила Постоянное Нагнетание и Уровень Пандуса интерполяционные таблицы Ки и показывает превосходное соответствие для равномерно расположенных с интервалами точек останова степени двойки относительно исходных табличных данных.

figure('Tag','CloseMe');
subplot(2,1,1);
plot(hDemo.orig_data.get('fuel').Values.Time, ...
     hDemo.orig_data.get('fuel').Values.Data,'r-');
hold
plot(hDemo.pow2_data.get('fuel').Values.Time, ...
     hDemo.pow2_data.get('fuel').Values.Data,'b-');
ylabel('FuelFlowRate (g/sec)');
title('Fuel Control System: Table Data Comparison');
legend('original','even power of two');
axis([0 8 .75 2.25]);
subplot(2,1,2);
plot(hDemo.orig_data.get('air_fuel_ratio').Values.Time, ...
     hDemo.orig_data.get('air_fuel_ratio').Values.Data,'r-');
hold
plot(hDemo.pow2_data.get('air_fuel_ratio').Values.Time, ...
     hDemo.pow2_data.get('air_fuel_ratio').Values.Data,'b-');
ylabel('Air/Fuel Ratio');
xlabel('Time (sec)');
legend('original','even power of 2','Location','SouthEast');
axis([0 8 11 16]);
Current plot held
Current plot held

Восстановите систему управления состава топливно-воздушной смеси и сравните различие в сгенерированном коде интерполяционной таблицы.

rtwbuild('sldemo_fuelsys/fuel_rate_control');
### Starting build procedure for model: fuel_rate_control
### Successful completion of build procedure for model: fuel_rate_control

Рисунок 6 показывает те же отрывки сгенерированного кода для 'Качающей Постоянной' интерполяционной таблицы. Сгенерированный код для равномерно расположенных с интервалами точек останова степени двойки значительно более эффективен, чем неравномерно расположенный с интервалами случай точки останова. Код состоит из двух простых вычислений точки останова и прямого индекса в 2D данные об интерполяционной таблице. Дорогого деления избегают, и данные о точке останова не требуются в памяти.

rtwtrace('sldemo_fuelsys/fuel_rate_control/airflow_calc/Pumping Constant');

Рисунок 6: Сгенерированный код для Нагнетания Постоянного поиска (равномерно распределенные точки останова степени двойки)

Закройте пример.

close(findobj(0,'Tag','CloseMe'));
clear hDemo* td ntd
close_system('sldemo_fuelsys',0);

Model Advisor для эффективности кода

Повышение эффективности кода при помощи равномерно расположенных с интервалами точек останова степени двойки является одной из нескольких важной оптимизации для генерации фиксированной точки. Simulink® Model Advisor является большим инструментом для идентификации других методов повышения эффективности кода для модели Stateflow® и Simulink®. Убедитесь, что осуществили проверки под папкой Embedded Coder®.

Связанные примеры

Похожие темы