Automatically Generate C Language Code and Executable Programs for Simulink Models in MATLAB
自动生成 Simulink 模型的 C 语言代码Permalink
在命令行中输入
matlab
1
open_system('rtwdemo_secondOrderSystem');
打开模型文件,之后将文件 rtwdemo_secondOrderSystem.slx 复制到新的工作文件夹中,使其成为可编辑状态。
打开复制后的模型文件:
这个 Simulink 模型模拟了一个理想的二阶质量-弹簧-阻尼(Mass-spring-damper)系统,系统方程为:
外力由 Signal Generator 模块施加,是一个幅值为 4 ,频率为 20 Hz 的方波:
该模块使用 Simulation time 作为波形的时间变量。
⚠ 由于使用 code generation 需要模型的求解器是 固定步长(fixed-step) 求解器,因此模型在整个仿真过程中使用的都是固定的步长,为 0.001。
下面将通过四个步骤来简单地学习 C 语言代码和可执行程序的自动生成。
Step1: 使用 Simulink Coder Quick Start Tool 生成 C 语言代码Permalink
Generate C Code by Using Simulink Coder Quick Start Tool
代码生成步骤Permalink
在 APPS 中点击 Simulink Coder
打开 C Code tab
之后点击 Quick Start 按钮,弹出配置对话框
这里都使用默认配置,一直点击 Next 按钮即可,最后点击 Finish 按钮。
✏ 注
一开始生成代码失败:
报错信息:
The default compiler, LCC, is not supported for XCP communication.
For information about compiler support, see https://www.mathworks.com/support/compilers/current_release
一开始点开这个网址,我以为是因为电脑缺少 C 语言的编译器,但是下载了 MinGW 后仍然抛出相同的报错信息。之后仔细看了这个报错信息,其实是由于默认的编译器不支持 XCP 通信,只需要更改一下编译器即可。
打开模型的参数配置界面,可以看到默认的编译器:
将编译器改为
Apply 后 OK,之后便可成功生成代码。
自动生成代码后,模型的所在文件夹中会出现两个文件夹,分别是 rtwdemo_secondOrderSystem_grt_rtw
和 slprj
:
自动生成文件夹的结构Permalink
rtwdemo_secondOrderSystem_grt_rtw 文件夹Permalink
rtwdemo_secondOrderSystem_grt_rtw
文件夹中存放着模型的源代码,其中有两个主要的文件:rtwdemo_secondOrderSystem.c
和 rtwdemo_secondOrderSystem.h
。
(1)rtwdemo_secondOrderSystem.c
rtwdemo_secondOrderSystem.c
文件中包含了算法代码,包括 ODE 求解器代码。
(2)rtwdemo_secondOrderSystem.h
调用方可通过 inclue 头文件 rtwdemo_secondOrderSystem.h
获得模型数据和入口函数(entry-point functions)。
rtwdemo_secondOrderSystem.h
文件中包含了模块输出(block outputs)、连续状态(continuous states),模型输出(model output),入口(entry points) 和时间数据(timing data)。
slprj 文件夹Permalink
在 ./slprj/grt/_sharedutils
文件夹中
头文件rtwtypes.h
定义了生成代码默认使用的标准数据类型(standard data types) 。
./slprj/grt/_sharedutils
文件夹所包含的这些文件都是可以或者必须在多个模型之间分享的。
入口函数与模型接口Permalink
Simulink 模型所自动生成的代码包含了一系列的入口函数(entry-point functions),这使得我们可以从外部应用调用模型源代码。比如,对于一个基于速率的模型(rate-baed model),入口函数包含了初始化函数(initialization function),执行函数(execution function),终止和重置函数(terminate and reset functions)。这些函数提供了外部程序与模型之间的接口,用于交换数据。
在 C Code tab
中点击 Open Report
按钮, 在 Code Interface Report
中可以看到自动生成的入口函数
这里的三个入口函数都是 void-void 接口,即它们不传递参数。这些函数通过 shared data structures 来获得数据。
点击 Code Generation Report 左端菜单中 Code 下的 rtwdemo_secondOrderSystem.c
查找入口函数 secondOrderSystem_step
,便可以看到该入口函数的定义
以及使用
之后,同样可以在 rtwdemo_secondOrderSystem.h
文件中进行查找
Step2: 验证生成的可执行程序的结果Permalink
Verify Generated Executable Program Results
配置模型Permalink
Dashboard Scope 模块Permalink
模型中的 Dashboard Scope 模块可以监视力
为了更好地显示曲线,我们需要对该模块进行配置。双击 Dashboard Scope 模块点开配置对话框
此时点击 Simulink 中的其他模块,配置选项卡中就会出现这信号,如果勾选,则该信号也会在 Dashboard Scope 显示出来。
之后设置纵坐标最大最小值
Apply 后 OK。
### Knob 模块
Knob 模块用于调节系统的阻尼系数
该模块的配置逻辑与 Dashboard Scope 模块类似。
配置 Code GenerationPermalink
在 C Code tab 中依次点击
(1)为了使模型或者可执行程序能够将 workspace data 记录在 Simulation Data Inspector 中,需要进行以下配置:
(2)我们的目标是生成一个 executable program(不只是生成代码),因此需要保证 Code Generation 中的 Generate code only 选项没有被勾选
(3)为可执行程序配置 toolchain
之后,可以点击 Validate Toolchain 按钮,检查是否可用
(4)为了将数据保存在内存中,并且当可执行程序运行时能够获取到这些数据,我们需要配置一些参数。
为了高效执行模型的 C 代码,我们不需要为 每一个 参数,信号和状态都分配内存。如果模型算法在计算输出时不需要某个数据,为了优化运行, code generation 生成代码时就不会为该数据分配空间。但是在硬件原型设计时,我们有时候需要为这些数据分配存储空间,因此我们需要禁用一些 code generation optimization。
- 将
Default paramater behavior
设置为Tunable
。这样设置后,一些模块的参数,比如 Gain 模块的 Gain 参数在生成代码中就是 可调的。 - 不勾选
Signal storage reuse
。如果不勾选,那么 code generator 就会为每一个信号都分配存储空间,当运行可执行程序时,我们可以监视这些信号的值。
(5) 配置 code generator,使其可以生成 nonfinite data,比如 NaN 和 Inf,和其他相关运算(related operations)。
确认 Support non-finite numbers
已被勾选。
(6)配置通信通道(communication channel)
为了使 Simulink 可以和由模型生成的可执行程序进行通信,模型必须包括对于通信通道的支持。本例子就使用基于 TCP/IP 协议的 XCP 协议作为传输层(transport layer)充当通信通道,需要进行以下配置:
(7)禁用 MAT-file logging
将数据从 MATLAB base workspace 加载到 Simulation Data Inspector 中。
运行仿真,查看结果Permalink
在 Simulation tab 中点击 Run 按钮进行仿真:
Run 按钮的右下角有一个小时钟,表明开启了 simulation pacing。simulation pacing 可以放慢仿真过程,使得我们可以观察到系统的行为,理解系统设计和识别设计问题,同时演示近实时行为(near real-time behavior)。
运行完毕之后,在 Simulation tab 中点击 Data Inspector:
选中需要展示的信号:
将上述结果留在 Simulation Data Inspector 中,后面我们将会比较这些信号与可执行程序所生成的信号
构建并运行可执行程序,查看结果Permalink
创建并且运行可执行程序。
在 Hardware tab 中点击 Monitor & Tune:
之后,Simulink 就开始构建可执行程序,当出现 Code Generation Report 时,构建过程就完成了。
此时在当前文件夹就出现了可执行程序 rtwdemo_secondOrderSystem.exe
。
生成 .exe 文件之后,官网提供了三种使用和部署的方式:
- Deploys the executable program as a separate process on your development computer.
- Connects the Simulink model to the executable program.
- Runs the model executable program code.
但是并没有给出具体的使用方法
比较仿真和可执行程序的结果Permalink
使用 Simulation Data Inspector 比较仿真和可执行程序的结果。但是在这里我比较的是两次仿真的结果,因为我并没有找到使用 .exe 文件的方法。
在 Simulation Data Inspector 点击 Cmpare ,选择想要比较的数据。比如,选取两次仿真数据——在 Baseline 和 Compare to 中分别选取 Run 5: rtwdemo_secondOrderSystem
和 Run 6: rtwdemo_secondOrderSystem
两次仿真的参数并没有改变,输出的信号是一样的,但是 Simulation Data Inspector 判断的结果是 mismatch:
这是 Global Tolerance 设置得太小了,系统默认设置为0,这个限制太严格。我们可以点击右上角的 [+]More 按钮可以进行修改:
再次点击 Compare
Step3: 在程序执行期间调整模型参数Permalink
Tune Parameter During Program Execution
- 本部分的模型配置与上一节模型的配置是一致的
- 本部分的示例展示的是可执行程序在运行期间的参数调整,但是在前一步中,我没有找到使用 .exe 的程序的方法,因此这一部分还是针对仿真过程中的参数调整,也因此跳过了一些配置过程
在仿真运行期间,我们可以通过调整 Knob block 以调整阻尼系数的值,并通过 Dashboard scope 模块实时展示出来。
Step4: 部署原型代码Permalink
Deploy Prototype Code and Artifacts
本部分是关于 Simulink 模型 C 语言代码的打包和发布