В этом примере показано, как создать код C из модели алгоритма управления и интегрировать этот код с существующим внешним кодом приложения. В полном приложении, состоящем из трех модулей, модуль алгоритма должен обмениваться данными с другими модулями через глобальные переменные. В этом примере созданный код настраивается для взаимодействия с существующими внешними переменными, напоминает внешний код по внешнему виду и организации и соответствует определенным требованиям к кодированию.
Установите текущую папку в доступное для записи расположение.
Копировать сценарий prepare_ext_code в текущую папку и запустите сценарий. Сценарий копирует файлы внешнего кода в несколько папок.
try copyfile(fullfile(matlabroot,'examples','ecoder','main','prepare_ext_code.m'),... 'prepare_ext_code.m','f'); catch end run('prepare_ext_code.m');
В текущей папке откройте ext_code_main.c. Этот код приложения представляет встроенную систему с тривиальным алгоритмом планирования (a while loop) и три модуля, алгоритмы которых выполняются в каждом цикле выполнения: ex_ext_inputs_proc, ex_ext_ctrl_alg, и ex_ext_outputs_proc.
type('ext_code_main.c')
В shared папка, проверка ex_ext_projTypes.h. Файл определяет два пользовательских типа данных (typedef), которые используются данными в модулях.
type(fullfile('shared','ex_ext_projTypes.h'))
В io_drivers папка, проверка ex_sensor_accessors.c. Этот файл определяет функции, get_fromSensor_flow и get_fromSensor_temp, которые возвращают необработанные данные, записанные датчиком расхода и датчиком температуры. Для этого примера функции возвращают тривиальные синусоидальные стимулы для алгоритма управления.
type(fullfile('io_drivers','ex_sensor_accessors.c'))
В ex_ext_inputs_proc папка, проверка ex_ext_inputs_proc.c. ex_ext_inputs_proc модуль считывает данные датчика (путем вызова функций доступа), фильтрует данные и сохраняет их в двух глобальных переменных, PROC_INPUT_FLOW и PROC_INPUT_TEMP. Эти глобальные переменные определяются в файле ex_ext_proc_inputs.c и объявлены в ex_ext_proc_inputs.h.
type(fullfile('ex_ext_inputs_proc','ex_ext_inputs_proc.c'))
Алгоритм фильтрации в этом модуле и алгоритмы в двух других модулях требуют данных о состоянии, которые должны сохраняться между циклами выполнения приложения. Каждый модуль сохраняет соответствующие данные состояния в виде глобальных переменных. Например, в ex_ext_inputs_proc модуль, ex_ext_inputs_proc.c определяет следующие переменные:
flowFilterIn_state_data
tempFilterIn_state_data
flowFilterIn_tmp_data
tempFilterIn_tmp_data
Пустое ex_ext_ctrl_alg является местозаполнителем созданного кода. ex_ext_ctrl_alg модуль должен осуществлять ПИД-контроль отфильтрованного потока и измерения температуры. Позже будут рассмотрены требования к этому коду, которые основаны на коде в других модулях.
В ex_ext_outputs_proc папка, проверка ex_ext_outputs_proc.c. Этот модуль считывает выходные сигналы PID из глобальных переменных с именем CONTR_SIG_FLOW и CONTR_SIG_TEMP. ex_ext_ctrl_alg модуль (сгенерированный код) должен определять эти переменные. ex_ext_outputs_proc затем модуль фильтрует эти сигналы и передает отфильтрованные значения функциям, которые представляют приводы устройств для приводов (например, клапан и нить накала нагревателя).
type(fullfile('ex_ext_outputs_proc','ex_ext_outputs_proc.c'))
Функции привода определены в io_drivers папка в файле ex_actuator_accessors.c.
На рисунке показан предполагаемый поток данных через систему. На рисунке также показаны файлы кода, которые определяют и объявляют данные (глобальные переменные), пересекающие границы модуля.

