目录
[生成用于集成到嵌入式应用程序的控制器 C 代码](#生成用于集成到嵌入式应用程序的控制器 C 代码)
[创建 PIL 实现](#创建 PIL 实现)
[准备用于 PIL 测试的控制器模型](#准备用于 PIL 测试的控制器模型)
此示例说明从电机控制算法生成 C 代码并验证其编译行为和执行时间的基本工作流和关键 API。使用处理器在环 (PIL) 仿真来确保 C 代码在集成到与电机硬件对接的嵌入式软件时按预期执行。虽然该工作流使用针对特定处理器的电机控制应用程序,但您可以将该工作流应用于另一个应用程序或处理器。
如图所示:
该示例使用永磁同步电机的磁场定向控制算法。该控制方法在混合动力汽车、机械制造和工业自动化领域的电机驱动系统中很常见。
概述
在此示例中,将从一种控制算法模型生成和验证 C 代码,您可以将此代码集成到与电机硬件对接所需的其他嵌入式软件。
使用一种仿真环境来对闭环电机控制系统的行为进行建模和验证。设定控制系统行为后,从控制器模型生成 C 代码。在检查代码后,通过使用处理器在环 (PIL) 测试来评估其功能性行为和执行时间。
如图所示:
为便于进行 PIL 测试,请选择测试信号来运行控制器模型并建立参考输出。查看一个针对 Texas Instruments™ F28335 处理器的 PIL 实现示例,该处理器通过串行连接与开发计算机上的 Simulink® 通信。可以基于此示例针对您自己的处理器创建一个 PIL 实现。要测量执行时间并根据仿真参考输出验证在嵌入式处理器上的代码的执行行为,请在 PIL 模式下运行控制器模型。
在嵌入式处理器的最终实现中,您将所生成的控制器 C 代码与其他嵌入式软件(例如与电机硬件对接所需的外设和中断)进行集成。
注释
Simscape™ Electrical™ 是"通过系统仿真验证行为"一节中的系统仿真所必需的。对其他任务而言,它不是必需的。
Texas Instruments F28335 PIL 实现是一种可应用于其他处理器的参考方法。但如果您要直接使用此实现,则需要 Texas Instruments 提供的其他支持文件、编译器和工具。有关详细信息,请参阅此示例中的"创建 PIL 实现和向 Simulink 注册"。该参考 PIL 实现不需要 Embedded Coder® 的 Texas Instruments C2000™ 嵌入式目标功能,但鼓励 C2000 用户使用附加功能资源管理器安装 Texas Instruments C2000 支持包。
通过系统仿真验证行为
在本节中,在闭环系统仿真中验证控制器。
系统模型测试平台包括测试输入、嵌入式处理器、电力电子元件和电机硬件以及可视化。可以使用系统模型来运行控制器并探索其预期行为。可以使用以下命令来执行模型并绘制记录的信号。
cpp
open_system('PMSMSystem');
out_system = sim('PMSMSystem');
pmsmfoc_plotsignals(out_system.logsout);
如图所示:
绘图显示电机在 motor_on 信号为真 (true) 之前一直处于静止状态。然后,电机以开环方式开始旋转,直到编码器的索引脉冲指示检测到已知位置。然后,控制器会转换到闭环操作,并且电机达到稳态速度。
探索模型架构
本节探讨模型架构,包括如何设定数据、如何从测试平台对控制器分区以及如何调度控制器。此架构便于进行系统仿真、算法代码生成和 PIL 测试。
数据定义文件会创建仿真和代码生成所需的 MATLAB® 数据。系统测试平台模型的 PreLoadFcn 回调会自动运行数据定义文件。
cpp
edit('pmsmfoc_data.m')
在系统测试平台模型中,会将嵌入式处理器建模为外设和控制器软件的组合。
cs
open_system('PMSMSystem/Embedded Processor');
如图所示:
控制器软件在单独的模型中指定。在该模型中,Mode_Scheduler 子系统使用 Stateflow® 来调度 Motor_Control 算法的不同操作模式。
cs
open_system('PMSMController');
如图所示:
在 Motor_Control 子系统中,传感器信号转换为工程单位并传递给核心控制器算法。控制器算法会计算电压。然后,电压将转换为驱动信号。
cs
open_system('PMSMController/Motor_Control');
如图所示:
磁场定向控制器起主要控制作用。该控制器用低速率外环控制速度,用高速率内环控制电流。
cpp
open_system('PMSMController/Motor_Control/Field_Oriented_Controller');
如图所示:
速度控制器外环以电流控制循环时间的倍数执行。可以查看指定这些采样时间的 MATLAB 变量:
cpp
fprintf('High rate sample time = %f seconds\n', ctrlConst.TsHi)
fprintf('Low rate sample time = %f seconds\n', ctrlConst.TsLo)
High rate sample time = 0.000040 seconds
Low rate sample time = 0.005000 seconds
请注意,控制器算法中的最高速率为 25 kHz。
cs
fprintf('High rate frequency = %5.0f Hz\n', 1/ctrlConst.TsHi)
High rate frequency = 25000 Hz
生成用于集成到嵌入式应用程序的控制器 C 代码
在本节中,生成并目视检查控制器的 C 代码函数。
为便于集成,将控制器模型配置为单任务模式,以便可以使用一个函数调用来调用生成的代码。此函数可处理较低和较高的速率。所生成的控制器函数必须以高速采样时间执行。
函数原型在模型配置参数中指定,输入和输出端口作为参数传递。可以查看控制器算法的函数设定。
cs
mdlFcn = RTW.getFunctionSpecification('PMSMController');
disp(mdlFcn.getPreview('init'))
disp(mdlFcn.getPreview('step'))
Controller_Init ( )
error = Controller ( motor_on, command_type, current_request, * sensors, * pwm_compare )
通过在生成的代码中使用全局结构体,可以访问磁场定向控制器的比例增益和积分增益。全局结构体在数据定义文件中指定。
cs
disp(ctrlParams.Value)
disp(ctrlParams.CoderInfo)
Current_P: 10
Current_I: 10000
Velocity_P: 0.0050
Velocity_I: 0.0150
Position_P: 0.1000
Position_I: 0.6000
StartupAcceleration: 1
StartupCurrent: 0.2000
RampToStopVelocity: 20
AdcZeroOffsetDriverUnits: 2.2522e+03
AdcDriverUnitsToAmps: 0.0049
EncoderToMechanicalZeroOffsetRads: 0
PmsmPolePairs: 4
Simulink.CoderInfo
StorageClass: 'ExportedGlobal'
Identifier: ''
Alignment: -1
从模型生成 C 代码。
cs
slbuild('PMSMController');
### Starting build procedure for: PMSMController
### Successful completion of build procedure for: PMSMController
Build Summary
Top model targets built:
Model Action Rebuild Reason
================================================================================================
PMSMController Code generated and compiled. Code generation information file does not exist.
1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 29.573s
使用生成的报告检查生成的 C 代码文件,并验证生成了正确的单步函数和初始化函数。还要验证参数结构体是作为全局变量创建的。
指定控制器模型的参考行为
在本节中,指定测试输入和参考输出,以帮助验证 PIL 测试期间的行为和探查执行时间。
制作控制器模型的一个本地副本,并加载一组在控制器内运行不同模式的测试输入信号。配置控制器模型以将记录的信号连接到输入端口。然后执行控制器模型,并将输出端口信号记录到工作区。
指定参考行为和测试环境的控制器模型的配置参数将按如下所述进行更改。指定控制器模型设计和生成生产代码的模块和参数不会更改。但是,为避免修改安装的控制器模型的任何部分,请保存模型并将其名称更改为 PMSMControllerLocal.slx。
cpp
save_system('PMSMController','PMSMControllerLocal.slx')
close_system('PMSMSystem',0);
close_system('PMSMController',0);
如图所示:
要探查执行时间,请选择一组将在控制器中执行关注路径的测试输入。获取这些测试输入和参考输出的一种方法是从系统仿真模型中记录它们。
cpp
in.motor_on = out_system.logsout.getElement('motor_on').Values;
in.command_type = out_system.logsout.getElement('command_type').Values;
in.command_value = out_system.logsout.getElement('command_value').Values;
in.sensors = out_system.logsout.getElement('sensors').Values;
disp(in)
motor_on: [1×1 timeseries]
command_type: [1×1 timeseries]
command_value: [1×1 timeseries]
sensors: [1×1 struct]
可以将信号附加到输入端口并将信号导入控制器模型中,以便它可以在系统模型中直接独立执行。这种方法的优点是您可以将控制器模型作为独立组件进行测试和验证,以便于重用和与其他系统模型或闭环测试平台进行集成。要详细说明或准备用于测试的控制器模型,请更改其配置参数,以附加输入信号并将日志信号记录在 MATLAB 工作区中。可以通过"配置参数"对话框进行更改,或以编程方式进行更改,如下所示。
cs
set_param('PMSMControllerLocal',...
'LoadExternalInput', 'on',...
'ExternalInput', 'in.motor_on, in.command_type, in.command_value, in.sensors',...
'StopTime','0.06',...
'ZeroInternalMemoryAtStartup','on',...
'SimulationMode', 'normal')
save_system('PMSMControllerLocal.slx')
现在,可以执行控制器模型并绘制与 PWM Compare 输出端口相关联的信号。
cs
out = sim('PMSMControllerLocal');
controller_mode = out.logsout.getElement('controller_mode').Values;
pwm_compare_ref = out.logsout.getElement('pwm_compare').Values;
pmsmfoc_plotpwmcompare(controller_mode, pwm_compare_ref)
如图所示:
记录的输出用作 PIL 测试的参考行为。
请注意,绘图带有注释,描述在每个时间步上有关控制器模式的信息。此模式信息在解释执行探查信息时非常有用。
创建 PIL 实现
在本节中,学习并使用一个示例 PIL 实现。首先查看 Embedded Coder 提供的先决条件帮助文档。然后将示例 PIL 实现复制到您的本地文件夹中,并向 Simulink 注册该实现。查看用于开发 PIL 实现的方法,并探索相关联的文件以获得更多见解。如果使用 Spectrum Digital Inc. 的具有 Code Composer v4 的 eZdsp F28335 板卡和串行连接,可以配置 PIL 实现以与控制器模型配合使用。如果使用的是其他处理器,则可以使用 PIL 实现作为实现的起点。
Create PIL Target Connectivity Configuration for Simulink中描述了创建自定义 PIL 实现的基础知识。熟悉使用 rtiostream API 的概念,以便在 PIL 测试期间在 Simulink(主机端)和嵌入式处理器(目标端)之间进行通信。请注意,Embedded Coder 提供默认 TCP/IP 实现的主机端驱动程序(适用于 Simulink 支持的所有平台)以及一个仅适用于 Windows® 的版本来支持串行通信。使用联编文件编译生成的代码。请参阅Customize Template Makefiles。要创建 PIL 实现,您必须在嵌入式环境中执行若干任务,包括编写目标端通信驱动程序、编写用于编译生成的代码的联编文件,以及自动化下载和执行编译的可执行文件。
如图所示:
使用该方法创建的 PIL 实现可用于 Spectrum Digital Inc. 的 eZdsp F28335 板。该实现包含以下目标连接 API 组件:
-
主机端通信 - 主机端连接驱动程序配置为使用串行通信。
-
目标端通信 - 目标端通信需要使用 rtiostream 函数以及计时器访问函数的手写串行实现。
-
编译过程 - 使用基于联编文件的方法来编译可执行应用程序。
-
启动程序 - 使用 Code Composer Studio™ v4 (CCSv4) 的调试服务器脚本 (DSS) 实用工具完成下载和运行可执行文件。
PIL 实现分三个阶段进行迭代开发。在开发 PIL 实现时,可以使用类似的方法。
第 1 阶段:使用 CCSv4 创建串行通信应用程序
-
安装 CCSv4 并验证它可以与 F28335 eZdsp 板卡连接。
-
编写用于发送和接收串行数据的嵌入式应用程序。
-
测试开发计算机和嵌入式应用程序之间的串行通信。
-
确定编译器、链接器和打包器使用联编文件编译应用程序所用的命令和选项。
-
使用 DSS 实用工具从 Windows 命令提示符下载并运行应用程序。
第 2 阶段:使用 MATLAB 实现和测试嵌入式串行 rtiostream 并启动自动化
-
扩展串行应用程序以实现用于回显数据的 rtiostream API 函数。编写 rtIOStreamOpen 来执行常规板卡初始化,包括配置串行端口。
-
使用 rtiostream_wrapper 函数验证通过嵌入式处理器从 MATLAB 发送和接收串行数据。
-
通过使用系统命令调用 DSS 实用工具,从 MATLAB 下载并运行应用程序。
第 3 阶段:使用 Simulink 实现和测试连接配置
-
创建一个连接配置类以配置主机端串行通信,指定必须在编译过程包含 rtiostream 应用程序中的哪些目标端代码文件,指定如何访问将用于收集探查数据的计时器,并集成调用 DSS 实用工具以启动嵌入式应用程序。
-
创建一个工具设定联编文件 (target_tools.mk),它指定编译器、链接器和打包器的命令和选项。此联编文件将包含在模板联编文件 (target_tools.mk) 中。
-
创建包含 target_tools.mk 的模板联编文件 (ec_target.tmf)。
-
确定可能依赖于安装的参数,并将其存储为 MATLAB 预设项。
-
创建一个 Simulink 自定义文件,用于指定 PIL 实现什么时候是有效的。
与 PIL 实现相关联的文件包含在 Embedded Coder 中,但不在 MATLAB 路径上。要浏览这些文件,可以将它们复制到本地文件夹中。您可以通过将文件夹添加到 MATLAB 路径并刷新 Simulink 自定义来注册 PIL 实现。
cpp
addpath(genpath(fullfile('.','examplePilF28335')))
sl_refresh_customizations
使用 MATLAB 预设项指定路径信息和主机串行 COM 端口号。如果直接使用 PIL 实现,则必须根据配置指定这些预设项。
cs
setpref('examplePilF28335','examplePilF28335Dir', fullfile('.','examplePilF28335'));
setpref('examplePilF28335','CCSRootDir', 'C:\Program Files\Texas Instruments\ccsv4');
setpref('examplePilF28335','TI_F28xxx_SysSWDir', 'C:\Program Files\Texas Instruments\TI_F28xxx_SysSW');
setpref('examplePilF28335','targetConfigFile', fullfile('.','examplePilF28335','f28335_ezdsp.ccxml'));
setpref('examplePilF28335','baudRate', 115200);
setpref('examplePilF28335','cpuClockRateMHz', 150);
setpref('examplePilF28335','boardConfigPLL', 10);
setpref('examplePilF28335','COMPort', 'COM4');
请注意,TI_F28xxx_SysSWDir 预设项指向 Texas Instruments 在其 C2000 Experimenter Kit Application Software (sprc675.zip) 中提供的一个文件夹。这些文件不包括在 Embedded Coder 中。
现在即可使用该 PIL 实现。
准备用于 PIL 测试的控制器模型
查看用于注册 PIL 实现的自定义文件,设置模型的配置参数以使用 PIL 实现,并启用控制器输出和执行探查数据的记录。
当开始 PIL 仿真时,Simulink 会检查注册的 PIL 实现是否有效。自定义文件指定哪些配置参数对应于有效的 PIL 实现。可以通过调用以下命令来浏览该实现的自定义文件。
cpp
edit(fullfile('.','examplePilF28335','sl_customization.m'));
请注意,该文件指定使用 PIL 实现所需的硬件设备和模板联编文件的设置。可以修改控制器模型中的配置参数以匹配设置。可以通过"配置参数"对话框进行修改,或以编程方式进行修改,如下所示。
cpp
set_param('PMSMControllerLocal',...
'ProdHWDeviceType', 'Texas Instruments->C2000',...
'TemplateMakefile', 'ec_target.tmf',...
'GenCodeOnly', 'off',...
'SimulationMode', 'processor-in-the-loop (pil)')
对于 PIL 仿真,请启用代码执行探查,从而将执行时间度量记录在变量 executionProfile 中。
cs
set_param('PMSMControllerLocal',...
'CodeExecutionProfiling', 'on',...
'CodeExecutionProfileVariable','executionProfile',...
'CodeProfilingSaveOptions','AllData');
save_system('PMSMControllerLocal.slx')
现在,可以运行控制器模型的 PIL 仿真。
测试生成的代码的行为和执行时间
在本节中,在 PIL 模式下运行控制器模型,并了解行为和执行的探查结果。验证编译的控制器代码的行为是否与参考仿真行为一致,然后验证代码的执行是否符合计时要求。
可以运行模型并绘制 PIL 仿真结果。当您第一次运行该模型时,Embedded Coder 会生成算法代码,将算法代码与串行通信接口代码链接,编译嵌入式应用程序,将应用程序下载到板卡,并开始进行目标系统上的仿真。请注意,在后续的 PIL 仿真过程中,仅当更改模型时,才会重新生成代码。由于存在与串行通信接口相关联的开销,PIL 仿真的运行速度可能比普通模式仿真慢。
以下 MATLAB 命令有意被注释掉,因为它们需要连接到硬件和使用前面所述的嵌入式开发工具。如果您连接了硬件并安装了嵌入式开发工具,请取消注释并执行这些行以运行模型,绘制结果,并验证其行为在数值上等同于普通模式仿真。否则,请继续阅读本节以了解 PIL 执行分析选项。
cs
% UNCOMMENT THE BELOW LINES TO RUN THE SIMULATION AND PLOT THE RESULTS
% if exist('slprj','dir'), rmdir('slprj','s'); end
% out = sim('PMSMControllerLocal')
% pwm_compare_pil = out.logsout.getElement('pwm_compare').Values;
% pmsmfoc_plotpwmcompare_pil(controller_mode, pwm_compare_pil, executionProfile)
如图所示:
上一张图是控制器 PWM Compare 的输出。请注意,PIL 仿真输出看起来与"建立控制器模型的参考行为"一节中所示的普通模式仿真输出相同。要检查数值等效性,可以从 PIL 仿真输出中减去普通模式仿真输出:
cs
% UNCOMMENT THE BELOW LINE TO VERIFY NUMERIC EQUIVALENCE OF THE OUTPUTS
% pilErrorWithRespectToReference = sum(abs(pwm_compare_pil.Data - pwm_compare_pil.Data))
pilErrorWithRespectToReference =
0 0 0
下图是在每个仿真时间步中执行控制器模型所花费的时间。"Stand By"状态需要的时间最少。执行时间中存在周期性小峰值,这是因为控制器是多速率、单任务型。周期性峰值对应于在同一任务中同时运行基本速率和 5 毫秒速率代码所需的时间。
由于控制器在嵌入式处理器上必须以 25 kHz 的速度执行,因此该算法必须在 40 微秒内完成执行(减去其他代码的额外余量要求,这些代码也可能在最终应用程序上执行)。探查结果表明,该算法将在为嵌入式环境的配置分配的时间内执行。
现在已经验证,生成的代码可提供在数值上等同的结果,并满足测试用例的执行计时要求。
cs
close_system('PMSMControllerLocal',0);
close_system('power_utile',0);
此 PIL 实现中使用的 MATLAB 预设项在各 MATLAB 会话之间持久保留。如果要删除预设项,请运行以下命令:
cpp
rmpref('examplePilF28335');
rmexamplePilF28335hooks();
结论
该示例使用永磁同步电机的磁场定向控制算法,说明如何使用系统级仿真和算法代码生成来探索控制器算法的功能性行为。该示例还展示嵌入式处理器的目标集成、功能测试和执行探查的一般方法。一旦算法行为正确,您就可以从控制器模型生成代码,并在目标处理器上测试和探查代码。要进行进一步测试,可以将验证过的算法代码和与电机硬件对接的嵌入式软件集成在一起。