Simulink利用共享内存读取向外发送仿真信号与运行控制

前言

Simulink广泛应用于工业建模与控制系统设计,对于在工业控制和仿真领域的专业人员使用方便,但是不进行科研仿真的实际使用客户使用则显的特别难以操作和使用,而一般的使用者经常要求具有良好的交互体验和图像可视化。利用共享内存能够使得不同应用软件之间交互数据,将Simulink仿真信号传递给第三方可视化软件,例如利用C#编写的具有三维动画效果,以及二维曲线等可视化良好的软件。同时,也可以通过在第三方软件中添加一些可视化良好的控件,利用共享内存传递给MATLAB/Simulink,从而达到控制MATLAB/Simulink的运行。
本篇博文给设计类似于Prescan软件的动画效果的工程人员给出了一些参考意义,首要条件时Prescan软件基于Simulink平台,而且Prescan在Simulink平台下用于车辆场景建模与辅助驾驶策略验证,该软件能够将Simulink的仿真信号传递给第三方软件,并利用三维模型引擎得到动画显示效果,极大的丰富了软件的可视化。
本博文中用到的所有程序和Simulink模型可在文末附件中下载。

Simulink如何调用C函数

Simulink使用共享内存的方式是调用能操作共享内存的C、C++函数;我们可以从Simulink如何调用C函数入手来实现这一过程,让 Simulink调用C函数主要有以下三种方式:
1.最简单的方法使用Simulink模块库中提供的 C Call 模块,该模块在MATLAB 的 2020a版本中可使用(估计以后的版本中均支持该模块),但是该种方式不能保护源代码,如果模型发布则源代码也必须附带。
2.使用stateflow调用C函数,该种方式非常适合状态机建模而且有需求调用C函数的情况下,在使用共享内存时,能够很好的解决共享内存调用时的写内存和读内存的执行顺序,而且可以利用stateflow,搭建出较好的调用顺序。非常推荐使用该种方式操作共享内存。
3.使用S函数,该种方式能够完全自定义共享内存函数的操作,但是该种方式需要写 C S MEX,一般不熟悉C 函数写 S 模块的使用者不太友好。

Simulink与应用程序交互实现

Simulink根据求解器设置的步长大小,每个步长执行一遍模型,因此如果利用Simulink调用C函数,在采样率为固定步长且调用C函数的模型采样时间为继承的条件下,Simulink每经过一个步长大小,遍执行一遍C函数。为表述方面,下文默认Simulink求解器为固定步长。

1、C函数操作共享内存

利用windows提供的开辟内存空间函数,调用如下函数便可开辟内存空间。该函数同样可以被MATLAB的m脚本调用。

/**************************************************************************
* Function open_shared_memory()
* Goal  : Creation of a memory-mapped file to share data between 2 processes
* IN    : -
* IN/OUT: -
* OUT   : - Error status in integer coded as following:
*          > 0 => No error occurred and the shared memory has been created
*          > 1 => The process could not create the memory-mapped file object
*          > 2 => The process could not return a pointer to the file view
**************************************************************************/
int open_shared_memory()
{
  /* Definition of the handle to the memory-mapped file object */
  HANDLE hMappingFile;

  /* Create a new shared memory area if it does not exist yet */
  if (sharedMemoryAddress == NULL)
  {
    /* Creation of the file mapping object */
    hMappingFile = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file
      NULL,                 // default security
      PAGE_READWRITE,       // read/write access
      0,                    // maximum object size (high-order DWORD)
      BUFFER_SIZE,          // maximum object size (low-order DWORD)
      SHARED_MEMORY_NAME);  // name of the mapping object
                            /* Exception handling */
    if (hMappingFile == NULL)
    {
      /* The file mapping object could not have been created */
      _tprintf(TEXT("Could not create the shared memory called: %s\n"), SHARED_MEMORY_NAME);
      return 1;
    }
    /* Create a view of the file in the process address space */
    sharedMemoryAddress = MapViewOfFile(hMappingFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFFER_SIZE);
    /* Exception handling */
    if (sharedMemoryAddress == NULL)
    {
      /* No pointer to the file view could have been returned */
      _tprintf(TEXT("Could not map the shared memory called: %s\n"), SHARED_MEMORY_NAME);
      /* The process no longer needs access to the file mapping object */
      CloseHandle(hMappingFile);
      return 2;
    }
  }
  /* No error occurred */
  return 0;
}