Открыть пример модели ex_ext_ctrl_alg.
open_system('ex_ext_ctrl_alg')
Блоки в модели реализуют требуемый алгоритм управления PID. Модель использует настройки генерации кода по умолчанию для целевого файла системы на основе ERT (ert.tlc).
Для завершения приложения выполните функцию ex_ext_ctrl_alg , код, сгенерированный на основе этой модели, должен:
Использовать пользовательские типы данных dataPath_flow_T и dataPath_temp_T из внешнего файла ex_ext_projTypes.h.
Считывание отфильтрованных данных датчика из глобальных переменных PROC_INPUT_FLOW и PROC_INPUT_TEMP. Созданный код не должен определять эти переменные, поскольку модуль ex_ext_inputs_proc определяет их, объявляя в ex_ext_proc_inputs.h.
Запись управляющих сигналов PID в глобальные переменные CONTR_SIG_FLOW и CONTR_SIG_TEMP. Созданный код должен определить эти переменные и объявить их в файле с именем ex_ext_ctrl_sigs.h. Затем, ex_ext_outputs_proc модуль может считывать с них необработанные управляющие сигналы.
Соответствие стандартам именования переменных, регулирующим внешнее приложение. Например, созданный код должен хранить данные о состоянии в глобальных переменных, имена которых заканчиваются на _data. Кроме того, для этого примера имена переменных локальных функций должны заканчиваться на _local.
Соответствие стандартам, регулирующим организацию кода в каждом из внешних файлов. Например, каждый файл содержит разделы, разделенные комментариями, которые объединяют аналогичные конструкции кода, такие как определения типов, объявления переменных и определения функций.
Для взаимодействия с алгоритмом управления во время выполнения, например, можно настроить сгенерированный код для определения и объявления. const глобальные переменные с именем PARAM_setpoint_flow и PARAM_setpoint_temp, которые представляют уставки контроллера PID. Определения должны отображаться в файле с именем ex_ext_ctrl_params.c и объявления должны отображаться в файле с именем ex_ext_ctrl_params.h.
Установите текущую папку в shared папка.
Используйте функцию Simulink.importExternalCTypes произвести Simulink.AliasType объекты, представляющие пользовательские типы данных dataPath_flow_T и dataPath_temp_T.
cd('shared') Simulink.importExternalCTypes('ex_ext_projTypes.h');
Объекты отображаются в базовом рабочем пространстве.
В ex_ext_ctrl_alg на вкладке Моделирование (Modeling) щелкните Редактор данных модели (Model Data Editor).
В редакторе данных модели для блока Inport, представляющего PROC_INPUT_FLOW, задайте для параметра «Тип данных» значение dataPath_flow_T.
Для блока Inport, представляющего PROC_INPUT_TEMP, задайте для параметра «Тип данных» значение dataPath_temp_T.
Выберите вкладку Signals (Сигналы).
В модели выберите выходной сигнал каждого блока константы. В редакторе данных модели задайте для параметра «Тип данных» значение Inherit: Inherit via back propagation. При этом параметре каждый блок константы наследует тип выходных данных от блока непосредственно за блоком Sum.
Кроме того, эти команды можно использовать для настройки типов данных в командной строке.
set_param('ex_ext_ctrl_alg/In1','OutDataTypeStr','dataPath_flow_T') set_param('ex_ext_ctrl_alg/In2','OutDataTypeStr','dataPath_temp_T') set_param('ex_ext_ctrl_alg/Flow Setpt','OutDataTypeStr',... 'Inherit: Inherit via back propagation') set_param('ex_ext_ctrl_alg/Temp Setpt','OutDataTypeStr',... 'Inherit: Inherit via back propagation')
Обновите блок-схему. Диаграмма показывает, что из-за наследования и распространения типа данных сигналы в модели используют пользовательский тип данных.
Настройте модель для создания кода, который получает доступ и определяет правильные глобальные переменные, такие как PROC_INPUT_FLOW и CONTR_SIG_TEMP.
В Редакторе данных модели (Model Data Editor) выберите вкладку Ввод/вывод (Inports/Outports) и задайте в раскрывающемся списке Изменить вид (Change view) значение Code.
Выберите строки, соответствующие двум блокам ввода.
Для любой строки установите класс хранения в значение ImportFromFile и файл заголовка в ex_ext_proc_inputs.h. С классом хранения ImportFromFileкаждый блок Inport отображается в сгенерированном коде как глобальная переменная. Однако сгенерированный код не определяет переменную, а включает (#include) объявление переменной из ex_ext_proc_inputs.h.
Для строк, соответствующих блокам Outport, задайте:
Класс хранения для ExportToFile
Заголовочный файл в ex_ext_ctrl_sigs.h
Файл определения для ex_ext_ctrl_sigs.c
С ExportToFile, сгенерированный код определяет глобальную переменную.
Кроме того, для конфигурирования сигналов в командной строке используйте эти команды.
temp = Simulink.Signal; temp.CoderInfo.StorageClass = 'Custom'; temp.CoderInfo.CustomStorageClass = 'ImportFromFile'; temp.CoderInfo.CustomAttributes.HeaderFile = 'ex_ext_proc_inputs.h'; portHandles = get_param('ex_ext_ctrl_alg/In1','portHandles'); outportHandle = portHandles.Outport; set_param(outportHandle,'SignalObject',copy(temp)) portHandles = get_param('ex_ext_ctrl_alg/In2','portHandles'); outportHandle = portHandles.Outport; set_param(outportHandle,'SignalObject',copy(temp)) temp.CoderInfo.CustomStorageClass = 'ExportToFile'; temp.CoderInfo.CustomAttributes.HeaderFile = 'ex_ext_ctrl_sigs.h'; temp.CoderInfo.CustomAttributes.DefinitionFile = 'ex_ext_ctrl_sigs.c'; set_param('ex_ext_ctrl_alg/Out1','SignalObject',copy(temp)) set_param('ex_ext_ctrl_alg/Out2','SignalObject',copy(temp))
Чтобы применить класс хранения к параметру блока, такому как параметр Constant value блока Constant, необходимо создать объект параметра, такой как Simulink.Parameter. Для создания объектов параметров можно использовать Редактор данных модели (Model Data Editor).
Выберите вкладку Параметры (Parameters) и задайте для параметра Изменить вид (Change view) значение Design.
В модели выберите блок «Константа» с меткой Flow Setpt.
В редакторе данных модели задайте для параметра «Значение» значение PARAM_setpoint_flow.
Рядом с PARAM_setpoint_flowнажмите кнопку действия (с тремя вертикальными точками) и выберите «Создать».
В диалоговом окне «Создание новых данных» задайте для параметра «Значение» значение Simulink.Parameter(3).
Задать расположение для Model Workspace и нажмите кнопку «Создать».
В PARAM_setpoint_flow диалоговое окно свойств, задайте для класса Storage значение Const.
Задать для файла заголовка значение ex_ext_ctrl_params.h и DefinityFile в ex_ext_ctrl_params.c.
Для другого блока константы используйте редактор данных модели для создания Simulink.Parameter объект с именем PARAM_setpoint_temp со значением 2.
Кроме того, чтобы настроить блоки, используйте эти команды в командной строке.
PARAM_setpoint_flow = Simulink.Parameter(3); PARAM_setpoint_flow.CoderInfo.StorageClass = 'Custom'; PARAM_setpoint_flow.CoderInfo.CustomStorageClass = 'Const'; PARAM_setpoint_flow.CoderInfo.CustomAttributes.HeaderFile = 'ex_ext_ctrl_params.h'; PARAM_setpoint_flow.CoderInfo.CustomAttributes.DefinitionFile = 'ex_ext_ctrl_params.c'; PARAM_setpoint_temp = copy(PARAM_setpoint_flow); PARAM_setpoint_temp.Value = 2; mdlwks = get_param('ex_ext_ctrl_alg','ModelWorkspace'); assignin(mdlwks,'PARAM_setpoint_flow',copy(PARAM_setpoint_flow)) assignin(mdlwks,'PARAM_setpoint_temp',copy(PARAM_setpoint_temp)) set_param('ex_ext_ctrl_alg/Flow Setpt','Value','PARAM_setpoint_flow') set_param('ex_ext_ctrl_alg/Temp Setpt','Value','PARAM_setpoint_temp') clear temp PARAM_setpoint_flow PARAM_setpoint_temp mdlwks portHandles outportHandle
Во внешнем коде внутренние данные, которые не участвуют в интерфейсах модуля, такие как данные состояния и локальные переменные в функциях, соответствуют схемам именования. В модели настройте внутренние данные, отображаемые в сгенерированном коде, для имитации этих схем именования.
В диалоговом окне Параметры конфигурации модели (model Configuration Parameters) проверьте панель Создание кода (Code Generation) > Идентификаторы (Identifiers). При указании значений для схем именования в разделе Управление форматом идентификатора:
$R представляет имя модели, ex_ext_ctrl_alg.
$N представляет имя каждого элемента модели, к которому применяется схема, например, сигнал, состояние блока или стандартная структура данных.
$M представляет собой текст, маскирующий имя, который при необходимости вставляется генератором кода во избежание конфликтов имен. Для большинства правил именования этот маркер необходим.
Задать для глобальных переменных значение $R$N_data$M. Этот параметр управляет именами глобальных переменных, например, представляющих данные о состоянии. Схема именования $R$N_data_$M наиболее точно аппроксимирует схему, которую используют переменные состояния во внешнем коде.
Установите локальные временные переменные и выходные переменные локального блока в значение $N_local$M.
Кроме того, чтобы задать параметры конфигурации, используйте эти команды в командной строке.
set_param('ex_ext_ctrl_alg','CustomSymbolStrGlobalVar','$R$N_data$M') set_param('ex_ext_ctrl_alg','CustomSymbolStrTmpVar','$N_local$M') set_param('ex_ext_ctrl_alg','CustomSymbolStrBlkIO','$N_local$M')
Настройте отображение данных состояния в модели в сгенерированном коде в виде отдельных глобальных переменных вместо полей стандартной структуры DWork. Включите ракурс «Код». В коллекции «Приложения» щелкните Встроенный кодер.
Под блок-схемой в разделе Сопоставления кодов > Значения по умолчанию для строки Внутренние данные в столбце Класс хранения выберите ExportedGlobal.
Кроме того, чтобы настроить этот класс хранения по умолчанию, используйте следующие команды в командной строке:
coder.mapping.create('ex_ext_ctrl_alg'); coder.mapping.defaults.set('ex_ext_ctrl_alg','InternalData',... 'StorageClass','ExportedGlobal');
Установите текущую папку в ex_ext_ctrl_alg папка.
cd(fullfile('..','ex_ext_ctrl_alg'))
В командной строке перейдите к папке, содержащей встроенный шаблон создания кода ert_code_template.cgt. По умолчанию при создании кода с системным целевым файлом ert.tlcэтот шаблон определяет организацию и, частично, внешний вид кода в каждом созданном файле.
currentFolder = pwd; cd(fullfile(matlabroot,'toolbox','rtw','targets','ecoder'))
Копировать ert_code_template.cgt файл в буфер обмена.
Вернуться к разделу ex_ext_ctrl_alg папка. Чтобы избежать перезаписи буфера обмена, вместо использования командной строки для перехода к папке можно использовать кнопку «Назад» в MATLAB.
cd(currentFolder)
clear currentFolder
Вставьте файл в ex_ext_ctrl_alg папка. Переименовать файл как ex_my_code_template.cgt.
Откройте файл и замените содержимое этим кодом.
type(fullfile(matlabroot,'examples','ecoder','data','ex_my_code_template.cgt'))
Этот новый шаблон более точно соответствует организации внешних файлов. Например, шаблон организует аналогичные конструкции кода в именованные разделы (разделенные комментариями) и в верхней части шаблона указывает только минимальную информацию о каждом созданном файле.
В модели выберите Параметры конфигурации > Создание кода > Шаблоны.
В разделе Шаблоны кода (Code templates) и Шаблоны данных (Data templates) задайте четыре параметра конфигурации как ex_my_code_template.cgt.
Кроме того, чтобы скопировать файл и задать параметры, используйте эти команды в командной строке.
copyfile(fullfile(matlabroot,'examples','ecoder','data','ex_my_code_template.cgt'),... 'ex_my_code_template.cgt','f') set_param('ex_ext_ctrl_alg','ERTSrcFileBannerTemplate','ex_my_code_template.cgt') set_param('ex_ext_ctrl_alg','ERTHdrFileBannerTemplate','ex_my_code_template.cgt') set_param('ex_ext_ctrl_alg','ERTDataSrcFileTemplate','ex_my_code_template.cgt') set_param('ex_ext_ctrl_alg','ERTDataHdrFileTemplate','ex_my_code_template.cgt')
Поскольку внешний код уже определяет main выберите Configuration Parameters > Generate code only и снимите флажок Configuration Parameters > Generate a example main program.
set_param('ex_ext_ctrl_alg','GenCodeOnly','on') set_param('ex_ext_ctrl_alg','GenerateSampleERTMain','off')
Создайте код из модели.
rtwbuild('ex_ext_ctrl_alg')
В отчете о создании кода проверьте созданные файлы. Код соответствует требованиям. Например, ex_ext_ctrl_sigs.c определяет управляющие выходные сигналы, CONTR_SIG_FLOW и CONTR_SIG_TEMP.
file = fullfile('ex_ext_ctrl_alg_ert_rtw','ex_ext_ctrl_sigs.c'); rtwdemodbtype(file,'dataPath_flow_T CONTR_SIG_FLOW;',... 'dataPath_temp_T CONTR_SIG_TEMP;',1,1)
Параметры уставки отображаются в ex_ext_ctrl_params.c.
file = fullfile('ex_ext_ctrl_alg_ert_rtw','ex_ext_ctrl_params.c'); rtwdemodbtype(file,'const dataPath_flow_T PARAM_setpoint_flow = 3.0;',... 'const dataPath_temp_T PARAM_setpoint_temp = 2.0;',1,1)
Файл ex_ext_ctrl_alg.c определяет глобальные переменные для хранения данных о состоянии. Переменные следуют указанной схеме именования. Код аналогичен следующему:
dataPath_temp_T ex_ext__Integrator_DSTATE_datag; dataPath_flow_T ex_ext_c_Integrator_DSTATE_data; dataPath_temp_T ex_ext_ctrl_Filter_DSTATE_datad; dataPath_flow_T ex_ext_ctrl__Filter_DSTATE_data;
В том же файле функция выполнения модели, ex_ext_ctrl_alg_stepсоздает локальные функциональные переменные для хранения временных вычислений. Переменные следуют указанной схеме именования. Код аналогичен следующему:
dataPath_flow_T Diff_local; dataPath_flow_T FilterCoefficient_local; dataPath_temp_T Diff1_local; dataPath_temp_T FilterCoefficient_locali;
Некоторые имена глобальных и локальных переменных содержат дополнительные искалечивающие символы, предотвращающие конфликты имен. Эти дополнительные символы соответствуют $M маркер, указанный в схемах именования.
Созданные файлы кода находятся в созданных папках ex_ext_ctrl_alg_ert_rtw и slprj. Для использования этих папок и файлов необходимо настроить системы управления файлами и средства построения.