Чтобы сохранить несколько независимых множеств значений для тех же блочных параметров, можно использовать массив структур. Чтобы переключиться между наборами параметра, создайте переменную, которая действует как индекс в массив, и измените значение переменной. Можно изменить значение переменной во время моделирования и, если переменная является настраиваемой, во время выполнения сгенерированного кода.
Откройте модель в качестве примера.
open_system('sldemo_fuelsys_dd_controller')
Эта модель представляет систему заправки бензинового двигателя. Вывод модели является уровнем топливного потока к механизму.
Перейдите к вложенной подсистеме switchable_compensation
.
open_system(['sldemo_fuelsys_dd_controller/fuel_calc/',... 'switchable_compensation'])
Эта подсистема исправляет и фильтрует шум из топливного сигнала уровня. Подсистема использует различные коэффициенты фильтра на основе режима заправки, который управляющая логика изменяет на основе отказов датчика в механизме. Например, алгоритм управления активирует подсистему low_mode
во время нормального функционирования. Это активирует подсистему rich_mode
в ответ на отказ датчика.
Откройте подсистему low_mode
.
open_system(['sldemo_fuelsys_dd_controller/fuel_calc/',... 'switchable_compensation/low_mode'])
Блок Discrete Filter фильтрует топливный сигнал уровня. В блочном диалоговом окне параметр Числителя устанавливает коэффициенты числителя фильтра.
Одноуровневый rich_mode
подсистемы также содержит блок Discrete Filter, который использует различные коэффициенты.
Обновите образцовую схему, чтобы отобразить типы данных сигнала. Сигналы ввода и вывода блока используют тип данных с плавающей точкой, с одинарной точностью single
.
В нижнем левом углу модели кликните по значку словаря данных. Словарь данных для этой модели, sldemo_fuelsys_dd_controller.sldd
, открывается в Образцовом Проводнике.
В Образцовой панели Иерархии модели Проводника выберите узел Данных проектирования.
В панели Содержимого просмотрите свойства объектов Simulink.NumericType
, таких как s16En15
. Все эти объекты в настоящее время представляют тип данных с плавающей точкой, с одинарной точностью single
. Модель использует эти объекты установить типы данных сигнала, включая сигналы ввода и вывода Дискретных блоков Фильтра.
Предположим, что во время моделирования и выполнения сгенерированного кода, вы хотите, чтобы каждая из этих подсистем переключилась между различными коэффициентами числителя на основе переменной, значением которой вы управляете.
Сохраните существующий набор коэффициентов числителя в объекте Simulink.Parameter
, значение которого является структурой. Каждое поле структуры хранит коэффициенты для одного из Дискретных блоков Фильтра.
lowBlock = ['sldemo_fuelsys_dd_controller/fuel_calc/'... 'switchable_compensation/low_mode/Discrete Filter']; richBlock = ['sldemo_fuelsys_dd_controller/fuel_calc/'... 'switchable_compensation/rich_mode/Discrete Filter']; params.lowNumerator = eval(get_param(lowBlock,'Numerator')); params.richNumerator = eval(get_param(richBlock,'Numerator')); params = Simulink.Parameter(params);
Скопируйте значение params
во временную переменную. Измените значения полей в этой временной структуре и присвойте измененную структуру как второй элемент params
.
temp = params.Value;
temp.lowNumerator = params.Value.lowNumerator * 2;
temp.richNumerator = params.Value.richNumerator * 2;
params.Value(2) = temp;
clear temp
Значение params
является массивом двух структур. Каждая структура хранит один набор коэффициентов фильтра.
Создайте объект Simulink.Parameter
под названием Ctrl
.
Ctrl = Simulink.Parameter(2);
Ctrl.DataType = 'uint8';
В подсистеме low_mode
, в диалоговом окне блока Discrete Filter, устанавливает параметр Числителя на выражение params(Ctrl).lowNumerator
.
set_param(lowBlock,'Numerator','params(Ctrl).lowNumerator');
В блоке Discrete Filter в подсистеме rich_mode
, установленной значение параметра Числителя к params(Ctrl).richNumerator
.
set_param(richBlock,'Numerator','params(Ctrl).richNumerator');
Выражения выбирают одну из структур в params
при помощи переменного Ctrl
. Выражения затем разыменовывают одно из полей в структуре. Значение поля устанавливает значения коэффициентов числителя.
Чтобы переключиться между наборами коэффициентов, вы изменяете значение Ctrl
к соответствующему индексу в массиве структур.
Опционально, создайте объект Simulink.Bus
использовать в качестве типа данных массива структур. Вы можете:
Управляйте формой структур.
Для каждого поля управляйте характеристиками, такими как тип данных и физические единицы измерения.
Управляйте именем типа struct
в сгенерированном коде.
Используйте функциональный Simulink.Bus.createObject
, чтобы создать объект и переименовать объект как paramsType
.
Simulink.Bus.createObject(params.Value)
paramsType = slBus1;
clear slBus1
Можно использовать объекты Simulink.NumericType
из словаря данных, чтобы управлять типами данных полей структуры. В объекте шины используйте имя объекта типа данных установить свойство DataType
каждого элемента.
paramsType.Elements(1).DataType = 's16En15'; paramsType.Elements(2).DataType = 's16En7';
Используйте объект шины в качестве типа данных массива структур.
params.DataType = 'Bus: paramsType';
Опционально, используйте перечислимый тип в качестве типа данных переключающейся переменной. Можно сопоставить каждый из наборов параметра с понятным именем и ограничить позволенные значения переключающейся переменной.
Создайте перечислимый тип под названием FilterCoeffs
. Создайте участника перечисления для каждой из структур в params
. Установите базовое целочисленное значение каждого участника перечисления к соответствующему индексу в params
.
Simulink.defineIntEnumType('FilterCoeffs',{'Weak','Aggressive'},[1 2])
Используйте перечислимый тип в качестве типа данных переключающейся переменной. Установите значение переменной к Aggressive
, который соответствует индексу 2
.
Ctrl.Value = FilterCoeffs.Aggressive;
Добавьте объекты, что вы создали к словарю данных sldemo_fuelsys_dd_controller.sldd
.
dictObj = Simulink.data.dictionary.open('sldemo_fuelsys_dd_controller.sldd'); sectObj = getSection(dictObj,'Design Data'); addEntry(sectObj,'Ctrl',Ctrl) addEntry(sectObj,'params',params) addEntry(sectObj,'paramsType',paramsType)
Можно также сохранить перечислимые типы в словарях данных. Однако вы не можете импортировать перечислимый тип в этом случае, потому что вы не можете сохранить изменения в sldemo_fuelsys_dd_controller.sldd
. Для получения дополнительной информации о хранении перечислимых типов в словарях данных, смотрите Перечисления в Словаре Данных.
Откройте модель в качестве примера sldemo_fuelsys_dd
, который ссылается на модель контроллера sldemo_fuelsys_dd_controller
.
open_system('sldemo_fuelsys_dd')
Установите время остановки моделирования на Inf
так, чтобы можно было взаимодействовать с моделью во время моделирования.
Начните запущенное моделирование и откройте блочное Scope диалоговое окно. Осциллограф показывает, что топливная скорость потока (сигнал fuel
) колеблется со значительной амплитудой во время нормального функционирования механизма.
В Образцовом Проводнике просмотрите содержимое словаря данных sldemo_fuelsys_dd_controller.sldd
. Установите значение Ctrl
к FilterCoeffs.Weak
.
Обновите схему модели sldemo_fuelsys_dd
. Осциллограф показывает, что амплитуда топливных колебаний уровня уменьшается из-за менее агрессивных коэффициентов фильтра.
Остановите моделирование.
Если у вас есть программное обеспечение Simulink Coder, можно сгенерировать код, который позволяет вам переключиться между наборами параметра во время выполнения кода.
В Образцовом Проводнике просмотрите содержимое словаря данных sldemo_fuelsys_dd_controller.sldd
. В панели Содержимого, Представлении Столбца набора к Storage Class
.
Используйте столбец StorageClass, чтобы применить класс памяти ExportedGlobal
к params
так, чтобы массив структур появился как настраиваемая глобальная переменная в сгенерированном коде. Примените тот же класс памяти к Ctrl
так, чтобы можно было изменить значение переключающейся переменной во время выполнения кода.
Также, чтобы сконфигурировать объекты, используйте эти команды:
tempEntryObj = getEntry(sectObj,'params'); params = getValue(tempEntryObj); params.StorageClass = 'ExportedGlobal'; setValue(tempEntryObj,params); tempEntryObj = getEntry(sectObj,'Ctrl'); Ctrl = getValue(tempEntryObj); Ctrl.StorageClass = 'ExportedGlobal'; setValue(tempEntryObj,Ctrl);
Сгенерируйте код от модели контроллера.
rtwbuild('sldemo_fuelsys_dd_controller')
### Starting build procedure for model: sldemo_fuelsys_dd_controller ### Successful completion of code generation for model: sldemo_fuelsys_dd_controller
В отчете генерации кода просмотрите заголовочный файл sldemo_fuelsys_dd_controller_types.h
h. Код задает перечислимый тип данных FilterCoeffs
.
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_fuelsys_dd_controller_types.h'); rtwdemodbtype(file,'#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_',... '/* Forward declaration for rtModel */',1,0)
#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_ #define DEFINED_TYPEDEF_FOR_FilterCoeffs_ typedef enum { Weak = 1, /* Default value */ Aggressive } FilterCoeffs; #endif
Код также задает тип структуры paramsType
, который соответствует объекту Simulink.Bus
. Поля используют тип данных с плавающей точкой, с одинарной точностью от модели.
rtwdemodbtype(file,'#ifndef DEFINED_TYPEDEF_FOR_paramsType_',... '#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_',1,0)
#ifndef DEFINED_TYPEDEF_FOR_paramsType_ #define DEFINED_TYPEDEF_FOR_paramsType_ typedef struct { real32_T lowNumerator[2]; real32_T richNumerator[2]; } paramsType; #endif
Просмотрите исходный файл sldemo_fuelsys_dd_controller.c
c. Код использует перечислимый тип, чтобы задать переключающийся переменный Ctrl
.
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_fuelsys_dd_controller.c'); rtwdemodbtype(file,'FilterCoeffs Ctrl = Aggressive;',... '/* Block signals (default storage) */',1,0)
FilterCoeffs Ctrl = Aggressive; /* Variable: Ctrl * Referenced by: * '<S12>/Discrete Filter' * '<S13>/Discrete Filter' */
Код также задает массив структур params
.
rtwdemodbtype(file,'/* Exported block parameters */',... '/* Variable: params',1,1)
/* Exported block parameters */ paramsType params[2] = { { { 8.7696F, -8.5104F }, { 0.0F, 0.2592F } }, { { 17.5392F, -17.0208F }, { 0.0F, 0.5184F } } } ; /* Variable: params
Алгоритм кода в образцовой функции step
использует переключающуюся переменную, чтобы индексировать в массив структур.
Чтобы переключиться между наборами параметра, сохраненными в массиве структур, измените значение Ctrl
во время выполнения кода.
Закройте связи со словарем данных. Этот пример отменяет несохраненные изменения. Чтобы сохранить изменения, используйте опцию '-save'
.
Simulink.data.dictionary.closeAll('sldemo_fuelsys_dd_controller.sldd','-discard')