S-Function是系統函式(System Function)的簡稱,可以十分方便地用來描述各種動態系統,尤其是複雜的動態系統,屬於Simulink動態系統的核心。我們常用的Simulink工具箱都是透過S-Function實現的,如果想開發一個新的模組或工具箱,S-Function可能是最好的選擇。
今天,將分兩部分內容來介紹S-Function。
1)S-Function簡介
:簡要介紹S-Function的關鍵資訊,理解S-Function的工作過程。
2)電機模型的S-Function實現
:以直流電機這一物理物件作為代表,透過S-Function實現電機的動態過程設計。
之前寫過一篇文章《Simulink中4種電機建模方式》,有朋友留言比較完美但缺少S-Function,今天藉著這個機會一併補上。
1、S-Function簡介
學習S-Function的最佳方式是先熟悉Matlab自帶的模板sfuntmpl。m,一般在以下路徑:C:\Program Files\MATLAB\toolbox\simulink\blocks。
一共40多行程式碼,主要包括1個主函式和6個子函式,模板程式碼如下:
function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)switch flag, case 0, [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes; case 1, sys=mdlDerivatives(t,x,u); case 2, sys=mdlUpdate(t,x,u); case 3, sys=mdlOutputs(t,x,u); case 4, sys=mdlGetTimeOfNextVarHit(t,x,u); case 9, sys=mdlTerminate(t,x,u); otherwise DAStudio。error(‘Simulink:blocks:unhandledFlag’, num2str(flag));endfunction [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizessizes = simsizes;sizes。NumContStates = 0;sizes。NumDiscStates = 0;sizes。NumOutputs = 0;sizes。NumInputs = 0;sizes。DirFeedthrough = 1;sizes。NumSampleTimes = 1; sys = simsizes(sizes);x0 = [];str = [];ts = [0 0];simStateCompliance = ‘UnknownSimState’;function sys=mdlDerivatives(t,x,u)sys = [];function sys= mdlUpdate (t,x,u)sys = [];function sys=mdlOutputs(t,x,u)sys = [];function sys=mdlGetTimeOfNextVarHit(t,x,u)sampleTime = 1; sys = t + sampleTime;function sys=mdlTerminate(t,x,u)sys = [];
主函式:
透過flag來選擇執行對應的子函式。
mdlInitializeSizes:
定義系統的初始條件、取樣時間等。
mdlDerivatives:
計算連續狀態的微分,即dx/dt。
mdlUpdate:
計算離散狀態x(K+1)。
mdlOutputs:
計算輸出y。
mdlGetTimeOfNextVarHit:
計算離散狀態的下一次取樣時間。
mdlTerminate:
結束函式。
需要注意的是,對於特定的系統可能僅需要排程部分子函式即可完成系統的設計。例如,對於僅存在連續狀態的系統,只需要排程mdlInitializeSizes、mdlDerivatives、mdlOutputs、mdlTerminate等4個子函式。這些都是S-Function透過flag去自動實現的。
2、電機模型的S-Function實現
在介紹以前,先回顧一下前面介紹的狀態空間搭建電機模型的方法。
選取電流I、轉速w作為狀態變數,轉速w作為輸出,直流電機的狀態方程和輸出方程可表達為:
式中紅色部分分別對應系統矩陣A、b、C。使用State-Space模組,完成以上的狀態方程搭建,模型如下圖。
使用S-Function搭建電機模型時,會借用到上面的引數A、b、C。具體搭建步驟如下:
1)把模板sfuntmpl。m改為motor。m,並新建一個空的mdl檔案,也可以命名為motor。mdl。
兩個檔案放在一起並置於當前目錄下,不然m檔案後面無法被mdl檔案引用。
2)在工具箱中找到S-Function模組,並拖入模型中。
雙擊開啟,將S-Function name設定為motor,S-Function parameter設定為A、b、C。
3)點選Edit,即可開啟motor。m檔案,進行電機模型設計,修改部分程式碼,如下面註釋。
function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag,A,b,C) %%增加參變數switch flag, case 0, [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes; case 1, sys=mdlDerivatives(t,x,u,A,b); %%增加參變數 case 2, sys=mdlUpdate(t,x,u); case 3, sys=mdlOutputs(t,x,u,C); %%增加參變數 case 4, sys=mdlGetTimeOfNextVarHit(t,x,u); case 9, sys=mdlTerminate(t,x,u); otherwise DAStudio。error(‘Simulink:blocks:unhandledFlag’, num2str(flag));endfunction [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizessizes = simsizes;sizes。NumContStates = 2; %%2個狀態變數sizes。NumDiscStates = 0;sizes。NumOutputs = 1; %%單輸入sizes。NumInputs = 1; %%單輸出sizes。DirFeedthrough = 1;sizes。NumSampleTimes = 1; sys = simsizes(sizes);x0 = [0 0]; %%初始狀態為0str = [];ts = [0 0];simStateCompliance = ‘UnknownSimState’;function sys=mdlDerivatives(t,x,u,A,b) %%增加參變數sys = A*x + b*u; %%計算狀態變數的導數function sys=mdlUpdate(t,x,u)sys = [];function sys=mdlOutputs(t,x,u,C) %%增加參變數sys = C*x; %%計算輸出function sys=mdlGetTimeOfNextVarHit(t,x,u)sampleTime = 1; sys = t + sampleTime;function sys=mdlTerminate(t,x,u)sys = [];
4)在mdl模型中新增對應的輸入,並與狀態空間的建模方式對比,如下圖。
模擬結果如下圖所示,可以看出,兩種方法的電機轉速曲線完全一致,S-Function的電機建模正確。
以上,以電機模型為例,介紹了利用S-Function的方式來描述系統動態過程的方法。