找回密码
 注册
Simdroid-非首页
查看: 616|回复: 16

[原创] S-Function Builder (MATLAB R2008a)初体验

[复制链接]
发表于 2008-3-30 19:29:02 | 显示全部楼层 |阅读模式 来自 新加坡
前言:

我学习使用matlab已经超过十年了,不过很少使用simulink,记得只是在一次培训课程中以练习的方式学习使用过simulink。但是从来没有用simulink解决过实际的问题。我个人还是习惯于使用matlab脚本语言以编程的方式解决实际问题。

最近在看到论坛上的一些讨论后,突然心血来潮,想学习使用simulink。经过一段摸索后,决定从s-function开始学起。具体来说,从c-mex的s-function来学起。

只是s-function比起mex文件来说,接口稍微复杂一些,如果每次手工编写的话,工作量有点大。经过一段摸索后发现使用matlab提供的s-functino builder可以使得这一过程变得相对容易一些。虽然matlab的在线帮助中已经有了很详细的说明,但是在我学习使用s-function builder的过程中还是遇到了一些困难。现在把我的例子归纳总结以后,希望对初学者有所帮助。


练习目的:
学习编写c-mex形式的s-function。具体来说,在s-function中,通过c-mex方式,实现simulink模型和matlab之间的交互。这个例子将会演示如何在s-function中通过c-mex的方式读取、写入matlab workspace的变量。仿真模型包含三个模块:Sine Wave,s-function builder,以及scope。模型入下图所示。scope上显示的波形将是Sine Wave的输出乘以从matlab workspace获得的变量myval以后的结果。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评分

1

查看全部评分

 楼主| 发表于 2008-3-30 19:31:17 | 显示全部楼层 来自 新加坡
Simdroid开发平台
练习环境:
Windows 2003 Server Std,matlab R2008a,Microsoft Visual Studio 2008。这是我的工作环境,做这个练习并不要求必须在这样的软件环境中操作。


练习步骤:
首先需要配置mex,在matlab的命令行运行:
  1. mex -setup
复制代码
结果如下:
  1. >> mex -setup
  2. Please choose your compiler for building external interface (MEX) files:

  3. Would you like mex to locate installed compilers [y]/n? y

  4. Select a compiler:
  5. [1] Lcc-win32 C 2.4.1 in H:\MACDCF~1\sys\lcc\bin
  6. [2] Microsoft Visual C++ 2008 in H:\Program Files\Microsoft Visual Studio 9.0
  7. [3] Microsoft Visual C++ 2005 in H:\Program Files\Microsoft Visual Studio 8
  8. [4] Microsoft Visual C++ 6.0 in H:\Program Files\Microsoft Visual Studio

  9. [0] None

  10. Compiler: 2

  11. Please verify your choices:

  12. Compiler: Microsoft Visual C++ 2008  
  13. Location: H:\Program Files\Microsoft Visual Studio 9.0

  14. Are these correct [y]/n? y

  15. ***************************************************************************
  16.   Warning: MEX-files generated using Microsoft Visual C++ 2008 require
  17.            that Microsoft Visual Studio 2008 run-time libraries be  
  18.            available on the computer they are run on.
  19.            If you plan to redistribute your MEX-files to other MATLAB
  20.            users, be sure that they have the run-time libraries.
  21. ***************************************************************************

  22. Trying to update options file: H:\Documents and Settings\DWG\Application Data\MathWorks\MATLAB\R2008a\mexopts.bat
  23. From template:              H:\MACDCF~1\bin\win32\mexopts\msvc90opts.bat

  24. Done . . .

  25. **************************************************************************
  26.   Warning: The MATLAB C and Fortran API has changed to support MATLAB
  27.            variables with more than 2^32-1 elements.  In the near future
  28.            you will be required to update your code to utilize the new
  29.            API. You can find more information about this at:
  30.            http://www.mathworks.com/support/solutions/data/1-5C27B9.html?solution=1-5C27B9
  31.            Building with the -largeArrayDims option enables the new API.
  32. **************************************************************************

  33. >>
复制代码
接下来运行simulink,创建仿真模型。具体来说,在matlab命令行环境运行simulink,然后
在看到“Simulink Library Browser”窗口后,创建新的模型:首先在Sources模型库种选择使用Sine Wave作为我们的仿真模型的输入信号;再从User-Defined Function模型库中选择使用S-Function Builder模块,然后在Sinks中选择使用Scope作为波形显示。然后把三个模块连起来,如下图所示:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复 不支持

使用道具 举报

 楼主| 发表于 2008-3-30 19:31:59 | 显示全部楼层 来自 新加坡
