Установление владения данными в иерархии модели

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

Можно создать глобальную переменную в сгенерированном коде путем применения класса памяти к элементу данных в модели-ссылке (см. Строение генерации кода C для элементов интерфейса модели). При определенные обстоятельства генератор кода помещает определение переменной с кодом, сгенерированным из верхней модели в иерархии. Это размещение по умолчанию может затруднить определение того, какая модель отвечает за данные, и управление изменениями кода в среде разработки на базе команды.

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

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

1. Скопируйте файл скрипта prepare_sldemo_fuelsys_dd_ctrl.m в текущую папку.

[~, ~] = copyfile(fullfile(matlabroot,'examples','ecoder','main','prepare_sldemo_fuelsys_dd_ctrl.m'),...
    'prepare_sldemo_fuelsys_dd_ctrl.m','f');

2. Запустите копию скрипта в текущей папке. Скрипт открывает модель sldemo_fuelsys_dd_controller и готовит его к этому примеру.

prepare_sldemo_fuelsys_dd_ctrl
open_system('sldemo_fuelsys_dd_controller')

Эти модели контроллеров содержат две модели, airflow_calc и fuel_calc. Два выхода airflow_calc, est_airflow и fb_correction, являются входами fuel_calc.

3. Откройте airflow_calc модель.

open_system('airflow_calc')

4. На вкладке Моделирование (Modeling) щелкните Редактор данных модели (Model Data Editor).

5. В Model Data Editor установите в раскрывающемся списке Изменить представление значение Code.

6. В airflow_calc модель, выберите est_airflow Блок вывода.

7. В Model Data Editor проверьте значение в столбце Классе памяти. Сигнал, который представляет этот блок, est_airflow, использует класс памяти ExportToFile. При этой настройке сигнал появляется в сгенерированном коде как глобальная переменная. Блок Outport маркирован fb_correction также использует эту настройку.

8. В Model Data Editor выберите вкладку Параметры и нажмите кнопку Показать/обновить дополнительную информацию. Теперь Model Data Editor показывает информацию о переменных рабочей области и объектах, таких как Simulink.Parameter объекты, которые модель использует, чтобы задать значения параметров блоков.

9. В поле Содержимое фильтра введите numerator. The Simulink.Parameter numerator_param объекта, который находится в базовом рабочем пространстве, устанавливает значение параметра Numerator в маркированном блоке Discrete Filter Throttle Transient. Объект использует класс памяти ExportToFile.

10. Выберите вкладку Signals. В поле Содержимое фильтра введите e0. Сигнал e0, который является внутренним по отношению к airflow_calc ссылка на модель, также использует ExportToFile. Сигнал является внутренним, потому что это не вход или выход корневого уровня модели.

11. Откройте fuel_calc модель.

open_system('fuel_calc')

12. В Model Data Editor для этой модели на вкладке Inports/Outports установите значение представления Change Code. Входной порт блокирует est_airflow и fb_correction использовать тот же класс памяти, ExportToFile, как соответствующие блоки Outport в airflow_calc. Блок Outport маркирован fuel_rate также использует ExportToFile.

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

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

evalc('slbuild(''sldemo_fuelsys_dd_controller'')');

В отчете о генерации кода в разделе Ссылочные Модели щелкните гиперссылку, чтобы просмотреть код, сгенерированный для airflow_calc.

Файл airflow_calc.c задает глобальную переменную, которая представляет сигнал e0. Потому что блоки, которые записывают и читают из e0 существует только в airflow_calcГенератор кода принимает, что эта модель владеет сигналом.

file = fullfile('slprj','ert','airflow_calc','airflow_calc.c');
rtwdemodbtype(file,'/* Definition for custom storage class: ExportToFile */',...
    'real32_T e0;',1,1)
/* Definition for custom storage class: ExportToFile */
real32_T e0;                           /* '<Root>/Sum1' */

В отчете генерации кода вернитесь к коду, сгенерированному для sldemo_fuelsys_dd_controller.

Файл sldemo_fuelsys_dd_controller.c задает другие глобальные переменные.

file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',...
    'sldemo_fuelsys_dd_controller.c');
rtwdemodbtype(file,...
    '/* Definition for custom storage class: ExportToFile */',...
    'real32_T numerator_param[2] = { 0.01F, -0.01F } ;',1,1);
/* Definition for custom storage class: ExportToFile */
real32_T est_airflow;                  /* '<Root>/airflow_calc' */
real32_T fb_correction;                /* '<Root>/airflow_calc' */
real32_T fuel_rate;                    /* '<Root>/fuel_calc' */
real32_T numerator_param[2] = { 0.01F, -0.01F } ;

