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

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

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

Откройте модель в качестве примера.

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

Похожие темы

Была ли эта тема полезной?