Главная страница

И.В.Черных. Simulink. И. В. Черных. "Simulink Инструмент моделирования динамических систем"


Скачать 3.7 Mb.
НазваниеИ. В. Черных. "Simulink Инструмент моделирования динамических систем"
Дата21.09.2022
Размер3.7 Mb.
Формат файлаdoc
Имя файлаИ.В.Черных. Simulink.doc
ТипДокументы
#689048
страница23 из 26
1   ...   18   19   20   21   22   23   24   25   26

const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));

const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S));

const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S));

const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S));

const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S));

const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));

DPT_Sfunc_1_C_Outputs_wrapper(u, y, xC, param0, p_width0, param1, p_width1, param2, p_width2,
param3, p_width3, param4, p_width4, param5, p_width5);

}
#undef MDL_UPDATE /* Change to #define to use the function */

#if defined(MDL_UPDATE)

/* Function: mdlUpdate ==================================================

* Abstract:

* This function is called once for every major integration time step.

* Discrete states are typically updated here, but this function is useful

* for performing any tasks that should only take place once per

* integration step.

*/

static void mdlUpdate(SimStruct *S, int_T tid)

{

const real_T *u = (const real_T *) ssGetInputPortSignal(S,0);

real_T *xD = ssGetDiscStates(S);

const real_T *y = ssGetOutputPortSignal(S,0);

const real_T *param0 = mxGetPr(PARAM_DEF0(S));

const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));

const real_T *param1 = mxGetPr(PARAM_DEF1(S));

const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S));

const real_T *param2 = mxGetPr(PARAM_DEF2(S));

const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S));

const real_T *param3 = mxGetPr(PARAM_DEF3(S));

const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S));

const real_T *param4 = mxGetPr(PARAM_DEF4(S));

const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S));

const real_T *param5 = mxGetPr(PARAM_DEF5(S));

const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));

DPT_Sfunc_1_C_Update_wrapper(u, y, param0, p_width0, param1, p_width1, param2, p_width2, param3,
p_width3, param4, p_width4, param5, p_width5);
}

#endif /* MDL_UPDATE */

#define MDL_DERIVATIVES /* Change to #undef to remove function */

#if defined(MDL_DERIVATIVES)

/* Function: mdlDerivatives ==============================================

* Abstract:

* In this function, you compute the S-function block's derivatives.

* The derivatives are placed in the derivative vector, ssGetdX(S).

*/

static void mdlDerivatives(SimStruct *S)

{

const real_T *u = (const real_T *) ssGetInputPortSignal(S,0);

real_T *dx = ssGetdX(S);

real_T *xC = ssGetContStates(S);

const real_T *y = ssGetOutputPortSignal(S,0);

const real_T *param0 = mxGetPr(PARAM_DEF0(S));

const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));

const real_T *param1 = mxGetPr(PARAM_DEF1(S));

const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S));

const real_T *param2 = mxGetPr(PARAM_DEF2(S));

const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S));

const real_T *param3 = mxGetPr(PARAM_DEF3(S));

const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S));

const real_T *param4 = mxGetPr(PARAM_DEF4(S));

const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S));

const real_T *param5 = mxGetPr(PARAM_DEF5(S));

const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));
DPT_Sfunc_1_C_Derivatives_wrapper(u, y, dx, xC, param0, p_width0, param1, p_width1, param2, p_width2,
param3, p_width3, param4, p_width4, param5, p_width5);

}

#endif /* MDL_DERIVATIVES */
/* Function: mdlTerminate ==================================================

* Abstract:

* No termination needed, but we are required to have this routine.

*/

static void mdlTerminate(SimStruct *S)

{

}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */

#include "simulink.c" /* MEX-file interface mechanism */

#else

#include "cg_sfun.h" /* Code generation registration function */

#endif

Жирным шрифтом в тексте S-функции выделены те строки кода, которые обеспечивают считывание параметров блока S-function, заданных в окне диалога. При инициализации S-функции создается структура с именем S, которая содержит в численном виде все свойства S-функции и из которой, собственно, и происходит извлечение параметров с помощью указанных строк кода. Например, строка const real_T *param0 = mxGetPr(PARAM_DEF0(S)); обеспечивает извлечение первого (из списка в окне параметров блока S-function) параметра, а в строке const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S)); переменной p_width0 присваивается значение размерности этого же параметра (параметры блока S-function могут быть не только скалярами, но и векторами). Отметим также, что такие строки кода имеются в каждом из методов - mdlDerivatives, mdlOutputs и mdlUpdate, благодаря чему параметры блока S-function являются доступными в каждом из методов. Таким образом, пользователю остается добавить выделенные строки в метод mdlInitializeSizes, записать в этом же методе выражения для вычисления нужных констант и обеспечить передачу рассчитанных значений в методы mdlDerivatives, mdlOutputs и mdlUpdate. Удобнее всего это сделать с помощью специально написанной функции. Ниже приводится текст такой функции (Sfun_Get_Parameters.c) для рассматриваемого примера.

Файл Sfun_Get_Parameters.c:

double A00, A01, A10, B00, B11, C00, C11;
void Sfun_Get_Parameters(SimStruct *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));
const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));

const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S));

const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S));

const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S));

const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S));

