分享

在simulink环境下实现实时仿真

 FADEC 2010-08-11
众所周知,基于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格式代码为例,要生成其他格式实时仿真程序,其做法与之完全相同

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多