This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28377D:DCL 控制器功能即使在输入正错误的情况下也输出负值

Guru**** 2563930 points
Other Parts Discussed in Thread: C2000WARE, SFRA

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1105555/tms320f28377d-dcl-controller-function-outputting-negative-values-even-with-positive-error-input

器件型号:TMS320F28377D
主题中讨论的其他器件:C2000WARESFRA

您好!

有点令人困惑、但我想知道为什么运行2P2Z 控制器的数字控制库函数可能会输出负值、尤其是在错误输入为正时。  

我已经多次尝试更改系数、但在调用函数后、我通常会返回一个明显的负电压、这使得控制器非常无用。 下面是一个屏幕截图:

即使在 ADC 引脚输入零电压以测量误差计算电压的情况下、该函数也经常返回负浮点值。 这只是一个系数问题吗?

如果我放置一个非常小的增益 Kdc (我使用的是 C2000Ware 补偿设计器)、电压输出可以是正的、但非常小。 然后、当我增加 KDC 增益时、函数的输出返回负值。 这非常令人沮丧、因为您会认为增加增益只会增加控制器输出、而不会使其变为负。  

我基本上是从 DCL 库示例编写此代码、并执行完全相同的函数。

是否有人可以提出可能发生这种情况的原因并提出可能的解决方法?  

编辑:我注意到在 DCL 用户指南中、以下内容:  

步骤3. 在链接器命令文件中分配控制器函数在 FPU32或 C28x 内核上运行的 DCL 函数可分配给链接器命令文件中的特定存储器块。 通常将控制器功能置于零等待状态内部 RAM 中、因为这允许控制器功能以器件的最高速度运行。 请注意、所有 CLA 函数都必须从内部零等待状态 RAM 运行。 所有 DCL 库函数都放置在用户定义的代码段.dclfuncs 中。 下面显示了如何将此段映射到内部 L4 RAM 存储器块的示例。dclfuncs:>RAML4,page = 0另请参见项目示例中的链接器命令文件 F28069_DCL.cmd (第5章)。 在独立应用中、代码必须存储在非易失性存储器(例如内部闪存)中、并在运行时复制到 RAM 中。 有关如何执行此操作的信息,请参阅使用数字控制库20应用手册“从 TMS320F28xxx DSP 上的内部闪存运行应用程序”,TI 文献编号 SPRA958。 有关链接器段分配的信息,请参阅《TMS320C28x 汇编语言工具用户指南》。  

我不确定我是否已经执行了此操作-如果我没有执行上述步骤、控制器代码是否会运行?  
如果代码能够在没有上述内容的情况下运行、它是否会导致控制器输出结果出现重大问题?
看起来运行正常-但我不确定它的执行速度以及我所展示的控制器输出结果的准确性:如果有人能够通过电子邮件将 F28069_DCL.cmd 文件发送给我、这将是一个很好的帮助: j.holland3@newcastle.ac.uk -由于我仍然遇到 C2000Ware 文件夹没有任何工程属性的问题、其中也没有包含命令文件。 我认为这可以解决我的问题。

此致、