const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));
double L, R, J, Cm, Cw, Fi;
L=*param0; R=*param1; J=*param2; Cm=*param3; Cw=*param4; Fi=*param5;
A00 = -R/L; A01 = -Cw*Fi/L; A10 = Cm*Fi/J;

B00 = 1/L; B11 = -1/J; C00 = Cm*Fi; C11 = 1;

}

В первой строке файла выполнено объявление переменных A00, A01, A10, B00, B11, C00, C11. Благодаря тому, что это объявление выполнено вне тела функции указанные переменные являются глобальными. Это облегчает реализацию их передачи в нужные методы. Затем в файле функции следует объявление самой функции, и, несколько строк кода, извлекающие параметры и их размерность из структуры S. Далее идет объявление переменных, являющихся параметрами электродвигателя и расчет значений переменных A00, A01, A10, B00, B11, C00, C11.

Таким образом, исходный файл DPT_Sfunc_1_C.c подвергается модернизации в двух местах:

  1. Необходимо вписать строку для подключения файла функции Sfun_Get_Parameters:
    #include "Sfun_Get_Parameters.c" .
    Указанную директиву необходимо записать сразу после всех директив #include и #define.

  2. В конце метода mdlInitializeSizes записать вызов функции Sfun_Get_Parameters:
    Sfun_Get_Parameters(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 the '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)
//=========================NEW CODE==================================

#include "Sfun_Get_Parameters.c"

//=========================NEW CODE==================================
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);
//=========================NEW CODE==================================

Sfun_Get_Parameters(S);

//=========================NEW CODE==================================
}
/* 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));

const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));

const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S));

const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S));

const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S));

const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S));

const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));


DPT_Sfunc_1_C_Outputs_wrapper(u, y, xC, param0, p_width0, param1, p_width1, param2, p_width2,
param3, p_width3, param4, p_width4, param5, p_width5);

}
#undef MDL_UPDATE /* Change to #define to use the function */

#if defined(MDL_UPDATE)

/* Function: mdlUpdate =================================================

* Abstract:

* This function is called once for every major integration time step.

* Discrete states are typically updated here, but this function is useful

* for performing any tasks that should only take place once per

* integration step.

*/

static void mdlUpdate(SimStruct *S, int_T tid)

{

const real_T *u = (const real_T *) ssGetInputPortSignal(S,0);

real_T *xD = ssGetDiscStates(S);

const real_T *y = ssGetOutputPortSignal(S,0);

const real_T *param0 = mxGetPr(PARAM_DEF0(S));

const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));

const real_T *param1 = mxGetPr(PARAM_DEF1(S));

const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S));

const real_T *param2 = mxGetPr(PARAM_DEF2(S));

const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S));

const real_T *param3 = mxGetPr(PARAM_DEF3(S));

const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S));

const real_T *param4 = mxGetPr(PARAM_DEF4(S));

const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S));

const real_T *param5 = mxGetPr(PARAM_DEF5(S));

const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));
DPT_Sfunc_1_C_Update_wrapper(u, y, param0, p_width0, param1, p_width1, param2, p_width2, param3,
p_width3, param4, p_width4, param5, p_width5);
}

#endif /* MDL_UPDATE */

#define MDL_DERIVATIVES /* Change to #undef to remove function */

#if defined(MDL_DERIVATIVES)

/* Function: mdlDerivatives =============================================

* Abstract:

* In this function, you compute the S-function block's derivatives.

* The derivatives are placed in the derivative vector, ssGetdX(S).

*/

static void mdlDerivatives(SimStruct *S)

{

const real_T *u = (const real_T *) ssGetInputPortSignal(S,0);

real_T *dx = ssGetdX(S);

real_T *xC = ssGetContStates(S);

const real_T *y = ssGetOutputPortSignal(S,0);

const real_T *param0 = mxGetPr(PARAM_DEF0(S));

const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));

const real_T *param1 = mxGetPr(PARAM_DEF1(S));

const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S));

const real_T *param2 = mxGetPr(PARAM_DEF2(S));

const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S));

const real_T *param3 = mxGetPr(PARAM_DEF3(S));

const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S));

const real_T *param4 = mxGetPr(PARAM_DEF4(S));

const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S));

const real_T *param5 = mxGetPr(PARAM_DEF5(S));

const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));
DPT_Sfunc_1_C_Derivatives_wrapper(u, y, dx, xC, param0, p_width0, param1, p_width1, param2,
p_width2, param3, p_width3, param4, p_width4, param5, p_width5);

}

#endif /* MDL_DERIVATIVES */
/* Function: mdlTerminate ==================================================

* Abstract:

* No termination needed, but we are required to have this routine.

*/

static void mdlTerminate(SimStruct *S)

{

}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */

#include "simulink.c" /* MEX-file interface mechanism */

#else

#include "cg_sfun.h" /* Code generation registration function */

#endif

Следующим шагом является модернизация файла DPT_Sfunc_1_C_wrapper.c, в котором содержится вычислительный код методов mdlDerivatives, mdlOutputs и mdlUpdate. Для рассматриваемого примера модернизация данного файла сводится к следующим шагам:

  1. Необходимо добавить объявление глобальных переменных:
    1   ...   18   19   20   21   22   23   24   25   26


написать администратору сайта