分享

大型C工程项目与Simulink无缝仿真与测试交互

 ZHAOHUI 2025-02-14 发布于上海
C语言作为一种通用的编程语言,被广泛应用于工程领域的项目开发中,而Simulink则是一款功能强大的仿真软件,被广泛应用于控制系统、通信系统等领域。将两者结合起来进行联合仿真,可以发挥各自的优势,实现系统级的仿真与分析。在工程领域,联合仿真技术的发展已成为提高系统设计效率和质量的重要手段。然而,对于大型C语言项目与Simulink模型的联合仿真来说,如何实现高效的交互和步长控制一直是一项挑战。传统基于S函数集成的方式虽然能够实现C与Simulink之间的通信,但存在着诸多局限性,如需改写C函数、工程体积增加等问题。今天,我们将介绍一种创新的方法,利用共享内存技术,将C语言项目与Simulink模型紧密集成,实现高效的联合仿真,并深入探讨这种方法的优势和具体实现细节。
1. 背景介绍
传统方式:(1)基于S函数集成原始C函数
传统的基于S函数的方式虽然可以实现C与Simulink之间的通信,如下图所示:
图片
这种方式通过将原始C函数与S function结合到一起,根据C函数原始的输入输出接口配置S function 的输入输出接口,进而将C 函数整合到Simulink环境中,但存在着一些明显的缺点:
修改工程体积增加:需要将C函数改写为S函数,这不仅增加了工程体积,还增加了集成的复杂性和工作量。
局部性限制:S函数通常需要在Simulink模型中调用,导致C函数的局部性受限,无法灵活地在工程中任意位置使用。
性能损失:S函数的调用会引入一定的性能损失,特别是在大型项目中,可能会影响仿真的准确性和效率
传统方式:(2)基于Simulink提供的C Caller模块调用C函数
MATLAB/Simulink在2020a版本以及之后的版本中,引入了C Caller模块,该模块能够将C语言代码嵌入到Simulink模型中,并调用自定义的C函数。它可以与Simulink模型中的其他模块交互,并在仿真期间执行C代码。这个模块非常适用于在Simulink模型中集成外部C代码、进行性能优化或者实现一些复杂的计算逻辑。
  • C Caller模块:可以接受多个输入,并返回多个输出,允许与Simulink模型中的其他模块进行数据交互。
  • C代码实现:编写C代码(如函数),并通过设置模块的路径将其链接到Simulink模型中。
  • 自定义代码的嵌入: C Caller模块是Simulink与C语言之间的桥梁,使得自定义的计算或者外部库可以直接应用于Simulink仿真中。

     如果C代码实现了高效的算法,使用C Caller模块可以显著提高仿真的运行速度,特别是在需要大量计算的情境下。另外,C Caller 允许用户将Simulink内建模块无法实现的自定义功能(如复杂的数学运算或特殊的硬件控制逻辑)嵌入模型,且而无需重写代码。然而, C Caller模块中的C代码不能直接在Simulink环境中调试,因此调试过程可能会变得较为复杂,通常需要在外部工具中进行调试。另外,该方式需要合适的编译环境来编译和链接C代码,可能会遇到与平台或工具链的兼容性问题。

