此示例说明从电机控制算法生成 C 代码并验证其编译行为和执行时间的基本工作流和关键 API。您将使用处理器在环 (PIL) 仿真来确保 C 代码在集成到与电机硬件对接的嵌入式软件时按预期执行。虽然此工作流使用针对特定处理器的电机控制应用程序,但您基本上可以将此工作流应用于任何应用程序或处理器。
xxrtwdemo_pmsmfoc_workflow.png
我们使用针对永磁同步电机的磁场定向控制算法来说明此工作流。这种控制技术在混合动力汽车、机械制造和工业自动化领域的电机驱动系统中很常见。

概述

在此示例中,您将从一种控制算法模型生成和验证 C 代码,您可以将此代码集成到与电机硬件对接所需的其他嵌入式软件。
您将使用一种仿真环境来对闭环电机控制系统的行为进行建模和验证。设定控制系统行为后,您将从控制器模型生成 C 代码。在检查代码后,您将使用处理器在环 (PIL) 测试来评估其功能性行为和执行时间。
xxrtwdemo_pmsmfoc_pil.png
为便于进行 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 支持包。


通过系统仿真验证行为


在本节中,您将在闭环系统仿真中验证控制器。
系统模型测试平台包括测试输入、嵌入式处理器、电力电子元件和电机硬件以及可视化。您可以使用系统模型来运行控制器并探索其预期行为。您可以使用以下命令来执行模型并绘制记录的信号。
open_system('rtwdemo_pmsmfoc_system')
  • out_system = sim('rtwdemo_pmsmfoc_system')
  • rtwdemo_pmsmfoc_plotsignals(out_system.logsout)
  • out_system =
  •   Simulink.SimulationOutput:
  •                 logsout: [1x1 Simulink.SimulationData.Dataset]
  •      SimulationMetadata: [1x1 Simulink.SimulationMetadata]
  •            ErrorMessage: [0x0 char]
  • 复制代码
    PMSMFieldOrientedControlExample_01.png
    PMSMFieldOrientedControlExample_02.png
    绘图显示电机在 motor_on 信号为真 (true) 之前一直处于静止状态。然后,电机以开环方式开始旋转,直到编码器的索引脉冲指示检测到已知位置。然后,控制器会转换到闭环操作,并且电机达到稳态速度。

    探索模型架构

    在本节中,您将探讨模型架构,包括如何设定数据、如何从测试平台对控制器分区以及如何调度控制器。此架构便于进行系统仿真、算法代码生成和 PIL 测试。
    数据定义文件会创建仿真和代码生成所需的 MATLAB® 数据。此数据文件会自动在系统测试平台模型的 PreLoadFcn 回调中运行。
    edit('rtwdemo_pmsmfoc_data.m')
    复制代码
    在系统测试平台模型中,会将嵌入式处理器建模为外设和控制器软件的组合。
    open_system('rtwdemo_pmsmfoc_system/Embedded Processor')
    复制代码
    PMSMFieldOrientedControlExample_03.png
    控制器软件在单独的模型中指定。在该模型中,Mode_Scheduler 子系统使用 Stateflow® 来调度 Motor_Control 算法的不同操作模式。
    open_system('rtwdemo_pmsmfoc')
    复制代码
    PMSMFieldOrientedControlExample_04.png
    在 Motor_Control 子系统中,传感器信号转换为工程单位并传递给核心控制器算法。控制器算法会计算电压。然后,电压将转换为驱动信号。
    open_system('rtwdemo_pmsmfoc/Motor_Control')
    复制代码
    PMSMFieldOrientedControlExample_05.png
    磁场定向控制器起主要控制作用。该控制器用低速率外环控制速度,用高速率内环控制电流。
    open_system('rtwdemo_pmsmfoc/Motor_Control/Field_Oriented_Controller')
    复制代码
    PMSMFieldOrientedControlExample_06.png
    速度控制器外环以电流控制循环时间的倍数执行。您可以查看指定这些采样时间的 MATLAB® 变量:
    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。
    fprintf('High rate frequency = %5.0f Hz\n', 1/ctrlConst.TsHi)
  • High rate frequency = 25000 Hz
  • 复制代码
    生成用于集成到嵌入式应用程序的控制器 C 代码

    在本节中,您将生成并目视检查控制器的 C 代码函数。
    为便于集成,将控制器模型配置为单任务模式,以便可以使用一个函数调用来调用生成的代码。此函数可处理较低和较高的速率。所生成的控制器函数必须以高速采样时间执行。
    函数原型在模型配置参数中指定,输入和输出端口作为参数传递。您可以查看控制器算法的函数设定。
    mdlFcn = RTW.getFunctionSpecification('rtwdemo_pmsmfoc');
  • disp(mdlFcn.getPreview('init'))
  • disp(mdlFcn.getPreview('step'))
  • Controller_Init ( )
  • error = Controller ( motor_on, command_type, current_request, * sensors, * pwm_compare )
  • 复制代码
    通过在生成的代码中使用全局结构体,可以访问磁场定向控制器的比例增益和积分增益。此全局结构体在数据定义文件中指定。
    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.2523e+03
  •                  AdcDriverUnitsToAmps: 0.0049
  •     EncoderToMechanicalZeroOffsetRads: 0
  •                         PmsmPolePairs: 4
  • Simulink.CoderInfo
  •     StorageClass: 'ExportedGlobal'
  •       Identifier: ''
  •        Alignment: -1
  • 复制代码
    从模型生成 C 代码,如下所示。
    slbuild('rtwdemo_pmsmfoc')
  • ### Starting build procedure for: rtwdemo_pmsmfoc
  • ### Successful completion of build procedure for: rtwdemo_pmsmfoc
  • Build Summary
  • Top model targets built:
  • Model            Action                       Rebuild Reason                                    
  • ================================================================================================
  • rtwdemo_pmsmfoc  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 59.217s
  • 复制代码
    使用生成的报告检查生成的 C 代码文件,并验证生成了正确的单步函数和初始化函数。还要验证参数结构体是作为全局变量创建的。

    建立控制器模型的参考行为

    在本节中,您将建立测试输入和参考输出,以帮助验证 PIL 测试期间的行为和探查执行时间。您将制作控制器模型的一个本地副本,然后加载一组在控制器内运行不同模式的测试输入信号。然后,您将配置控制器模型,以将这些记录的信号附加到输入端口,执行控制器模型,并将输出端口信号记录到工作区。
    用于建立参考行为和测试环境的控制器模型的配置参数将按如下所述进行更改。用于指定控制器模型设计和生成生产代码的模块和参数不会更改。但是,为避免修改安装的控制器模型的任何部分,请保存模型并将其名称更改为 rtwdemo_pmsmfoc_local.slx。
    save_system('rtwdemo_pmsmfoc','rtwdemo_pmsmfoc_local.slx')
  • close_system('rtwdemo_pmsmfoc_system',0);
  • close_system('rtwdemo_pmsmfoc',0);
  • omCallMethod failed on slmsgviewer.renameTab
  • 复制代码
    PMSMFieldOrientedControlExample_07.png
    要探查执行时间,请选择一组将在控制器中执行关注路径的测试输入。获取这些测试输入和参考输出的一种方法是从系统仿真模型中记录它们。
    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;
  • display(in)
  • in =
  •   struct with fields:
  •          motor_on: [1×1 timeseries]
  •      command_type: [1×1 timeseries]
  •     command_value: [1×1 timeseries]
  •           sensors: [1×1 struct]
  • 复制代码
    这些信号现在可以附加到输入端口并导入控制器模型中,使其可以独立于系统模型直接执行。这种方法的优点是可以将控制器模型作为独立组件进行测试和验证,从而便于重用和与其他系统模型或闭环测试平台进行集成。要详细说明或准备用于测试的控制器模型,请更改其配置参数,以附加输入信号并将日志信号记录在 MATLAB® 工作区中。这些更改可以图形化界面方式在模型的“Configuration Parameters”对话框中进行,或以编程方式进行,如下所示。
    set_param('rtwdemo_pmsmfoc_local',...
  •     'LoadExternalInput', 'on',...
  •     'ExternalInput', 'in.motor_on, in.command_type, in.command_value, in.sensors',...
  •     'StopTime','0.06',...
  •     'ZeroInternalMemoryAtStartup','on',...
  •     'SimulationMode', 'normal')
  • save_system('rtwdemo_pmsmfoc_local.slx')
  • 复制代码
    现在,您可以执行控制器模型并绘制与 PWM Compare 输出端口相关联的信号。
    out = sim('rtwdemo_pmsmfoc_local')
  • controller_mode = out.logsout.getElement('controller_mode').Values;
  • pwm_compare_ref = out.logsout.getElement('pwm_compare').Values;
  • rtwdemo_pmsmfoc_plotpwmcompare(controller_mode, pwm_compare_ref)
  • out =
  •   Simulink.SimulationOutput:
  •                 logsout: [1x1 Simulink.SimulationData.Dataset]
  •      SimulationMetadata: [1x1 Simulink.SimulationMetadata]
  •            ErrorMessage: [0x0 char]
  • 复制代码
    PMSMFieldOrientedControlExample_08.png
    所记录的输出将用作 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 实现,您需要在嵌入式环境中执行若干任务,包括编写目标端通信驱动程序、编写用于编译生成的代码的联编文件,以及自动化下载和执行编译的可执行文件。
    xxrtwdemo_pmsmfoc_pilapi.png
    使用上述方法,即可创建一个适用于 Spectrum Digital Inc. 的 eZdsp F28335 板卡的 PIL 实现。以下是此实现中使用的目标连接 API 组件的摘要说明。

    • Host-Side Communication - 主机端连接驱动程序配置为使用串行通信。
    • Target-Side Communication - 目标端通信需要使用 rtiostream 函数以及计时器访问函数的手写串行实现。
    • Build Process - 使用基于联编文件的方法来编译可执行应用程序。
    • Launcher - 使用 Code Composer Studio™ v4 (CCSv4) 的 Debug Server Scripting (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 实现。
    %copyfile(fullfile(matlabroot,'toolbox','rtw','rtwdemos','examplePilF28335'),'examplePilF28335','f')
  • addpath(genpath(fullfile(matlabroot,'toolbox','rtw','rtwdemos','examplePilF28335')))
  • sl_refresh_customizations
  • 复制代码
    MATLAB® 预设用于指定路径信息和主机串行 COM 端口号。如果您直接使用此 PIL 实现,则必须根据您的配置指定这些预设。
    请注意,TI_F28xxx_SysSWDir 预设指向 Texas Instruments™ 在其 C2000™ Experimenter Kit Application Software (sprc675.zip) 中提供的一个目录。这些文件不包括在 Embedded Coder® 中。
    setpref('examplePilF28335','examplePilF28335Dir', fullfile(matlabroot,'toolbox','rtw','rtwdemos','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(matlabroot,'toolbox','rtw','rtwdemos','examplePilF28335','f28335_ezdsp.ccxml'));
  • setpref('examplePilF28335','baudRate',            115200);
  • setpref('examplePilF28335','cpuClockRateMHz',     150);
  • setpref('examplePilF28335','boardConfigPLL',      10);
  • setpref('examplePilF28335','COMPort',             'COM4');
  • 复制代码
    现在即可使用该 PIL 实现。

    准备用于 PIL 测试的控制器模型

    在本节中,您将配置控制器模型以使用 PIL 实现。您将查看用于注册 PIL 实现的自定义文件,设置模型的配置参数以使用 PIL 实现,并启用记录控制器输出和执行探查数据。
    当您在 PIL 模式下开始仿真时,Simulink® 将检查已注册的 PIL 实现是否有效。自定义文件指定哪些配置参数对应于有效的 PIL 实现。您可以通过调用以下命令来浏览此实现的自定义文件。
    edit(fullfile(matlabroot,'toolbox','rtw','rtwdemos','examplePilF28335','sl_customization.m'));
    复制代码
    请注意,此文件指定使用此 PIL 实现所需的硬件设备和模板联编文件的设置。您可以修改控制器模型中的配置参数以匹配这些设置。这些更改可以图形化界面方式在模型的“Configuration Parameters”对话框中进行,或以编程方式进行,如下所示。
    set_param('rtwdemo_pmsmfoc_local',...
  •        'ProdHWDeviceType', 'Texas Instruments->C2000',...
  •        'TemplateMakefile', 'ec_target.tmf',...
  •        'GenCodeOnly', 'off',...
  •        'SimulationMode', 'processor-in-the-loop (pil)')
  • 复制代码
    您可以指定在 PIL 测试期间收集执行的探查信息,使用变量 pilOut 记录仿真输出值,使用变量 executionProfile 记录执行的探查信息。这些更改可以图形化界面方式在模型的“Configuration Parameters”对话框中进行,或以编程方式进行,如下所示。
    set_param('rtwdemo_pmsmfoc_local',...
  •     'CodeExecutionProfiling', 'on',...
  •     'CodeExecutionProfileVariable','executionProfile',...
  •     'CodeProfilingSaveOptions','AllData');
  • save_system('rtwdemo_pmsmfoc_local.slx')
  • 复制代码
    控制器模型现在即可在 PIL 模式下运行。

    测试生成的代码的行为和执行时间

    在本节中,您将在 PIL 模式下运行控制器模型,并了解行为和执行的探查结果。您将验证编译的控制器代码的行为是否与参考仿真行为一致,然后验证代码的执行是否符合计时要求。
    您可以运行模型并绘制 PIL 仿真结果。当您第一次启动该模型时,Embedded Coder® 会生成算法代码,将算法代码与串行通信接口代码链接,编译嵌入式应用程序,将应用程序下载到板卡,并开始进行目标系统上的仿真。请注意,在随后的 PIL 仿真期间,仅当模型更改时才会重新生成代码。由于存在与串行通信接口相关联的开销,PIL 仿真可能比在普通模式下的模型运行速度慢。
    以下 MATLAB® 命令有意被注释掉,因为它们需要连接到硬件和使用前面所述的嵌入式开发工具。如果您连接了硬件并安装了嵌入式开发工具,请取消注释并执行这些行以运行模型,绘制结果,并验证其行为在数值上等同于在普通模式下运行的仿真。否则,请继续阅读本节以了解 PIL 执行分析选项。
    % UNCOMMENT THE BELOW LINES TO RUN THE SIMULATION AND PLOT THE RESULTS
  • % if exist('slprj','dir'), rmdir('slprj','s'); end
  • % out = sim('rtwdemo_pmsmfoc_local')
  • % pwm_compare_pil = out.logsout.getElement('pwm_compare').Values;
  • % rtwdemo_pmsmfoc_plotpwmcompare_pil(controller_mode, pwm_compare_pil, executionProfile)
  • 复制代码
    xxrtwdemo_pmsmfoc_plotpil_zh_CN.png
    上一张图是控制器 PWM Compare 的输出。请注意,PIL 模式下的输出与“建立控制器模型的参考行为”一节中所示的普通模式下的仿真输出相同。您可以从 PIL 模式下的仿真输出中减去普通模式仿真的输出,以验证它们在数值上相等:
    % UNCOMMENT THE BELOW LINE TO VERIFY NUMERICAL 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 微秒内完成执行(减去其他代码的额外余量要求,这些代码也可能在最终应用程序上执行)。探查结果表明,该算法将在为嵌入式环境的配置分配的时间内执行。
    现在已经验证,生成的代码可提供在数值上等同的结果,并满足此测试用例的执行计时要求。
    close_system('rtwdemo_pmsmfoc_local',0);
  • close_system('power_utile',0);
  • 复制代码
    此 PIL 实现中使用的 MATLAB® 预设在各 MATLAB® 会话之间持久保留。如果要删除这些预设,请运行以下命令。
    rmpref('examplePilF28335');
  • rmexamplePilF28335hooks();
  • 复制代码
    结论

    此示例说明如何使用永磁同步电机的磁场定向控制算法进行系统级仿真和算法代码生成,以了解控制器算法的功能性行为。它还说明了对嵌入式处理器进行目标集成、功能测试和执行探查的一般方法。在验证算法行为正确后,从控制器模型生成代码,并在目标处理器上进行测试和探查。算法代码现已经过验证,可以与嵌入式软件集成,该软件与电机硬件对接以进行进一步测试。