И.В.Черных. Simulink. И. В. Черных. "Simulink Инструмент моделирования динамических систем"
Скачать 3.7 Mb.
|
void sfun_Derivatives_wrapper(const real_T *u, const real_T *y, real_T *dx, real_T *xC, const real_T *param0, /* optional */ int_T p_width0, /* optional */ real_T *param1,/* optional */ int_T p_width1, /* optional */ int_T y_width, /* optional */ int_T u_width) /* optional */ { /* Место для ввода расчетного кода */ } Окно S-Function Builder с открытой вкладкой Continuous Derivatives показано на рис . 16.15. Рис . 16.16 Окно S-Function Builder ( вкладка Continuous Derivatives ) В примере на рис. 16.16 в первых двух строках объявляются переменные - параметры электродвигателя, и этим переменным присваиваются значения параметров передаваемых в S -функцию через окно диалога. В следующих двух строках объявляются и вычисляются переменные AOO … B 11 , входящие в уравнения (15), (16). В последних двух строках записаны выражения для расчета производных непрерывных переменных состояния в соответствии с уравнениями (15) и (16). 5. Discrete Update - Расчет дискретных переменных состояния. В текстовом окне вкладки записываются выражения для расчета дискретных переменных состояния. В расчетных выражениях можно использовать те же переменные, что и на вкладке Outputs , за исключением непрерывных переменных состояния x С . Сами дискретные переменные состояния обозначаются как xD [0], xD [1], xD [2] и т.п. Текст автоматически генерируемо метода mdl Update , приведен ниже: void sfun_Update_wrapper(const real_T *u, const real_T *y, real_T *xD, const real_T *param0, /* optional */ int_T p_width0, /* optional */ real_T *param1,/* optional */ int_T p_width1, /* optional */ int_T y_width, /* optional */ int_T u_width) /* optional */ { /* Место для ввода расчетного кода */ } Окно S - Function Builder с открытой вкладкой Discrete Update показано на рис. 16.17. Рис . 16.17 Окно S-Function Builder ( вкладка Discrete Update ). В рассматриваемом примере отсутствуют дискретные переменные состояния, поэтому на рисунке дан лишь пример расчетного выражения. 6. Build Info - Информация о компоновке. На вкладке в окне Compilation diagnostics (диагностические сообщения о ходе компиляции) отображается информацию о процессе компоновки S-функции . На вкладке Build Info с помощью флажков можно установить следующие параметры: Show compile steps - Отображать стадии компиляции. При установленном флажке в окне Compilation diagnostics будут отображены все сообщения компилятора о процессе компиляции. Данный параметр желательно устанавливать при сборке S -функции , использующей внешние функции. Create a debuggable MEX - file - Создавать отлаживаемый исполняемый файл. При установленном флажке в процессе компиляции будет создан файл, позволяющий выполнять отладку Simulink -модели. Generate wrapper TLC - Создавать TLC- файл . Флажок устанавливается, если предполагается использовать ускоренный режим расчетов или Realtime Workshop . Save code only - Создавать только текстовый код. Если флажок установлен, то будут созданы только текстовые файлы на языке С. Перед началом компиляции необходимо выбрать (настроить) компилятор. Для этого в командном окне MATLAB следует ввести команду: mex - setup и далее следовать диалогу с компилятором. С программой MATLAB поставляется компилятор Lcc . Ниже приводится пример такого диалога: Please choose your compiler for building external interface (MEX) files: Would you like mex to locate installed compilers [y]/n? n - Ответ пользователя Select a compiler: [1] Borland C++Builder version 5.0 [2] Borland C++Builder version 4.0 [3] Borland C++Builder version 3.0 [4] Borland C/C++ version 5.02 [5] Borland C/C++ version 5.0 [6] Borland C/C++ (free command line tools) version 5.5 [7] Compaq Visual Fortran version 6.1 [8] Compaq Visual Fortran version 6.5 [9] Digital Visual Fortran version 6.0 [10] Digital Visual Fortran version 5.0 [11] Lcc C version 2.4 [12] Microsoft Visual C/C++ version 6.0 [13] Microsoft Visual C/C++ version 5.0 [14] WATCOM C/C++ version 11 [15] WATCOM C/C++ version 10.6 [0] None Compiler: 11 - Ответ пользователя Your machine has a Lcc C compiler located at C:\MATLAB6\sys\lcc. Do you want to use this compiler [y]/n? y - Ответ пользователя Please verify your choices: Compiler: Lcc C 2.4 Location: C:\MATLAB6\sys\lcc Are these correct?([y]/n): y - Ответ пользователя The default options file: "C:\Documents and Settings\Администратор\Application Data\MathWorks\MATLAB\R12\mexopts.bat" is being updated from C:\MATLAB6\BIN\WIN32\mexopts\lccopts.bat... Процесс компиляции начинается после нажатия на кнопку Build . Об успешном завершении процесса компиляции свидетельствует сообщение вида: ### S-function 'DPT_Sfunc_1_C.dll' created successfully . По завершении процесса компиляции в рабочей папке будут созданы текстовые файлы с названиями вида: sfun_C.c , sfun_wrapper.c и sfun.dll > . Последний является исполняемым файлом. В файле sfun _ C . c находится текст S -функции , а в файле sfun _ wrapper . c - методы, сгенерированные S- Function Builder . Окно S - Function Builder с открытой вкладкой Build Info показано на рис. 16.18. Рис . 16.18 Окно S-Function Builder ( вкладка Build Info ). Результаты расчетов, выполненных с использованием созданной таким образом S -функции , полностью совпадают с результатами, приведенными в п. 16.7.6.2 . Скорость расчета модели с использованием S -функции , написанной на языке C в несколько раз выше, чем при использовании языка MATLAB . [Скачать пример] 16.9. Модернизация S-функций, созданных с помощью S-Function Builder S-функции, созданные с помощью S-Function Builder обладают одним существенным недостатком. В большинстве случаев при расчете переменных состояния, выходных сигналов либо производных непрерывных переменных состояния должны использоваться некоторые ранее вычисленные константы. В задаче моделирования двигателя постоянного тока - это элементы матриц A, B, С уравнений пространства-состояния, рассчитываемые через параметры двигателя (сопротивление, индуктивность и т.п.). В примере на языке MATLAB (см. п. 16.7.6) расчет матриц выполняется в методе mdlInitializeSizes, благодаря чему этот расчет производится только один раз - на этапе инициализации модели. Далее рассчитанные матрицы только используются для вычисления производных переменных состояния в методе mdlDerivatives и выходных сигналов в методе mdlOutputs. Такая компоновка S-функции обеспечивает наибольшую скорость вычислений. К сожалению, в S-Function Builder отсутствует возможность ввести фрагмент кода на вкладке Initialization, а также скрыты заголовки методов, что делает невозможным добавление новых параметров, которые могли бы передаваться в эти методы. Такая ситуация приводит к тому, что константы, которые можно было бы вычислить всего один раз и, затем лишь использовать, вычисляются вновь и вновь на каждом шаге расчета (в примере с двигателем постоянного тока п.16.6 - это A00, A01, B00 и т.д.). И, если в относительно простых моделях с эти еще можно смириться, то для сложных моделей с большим объемом предварительных вычислений такая ситуация приведет к существенному замедлению процесса расчета. Выходом из сложившейся ситуации может явиться редактирование автоматически сгенерированного кода S-функции. Редактирование должно обеспечить вычисление констант один раз на этапе инициализации и передачу их в нужные методы. В рассматриваемом примере модели двигателя постоянного тока на этапе инициализации должны вычисляться константы A00, A01, B00 и т.д., а затем, передаваться в методы для расчета производных и выходных переменных. Для реализации поставленной задачи следует проанализировать полученные с помощью S-Function Builder файлы DPT_Sfunc_1_C.c и DPT_Sfunc_1_C_wrapper.c. Первый файл содержит исходный текст S-функции, а второй текст методов этой S-функции. Текст файла DPT_Sfunc_1_C.c приведен ниже: /* * File: DPT_Sfunc_1_C.c * * * * --- THIS FILE GENERATED BY S-FUNCTION BUILDER: BASIC, 1.0 --- * * This file is an S-function produced by the Basic S-Function * Builder which only recognizes certain fields. Changes made * outside these fields will be lost the next time the block is * used to load, edit, and resave this file. This file will be overwritten * by the S-function Builder block. If you want to edit this file by hand, * you must change it only in the area defined as: * * %%%-SFUNWIZ_defines_Changes_BEGIN * #define NAME 'replacement text' * %%% SFUNWIZ_defines_Changes_END * * DO NOT change NAME--Change te 'replacement text' only. * * For better compatibility with the Real-Time Workshop, the * "wrapper" S-function technique is used. This is discussed * in the Real-Time Workshop User's Manual in the Chapter titled, * "Wrapper S-functions". * * ------------------------------------------------------------------------ *| See matlabroot/simulink/src/sfuntmpl_doc.c for a more detailed template | * ------------------------------------------------------------------------ * Created: Sun Mar 30 13:07:10 2003 * * */ #define S_FUNCTION_NAME DPT_Sfunc_1_C #define S_FUNCTION_LEVEL 2 /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ /* %%%-SFUNWIZ_defines_Changes_BEGIN --- EDIT HERE TO _END */ #define NUM_INPUTS 1 #define INPUT_0_WIDTH 2 #define INPUT_0_FEEDTHROUGH 0 #define NUM_OUTPUTS 1 #define OUTPUT_0_WIDTH 2 #define NPARAMS 6 #define SAMPLE_TIME_0 INHERITED_SAMPLE_TIME #define NUM_DISC_STATES 0 #define DISC_STATES_IC [0] #define NUM_CONT_STATES 2 #define CONT_STATES_IC [0,0] #define SFUNWIZ_GENERATE_TLC 1 #define SOURCEFILES "//my_lib.lib" #define PANELINDEX 5 #define SFUNWIZ_REVISION 1.0 /* %%%-SFUNWIZ_defines_Changes_END --- EDIT HERE TO _BEGIN */ /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ #include "simstruc.h" #define PARAM_DEF0(S) ssGetSFcnParam(S, 0) #define PARAM_DEF1(S) ssGetSFcnParam(S, 1) #define PARAM_DEF2(S) ssGetSFcnParam(S, 2) #define PARAM_DEF3(S) ssGetSFcnParam(S, 3) #define PARAM_DEF4(S) ssGetSFcnParam(S, 4) #define PARAM_DEF5(S) ssGetSFcnParam(S, 5) extern void DPT_Sfunc_1_C_Outputs_wrapper(const real_T *u, real_T *y, const real_T *xC, const real_T *param0, const int_T p_width0, const real_T *param1, const int_T p_width1, const real_T *param2, const int_T p_width2, const real_T *param3, const int_T p_width3, const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5); extern void DPT_Sfunc_1_C_Update_wrapper(const real_T *u, const real_T *y, const real_T *param0, const int_T p_width0,const real_T *param1, const int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const int_T p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5); extern void DPT_Sfunc_1_C_Derivatives_wrapper(const real_T *u, const real_T *y, real_T *dx, real_T *xC, const real_T *param0, const int_T p_width0,const real_T *param1, const int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const int_T p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5); /*====================* * S-function methods * *====================*/ #define MDL_CHECK_PARAMETERS #if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE) /* Function: mdlCheckParameters========================================== * Abstract: * Validate our parameters to verify they are okay. */ static void mdlCheckParameters(SimStruct *S) { int i; bool validParam = false; /* All parameters must be scalar */ for (i = 0; i < ssGetSFcnParamsCount(S); i++) { const mxArray *pVal = ssGetSFcnParam(S,i); if ( !mxIsNumeric(pVal) || !mxIsDouble(pVal) || mxIsLogical(pVal) || mxIsComplex(pVal) || mxIsSparse(pVal) || !mxIsFinite(mxGetPr(pVal)[0])) { validParam = true; break; } } if (validParam) { ssSetErrorStatus(S,"All parameters must be a scalar or vectors"); return; } } #endif /* MDL_CHECK_PARAMETERS */ /* Function: mdlInitializeSizes =========================================== * Abstract: * Setup sizes of the various vectors. */ static void mdlInitializeSizes(SimStruct *S) { DECL_AND_INIT_DIMSINFO(inputDimsInfo); DECL_AND_INIT_DIMSINFO(outputDimsInfo); ssSetNumSFcnParams(S, NPARAMS); /* Number of expected parameters */ #if defined(MATLAB_MEX_FILE) if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) { mdlCheckParameters(S); if (ssGetErrorStatus(S) != NULL) { return; } } else { return; /* Parameter mismatch will be reported by Simulink */ } #endif ssSetNumContStates(S, NUM_CONT_STATES); ssSetNumDiscStates(S, NUM_DISC_STATES); if (!ssSetNumInputPorts(S, 1)) return; inputDimsInfo.width = INPUT_0_WIDTH; ssSetInputPortDimensionInfo(S, 0, &inputDimsInfo); ssSetInputPortFrameData(S, 0, FRAME_INHERITED); ssSetInputPortDirectFeedThrough(S, 0, INPUT_0_FEEDTHROUGH); ssSetInputPortRequiredContiguous(S, 0, 1); /*direct input signal access*/ if (!ssSetNumOutputPorts(S,1)) return; outputDimsInfo.width = OUTPUT_0_WIDTH; ssSetOutputPortDimensionInfo(S, 0, &outputDimsInfo); ssSetOutputPortFrameData(S, 0, FRAME_INHERITED); ssSetNumSampleTimes(S, 1); ssSetNumRWork(S, 0); ssSetNumIWork(S, 0); ssSetNumPWork(S, 0); ssSetNumModes(S, 0); ssSetNumNonsampledZCs(S, 0); /* Take care when specifying exception free code - see sfuntmpl_doc.c */ ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_USE_TLC_WITH_ACCELERATOR); } /* Function: mdlInitializeSampleTimes ====================================== * Abstract: * Specifiy the sample time. */ static void mdlInitializeSampleTimes(SimStruct *S) { ssSetSampleTime(S, 0, SAMPLE_TIME_0); ssSetOffsetTime(S, 0, 0.0); } #define MDL_INITIALIZE_CONDITIONS /* Function: mdlInitializeConditions ====================================== * Abstract: * Initialize the states */ static void mdlInitializeConditions(SimStruct *S) { real_T *xC = ssGetContStates(S); xC[0] = 0; xC[1] = 0; } /* Function: mdlOutputs =================================================== * */ static void mdlOutputs(SimStruct *S, int_T tid) { const real_T *u = (const real_T*) ssGetInputPortSignal(S,0); real_T *y = ssGetOutputPortRealSignal(S,0); const real_T *xC = ssGetContStates(S); const real_T *param0 = mxGetPr(PARAM_DEF0(S)); const real_T *param1 = mxGetPr(PARAM_DEF1(S)); const real_T *param2 = mxGetPr(PARAM_DEF2(S)); const real_T *param3 = mxGetPr(PARAM_DEF3(S)); const real_T *param4 = mxGetPr(PARAM_DEF4(S)); const real_T *param5 = mxGetPr(PARAM_DEF5(S)); |