创新方式:基于共享内存的联合仿真
为了克服传统方式的局限性,我们提出了一种创新的方法,即基于共享内存的联合仿真。而不是采用C caller这种面向项目函数数量小且文件体量几乎没有的集成方式,也不需要使用Legacy Code Tool改写C函数或者编译为S函数。共享内存通信作为一种高效的数据交换方式,为C与Simulink之间的交互提供了便捷的途径。通过在两者之间建立共享内存通信通道,可以实现数据的实时交换和同步,从而实现联合仿真的目的。该方法不仅避免了修改C函数和增加工程体积的问题,还具有以下优势:
零修改原C/C++工程:几乎可以做到对工程零修改,不需要修改C函数或编译为S函数,大大降低了集成的复杂性和工作量。
灵活性与自由度:共享内存通信方式无需局部调用,C函数的位置不受限制,可以在工程中任意位置使用,实现了更大的灵活性和自由度。
高效实时性:基于共享内存的通信方式具有低延迟、高吞吐量的特点,能够实现数据的实时传输和处理,满足对实时性要求较高的系统仿真需求。
在介绍具体实现细节之前,先说一下这个开发这种联合仿真形式的技术背景,作者在开发自动驾驶应用程序软件一般为C、C++程序,然而在车辆一般是采用Simulink MBD方式,在使用Simulink构造测试用例、复杂的被控对象非常好用。为此,作者苦苦在网上查找是否有开发相关的便捷方式,结果找到几个相关的工具软件,例如FMU、CosiMate、NI TestStand、AVL Model.Connect等工具,然而这些工具不能灵活定义,而且提供的API也开放程序也不高,仔细一想,联合仿真无非就是应用之间相互传递数据,而且现在也有很多应用之间的通信方式,为此,受到这些软件的启发,决定自行编写联合仿真程序,在这些联合仿真软件中,一般与Simulink的联合仿真通常通过应用数据通信技术来实现。这种技术允许将第三方应用程序和Simulink中的模型连接起来,以便在仿真环境中执行联合仿真。总结联合仿真共同特点如下:
模型建立: 首先,您需要在C APP(代指第三方仿真程序)和Simulink中分别建立您的模型。这些模型可能涉及到不同的物理领域,比如机械、电气、液压等。
接口定义: 接下来,您需要定义C APP和Simulink之间的接口,确定哪些信号将在两个环境之间传递。这可以通过定义数据交换接口或共享变量来实现。
桥接连接: 然后,您需要使用C APP提供的桥接工具或接口将两个环境连接起来。这通常涉及编写一些代码来处理数据交换和通信。
联合仿真: 一旦连接建立好,您就可以在C APP中启动联合仿真。在仿真过程中,C APP和Simulink中的模型将同时运行,并且通过接口进行数据交换,以实现系统级的仿真和分析。
通过这种方式,您可以利用C APP和Simulink各自的优势,实现跨领域的联合仿真,从而更全面地分析和优化系统行为。
2. 具体实现
在进行联合仿真设计时,存在以下两个关键难点问题:


1)任务调度问题

  1. 使用信号量进行同步:在共享内存中设置信号量,用于同步任务的执行顺序。每个任务在开始执行前需要获取信号量,执行完成后释放信号量。这样可以确保任务按照预期的顺序执行。

  2. 制定任务优先级:对不同的任务分配不同的优先级,确保高优先级任务能够及时执行。可以使用操作系统提供的任务调度器来管理任务的优先级。


2)时序同步问题:

  1. 采样周期同步:在共享内存中添加时间戳,记录每个数据的产生时间。在数据传输时,确保数据的时间戳与实际产生时间一致。Simulink模型可以根据时间戳来处理数据,以保持与C项目的时序同步。

  2. 时间同步策略:使用统一的时间同步策略,例如使用全局时钟源或者网络时间协议(NTP)来确保C项目和Simulink模型的时钟同步。这可以减少由于时钟差异而引起的时序问题。

  3. 数据处理延迟:考虑到数据传输和处理可能存在的延迟,设计合适的数据处理策略,确保C项目和Simulink模型能够正确处理延迟数据。

  4. 时序校正:在联合仿真的过程中,定期对时序进行校正和调整。根据实际情况,调整任务的执行顺序、采样周期等参数,以确保两者之间的时序同步。

这些方法在设计和实现过程中,需要根据具体的应用场景和系统要求进行调整和优化。同时,充分的测试和调试也是确保系统稳定运行的重要步骤。

为了实现共享数据,技术点如下:

1)共享内存通信设置:在C语言项目和Simulink模型之间建立共享内存通信通道,以实现数据的实时交换和同步。
2)数据传输与步长控制:使用共享内存通信技术,可以实现C与Simulink之间的数据传输和步长控制,保证两者的时序同步和数据交互的准确性。
3)自动生成接口模块:通过定义好通道接口名称和序号,Simulink接口模块能够自动化生成,大大提高了集成的效率。
整个联合仿真的C APP 主函数运行框架如下所示:
图片
图片

