Этот пример показывает, как сгенерировать и оптимизировать код для системы управления состава топливно-воздушной смеси фиксированной точки, разработанной с 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);
Повышение эффективности кода при помощи равномерно расположенных с интервалами точек останова степени двойки является одной из нескольких важной оптимизации для генерации фиксированной точки. Simulink® Model Advisor является большим инструментом для идентификации других методов повышения эффективности кода для модели Stateflow® и Simulink®. Убедитесь, что осуществили проверки под папкой Embedded Coder®.
Проект фиксированной точки: Топливная Система управления Уровня фиксированной точки (Fixed-Point Designer)
Производство генерация кода C/C++: Система управления Состава топливно-воздушной смеси с диаграммами Stateflow (Simulink Coder)