当开辟内存空间后,即可使用共享内存写函数将数值写入共享内存中:


void write_register_val(unsigned short address, double val1)
{
  /* Access the shared memory area */
  if (open_shared_memory() == 0)
  {
    /* Set the new value in the desired register */
    double * temp = (sharedMemoryAddress + address);
    *temp = val1;
  }
  else
  {
    getchar();
    exit(EXIT_FAILURE);
  }
}

2、Simulink与第三方应用程序数据交互框架

利用C共享内存函数(C或者C++类似),利用stateflow调用写共享内存函数。值得说明的是,由于Simulink每个步长需要执行一遍写共享内存函数,在下次运行共享内存写入函数之前,即Simulink运行下一个步长之前,需要查看是否第三方的软件应用读取到该地址上的数值。因此需要设定是否可写标志位,用于协调Simulink运行速度和第三方软件应用。Simulink的协调流程如下图所示:

前后台数据传递流程

流程图1:前后台数据交互流程

首先清空前后台是否写入标志位,使得首个步长能够写入共享内存;当写入内存后,便可将写入标志位置位;然后进入下一次Simulink的调用,当第三方程序没有读取共享内存的数据时,写入标志位不变,则下次运行到该stateflow模块时会一直判断是否可写入数据,(为了避免长时间死循环等待,这里增加了粗略的超时计数器,即每检测可写状态一次,计数器自增,然后判断计数器大于某个数据便可退出死循环);当第三方应用程序读取到共享内存中的数据时,则会将写入标志位清零,这样Simulink就不会一直等待在死循环中了。
Simulink与第三方应用程序配合,便可以将每个步长下Simulink运行得到的数据写入共享内存中了。同时,第三方应用程序也会依次将共享内存中的数据读取出来了。

注:为了避免Simulink运行过快,而第三方应用程序读取速度慢从而导致拖慢Simulink的现象,因此需要第三方应用程序开辟新的线程,专门使用一个缓冲队列来接收Simulink发送过来的数据,这样第三方应用程序展示数据的速度和Simulink的仿真速度之间不协调的现象缓解,同时第三方应用程序也不太受到Simulink仿真速度的限制。

3、第三方应用程序控制Simulink

利用第三方应用程序控制Simulink主要有两种方式,分别为:
1、利用第三方应用程序调用MATLAB提供的COM接口,直接控制MATLAB执行控制命令,关于第三方应用程序调用COM接口函数的方法可参考我的另一篇博文,C#应用程序与MATLAB联合编程
在MATLAB中控制Simulink的开始、暂停、终止、继续、步进运行,控制指令分别为:

model_name = gcs;
set_param( model_name,'SimulationCommand' ,'start'); % 启动Simulink
set_param( model_name,'SimulationCommand' ,'pause'); % 暂停 Simulink
set_param( model_name,'SimulationCommand' ,'stop');  % 停止 Simulink
set_param( model_name,'SimulationCommand' ,'continue'); % 继续 Simulink
set_param(model_name, 'SimulationCommand', 'step');     % 步进 Simulink

注:该种方式需要MATLAB不能正在运行其他M脚本,需要MATLAB处于正常状态
2、利用第三方应用程序共享内存写入运行标志控制MATLAB脚本运行,进而通过 MATLAB 脚本控制Simulink运行。该种方式能够对MATLAB最为全面的控制,推荐使用。
这里需要介绍一下MATLAB和Simulink之间的运行机制,当Simulink正在运行时,MATLAB可以在命令窗口中执行控制指令。因此我们才可以利用第一种方式对Simulink进行控制。当MATLAB执行脚本函数时,Simulink不能执行,处于等待状态,只有脚本暂停执行时,Simulink才能继续执行。
由于第三方应用程序是通过共享内存的方式对MATLAB进行控制,因此需要MATLAB一直监控共享内存的标志位状态。这就需要MATLAB一直运行M脚本函数来实现这一过程,这样就导致Simulink一直处于阻塞,不能进行仿真运行。因此,在需要执行Simulink模型时,需要M函数在监控共享内存标志位的同时,短暂的暂停一段时间,用于Simulink运行。下面采用该种方法对 MATLAB/Simulink 进行控制。