鼠标右键点击某个模块,可以改变模块的默写属性,比如字体大小等

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复 不支持

使用道具 举报

 楼主| 发表于 2008-3-30 19:33:07 | 显示全部楼层 来自 新加坡
接下来利用S-Function Builder来创建一个S-Functino。鼠标双击该模块,看见S-Function Builder的窗口入下图所示。由于篇幅和个人水平有限,这里无法一一解释该窗口上所有的内容,下面仅就这个例子所能用到的几个地方加以介绍:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复 不支持

使用道具 举报

 楼主| 发表于 2008-3-30 19:34:09 | 显示全部楼层 来自 新加坡
首先是Libraries标签,在这里我们可以列出所有要用到的外部函数及其声明等。在这个标签上有三个编辑框:
1. Library/Object/Source files (one per line)
2. Include files and extenal function declarations
3. External function declarations:
为方便介绍,我们分别把它们称作Box1,Box2,Box3。

在box1中,我们可以给出所用到的外部函数的源文件名,或者外部库函数等。这个例子中,我们将会创建一个C源文件,在其中通过mexGetVariable/mexPutVariable来和matlab的workspace打交道。假设我们的C源文件名为getmyval.c,它就和模型文件在同一个目录中,所以我们只需简单的把它的文件名填入Box1。getmyval.c的内容如下:
  1. #include <mex.h>

  2. double getMyVal()
  3. {
  4.         mxArray* pMyVal=NULL;
  5.         double* pData;
  6.         double myval;

  7.         pMyVal = mexGetVariable("global", "myval");
  8.         if( pMyVal == NULL )
  9.         {
  10.                 mexPrintf("Failed to get myval from the global workspace.\n");
  11.                
  12.                 pMyVal = mxCreateDoubleMatrix(1,1,mxREAL);
  13.                 mexPutVariable("global", "myval", pMyVal);
  14.         }

  15.         pData = mxGetPr( pMyVal );
  16.         if( pData[0] < 10 )
  17.         {
  18.                 myval = 10.0;
  19.         }
  20.         else
  21.         {
  22.                 myval = pData[0];
  23.         }

  24.         return myval;
  25. }
复制代码
这段代码的功能汉简单,它首先从matlab的global workspace尝试获得变量myval,如果没有找到该变量,则先创建一个。然后根据myval的数值判断,如果该数值小于10,则返回10,如果该数值大于10,则返回该数值。我们将在下面的步骤中调用这个函数,以获得scaler值。

在Box2中我们可以填写必须的头文件包含语句。这里关于math.h的内容是系统缺省给的。这个例子没有另外需要包含的头文件。

然后在Box3中,我们给出需要调用的外部函数的声明,在这个例子中,我们需要调用mygetval.c中的getMyVal()函数,所以,在Box3中如图所示填写。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复 不支持

使用道具 举报

 楼主| 发表于 2008-3-30 19:34:47 | 显示全部楼层 来自 新加坡
接下来我们需要填写S-Function Builder窗口上的Outputs标签,这是重要的一步,在这里,我们定义输出函数。在这个例子中其功能很简单,我们需要调用getMyVal()函数获得增益,然后使得输出等于输入乘以增益。所以填写内容如下:
  1. double myval = getMyVal();
  2. y0[0] = myval * u0[0];
复制代码
如图所示,其中注释的部分是系统缺省的提示。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复 不支持

使用道具 举报

 楼主| 发表于 2008-3-30 19:36:21 | 显示全部楼层 来自 新加坡
最后,不要忘记给出S-function name。在这个例子中,我用mysfunc01。

至此,我们已经完成来对S-Function Builder的配置,可以编译S-Function了,鼠标点击S-Function Builder窗口上的Build按钮。

如果编译没有问题,我们就可以运行这个模型。Scope上会有如下的显示。大功告成!

附:刚开始学习simulink。由于时间、水平有限,有些地方的介绍可能过于简单。希望大家指正。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复 不支持

使用道具 举报

发表于 2008-3-30 19:54:31 | 显示全部楼层 来自 湖北武汉
感谢Taohe兄
一批对技术不断追求的MATLAB Fans的活跃存在是本版的精神支柱。
虽为仿真论坛,但版面上Simulink的氛围并不浓厚,希望有兴趣研究的版友活跃参与
讨论,众人拾柴火焰高。
随着MATLAB新版本的推出,希望有更多的版友就新版本的某一方面展开讨论。
回复 不支持

使用道具 举报