Потому что сигналы est_airflow и fb_correction пройти между двумя моделями и через модели контроллеров верхнего уровня, генератор кода принимает, что sldemo_fuelsys_dd_controller владеет сигналами. Генератор кода делает аналогичное предположение о fuel_rate. Потому что объект параметра numerator_param существует в базовом рабочем пространстве, любая модель в иерархии может использовать объект. Поэтому генератор кода принимает, что sldemo_fuelsys_dd_controller владеет параметром.

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

Сконфигурируйте владение данными

В этом примере вы конфигурируете настройки генерации кода так, чтобы:

  • Код, сгенерированный для airflow_calc модель определяет сигналы, которые проходят между двумя моделями, est_airflow и fb_correction.

  • Код, сгенерированный для airflow_calc определяет данные параметра, numerator_param.

  • Код, сгенерированный для fuel_calc определяет сигнал выхода, который он вычисляет, fuel_rate.

1. В airflow_calc модель, на вкладке Modeling, в разделе Design, нажмите Property Inspector.

2. В Model Data Editor выберите вкладку Inports/Outports.

3. Выберите строку, которая соответствует блоку Outport est_airflow. Property Inspector показывает свойства блока Outport.

4. В Property Inspector в разделе «Коде» установите значение «Владелец» равным airflow_calc. Генератор кода помещает определение глобальной переменной с кодом, сгенерированным для airflow_calc.

5. Для fb_correction, используйте Model Data Editor и Property Inspector, чтобы задать значение Owner airflow_calc.

6. Выберите вкладку Parameters.

7. Найдите строку, которая соответствует объекту параметра, numerator_param. В строке дважды щелкните значок в левом столбце. Откроется Обозреватель моделей (Model Explorer), в котором отобразятся свойства numerator_param.

8. На панели Иерархия модели разверните узел airflow_calc так, чтобы вы могли увидеть подчиненный узел Рабочего пространства модели.

9. Используйте браузер Model Explorer, чтобы переместить numerator_param из базового рабочего пространства в airflow_calc рабочего пространства модели. Для примера на панели Иерархия модели выберите Базовое рабочее пространство. Затем перетащите мышью numerator_param от панели Содержимое до узла Рабочего пространства модели на панели иерархии модели. С этим изменением генератор кода принимает, что airflow_calc владеет numerator_param, и помещает определение переменной в код, сгенерированный для airflow_calc.

10. В fuel_calc модель, на вкладке Modeling, в разделе Design, нажмите Property Inspector.

11. Для блоков Inport est_airflow и fb_correction, используйте Model Data Editor и Property Inspector, чтобы задать значение Owner airflow_calc. С помощью этого строения fuel_calc код не определяет переменные.

12. Для блока Outport используйте Model Data Editor и Property Inspector, чтобы задать значение Owner fuel_calc.

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

temp = Simulink.Signal;
temp.CoderInfo.StorageClass = 'Custom';
temp.CoderInfo.CustomStorageClass = 'ExportToFile';
temp.CoderInfo.CustomAttributes.Owner = 'airflow_calc';

set_param('airflow_calc/est_airflow','SignalName','est_airflow')
set_param('airflow_calc/est_airflow','SignalObject',copy(temp))

set_param('airflow_calc/fb_correction','SignalName','fb_correction')
set_param('airflow_calc/fb_correction','SignalObject',copy(temp))

mdlwks = get_param('airflow_calc','ModelWorkspace');
assignin(mdlwks,'numerator_param',copy(numerator_param));

portHandles = get_param('fuel_calc/est_airflow','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','est_airflow')
set_param(outportHandle,'SignalObject',copy(temp))

portHandles = get_param('fuel_calc/fb_correction','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','fb_correction')
set_param(outportHandle,'SignalObject',copy(temp))

temp.CoderInfo.CustomAttributes.Owner = 'fuel_calc';

set_param('fuel_calc/fuel_rate','SignalName','fuel_rate')
set_param('fuel_calc/fuel_rate','SignalObject',copy(temp))

clear temp portHandles outportHandle numerator_param

13. В каждой из трех моделей выберите Параметры конфигурации > Использовать владельца из объекта данных для размещения определения данных. Когда этот параметр снят (по умолчанию), генератор кода игнорирует значения, заданные для Owner.

set_param('fuel_calc','EnableDataOwnership','on')
set_param('airflow_calc','EnableDataOwnership','on')
set_param('sldemo_fuelsys_dd_controller','EnableDataOwnership','on')

14. Сохраните ссылку на модели.

save_system('fuel_calc')
save_system('airflow_calc')

Сгенерируйте улучшенный код

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

evalc('slbuild(''sldemo_fuelsys_dd_controller'')');