4、实现方法

前台控制后台Simulink与仿真程序的运行流程2所示。本流程为M脚本的执行流程。主要的详细部分为Simulink相互的控制部分。当运行完成前处理后,主函数将调用模型仿真。首次判断前台是否允许模型启动仿真,当前台未允许进行仿真时,后台m主程序将暂停并等待,直到前台允许仿真为止。当前台使能后台模型仿真后,后台将控制Simulink仿真运行,然后M文件将暂停,等待Simulink运行。M文件暂停结束后,再检测前台的控制命令,接收前台的控制指令。这样遍实现了M文件能够接受前台的控制指令的同时,也能让Simulink运行并接受前台的控制。

在这里插入图片描述

流程图2:前台控制后台运行流程

从图中可以看出,前台控制后台运行的控制指令是通过共享内存的标志位完成的。前台控制Simulink运行的指令包括:启动、步进、暂停、继续、和终止。
注意:当前台运行较快时,由于M文件在暂停的时候Simulink运行,而且Simulink运行完成后将模型运行完成标志位置位,这时M文件还在暂停状态,而且前台接收到运行完成状态后将模型运行完成标志位置位,这时M文件暂停结束,会导致M文件仍在运行的错误状态。因此需要前台在模型运行完成与指示下次模型运行的这段时间大于M文件暂停的时间间隔,避免这种情况的发生。

附件

### 回答1: c simulink联合仿真是指利用c语言和simulink两个工具进行联合仿真。c语言是一种高级编程语言,常用于编写软件程序。simulink是一种基于图形化编程的仿真平台,常用于进行系统级仿真。 c simulink联合仿真的主要优势在于可以结合c语言的编程能力和simulink仿真能力,实现更加灵活和高效的仿真。通过c语言,我们可以编写复杂的控制算法、数学模型和逻辑判断等功能,而通过simulink,我们可以将c语言编写的代码与其他模块进行联合仿真,验证程序的正确性和性能。 在c simulink联合仿真中,c语言编写的代码可以作为simulink中的一个子系统,与其他simulink模块进行连接和交互。通过这种方式,我们可以使用c语言编写的代码来控制系统的行为,例如控制信号的生成和处理、数据的读取和写入,甚至是和硬件设备的通信等。同时,通过simulink仿真能力,我们可以对整个系统进行全面的仿真和调试,包括对系统性能、稳定性、鲁棒性等方面进行评估。 c simulink联合仿真广泛应用于各个领域,特别是在控制系统设计和嵌入式系统开发中。它可以帮助工程师们更好地理解和掌握系统的行为,提高系统的性能和可靠性。同时,它也为学术研究提供了一个强大的工具,可以用于验证和验证新的控制算法、模型和理论。 ### 回答2: c simulink联合仿真是一种基于MATLAB仿真技术,用于模拟和分析复杂的动态系统。在这种仿真中,c simulink作为主程序,引入了其他的仿真模型,通过联合协同工作来实现系统级的仿真。 c simulink联合仿真的优势之一是它的模块化设计。通过使用不同的仿真模型,可以将系统的各个方面进行模拟,从而更全面地理解系统的行为。这样,可以更好地设计、优化和验证系统,提高系统的性能和可靠性。 此外,c simulink联合仿真还具有多学科集成的能力。不同领域的仿真模型可以被集成到一个统一的仿真平台中,从而实现多学科的交互与协同。这可以促进不同学科之间的合作和共享,提高系统级仿真的准确性和有效性。 c simulink联合仿真还可以用于系统级仿真和硬件软件协同设计。通过在仿真环境中模拟系统的全部或部分功能,可以预测系统的行为和性能。此外,可以将硬件和软件部分集成在仿真平台中,进行系统级调试和验证,从而提前发现和解决问题,提高开发效率。 综上所述,c simulink联合仿真是一种强大的仿真技术,可以用于模拟和分析复杂的动态系统。它具有模块化设计、多学科集成和硬件软件协同设计等优势,可以提高系统的设计、优化和验证效率,从而推动科学研究和工程实践的发展。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值