发表于 2008-3-31 03:04:05 | 显示全部楼层 来自 新疆乌鲁木齐
看了taohe兄的配置,感觉你真是狂人,一台电脑上装了三个VS版本,很好很强大...
S-Function Builder不是新东西,我孤陋寡闻了一把,抱歉。
关于C语言编写的S-Function貌似比在MATLAB环境下的S-Function复杂得多啊,在不同的模型中会出现很多种错误,希望大家都总结总结,按taohe兄和shunfly兄的话:“一起simulink”。
回复 不支持

使用道具 举报

发表于 2008-3-31 03:09:15 | 显示全部楼层 来自 新疆乌鲁木齐

转贴一篇S-Function的文章

S-Function
S-Function,在library里面有很多模板,有C,C++,M,Ada,Fortran的版本,
其实都大同小异,只要了解几个函数就很容易使用了,当然初学者也可以用S-Function Builder
来构建。
当然了解了代码后,那个Builder生成的代码就更容易懂了。
下面咱们以一个例子开始把
任务:
构建一个C的S-Function。
2个input,2个output,2个parameter
input都为3*1向量,output也是3*1向量。
从S-function模块中选择C-file examples里面的Basic C-MEX template。
打开它,另存为我们的模块名字就ok了。
我们存为test.c把

下面我们来分析代码:
1.
  1. #define S_FUNCTION_NAME   sfuntmpl_basic
  2. #define S_FUNCTION_LEVEL 2
  3. #define INPUT_NUM 2
  4. #define OUTPUT_NUM 2
复制代码
这儿我们需要修改下文件名了。把sfuntmpl_basic 改为 test
2.
  1. #include "simstruc.h"
复制代码
此处引用头文件,当我们需要其他头文件,例如math.h,stdio.h等,看你需要啥函数了。

3.
  1. static void mdlInitializeSizes(SimStruct *S)
复制代码
这个函数我们用来设置输入,输入,和参数的。
参数就是,我们点击模块时候,那个对话框里面需要设置的。参数之间空格隔开
4.
  1. ssSetNumSFcnParams(S, PARA_NUM);   /* Number of expected parameters */
  2. if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
  3.        /* Return if number of expected != number of actual parameters */
  4.        return;
  5. }
复制代码
PARA_NUM 就是你自己需要设置的参数个数
5.
  1. ssSetNumContStates(S, 0);  
  2. ssSetNumDiscStates(S, 0);
复制代码
设置连续状态和离散状态个数。缺省都为0
6.
  1. if (!ssSetNumInputPorts(S, INPUT_NUM)) return;
  2. ssSetInputPortWidth(S, 0,3);   //设置端口的维数,现在为3*1
  3. ssSetInputPortRequiredContiguous(S, 0, true); /*direct input signal access*/
  4. ssSetInputPortWidth(S, 1,3);   //设置端口的维数,现在为3*1
  5. ssSetInputPortRequiredContiguous(S, 1, true); /*direct input signal access*/
  6. ssSetInputPortDirectFeedThrough(S, 0, 1);
  7. ssSetInputPortDirectFeedThrough(S, 1, 1);
复制代码
INPUT_NUM就是输入端口的个数,分别设置每个端口的维数,注意端口号从0开始的。
ssSetInputPortRequiredContiguous是设置input的访问方式,true就是临近访问,这样指针的增量后
就可以直接访问下个input端口了。
ssSetInputPortDirectFeedThrough设置输入端口的信号是否mdlOutputs函数中使用,这儿设置为true。

7.
  1. if (!ssSetNumOutputPorts(S, OUTPUT_NUM)) return;
  2. ssSetOutputPortWidth(S, 0, 3);
  3. ssSetOutputPortWidth(S, 1, 3);
复制代码
同样设置2个输出端口,以及维数
8.
  1. ssSetNumSampleTimes(S, 1);
  2. ssSetNumRWork(S, 0);
  3. ssSetNumIWork(S, 0);
  4. ssSetNumPWork(S, 0);
  5. ssSetNumModes(S, 0);
  6. ssSetNumNonsampledZCs(S, 0);
复制代码
设置采样时间,此处为1s。
ssSetNumRWork,设置浮点向量的大小,0表示继承信号大小,DYNAMICALLY_SIZED表示可用
mdlSetWorkWidths来自己设置。
下面的函数依次是设置整型,指针,模式向量的大小。模式向量是专用模块的编写的。
ssSetNumNonsampledZCs设置采样点之间的zero crossing的模块的状态个数
9.
mdlInitializeSizes函数搞定。
其他
mdlInitializeSampleTimes
mdlInitializeConditions
mdlStart
我们暂时不管了,一些初始化的东西,大家可以放在这里。
我们直接奔
mdlOutputs函数把。