Теперь файл sldemo_fuelsys_dd_controller.c не задает ни одну из глобальных переменных.

В отчете о генерации кода проверьте код, сгенерированный для airflow_calc.

Файл airflow_calc.c теперь задает глобальные переменные, которые относятся к airflow_calc.

file = fullfile('slprj','ert','airflow_calc','airflow_calc.c');
rtwdemodbtype(file,'/* Definition for custom storage class: ExportToFile */',...
    'real32_T numerator_param[2] = { 0.01F, -0.01F } ;',1,1)
/* Definition for custom storage class: ExportToFile */
real32_T e0;                           /* '<Root>/Sum1' */
real32_T est_airflow;                  /* '<Root>/Sum' */
real32_T fb_correction;                /* '<Root>/Discrete Integrator' */
real32_T numerator_param[2] = { 0.01F, -0.01F } ;

Смотрите код, сгенерированный для fuel_calc. Файл fuel_calc.c задает глобальную переменную fuel_rate.

file = fullfile('slprj','ert','fuel_calc','fuel_calc.c');
rtwdemodbtype(file,'/* Definition for custom storage class: ExportToFile */',...
    'real32_T fuel_rate;',1,1)
/* Definition for custom storage class: ExportToFile */
real32_T fuel_rate;                    /* '<S2>/Merge' */

Создайте одну точку спецификации для сигналов, которые проходят между моделями

Элементы данных сигнала est_airflow и fb_correction представлены блоками Outport в airflow_calc и блоками Inport в fuel_calc. Если вы хотите изменить строение одного из этих сигналов, вы должны сделать изменение в обеих моделях. Для примера, если вы хотите изменить класс памяти est_airflow от ExportToFile на Volatileнеобходимо изменить класс памяти дважды: один раз для блока Outport в airflow_calc и снова для блока Inport в fuel_calc.

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

1. В Model Data Editor для airflow_calc, на вкладке Inports/Outports найдите строку, которая соответствует est_airflow. Для этой строки в столбце «Имя сигнала» щелкните камеру.

2. В камере, рядом с est_airflow нажмите кнопку действия (с тремя вертикальными точками). Выберите «Создать и решить».

3. В диалоговом окне «Создание новых данных» установите значение Simulink.Signal и нажмите «Создать». A Simulink.Signal объект с именем est_airflow появляется в базовом рабочем пространстве. В Model Data Editor для est_airflowустановлен флажок в флажке Разрешить (Resolve), что означает, что блок Outport получает настройки генерации кода от объекта сигнала в базовом рабочем пространстве.

4. В est_airflow диалоговое окно свойств, установите для класса памяти значение ExportToFile.

5. Установите для владельца значение airflow_calc.

6. Используйте Model Data Editor, чтобы создать аналогичный объект сигнала для fb_correction.

В Model Data Editor для fuel_calc, на вкладке Inports/Outports, в столбце Resolve, установите флажки для est_airflow и fb_correction. Теперь каждый блок Inport получает настройки генерации кода от соответствующего объекта сигнала.

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

est_airflow = Simulink.Signal;
est_airflow.CoderInfo.StorageClass = 'Custom';
est_airflow.CoderInfo.CustomStorageClass = 'ExportToFile';
est_airflow.CoderInfo.CustomAttributes.Owner = 'airflow_calc';

fb_correction = Simulink.Signal;
fb_correction.CoderInfo.StorageClass = 'Custom';
fb_correction.CoderInfo.CustomStorageClass = 'ExportToFile';
fb_correction.CoderInfo.CustomAttributes.Owner = 'airflow_calc';

set_param('airflow_calc/est_airflow', 'StorageClass', 'Auto')
set_param('airflow_calc/est_airflow','MustResolveToSignalObject','on')

set_param('airflow_calc/fb_correction', 'StorageClass', 'Auto')
set_param('airflow_calc/fb_correction','MustResolveToSignalObject','on')

portHandles = get_param('fuel_calc/est_airflow','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle, 'StorageClass', 'Auto')
set_param(outportHandle,'MustResolveToSignalObject','on')

portHandles = get_param('fuel_calc/fb_correction','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle, 'StorageClass', 'Auto')
set_param(outportHandle,'MustResolveToSignalObject','on')

clear portHandles outportHandle

7. Сохраните модели и сгенерируйте код из sldemo_fuelsys_dd_controller. Код такой же, как был до того, как вы создали Simulink.Signal объекты. Теперь можно вносить изменения в объекты сигнала вместо соответствующих блоков и линий в моделях.

save_system('airflow_calc')
save_system('fuel_calc')
evalc('slbuild(''sldemo_fuelsys_dd_controller'')');

Похожие темы