Переключение между наборами значений параметров во время симуляции и выполнения кода

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

Исследуйте модель примера

Откройте пример модели.

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 фильтрует сигнал расхода топлива. В диалоговом окне блока Numerator наборов параметров коэффициенты числителя фильтра.

Подсистема одноуровневого rich_mode также содержит блок Дискретного Фильтра, который использует различные коэффициенты.

Обновите диаграмму модели, чтобы отобразить типы данных сигнала. Входной и выходной сигналы блока используют тип данных с одной точностью и плавающей точкой single.

В левом нижнем углу модели щелкните значок данных моделей, а затем щелкните ссылку Data Dictionary. Словарь данных для этой модели, sldemo_fuelsys_dd_controller.sldd, откроется в Model Explorer.

На панели иерархии модели Model Explorer выберите узел Данные.

На панели «Содержимое» просмотрите свойства 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 подсистема в диалоговое окно блока Дискретного Фильтра устанавливает параметр Numerator в выражение params(Ctrl).lowNumerator.

set_param(lowBlock,'Numerator','params(Ctrl).lowNumerator');

В блоке Дискретный Фильтр в rich_mode подсистема, установите значение параметра Numerator равным 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';

Используйте перечисленный тип для переменной Switching

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

Создайте перечисленный тип с именем FilterCoeffs. Создайте представителя перечисления для каждой из структур в params. Установите базовое целое значение каждого представителя перечисления в соответствующий индекс params.

Simulink.defineIntEnumType('FilterCoeffs',{'Weak','Aggressive'},[1 2])

Используйте перечисленный тип в качестве типа данных переменной switching. Установите значение переменной равным 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 чтобы можно было взаимодействовать с моделью во время симуляции.

Начните запуск симуляции и откройте Возможности диалогового окна блока. Эти возможности показывают, что топливо скорости потока жидкости (fuel сигнал) колеблется со значительной амплитудой при нормальной операции двигателя.

В Model Explorer просмотрите содержимое словаря данных sldemo_fuelsys_dd_controller.sldd. Установите значение Ctrl на FilterCoeffs.Weak.

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

Остановите симуляцию.

Сгенерируйте и смотрите код

Если у вас есть программное обеспечение Simulink Coder, можно сгенерировать код, который позволяет вам переключаться между наборами параметров во время выполнения кода.

В Model Explorer просмотрите содержимое словаря данных sldemo_fuelsys_dd_controller.sldd. На панели «Содержимое» установите для представления столбца значение Storage Class.

Используйте столбец StorageClass, чтобы применить класс памяти ExportedGlobal на params так, что массив структур появляется как настраиваемая глобальная переменная в сгенерированном коде. Применить тот же класс памяти к Ctrl таким образом можно изменить значение переменной switching во время выполнения кода.

Кроме того, чтобы сконфигурировать объекты, используйте следующие команды:

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);

Сгенерируйте код из моделей контроллеров.

slbuild('sldemo_fuelsys_dd_controller')
### Starting build procedure for: sldemo_fuelsys_dd_controller
### Successful completion of code generation for: sldemo_fuelsys_dd_controller

Build Summary

Top model targets built:

Model                         Action          Rebuild Reason                                    
================================================================================================
sldemo_fuelsys_dd_controller  Code generated  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 25.82s

В отчете о генерации кода просмотрите заголовочный файл sldemo_fuelsys_dd_controller_types.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. Код использует перечисленный тип, чтобы задать переменную переключения 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 функция использует переменную switching для индекса в массив структур.

Чтобы переключиться между наборами параметров, хранящимися в массиве структур, измените значение Ctrl во время выполнения кода.

Закройте соединения со словарем данных. Этот пример отбрасывает несохраненные изменения. Чтобы сохранить изменения, используйте '-save' опция.

Simulink.data.dictionary.closeAll('sldemo_fuelsys_dd_controller.sldd','-discard')

Похожие темы