zoukankan      html  css  js  c++  java
  • 在simulink环境下实现实时仿真

     
     
    众所周知,基于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格式代码为例,要生成其他格式实时仿真程序,其做法与之完全相同.
  • 相关阅读:
    vue登录注册及token验证
    react实现登录注册
    React Native仿京东客户端实现(首页 分类 发现 购物车 我的)五个Tab导航页面
    进度条效果
    手风琴切换效果
    React实现了一个鼠标移入的菜单栏效果
    react购物车
    react实现tab切换效果
    网络缓存
    java线程面试手写题
  • 原文地址:https://www.cnblogs.com/yunbo/p/766981.html
Copyright © 2011-2022 走看看