Joel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我意识到我对该代码使用了部分控制器结果。 我将其更改为使用 DF22_L1、这是完整的控制器实现。 但是、即使是非常小的系数、我的控制器现在也会从+INF 回弹到-INF、在最大和最小占空比之间切换:

    任何建议都受到欢迎,根本不知道这里发生了什么。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Joel、

    请注意、今天的30日是美国假日、您应该期待明天美国时间我们的一位工程师提供技术回复。

    最棒的

    Matthew

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Matthew、  

    只需在这里为 DCL/CLA 代码输入我的代码、看看是否有人可以发现代码有问题。  

    #include "DCLCLA.h"
    #include "F2837xD_Cla_typedefs.h"
    #include <stdbool.h>
    #include "F2837xD_Cla_defines.h"
    #include "F28x_Project.h"
    
    // Digital Control Library Structures
    DCL_DF22_CLA v_ctrl2;              // Pre-computation controller structure definition for voltage compensation
    DCL_DF11_CLA i_ctrl2;              // Pre-computation controller structure definition for current compensation
    
    float32_t flagVolts, flagCurr;         // Clamp flag variables
    float32_t i_upperLim, i_lowerLim;      // Upper clamp limit of digital compensation block
    float32_t v_upperLim, v_lowerLim;      // Lower clamp limit of digital compensation block
    
    // Sensor data that is passed from the CLA to CPU must be declared as external (shared memory)
    //extern uint16_t inputVolts;
    extern float32_t flyVolts, flyCurr;
    extern float32_t cathodeRef;            // Soft-started from CPU1 ISR background loop
    extern float32_t flyback_command;
    float32_t clamp_switch;                  // Clamp switch is not communicated to CPU1 so does not need external declaration
    float32_t voltage_command;               // Fly-back command only needs to be defined as shared variable in CPU1
    float32_t voltageCommand_partialResult;
    float32_t voltage_command_neg_check;
    float32_t flyback_command_neg_check;
    
    float32_t controllerDifference;
    
    // Feedback the HRPWM calculations to CPU1
    extern uint32_t compCount_clamp;
    extern uint32_t compCount_flyback;
    
    // Error values
    float32_t voltError, currError;
    
    // CLA1 C Task Prototypes
    __interrupt void Cla1Task1();
    __interrupt void Cla1Task2();
    __interrupt void Cla1Task3();
    __interrupt void Cla1Task4();
    __interrupt void Cla1Task5();
    __interrupt void Cla1Task6();
    __interrupt void Cla1Task7();
    __interrupt void Cla1Task8();
    
    interrupt void Cla1Task1 (void)
    {
    
    // 100MHz/100 = 1MHz.
    uint32_t HRPWM_FLY_PERIOD_CLA = 100UL;
    
    // Calculate the error signal
    voltError = 1.338f - flyVolts;
    
    // Clamp the error to zero, avoid negative error values
    // At zero error, the duty cycle should go to zero - with negative values it still shows the error being 3.0f.
    if(voltError < 0) voltError = 0.000f;
    
    // run full controller, L1. L2 is partial controller.
    voltage_command = DCL_runDF22_L1(&v_ctrl2, voltError);
    voltage_command_neg_check = voltage_command;       // Check if negative, before clamp action applied
    
    voltageCommand_partialResult = DCL_runDF22_L2(&v_ctrl2, voltError);
    
    // Call clamp function to clamp result and set clamp flag to check range
    flagVolts = DCL_runClamp_L1(&voltage_command, v_upperLim, v_lowerLim);
    
            // Check that the immediate part of the controller is "in range"
            if (0.0f == flagVolts)
            {
                DCL_runDF22_L3(&v_ctrl2, voltError, voltage_command);
            }
    
            controllerDifference = voltage_command - voltageCommand_partialResult;
    
             if(voltage_command < 0.000f) voltage_command = 0.000f;
    
            // Clamp maximum and minimum average current command to inner current loop
            voltage_command = (voltage_command > v_upperLim)?
                                    v_upperLim:voltage_command;
            voltage_command = (voltage_command < v_lowerLim)?
                                    v_lowerLim:voltage_command;
    
    // Calculate the average current error using the previous compensated voltage error as target reference
    // DCL library uses floats, but flyCurr is an int, so type-cast
    currError = voltage_command - flyCurr;
    
    // Run partial DF11 Controller and clamp function
    flyback_command = DCL_runDF11_L1(&i_ctrl2, currError);
    flyback_command_neg_check = flyback_command; // Before clamping, let's see if negative output value
    
            // Clamp maximum and minimum duty cycles
            // sets to between 0.1 and 0.35
            flyback_command = (flyback_command > i_upperLim)?
                                    i_upperLim:flyback_command;
            flyback_command = (flyback_command < i_lowerLim)?
                                    i_lowerLim:flyback_command;
    
            clamp_switch = (1 - flyback_command);
    
            // HRPWM Calculations
            float32_t count_clamp = (flyback_command * (float32_t)(HRPWM_FLY_PERIOD_CLA/2 << 8));
                            compCount_clamp = (count_clamp);
                            uint32_t hrCompCount_clamp = (compCount_clamp & (0x000000FF));
                            if (hrCompCount_clamp == 0)
                            {
                                // Add 1 to not have CMPxHR = 0
                                compCount_clamp |= 0x00000001;
                            }
    
            float32_t count_flyback = (clamp_switch * (float32_t)(HRPWM_FLY_PERIOD_CLA/2 << 8));
                            compCount_flyback = (count_flyback);
                            uint32_t hrCompCount_flyback = (compCount_flyback & (0x000000FF));
                            if (hrCompCount_flyback == 0)
                            {
                            // Add 1 to not have CMPxHR = 0
                            compCount_flyback |= 0x00000001;
                            }
    }
    
    __interrupt void Cla1Task2 ( void ) {}
    
    __interrupt void Cla1Task3 ( void ) {}
    
    __interrupt void Cla1Task4 ( void ) {}
    
    __interrupt void Cla1Task5 ( void ) {}
    
    _interrupt void Cla1Task6 ( void ) {}
    
    __interrupt void Cla1Task7 ( void ) {}
    
    //Task 8 will initialize the variables used in Task 3
    __interrupt void Cla1Task8 ( void ) {
    //  __mdebugstop();
    
        // Initialise DF22 Full Voltage Controller Compensation Coefficients
        // Use the GUI in POWERSUITE for Digital Compensation for easy coefficient calculations according to the poles and zeroes in HZ
        v_ctrl2.a1 = 1.1201983f;
        v_ctrl2.a2 = -0.1201983f;
        v_ctrl2.b0 = 0.0798453f;
        v_ctrl2.b1 = -0.1482259f;
        v_ctrl2.b2 = 0.0686588f;
    
        // Initialise DF11 Full Current Controller Compensation Coefficients
        i_ctrl2.a1 = 0.21606f;
        i_ctrl2.b0 = 0.22090f;
        i_ctrl2.b1 = 0.31307f;
    
        // clamp limits of both the voltage and current controllers
        v_upperLim = 100.000f;    //3.000f replaced, just for voltage mode control for now    // 3A (3V) average current limitation
        v_lowerLim = -100.000f;
        i_upperLim = 0.850000f;       // 35% duty cycle limitation maximum
        i_lowerLim = 0.1500f;         // 0% minimum duty cycle limitation
        flyback_command = 0.0f;       // Initialise fly-back command
        voltage_command = 0.0f;       // Initialise average current reference command
        voltageCommand_partialResult = 0.0f;
        controllerDifference = 0.0f;
    
        voltError = 0.0f;             // Initialise voltage and current errors
        currError = 0.0f;
    
        voltage_command_neg_check = 0.000f;
        flyback_command_neg_check = 0.000f;
    
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joel、

    感谢您共享代码。 我看到您正在为同一补偿器(v_ctrl2)在同一 CLA 任务中调用 DF22函数的 L1、L2和 L3。 这不是我们为这些函数设计的。 您应该单独使用 L1/L4或使用 L2 + L3。 除非您有特定的原因来分离补偿器(控制信号的饱和或早期更新)、否则将更容易为补偿器使用 L1/L4。

    我必须消除在 CMD 文件或其他位置设置时可能出现的错误的一个建议是使用 L4、L4在 C 中实现、不应受任何其他设置的影响。

    关于补偿器系数、您是否尝试使用 MATLAB Simulink 等仿真软件来仿真补偿器系数? 在硬件上尝试之前、您可以确保它在仿真中正常工作。 我们有一个补偿器设计器工具(位于 C2000数字电源 SDK https://www.ti.com/tool/C2000WARE-DIGITALPOWER-SDK 库中的 SFRA 文件夹下)、您可以使用该工具根据所需的增益和极点/零点位置生成补偿器系数。

    此致、

    韩文

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好  。 我现在尝试仅使用 L4、因此没有汇编、但仍然有问题。 控制器的输出就在这里。

    我偶然发现了导致问题的原因、但我不知道为什么或如何解决。  

    而不是通过获取基准并减去反激式输出电压来计算误差电压:

    voltage_error = cathodeRef - flyVolts;

    下面是调试器的图形、您可以看到它位于整个位置:

    相反、我使用不使用 ADC 样本的固定误差电压初始化代码:

    voltage_error = 3.0f;

    以下是该版本的调试器的图形:

    控制器输出固定在0.01823左右!

    控制器似乎具有良好的恒定固定输出。 当我使用第一个代码时、输出电压完全不稳定、并且几乎会振荡、即使 ADC 电压传感器被指定为零伏。  

    导致此行为的原因可能是什么? 如何初始化 CPU1和 CLA1之间共享的存储器是否可能存在问题? 我不确定情况是否如此、因为在调试器中、我们可以看到 FlyVolts 和 ERROR_VOLTAGE 正在正确计算。 阴极 ADC 值读数的这些极小的浮点值变化会导致控制器完全不稳定、但如果我们将其从公式中取出、则完全稳定!

    有什么建议可以从这里出发去哪里?

    最棒的
    Joel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joel、

    不太可能是设置问题。 您可能需要优化补偿器设计(尤其是在尚未验证的情况下)。 DCL 库版本的 models 文件夹中确实包含 DCL 块(包括 DF22)的 Simulink 模型。

    如果您仍然有问题、您可以尝试从 CLA 收集 VOLTGE_ERROR 并将其绘制在图形上。 这样、您就可以验证您的反馈值是否是问题。

    您还可以通过在 RAM 中收集反馈和控制输出、将它们导出到 PC 并在 PC 上验证计算结果、来验证 CLA 中的补偿器计算。

    我没有看到您的反馈信号是什么样子的、但是如果您的补偿器过于激进并且使输出电压快速振荡、则控制信号看起来似乎是合理的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经使用了 C2000 DF22计算器、并将系数设置为等于我希望在所选频率下放置极点和零点的系数。 明天我将尝试 MATLAB 等。  

    如果控制器的最佳增益值导致控制器的输出低于所需的最小占空比、会发生什么情况? 是否可以接受用某个换算值“换算”控制器输出? 将控制器输出乘以附加增益是否会导致控制器不正确? 我知道您可以通过增大控制器的 B 系数值来增大实际控制器的增益、但这似乎是导致控制器输出不稳定的原因。  

    按附加因素调整实际控制器输出是否会导致不稳定问题?  

    为清楚起见、我的反激电压可以是0.0001、这会导致我的误差电压从3.0000变为2.9999、并且仍然会观察到0-15%占空比的不稳定控制器响应。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joel、

    实际上,“缩放输出”等效于更改补偿器增益。 因此、如果您以相同的方式调整输出、则在您上调控制器系数时可能发生的一切都将发生。 同样、您实际上可以首先在仿真中验证输出比例的影响、并根据需要在运行硬件测试之前查看该影响。

    韩文

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Han、

    再次查看 DCL 用户指南后、似乎在执行和调试代码之前没有重置 DCL 延迟线。 用户指南指出、为了避免错误的结果、必须在主代码中将延迟线初始化为零。

    但是、对于 DF22控制器而言、没有实现控制器延迟线复位的功能...唯一的功能是 void DCL_resetDF22 (DCL_DF22 * p)、保留在 DCLF32.h 中 该参数用于 DCL_DF22、没有允许 DCL_DF22_CLA 作为输入的复位函数。 这是为什么? 在实现 CLA 控制器时、如何将延迟线设置为零? 是否有某种机制允许在不执行此代码的情况下将控制器设置为零?

    此致...
    Joel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joel、

    如果您尝试对延迟线进行初始复位(在启用 CLA 任务之前)、您只需从 CPU 上的 DCL_DF22_CLA 结构中设置 x1和 x2、因为 CPU 对 CLA 数据 RAM 具有完全访问权限。 如果你想在启用 CLA 任务后在移动中执行它、你可以考虑在复位两个寄存器之前禁用 CLA 任务、并在之后重新启用它。 希望这能回答您的问题。 谢谢。

    韩文

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Han、

    我在 DF23 CLA 代码的另一个示例中看到、在 CLA 初始化任务中、X1、X2和 X3延迟线可以按照设置系数的相同方式设置为0.0f。 在 CLA 中、我向现有的初始化代码添加了以下内容;

    //从0dB = 1.0f 增益开始。
    V_ctrl2.A1 = 1.0062300f;
    V_ctrl2.A2 = 0.0444510f;
    v_ctrl2.A3 =-0.0506810f;
    v_ctrl2.b0 = 2.5101066f;
    v_ctrl2.b1 =-6.7263321f;
    v_ctrl2.b2 = 6.0075406f;
    v_ctrl2.b3 =-1.7883328f;
    V_ctrl2.x1 = 0.0f;
    V_ctrl2.x2 = 0.0f;
    v_ctrl2.x3 = 0.0f;

    我可以看到更多有关控制器的信息。 例如、全误差时:  

    然后、在接近零误差时:  

    尽管 X1、X2和 X3值明显下降、但 u1k 和 u2k 值仍然存在。 不确定这是否表明存在任何问题。

    对于 C2000Ware 数字补偿器设计器、您是否必须对要控制的转换器建模? 数字补偿器系数是否完全取决于要控制的转换器的模型?

    我的理解是、如果我确切地知道我的极点需要位于何处、因为我计算了它们需要来自输出电容器、电感器、 ESR 和控制频率等-我可以在数字补偿器设计器中设置这些频率并复制和粘贴输出系数、而不必担心我正在补偿的受控体。 这是错误的吗? 如果我要在 SFRA 中对降压转换器进行实际建模、即使极点和零点位置保持不变、这是否会导致数字控制器系数发生显著变化?

    最棒的
    Joel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joel、

    您可以确保以两种方式使用补偿器设计器。 如果您知道零点、极点和增益的位置、则可以将其用作仅计算补偿器系数的工具。 请确保您输入设计器的采样频率与您的采样/CLA 任务频率相匹配。

    如果您使用 SFRA 来获取功率级的频率响应、则在设计补偿器时、您将能够获得开环/闭环频率响应的交互式视图、这将帮助您做出设计决策。 这与 Mathworks 提供的 SISOtool 类似。

    BTW、我对您展示的 DF23参数进行了快速仿真。 我不确定您拥有的采样频率、但根据先前的讨论、它看起来像是1Msps。 我确实得到了一个响应、它将在进入一个常数之前振荡几轮。 请参见下图。 我在仿真中设置了1.0常量误差。 谢谢。

    韩文

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Han、

    感谢您提供了内容丰富的回复。 我认为设计人员的频率输入是缝合频率、而不是采样频率。 我以400kHz 的频率进行采样、对信号求平均值、然后以70khZ 的频率启动 CLA、这是转换器的环路带宽/交叉频率-在这种情况下、您会为设计人员输入选择哪种频率? 如果不是开关频率、是采样频率还是 ISR 频率-因为它们并不总是相同的! 极点频率将比设计人员使用的采样频率/频率高得多、因为我们通常将它们放置在开关频率(500kHz)的一半及更高的区域。

    根据您提供的 MATLAB 图、您会认为控制器在一段时间后确实是稳定的。 正如我说过的、我在 ADC 输入上保持了0V、这样除了一些余量测量或偏移之外、误差应该非常接近常量。 您是否愿意发送 MATLAB 文件、以便我了解您是如何仿真数字控制器的?  

    此致、祝您周末愉快。  
    Joel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joel、

    系统中似乎有3个频率:开关、采样和控制(CLA)更新频率。 最简单的方法(理想)是使所有3个频率保持不变。 这将避免您的设计中出现混淆。 如果您必须具有不同的值、则用于补偿器设计的值应为控制更新(CLA)频率。

    如果您的补偿器很复杂且周期数较高、或者您具有非常快的开关频率(例如1MHz)、您还可以将采样/控制频率设置为开关频率的整数分之一(除非您具有 LLC 等可变频率拓扑)。 如果您只有 DF22补偿器、我们就没有压力以400kHz 采样频率运行补偿器。

    根据数字控制理论、您的采样频率需要为环路带宽(交叉频率)的10-20倍、以保持系统稳定。 如果您具有70k 带宽且控制频率仅为70kHz、则系统将不稳定。 请确保在仿真中验证您的系统设计(包括您的采样、平均值、控制、更新方式)、以确保您的系统稳定。

    韩文

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Han、  

    我对上述发言感到十分困惑。 转换器的控制带宽是系统可以令人满意地响应的频带。 如果您的控制器具有83kHz 的带宽、如果系统无法以高于此带宽的频率响应、为何要以高于此带宽的任何频率启动控制器? 在这种情况下、数字控制器/补偿器的输出将不会有用。  

    因此、最大"控制频率"受控制器"带宽"的限制是合理的。 为什么不能在最大带宽或仅低于最大带宽启动补偿器是没有意义的、当然、正如您建议的那样、启动补偿器比启动速度更快似乎更有意义?

    您能澄清一下吗?

    此致、

    Joel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joel、

    在数字控制中,ADC 采样-->补偿器计算--> PWM 输出过程将引入~ 1.5倍采样时间的延迟,这将导致相位滞后,并在系统带宽过高(接近采样频率)时导致系统运行不稳定。 在经典控制理论中、建议采样频率> 20x 控制带宽。

    请注意 、E2E 主要用于支持客户调试问题或在其器件中遇到意外错误。 我们在这些支持中具有有限的带宽、无法深入了解控制理论。 在实际硬件实现中测试分立式控制器之前、您可能需要参考一些经典控制/数字控制文本簿、或在设计的分立式控制器上的 MATLAB Simulink 等软件中进行一些更多仿真。 这将帮助您消除设计错误和 C2000实现问题。 谢谢。

    此致、

    韩文