10.
在这个函数里面,我们执行我们的复杂逻辑关系,和我们的代码了。
首先,我们得到我们参数,输入,输出的指针把。这样我们才能操作。
  1. real_T *para1 = mxGetPr(ssGetSFcnParam(S,0));
  2.     real_T *para2 = mxGetPr(ssGetSFcnParam(S,1));
  3. const real_T *u1 = (const real_T*) ssGetInputPortSignal(S,0);
  4. const real_T *u2 = (const real_T*) ssGetInputPortSignal(S,1);

  5. real_T    *y1 = ssGetOutputPortSignal(S,0);
  6. real_T    *y2 = ssGetOutputPortSignal(S,1);
复制代码
下面我们简单把输入乘上参数1或参数2,然后赋值给输出。
  1. y1[0] = para1[0]*u1[0];
  2. y1[1] = para1[0]*u1[1];
  3. y1[2] = para1[0]*u1[2];
  4. y2[0]=para2[0]*u2[0];
  5. y2[1]=para2[0]*u2[1];
  6. y2[2]=para2[0]*u2[2];
复制代码
注意,参数是指针,所以要那么引用它。ok那么在matlab得command window里面用语句“mex test.c”编译把

11.
mdlUpdate
mdlDerivatives
这几个函数以后再探讨了
mdlTerminate
这个函数必须提下,当你在s-funtion里面定义全局变量后,一定要在这里赋值为0,或者其他值,
不然在下次仿真时候,全局变量还是上次仿真的值哦。

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2008-3-31 03:10:27 | 显示全部楼层 来自 新疆乌鲁木齐

CSDN还有一篇比较详细的介绍

http://blog.csdn.net/complexadap ... 6/07/14/919938.aspx
不过是翻译Mathworks的帮助:victory:
回复 不支持

使用道具 举报

 楼主| 发表于 2008-3-31 21:37:18 | 显示全部楼层 来自 新加坡
原帖由 bainhome 于 2008-3-31 03:04 发表
看了taohe兄的配置,感觉你真是狂人,一台电脑上装了三个VS版本,很好很强大...
S-Function Builder不是新东西,我孤陋寡闻了一把,抱歉。
关于C语言编写的S-Function貌似比在MATLAB环境下的S-Function复杂得多啊, ...


那都是因为无聊,或者手痒才安装的,这样作的结果就是硬盘空间吃紧。

至于使用,我觉得vc6用起来很顺手,不过新版编译器对标准支持很好,忍不住就都装了。

关于用c语言编写s-function,就像你上面的转帖讲的,过程比较复杂,而且容易出错。如果使用S-Function Builder,可以使我们不必担心接口编写,于是我们可以专心于具体的算法上面,这很符合实际的使用情况,因为在实际使用中,我们几乎不用担心那个接口是怎样编写、实现的,只要我们能得到一个可用的S-Function,就好了。而我们最关心的就是正在编写的模块的具体算法,比如我的例子中的getMyVal()(当然实际例子可能要复杂的多)。

不过,那片转帖是个好东东,我觉得应该收藏起来多琢磨琢磨。谢谢转帖。
回复 不支持

使用道具 举报

发表于 2008-4-1 13:54:16 | 显示全部楼层 来自 河北廊坊
我的配置还停留在XP,matlab7.1, VC6,呵呵.
S-Function Builder 没有用过,当时会用了才发现有这个模块,已经没必要再用它了.
C S-function是matlab与硬件连接的一个基础,可以利用C语言实现硬件所支持的一切功能.而Simulink是仿真或半实物仿真的基本工具,是matlab在硬件在回路仿真最核心的内容.其基本结构是,simulink模块搭建动力学,stateflow(或C sfunction)编写控制算法(可通过代码生成下载到目标机) , C sfunction编写接口通信程序.
matlab在汽车,航空航天等方面商业应用也是围绕simulink展开的.
忽然间有感而发,让行家见笑了.

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2010-7-12 01:19:27 | 显示全部楼层 来自 上海
牛人到处有啊,好好学习LZ

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2013-2-22 21:09:51 | 显示全部楼层 来自 甘肃
感谢Taohe版主,
论坛有一批对技术不断追求的高手

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2013-5-3 14:48:44 | 显示全部楼层 来自 江苏南京
谢谢分享           学习了啊

评分

1

查看全部评分

回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-4-24 15:59 , Processed in 0.049666 second(s), 15 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表