simulink之S函数
s函數是system Function的簡稱,用它來寫自己的simulink模塊。(夠簡單吧,^_^,詳細的概念介紹大伙看幫助吧)可以用matlab、C、C++、Fortran、Ada等語言來寫,這兒我只介紹怎樣用matlab語言來寫吧(主要是它比較簡單)
????先講講為什么要用s函數,我覺得用s函數可以利用matlab的豐富資源,而不僅僅局限于simulink提供的模塊,而用c或c++等語言寫的s函數還可以實現對硬件端口的操作,還可以操作windows API等的
?????先介紹一下simulink的仿真過程(以便理解s函數),simulink的仿真有兩個階段:一個為初始化,這個階段主要是設置一些參數,像系統的輸入輸出個數、狀態初值、采樣時間等;第二個階段就是運行階段,這個階段里要進行計算輸出、更新離散狀態、計算連續狀態等等,這個階段需要反復運行,直至結束。
?????在matlab的workspace里打edit sfuntmpl(這是matlab自己提供的s函數模板),我們看它來具體分析s函數的結構。?它的第一行是這樣的:function [sys,x0,str,ts]=sfuntmpl(t,x,u,flag)
先講輸入與輸出變量的含義:t是采樣時間,x是狀態變量,u是輸入(是做成simulink模塊的輸入),flag是仿真過程中的狀態標志(以它來判斷當前是初始化還是運行等);sys輸出根據flag的不同而不同(下面將結合flag來講sys的含義),x0是狀態變量的初始值,str是保留參數(mathworks公司還沒想好該怎么用它,嘻嘻,一般在初始化中將它置空就可以了,str=[]),ts是一個1×2的向量,ts(1)是采樣周期,ts(2)是偏移量。
下面結合sfuntmpl.m中的代碼來講具體的結構:
switch flag,??????????????????%判斷flag,看當前處于哪個狀態
case 0,
????[sys,x0,str,ts]=mdlInitializeSizes;
flag=0表示處于初始化狀態,此時用函數mdlInitializeSizes進行初始化,此函數在?sfuntmpl.m的149行
我們找到他,在初始化狀態下,sys是一個結構體,用它來設置模塊的一些參數,各個參數詳細說明如下
????size = simsizes;%用于設置模塊參數的結構體用simsizes來生成
????sizes.NumContStates = 0;%模塊連續狀態變量的個數
????sizes.NumDiscStates = 0;%模塊離散狀態變量的個數
????sizes.NumOutputs?????= 0;%模塊輸出變量的個數
????sizes.NumInputs??????= 0;%模塊輸入變量的個數
????sizes.DirFeedthrough = 1;%模塊是否存在直接貫通(直接貫通我的理解是輸入能?%直接控制輸出)
????sizes.NumSampleTimes = 1;%模塊的采樣時間個數,至少是一個
????sys = simsizes(sizes);???%設置完后賦給sys輸出
舉個例子,考慮如下模型:
???????????????dx/dt=fc(t,x,u)?也可以用連續狀態方程描述:dx/dt=A*x+B*u
???????????????x(k+1)=fd(t,x,u)?也可以用離散狀態方程描述:x(k+1)=H*x(k)+G*u(k)
???????????????y=fo(t,x,u)?也可以用輸出狀態方程描述:y=C*x+D*u
設上述模型連續狀態變量、離散狀態變量、輸入變量、輸出變量均為1個,我們就只需改上面那一段代碼為:
(一般連續狀態與離散狀態不會一塊用,我這兒是為了方便說明)
sizes.NumContStates=1;sizes.NumDiscStates=1;sizes.NumOutputs=1;sizes.NumInpu
ts=1;
其他的可以不變。繼續在mdlInitializeSizes函數中往下看:
?????x0 = [];????%狀態變量設置為空,表示沒有狀態變量,以我們上面的假設,可改?%為x0=[0,0](離散和連續的狀態變量我們都設它初值為0)
?????str = [];????%這個就不用說了,保留參數嘛,置[]就可以了,反正沒什么用,可?%能7.0會給它一些意義
?????ts = [0 0]; %采樣周期設為0表示是連續系統,如果是離散系統在下面的mdlGet %TimeOfNextVarHit函數中具體介紹
嘻嘻,總算講完了初始化,后面的應該快了
在sfuntmpl的106行繼續往下看:
????case 1,
??????sys=mdlDerivatives(t,x,u);
flag=1表示此時要計算連續狀態的微分,即上面提到的dx/dt=fc(t,x,u)中的dx/dt,找到?mdlDerivatives函數(在193行)如果設置連續狀態變量個數為0,此處只需sys=[];?就可以了(如sfuntmpl中一樣),按我們上述討論的那個模型,此處改成?sys=fc(t,x(1),u)或sys=A*x(1)+B*u %我們這兒x(1)是連續狀態變量,而x(2)是離散的,這兒只用到連續的,此時的輸出sys就是微分
繼續,在sfuntmpl的112行:
???case 2,
???????sys=mdlUpdate(t,x,u);
flag=2表示此時要計算下一個離散狀態,即上面提到的x(k+1)=fd(t,x,u),找到mdlUpd ate函數(在206行)它這兒sys=[];表示沒有離散狀態,我們這而可以改成?sys=fd(t,x(2),u)或sys=H*x(2)+G*u;%sys即為x(k+1)
看來后面幾個一兩句話就可了,呵呵,在sfuntmpl的118行
????case 3,
???????sys=mdlOutputs(t,x,u);
flag=3表示此時要計算輸出,即y=fo(t,x,u),找到mdlOutputs函數(在218行),如上,如果sys=[]表示沒有輸出,我們改成sys=fo(t,x,u)或sys=C*x+D*u %sys此時為輸出y
好像快完了,嘻嘻,在sfuntmpl的124行
????case 4,
????????sys=mdlGetTimeOfNextVarHit(t,x,u);
flag=4表示此時要計算下一次采樣的時間,只在離散采樣系統中有用(即上文的mdlInit ializeSizes中提到的ts設置ts(1)不為0)
連續系統中只需在mdlGetTimeOfNextVarHit函數中寫上sys=[];這個函數主要用于變步長的設置,具體實現大家可以用edit vsfunc看vsfunc.m這個例子
最后一個,在sfuntmpl的130行
????case 9,
???????sys=mdlTerminate(t,x,u);
flag=9表示此時系統要結束,一般來說寫上在mdlTerminate函數中寫上sys=[]就可,如果你在結束時還要設置什么,就在此函數中寫
關于sfuntmpl這個s函數的模板講完了。
s函數還可以帶用戶參數,下面給個例子,和simulink下的gain模塊功能一樣。
function [sys,x0,str,ts] = sfungain(t,x,u,flag,gain)
switch flag,
case 0,
??????sizes = simsizes;
??????sizes.NumContStates = 0;
??????sizes.NumDiscStates = 0;
??????sizes.NumOutputs?????= 1;
??????sizes.NumInputs??????= 1;
??????sizes.DirFeedthrough = 1;
??????sizes.NumSampleTimes = 1;
??????sys = simsizes(sizes);
??????x0=[];
??????str=[];
??????ts=[0,0];
case 3,
??????sys=gain*u;
case {1,2,4,9},
????sys = [];
end
SIMULINK s-function的設計
Simulink為用戶提供了許多內置的基本庫模塊,通過這些模塊進行連接而構成系統的模型。對于那些經常使用的模塊進行組合并封裝可以構建出重復使用的新模塊,但它依然是基于Simulink原來提供的內置模塊。
而Simulink s-function是一種強大的對模塊庫進行擴展的新工具。
(一)、s-function的概念
s-function是一個動態系統的計算機語言描述,在MATLAB里,用戶可以選擇用m文件編寫,也可以用c或mex文件編寫,在這里只給大家介紹如何用m文件編寫s-function。
S-function提供了擴展Simulink模塊庫的有力工具,它采用一種特定的調用語法,使函數和Simulink解法器進行交互。
S-function最廣泛的用途是定制用戶自己的Simulink模塊。它的形式十分通用,能夠支持連續系統、離散系統和混合系統。
(二)、建立m文件s-function
1、使用模板文件:sfuntmp1. m?格式:?[sys,x0]=function(t,x,u,flag)
該模板文件位于MATLAB根目錄下toolbox/simulink/blocks目錄下。
模板文件里s-function的結構十分簡單,它只為不同的flag的值指定要相應調用的m文件子函數。比如當flag=3時,即模塊處于計算輸出這個仿真階段時,相應調用的子函數為sys=mdloutputs(t,x,u)。
模板文件使用switch語句來完成這種指定,當然這種結構并不唯一,用戶也可以使用if語句來完成同樣的功能。而且在實際運用時,可以根據實際需要來去掉某些值,因為并不是每個模塊都需要經過所有的子函數調用。
模板文件只是Simulink為方便用戶而提供的一種參考格式,并不是編寫s-function的語法要求,用戶完全可以改變子函數的名稱,或者直接把代碼寫在主函數里,但使用模板文件的好處是,比較方便,而且條理清晰。
使用模板編寫s-function,用戶只需把s-函數名換成期望的函數名稱,如果需要額外的輸入參量,還需在輸入參數列表的后面增加這些參數,因為前面的4個參數是simulink調用s-function時自動傳入的。對于輸出參數,最好不做修改。接下去的工作就是根據所編s-function要完成的任務,用相應的代碼去替代模板里各個子函數的代碼即可。
Simulink在每個仿真階段都會對s-function進行調用,在調用時,Simulink會根據所處的仿真階段為flag傳入不同的值,而且還會為sys這個返回參數指定不同的角色,也就是說盡管是相同的sys變量,但在不同的仿真階段其意義卻不相同,這種變化由simulink自動完成。
m文件s-function可用的子函數說明如下:
mdlInitializeSizes(flag=0):定義s-function模塊的基本特性,包括采樣時間、連續或者離散狀態的初始條件和sizes數組。
mdlDerivatives(flag=1):計算連續狀態變量的微分方程。
mdlUpdate(flag=2):更新離散狀態、采樣時間和主時間步的要求。
mdlOutputs(flag=3):計算s-function的輸出。
mdlGetTimeOfNextVarHit(flag=4):計算下一個采樣點的絕對時間,這個方法僅僅是在用戶在mdlInitializeSizes?里說明了一個可變的離散采樣時間。
概括說來,建立s-function可以分成兩個分離的任務:
初始化模塊特性包括輸入輸出信號的寬度,離散連續狀態的初始條件和采樣時間。
將算法放到合適的s-function子函數中去。
2、定義s-function的初始信息
為了讓Simulink識別出一個m文件s-function,用戶必須在s-函數里提供有關s-函數的說明信息,包括采樣時間、連續或者離散狀態個數等初始條件。這一部分主要是在mdlInitializeSizes子函數里完成。
Sizes數組是s-function函數信息的載體,它內部的字段意義為:
NumContStates(sys(1)):連續狀態的個數(狀態向量連續部分的寬度)
NumDiscStates(sys(2)):離散狀態的個數(狀態向量離散部分的寬度)
NumOutputs(sys(3)):?輸出變量的個數(輸出向量的寬度)
NumInputs(sys(4)):輸入變量的個數(輸入向量的寬度)
DirFeedthrough(sys(5)):有不連續根的數量
NumSampleTimes(sys(6)):采樣時間的個數,有無代數循環標志
如果字段代表的向量寬度為動態可變,則可以將它們賦值為-1。
注意DirFeedthrough是一個布爾變量,它的取值只有0和1兩種,0表示沒有直接饋入,此時用戶在編寫mdlOutputs子函數時就要確保子函數的代碼里不出現輸入變量u;1表示有直接饋入。
NumSampleTimes表示采樣時間的個數,也就是ts變量的行數,與用戶對ts的定義有關。
需要指出的是,由于s-function會忽略端口,所以當有多個輸入變量或多個輸出變量時,必須用mux模塊或demux模塊將多個單一輸入合成一個復合輸入向量或將一個復合輸出向量分解為多個單一輸出。
3、輸入和輸出參量說明
S-function默認的4個輸入參數為t、x、u和flag,它們的次序不能變動,代表的意義分別為:
t:代表當前的仿真時間,這個輸入參數通常用于決定下一個采樣時刻,或者在多采樣速率系統中,用來區分不同的采樣時刻點,并據此進行不同的處理。
x:表示狀態向量,這個參數是必須的,甚至在系統中不存在狀態時也是如此。它具有很靈活的運用。
u:表示輸入向量。
flag:是一個控制在每一個仿真階段調用哪一個子函數的參數,由Simulink在調用時自動取值。
S-function默認的4個返回參數為sys、x0、它們的次序不能變動,代表的意義分別為:
sys:是一個通用的返回參數,它所返回值的意義取決于flag的值。
x0:是初始的狀態值(沒有狀態時是一個空矩陣[]),這個返回參數只在flag值為0時才有效,其他時候都會被忽略。
一、有一系統如下:
dx1=x2
dx2=9.81*sin(x(1))-2*x(2)+u
求出系統在單位階躍輸入下的x1的狀態變化曲線,假設x1,x2初值為0。
function [sys,x0]=dong(t,x,u,flag)
if flag==0
????sys=[2;0;2;1;0;0];
????x0=[0;0];
elseif flag==1
????sys=[x(2);9.81*sin(x(1))-2*x(2)+u];
elseif flag==3
????sys=[x(1);x(2)];
else
????sys=[];
end
原文鏈接:http://blog.sina.com.cn/s/blog_4fa8810401012uq9.html
總結
以上是生活随笔為你收集整理的simulink之S函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [学习笔记]状压dp
- 下一篇: 算法61---两个字符串的最小ASCII