Этот пример показывает, как сгенерировать и оптимизировать код для системы управления составом топливно-воздушной смеси с фиксированной точкой, разработанной с Simulink ® и Stateflow ®. Подробное объяснение модели смотрите в:
В примере используется целевой файл системы Embedded Coder ® (ert.tlc
).
На фиг.1-4 показаны соответствующие фрагменты sldemo_fuelsys
модель, которая является системой с обратной связью, содержащей подсистему объекта управления и подсистему контроллера. Этот объект позволяет инженерам проверять контроллер посредством симуляции в начале рабочего цикла. В этом примере сгенерируйте код для соответствующей подсистемы контроллера fuel_rate_control
. Рисунок 1 показывает модель симуляции верхнего уровня.
% Open |sldemo_fuelsys|, set the parameters and update the model diagram % to view the signal data types. close_system('sldemo_fuelsys',0) load_system('sldemo_fuelsys'); rtwconfiguredemo('sldemo_fuelsys','ERT','fixed'); sldemo_fuelsys_data('sldemo_fuelsys','switch_data_type','fixed'); sldemo_fuelsys_data('sldemo_fuelsys','set_info_text','rtwdemo_fuelsys_fxp_script'); sldemo_fuelsys_data('sldemo_fuelsys','top_level_logging','on'); set_param('sldemo_fuelsys','ShowPortDataTypes','on'); set_param('sldemo_fuelsys','SampleTimeColors','on'); set_param('sldemo_fuelsys','Dirty','off'); sldemo_fuelsys([],[],[],'compile'); sldemo_fuelsys([],[],[],'term');
Фигура 1: Модель верхнего уровня объекта управления и контроллера
Система управления составом топливно-воздушной смеси состоит из блоков Simulink ® и Stateflow ®. Это фрагмент модели, для которой нужно сгенерировать код.
open_system('sldemo_fuelsys/fuel_rate_control');
Фигура 2: Подсистема контроллера состава топливно-воздушной смеси
Система оценки всасываемого воздушного потока и коррекции замкнутого цикла содержит две интерполяционные таблицы, Pumping Constant и Ramp Rate Ki.
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: fuel_rate_control ### Successful completion of build procedure for: fuel_rate_control Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================================== fuel_rate_control Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 15.844s
На фиг.5 показаны фрагменты сгенерированного кода для интерполяционной таблицы Pumping Constant.
Чтобы увидеть код для Pumping Constant, щелкните правой кнопкой мыши по блоку и выберите C/C + + Code > Navigate To C/C + + Code.
rtwtrace('sldemo_fuelsys/fuel_rate_control/airflow_calc/Pumping Constant');
Код для константы накачки содержит два поиска точек останова и 2D интерполяцию. The 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);
Пересчет данных таблицы скорости наклона.
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;
Сравните результат симуляции по скорости потока жидкости топлива и отношению воздушного топлива. Симуляция выполнила интерполяционные таблицы Pumping Constant и Ramp Rate Ki и показывает отличное соответствие для равномерно распределенной степени двойки точек останова относительно исходных данных таблицы.
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: fuel_rate_control ### Successful completion of build procedure for: fuel_rate_control Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================= fuel_rate_control Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 13.801s
На фиг.6 показаны те же фрагменты сгенерированного кода для интерполяционной таблицы 'Pumping Constant'. Сгенерированный код для равномерно разнесенной степени двойки точек останова значительно эффективнее, чем неравномерно разнесенный случай точки останова. Код состоит из двух вычислений простых точек по оси Х и прямого индекса в данные интерполяционной таблицы 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); rtwdemoclean;
Повышение эффективности кода путем использования равномерно разнесенной степени двойки точек останова является одной из нескольких важных оптимизаций для генерации кода с фиксированной точкой. Simulink ® Model Advisor является отличным инструментом для определения других методов повышения эффективности кода для моделей Simulink ® и Stateflow ®. Обязательно запустите проверки в папке Embedded Coder ® или Simulink Coder ®.
Проект с фиксированной точкой: Система управления расходом топлива с фиксированной точкой (Fixed-Point Designer)
Производственная генерация кода C/C + +: система управления составом топливно-воздушной смеси с диаграммами Stateflow