为 C 代码生成准备控制算法模型
生成用于控制算法模型的代码,将生成的代码与现有系统集成,并验证仿真和可执行文件的结果。
了解模型
此示例从行为和结构角度对模型进行了说明和描述。还说明了如何为代码生成配置模型以及如何生成代码。您将:
了解示例模型的功能性行为。
了解如何验证模型。
熟悉模型检查工具。
熟悉影响代码生成的配置选项。
从模型中生成代码。
了解模型的功能设计
此示例使用节气门控制器的一个简单模型。该模型的特点是具有冗余性,这在安全至关重要的线控应用中很常见。该模型重点介绍算法设计中的一个标准模型结构和一组基本模块。
在当前配置中,模型生成的代码未针对生产目标系统进行配置。在此示例中,您需要更改目标配置,并观察由此给所生成的代码带来的格式更改。
检查顶层模型
顶层模型包括:
四个子系统:
PI_ctrl_1
、PI_ctrl_2
、Define_Throt_Param
和Pos_Command_Arbitration
。顶层输入:
pos_rqst
、fbk_1
和fbk_2
。顶层输出:
pos_cmd_one
、pos_cmd_two
和ThrotComm
。信号路由。
没有转换模块。转换模块更改信号的值,例如 Sum 模块和 Integrator 模块。
布局显示基本的模型架构风格。
计算与信号路由(信号线和总线)分离
划分为子系统
这种风格适合多种模型类型。
检查子系统
两个子系统表示 PI 控制器:PI_ctrl_1
和 PI_ctrl_2
。这两个子系统具有相同的内容,而且现在使用的数据也相同。稍后,您可以使用这两个子系统了解代码生成器如何创建可重用的函数。
PI 控制器来自一个库,库是您要重用的一组相关模块或模型。库提供包含和重用模型的两种方法之一。本系列在后面的部分介绍了第二种方法 - 模型引用。
在模型中使用库模块时,您不能编辑模型中的模块实例。但可以编辑库中的模块定义。这样,不同模型中模块的实例就会保持一致。
Stateflow® 图 Pos_Command_Arbitration
会对这两个命令信号执行基本的错误检查。如果这些命令信号相距太远,Stateflow 图会将输出设置为 fail_safe
位置。
检查代码生成的模型配置参数设置
要为代码生成准备模型,请打开 Embedded Coder App。然后,设置代码生成模型配置参数。这些参数确定代码生成器用于生成代码的方法以及生成的代码的格式。
代码生成目标
您可以手动配置模型配置参数。也可以从预定义的目标中进行选择,以自动配置模型配置参数。
您可以从下列高级代码生成目标中进行选择:
执行效率
ROM 效率
RAM 效率
可追溯性
安全预警
调试
每个目标都会根据目标的推荐值检查当前模型配置参数。每个目标还包括一组 Code Generation Advisor 检查。您可以使用这些附加检查来验证模型配置参数是否设置为创建符合目标的代码。
目标的一些推荐项与 Code Generation Advisor 检查有冲突。您选择目标的顺序会决定结果。Simulink® 通过满足具有更高优先级的目标来解决冲突。
下图显示如何将优先级设置为 Execution efficiency
> ROM efficiency
> RAM efficiency
。要打开对话框,请在 Configuration Parameters 对话框中,选择 Code Generation 窗格。然后,点击 Set Objectives。
您可以运行 Code Generation Advisor 来基于指定的目标检查模型。要打开 Code Generation Advisor,请在 C Code 选项卡中,点击 C/C++ Code Advisor。
Code Generation Advisor 根据您选择的目标创建检查列表。第一个检查会检查模型配置参数的当前值,并基于目标推荐替代值。该检查提供将参数设置为推荐值的自动化方法。
手动配置选项
在 Model Configuration Parameters 对话框中,下列窗格与代码生成相关:
Solver
Hardware Implementation
Code Generation
Solver
要为模型生成代码,您必须将模型配置参数 Type 设置为
Fixed-step
。参数 Fixed-step size 设置系统的基本速率。将参数设置为系统中速率的最小公倍数。
参数 Solver 控制代码生成器使用的积分算法。
要为系统中的每个速率生成一个入口函数,请选择参数 Treat each discrete rate as a separate task。
Hardware Implementation
打开 Hardware Implementation 窗格。
使用硬件实现参数来指定硬件板。Simulink® 根据您选择的硬件板调整窗格上的其他设置,包括隐藏的微处理器设备详细信息。要查看或调整隐藏的参数设置,如字长和字节顺序,请点击 Device details。
Code Generation
使用 Code Generation 窗格指定系统目标文件和优化。此示例使用 Embedded Coder® 系统目标文件 (ert.tlc
)。您可以扩展系统目标文件来创建自定义配置。Code Generation 窗格及其子窗格中的一些基本参数包括:
System target file
ert.tlc -“基本”Embedded Coder®
grt.tlc -“基本”通用实时目标
特定于硬件的目标
Make file
Code optimizations
从代码中删除未使用的分支,并控制临时变量的创建。
控制哪些信号有显式初始化代码。
启用或禁用溢出和被零除保护代码的使用。
Code formatting options
使用括号
头文件信息
变量命名约定
Inclusion of custom code
C 文件
H 文件
目标文件
文件夹路径
Generation of ASAP2 files
保存模型配置参数
您可以将模型配置参数的值保存为 MATLAB® 函数。在命令提示符下,输入:
hCs = getActiveConfigSet('rtwdemo_PCG_Eval_P1'); hCs.saveAs('ConfiguredData');
MATLAB® 函数保存配置参数对象的文本表示。您可以使用生成的文件来归档,也可以使用传统的差异工具比较文件的不同版本。您还可以目测检查文件的内容。
您可以运行该函数来设置其他模型的配置参数。
hCs2 = ConfiguredData; attachConfigSet('myModel', hCs2, true); setActiveConfigSet('myModel', hCs2.Name);
了解仿真测试环境
您可以在名为测试框架的单独模型中测试节气门控制器模型。测试框架是一个用于评估控制算法的模型。可使用测试框架:
将测试数据与控制算法分开
将被控对象或反馈模型与控制算法分开
为控制算法的多个版本提供可重用的环境
典型的仿真测试环境由以下部分组成:
在测单元
测试向量源
计算和记录
被控对象或反馈系统
输入和输出缩放
控制算法是在测单元。测试框架模型通过 Model 模块引用控制算法。使用 Model 模块,您可以重用组件。Model 模块通过名称 (rtwdemo_PCG_Eval_P1
) 引用控制算法。
Model 模块以编译函数的形式在一个模型中包含(引用)另一个模型。默认情况下,如果您更改了引用模型,Simulink® 会对其进行编译。相对于库,编译函数有下列优点:
大型模型的仿真速度更快。
您可以直接仿真编译函数。
仿真需要的内存更少。当添加模型的多个实例(多个 Model 模块)时,内存中只有一个编译模型副本。
该模型使用一个 Signal Builder 模块作为测试向量源。该模块具有驱动仿真的数据 (pos_rqst
) 和 Verification 子系统使用的预期结果。此示例仅使用一组测试数据,但在典型的应用中,您需要创建一组完全覆盖系统运行的测试套件。
测试框架将仿真结果与黄金数据进行比较,黄金数据是一组指示所需的模型行为的测试结果。在该模型中,V&V Assertion 模块将来自被控对象的经过仿真的节气门值位置与测试框架提供的黄金值进行比较。如果两个信号之间的差值大于 5%,则测试失败,Assertion 模块将停止仿真。
您也可以在仿真完成执行后计算仿真数据。您可以使用 MATLAB® 脚本或第三方工具来执行计算。在执行后进行计算可在分析数据方面具有更高的灵活性,不过您必须等到执行完成。结合使用这两种方法可以打造高度灵活和高效的测试环境。
load_system('rtwdemo_PCGEvalHarness') open_system('rtwdemo_PCGEvalHarness/Verification')
此示例通过将传递函数分解为一种标准形式来对节气门动态进行建模。您可以创建被控对象模型来对特定级别的保真度进行建模。许多应用在每个测试阶段使用不同的被控对象模型。
对输入和输出进行缩放的子系统执行下列主要功能:
选择要路由到在测单元和被控对象的信号。
在工程单位和在测单元所需的单位之间再次缩放信号。
处理被控对象与在测单元之间的速率转换。
运行仿真测试
要运行测试框架模型仿真,请点击 Start 或点击以下超链接。
测试框架第一次运行时,Simulink® 必须编译引用模型。您可以在命令行窗口中监视编译进度。
模型仿真完成后,Simulink® 会在绘图图窗中显示结果。
sim('rtwdemo_PCGEvalHarness')
右下图显示预期(黄金)节气门位置和被控对象计算的节气门位置之间的差异。
生成代码
要生成代码,请打开 Embedded Coder App。然后,使用以下方法之一:
在模型中,按 Ctrl+B。
在 C Code 选项卡中,选择 Build 或 Generate Code。
点击以下超链接:
代码生成器生成几个文件。所生成的代码虽然在计算方面很高效,但尚未针对集成到生产环境进行组织。
检查生成的代码
代码生成器创建多个文件,您可以从 Code 视图或代码生成报告中查看这些文件。除了标准的 C 定义和头文件之外,代码生成器还会创建一组 HTML 文件。HTML 文件提供代码和模型之间的超链接。
在生成的代码中,观察:
控制器代码存在于文件
rtwdemo_PCG_Eval_P1.c
中名为ModelName_step
的一个函数中。代码生成器将多个模块的运算折叠为一个代码语句。
函数
ModelName_initialize
会初始化变量。数据结构体定义模型数据(例如,
rtwdemo_PCG_Eval_P1_U.pos_rqst
)。
rtwdemo_PCG_Eval_P1.c
:用于定义单步函数和初始化函数的 C 文件ert_main.c
:包含一个简单调度器的示例主文件rtwdemo_PCG_Eval_P1.h
:包含 Simulink® Coder™ 数据结构体的类型定义的 H 文件PCG_Eval_p1_private.h
:声明仅供生成的代码所使用的数据的文件rtwdemo_PCG_Eval_P1_types.h
:声明实时模型数据结构体的 H 文件
有关本系列中的下一个示例,请参阅 配置生成的代码中的数据接口。