在simulink環境下實現即時模擬
來源:互聯網
上載者:User
眾所周知,基於simulink的模擬屬於偽即時模擬,其模擬時間並不與實際時間同步,而與機器執行速度和模型複雜度有關。那麼怎樣實現simulink環境下的即時模擬呢。Matlab提供一個即時工作環境(RTW)用於將simulink模型轉化成C程式,在外部模式下這個C程式是可以和simulink進行資料交換的。如果在C程式中加入時鐘中斷,就可實現simulink下的即時模擬。下面談談這種方法的具體實現步驟。第一步、建立模型,這個模型要包含訊號顯示的模組(scope等);第二步、設定模型參數。
1.求解器參數設定
Solver->Solver options->Type=Fixed-step(必須) 模擬演算法為ode5 Fixed step size設定為任意值(0~1)
2.即時工作空間參數設定
當Category為Target configuration時,單擊Browse選擇產生代碼的類型,這裡我們選擇通用即時malloc代碼格式--grt_malloc.tlc,同時修改模板聯編檔案(Template makefile)為:grt_malloc_vc.tmf,其他預設。將Category切換至GRT code generation options,選擇External mode複選框,使產生的代碼支援外部模式。第三步、修改grt_main.c檔案,在其中加入時鐘中斷代碼。
grt_malloc_main.c是通用即時malloc c程式的main函數實現檔案,RTW在代碼產生過程將自動將其與模型代碼編譯連結成可執行檔。grt_malloc_main.c位於<matlabroot>\rtw\c\grt_malloc目錄下。關於時鐘中斷代碼的添加問題,參看下面關於"添加時間中斷代碼"的介紹。第四步、產生代碼。
儲存好參數設定後單擊Build按鈕或者單擊工具列的Build All表徵圖產生代碼。第五步、運行模擬程式,查看模擬結果。
首先在命令提示字元下運行模擬程式,命令為 mdlname -tf -inf -w
mdlname為第一步建立的模型,參數-tf指定模擬時間,inf表示無限執行,具體時間可任意指定(單位為S);參數-w表示等待simulink啟動模擬的命令.然後將simulink切換至外部模式(External,預設為Normal),這時可以看到工具列的表徵圖發生了一點變化,單擊Connect to real-time target表徵圖與即時模擬程式建立連結,連結建立好之後,單擊start the real-time code啟動即時模擬程式。這時mdlname.exe接收到simulink啟動模擬的命令,開始執行模型代碼,直至接收到simulink停止模擬的命令或者指定的模擬時間。模擬期間,從模型的訊號顯示模組中看到動態即時模擬結果.通過External Mode Control Panel 還可實現線上參數調整等功能. 添加時間中斷代碼
windows提供四種定時的方法:計時器、多媒體定時器、高精度運行計數器、虛擬設備驅動直接管理的系統時鐘。計時器的解析度不高,不能滿足稍高採樣頻率的要求;虛擬設備驅動直接管理的系統時鐘需編寫虛擬設備驅動,編程複雜,實現起來不易。下面給出用多媒體定時器和高精度計數器實現時間中斷代碼。grt_malloc_main.c 1.使用多媒體定時器//多媒體定時器的回呼函數--以固定的頻率推進模擬
void CALLBACK DoSimulation(UINT uID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2){
rt_OneStep(S);
}在main函數中添加時間中斷代碼int_T main(int_T argc, const char_T *argv[])
{
UINT wTimerRes=TIMER_ACCURACY; //定義時間間隔,
UINT wAccuracy; //定義解析度,可模數型的模擬步長
UINT TimerID; //定義定時器控制代碼 TIMECAPS tc; ............
............ //下面這段代碼加在模型初始化代碼後,即InitializeModel(S,finaltime)後
if(timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR_NOERROR)
{
wAccuracy=min(max(tc.wPeriodMin,TIMER_ACCURACY),tc.wPeriodMax);
timeBeginPeriod(wAccuracy); //設定定時器解析度
}
if((TimerID=timeSetEvent(wTimerRes,wAccuracy,(LPTIMECALLBACK)DoSimulation,0,TIME_PERIODIC))==0)
{
exit(0);
}
.............
............
}在檔案開始先定義TIMER_ACCURACY
#define TIMER_ACCURACY 100 //100ms 2.使用高精度運行計數器(high resolution performance counter)int_T main(int_T argc, const char_T *argv[])
{
LARGE_INTEGER Frequency,LastCount,CurrentCount; ...........
...........
//下面的代碼添加到執行模型(Execute the model)代碼相應的部位
if(!QueryPerformanceFrequency(&Frequency)) //擷取系統高精度運行計數器的頻率
{
exit(EXIT_FAILURE);
} QueryPerformanceCounter(&LastCount); //查詢高精度運行計數器的計數值,並將結果儲存在LastCount中 while (!GBLbuf.stopExecutionFlag &&
(rtmGetTFinal(S) == RUN_FOREVER ||
rtmGetTFinal(S)-rtmGetT(S) > rtmGetT(S)*DBL_EPSILON))
{ rtExtModePauseIfNeeded(rtmGetRTWExtModeInfo(S),
(boolean_T *)&rtmGetStopRequested(S)); if (rtmGetStopRequested(S)) break; do
{
QueryPerformanceCounter(&CurrentCount); //查詢當前高精度運行計數器的計數值
}while((CurrentCount.QuadPart-LastCount.QuadPart)/Frequency.QuadPart<0.1); //0.1為模擬步長
rt_OneStep(S);
QueryPerformanceCounter(&LastCount);
}
..........
}
注意:
1.無論是多媒體定時器還是高精度運行計數器,都使用了windowsAPI所以要在grt_malloc_main.c中include <windows.h>;
2.使用多媒體定時器需要winmm.lib的支援,所以需將winmm.lib添加到編譯連結的LIBS路徑中.具體做法是:
將(VC_ROOT)\lib目錄下的winmm.lib拷貝到(MATLAB_ROOT)\rtw\c\lib\win32目錄下,然後對(MATLAB_ROOT)\rtw\c\grt_malloc目錄下的grt_malloc_vc.tmf進行修改,將(MATLAB_ROOT)\rtw\c\lib\win32\winmm.lib添加到LIBS中.修改之後的Additional Libraries下的內容如下所示:
LIBS =
|>START_PRECOMP_LIBRARIES<|
!if "$(OPT_OPTS)" == "$(DEFAULT_OPT_OPTS)"
LIBS = $(LIBS) |>EXPAND_LIBRARY_LOCATION<|\|>EXPAND_LIBRARY_NAME<|_vc.lib
$(MATLAB_ROOT)\rtw\c\lib\win32\winmm.lib
!else
LIBS = $(LIBS) |>EXPAND_LIBRARY_NAME<|.lib
$(MATLAB_ROOT)\rtw\c\lib\win32\winmm.lib
!endif |>END_PRECOMP_LIBRARIES<|
|>START_EXPAND_LIBRARIES<|
LIBS = $(LIBS) |>EXPAND_LIBRARY_NAME<|.lib |>END_EXPAND_LIBRARIES<|
3.使用高精度運行計數器時,建立一個線程執行模擬任務,將會發生錯誤.使用多媒體定時器則沒有這個,雖然其回呼函數也是在一個新的線程中執行.
4.模擬步長(step size)可由rtmGetStepSize(S)或者(S)->Timing.stepSize獲得. 上面是以通用即時malloc格式代碼為例,要產生其他格式即時模擬程式,其做法與之完全相同.