在这个程序中,主要包含步骤如下:
1)接口初始化
初始化所有输入输出接口链表,包括与Simulink交互的接口和程序内部的接口。包括定义数据名称、方向和指针等。为方便接口定义,通过C项目中声明的接口,自动化生成接口描述XML文件,供MATLAB脚本自动生成Simulink接口模块。
2)数据交互
在while循环中,首先检查Simulink是否在运行状态,如果是,则进行数据交互。通过共享内存通信技术,批量读取Simulink传入的信号,并进行数据类型转换和单位转换。根据不同的调度周期,执行相应的数据交互任务,包括5ms、10ms、20ms和40ms的数据交互。在数据读取和处理完成后,设置Simulink可写入数据,以便Simulink读取C程序计算得到的结果。
3)任务调度
根据不同的调度周期,执行相应的任务。任务包括不同步长的主函数执行,以及相关的数据交互函数执行。通过判断不同步长任务的触发标志,保证了任务的时序同步和数据交互的准确性。
4)仿真控制
通过判断Simulink是否在运行状态,控制仿真的启动和暂停。在仿真结束时,记录仿真运行时间,并重新初始化参数,准备进行下一次仿真。
5)输出信息
在程序开始时,输出一些提示信息,以便用户了解程序运行状态和仿真状态。输出调试信息,如任务触发次数等,方便调试和性能优化。
这个主程序框架通过循环实现了程序的持续运行,并根据Simulink的状态进行相应的数据交互和任务调度。同时,通过共享内存技术,实现了C程序与Simulink之间的高效通信,保证了仿真的准确性和稳定性。整体结构清晰,逻辑合理,是一个较为完整的与Simulink自动化联合仿真相关的主程序框架。
上述框架不仅避免了调用S function或C caller等集成方式所带来的工程体积增加和修改工作量,更重要的是,几乎可以做到对工程零修改。这种方式非常适合大型C、C++或C#项目与Simulink集成测试使用场景,能够快速集成到基于模型MBD的设计中。Simulink中的信号能够直接注入到C工程的任何位置,实现工程中的变量改写。而只需在C工程中定义好通道接口名称和序号,Simulink与Visual Studio交互的Simulink接口模块能够自动化生成,方便快捷,不用手动调整共享内存地址。
3. 总结
这个联合仿真框架为Simulink与大型C语言项目之间的交互和步长控制提供了一套完整的解决方案。与传统的集成方式(如Stateflow或C Caller)相比,它不需要修改C函数或将其编译为S函数,几乎可以实现零工程修改。这种方法特别适合于大型C、C++或C#项目与Simulink的集成测试,可以快速将大型项目工程集成到基于模型的设计中,实现基于模型的设计(MBD)。
通过基于Windows共享内存机制,实现了Simulink与Visual Studio之间的数据传递,数据传输量大且快,通信延迟很小。C项目中的信号可以直接在Simulink中查看,无需额外的数据处理。同时,Simulink中的信号也可以注入到C工程的任何位置,实现工程中的变量改写。
只需在C工程中定义好通道接口名称和序号,Simulink与Visual Studio之间的接口模块就可以自动生成,省去了手动调整共享内存地址的麻烦,提高了集成效率。
此外,该框架还支持C项目多个步长任务的控制与数据交互,适用于大型基于C的嵌入式项目控制器策略应用层的快速验证,并且支持多任务调度,满足了实际工程中的需求。
4. 结语
通过共享内存技术实现C与Simulink的联合仿真,我们为工程师们提供了一种创新的思路和解决方案。在未来的工程实践中,我们相信这种方法将会越来越受到重视和应用,为工程技术的发展注入新的活力和动力。
5. 致谢
感谢您阅读本文,如果您对C与Simulink共享内存联合仿真有任何疑问或者想法,欢迎在评论区留言,期待进一步交流和探讨!
6. 工程浏览与技术支持
C APP在Visual Studio中的工程浏览:
图片

MATLAB自动化建模与接口文件示例浏览:

图片
图片
图片

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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多