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.

[参考译文] LAUNCHXL-F28069M:帮助使用 PID 算法对工程进行调优

Guru**** 2540720 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1550492/launchxl-f28069m-help-with-tuning-using-pid-algorithm-for-a-project

器件型号:LAUNCHXL-F28069M
主题:C2000WARE 中讨论的其他器件

工具/软件:

您好、我需要我的高级设计项目方面的帮助。  我的高级设计项目目标是创建一个 PID 负载控制器、使用电池储能系统为商业楼宇供电、以便在超过公用电网可提供的电量时对楼宇进行放电。 我使用 F28069M 微控制器的目标是使用一种算法、使实际功率需求(C 列)能够调整到相对于平均值的设定点、即 93.62KW。 我查看了 DCL 库提供的服务器代码、并尝试找到一个代码、以便我能够准确地调整值以实现快速系统响应、并以与调优值相对应的占空比生成 PWM 信号。 我查看的代码是下面提供的代码:

/* Example_F28069_pid.c
*
*版权所有 (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
保留所有权利
*
*/

//头文件
#include “F2806x_Device.h"</s>“
#include “F2806x_examples.h"</s>“
#include “F2806x_GlobalPrototypes.h"</s>“
#include “DCLF32.h"</s>“

//函数原型
外部中断无效 control_isr (void);

//全局变量
长 IdleLoopCount = 0;
长 IsrCount = 0;
浮点数= 0.25f;
浮动 YK;
浮动 lk;
Float UK;
DCL_PID pid1 = PID_DEFAULTS;
浮动占空比;
浮点数= 0.95f;
浮动 lowerlim = 0.05f;
unsigned int clampactive;


/* main */
main()

/*初始化系统*/
InitSysCtrl ();//[F2806x_sysctrl.c]
dint;//禁用中断
IER = 0x0000;
IFR = 0x0000;
InitPiectrl ();//初始化 PIE 控制寄存器[F2806x_PIECTRL.c]
InitPieVectTable ();//初始化 PIE 矢量表[F2806x_PieVect.c]
EALLOW;
PieVectTable.ADCINT1 =&CONTROL_ISR;//[F28069_PID_CISR.c]
EDIS;

/*配置 ePWM1 */
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
InitEPwm ();//[F2806x_epwm.c]
EPwm1Regs.TBCTL.BIT.CTRMODE = 3;//冻结 TB 计数器
EPwm1Regs.TBCTL.bit.PRDLD = 1;//立即加载
EPwm1Regs.TBCTL.BIT.PHSEN = 0;//禁用相位加载
EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;//禁用 SYNCOUT 信号
EPwm1Regs.TBCTL.BIT.HSPCLKDIV = 0;// TBCLK = SYSCLKOUT
EPwm1Regs.TBCTL.BIT.CLKDIV = 0;//时钟分频器=/1
EPwm1Regs.TBCTL.BIT.FREE_SOFT = 2;//在仿真暂停时自由运行
EPwm1Regs.TBPRD = 0x2328;//为 ePWM1 设置周期 (0x2328 = 10kHz)
EPwm1Regs.TBPHS.all = 0;//时基相位寄存器
EPwm1Regs.TBCTR = 0;//时基计数器寄存器
EPwm1Regs.ETSEL.BIT.SOCAEN = 1;//启用一个组上的 SOC
EPwm1Regs.ETSEL.bit.SOCASEL = 1;//从零匹配中选择 SOC
EPwm1Regs.ETPS.bit.SOCAPRD = 1;//在发生第 1 个事件时生成脉冲
EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;//启用影子模式
EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;//在 CTR =零时重新加载
EPwm1Regs.CMPA.HALF.CMPA = 0x0080;//设置比较 A 值
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;//在 CMPA 向上匹配时为高电平
EPwm1Regs.AQCTLA.bit.ZRO = AQCLEAR;//在零匹配时为低电平
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;

/*配置 ADC */
InitAdc ();//[F2806x_ADC.c]
EALLOW;
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0;//早期中断生成
AdcRegs.INTSEL1N2.bit.INT1E = 1;//启用 ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0;//禁用 ADCINT1 连续模式
AdcRegs.INTSEL1N2.bit.INT1SEL = 1;//设置 EOC1 以触发 ADCINT1
AdcRegs.INTSEL1N2.bit.INT2E = 0;//启用 ADCINT2
AdcRegs.INTSEL1N2.bit.INT2CONT = 0;//禁用 ADCINT1 连续模式
AdcRegs.INTSEL1N2.bit.INT2SEL = 0;//设置 EOC1 以触发 ADCINT2
AdcRegs.ADCSOC0CTL.BIT.CHSEL = 0;//将 SOC0 通道选择设置为 ADCINA0
AdcRegs.ADCSOC1CTL.BIT.CHSEL = 8;//将 SOC1 通道选择设置为 ADCINB0
AdcRegs.ADCSOC0CTL.BIT.TRIGSEL = 5;//由于轮循 SOC0 首先转换、然后是 SOC1、因此在 EPWM1A 上设置 SOC0 开始触发
AdcRegs.ADCSOC1CTL.BIT.TRIGSEL = 5;//由于轮循 SOC0 首先转换、然后是 SOC1、因此在 EPWM1A 上设置 SOC1 开始触发
AdcRegs.ADCSOC0CTL.BIT.ACQPS = 6;//将 SOC0 S/H 窗口设置为 7 个 ADC 时钟周期 (6 ACQPS 加 1)
AdcRegs.ADCSOC1CTL.BIT.ACQPS = 6;//将 SOC1 S/H 窗口设置为 7 个 ADC 时钟周期 (6 个 ACQPS 加 1)
EDIS;

/*配置 GPIO */
InitGpio ();//[F2806x_GPIO.c]
EALLOW;
GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;// GPIO34 = I/O 引脚
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;// GPIO34 =输出
GpioDataRegs.GPBSET.bit.GPIO34 = 1;// GPIO34 = 1
GpioCtrlRegs.GPBMUX1.bit.GPIO39 = 0;// GPIO39 = I/O 引脚
GpioCtrlRegs.GPBDIR.bit.GPIO39 = 1;// GPIO39 =输出
GpioDataRegs.GPBCLEar.bit.GPIO39 = 1;// GPIO39 = 0
EDIS;

/*初始化控制器变量*/
pid1.kp = 9.0f;
pid1.Ki = 0.015f;
pid1.kd = 0.35f;
pid1.kr = 1.0f;
pid1.c1 = 188.0296600613396f;
pid1.c2 = 0.880296600613396f;
pid1.d2 = 0.0f;
pid1.d3 = 0.0f;
pid1.i10 = 0.0f;
pid1.i14 = 1.0f;
pid1.Umax = 1.0f;
pid1.Umin =–1.0f;

RK = 0.25f;//控制参考的初始值
LK = 1.0f;//控制循环未饱和

/*启用中断*/
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;//启用 PIE INT 1.1 (ADCINT1)-[adcisr]
IER |= M_INT1;//启用内核中断 1 (ADC)-[CONTROL_ISR]
SetDBGIER (0x0001);//启用实时调试中断
EINT;//启用全局中断屏蔽

EALLOW;
EPwm1Regs.TBCTL.BIT.CTRMODE = 0;// PWM1 计时器:递增和启动
EDIS;

/*空闲循环*/
while (1)

IdleLoopCount++;//递增循环计数器
asm(“ NOP“);
}// while

}//主要


/*控制 ISR:由 ADC EOC 触发*/
中断无效 CONTROL_ISR (void)

PieCtrlRegs.PIEACK.ALL = PIEACK_GROUP1;
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;

//读取 ADC 通道
YK =((float) AdcResult.ADCRESULT0 - 2048.0f)/ 2047.0f;

//运行 PID 控制器
UK = DCL_runPID_C4 (&pid1、rk、YK、lk);

//用于防饱和复位的外部钳位
clampactive = DCL_runClamp_c1 (&UK、upperlim、lowerlim);
LK =(clampactive == 0U)? 1.0f:0.0f;

//将 u (k) 写入 PWM
占空比=(UK / 2.0f + 0.5f)*(float) EPwm1Regs.TBPRD;
EPwm1Regs.CMPA.HALF.CMPA =(UINT16) 占空比;

IsrCount++;
}


/*文件结尾*/

我知道这个代码能够生成 PWM 信号;但是、我需要一个能够提供准确且与系统对应的 KP、KI、KD 值的代码。 我知道这个问题很乏味、但我真的陷入困境、需要一些有关控制器的帮助、因为我在控制器或控制系统方面没有那么多的经验。 下面附件是 Excel 文件、其中“实际功率需求“列突出显示了我尝试调整的值。

e2e.ti.com/.../final-data.xlsx

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

    您可以查看  用于电机控制的 InstaSPIN-FOC 和 InstaSPIN-MOTION 用户指南中的第 11 章稳压器作为参考。

    https://www.ti.com/lit/spruhj1 

    此外、您还可以在一些工程网站(如下所示)上找到更多关于 PID 的文章、这些文章可用于计算此处的增益。

    https://realpars.com/pid-tuning/

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

    感谢他们的视频、帮助我理解我要尝试的代码、让代码能够显示上升时间、设置时间、以及在调优控制器时注意到的过冲值。 我一直在努力工作一段时间,添加到以前的代码,我尝试使用 AI 的共鸣,但我只是继续运行在一个墙 tyring 来修复它下面是代码,我正在努力添加到前进.  

    Example_F28069_pid.c
    *
    *添加了阶跃响应指标:
    *-上升时间 (10–90%)
    *-过冲百分比
    *-稳定时间(默认为±5 %,带保持时间)
    *
    *指标就绪时,控制台打印在主循环中完成。
    */

    #include “F2806x_Device.h"</s>“
    #include “F2806x_examples.h"</s>“
    #include “F2806x_GlobalPrototypes.h"</s>“
    #include “DCLF32.h"</s>“
    #include // fabsf、fmaxf
    #include // printf(在 CCS 中启用半主机/I/O 重定向)

    /*函数原型*/
    外部中断无效 control_isr (void);

    /*全局变量*/
    长 IdleLoopCount = 0;
    长 IsrCount = 0;
    浮点数= 0.25f;
    浮动 YK;
    浮动 lk;
    Float UK;
    DCL_PID pid1 = PID_DEFAULTS;
    浮动占空比;
    浮点数= 0.95f;
    浮动 lowerlim = 0.05f;
    unsigned int clampactive;

    /*--指标:配置/状态--*/
    易失性浮点 TS = 0.0001f;// ISR 采样时间 (10kHz)
    Volatile float tol = 0.05f;//±5%稳定带
    Volatile unsigned long settle_hold_samples = 200u;//必须保留在这个如此多的样本的频带内

    易失性 float last_rk = 0.25f;
    Volatile unsigned int 测量= 0U;
    Volatile unsigned long k_now = 0UL;//自阶跃以来的样本索引
    Volatile unsigned long k_T10 = 0UL;//时间索引处于 10%级别
    Volatile unsigned long k_t90 = 0UL;//时间索引处于 90%级别
    Volatile unsigned long settle_count = 0UL;

    易失性浮点 y_START = 0.0f;
    易失性浮点 y_final = 0.0f;
    易失性浮点放大器= 0.0f;
    易失性浮点 Y10 = 0.0f;
    易失性浮点 Y90 = 0.0f;
    易失性浮点 y_max =–1e30f;
    易失性浮点 y_MIN = 1e30f;

    Volatile unsigned int Have_T10 = 0U;
    Volatile unsigned int Have_t90 = 0u;
    Volatile unsigned int state = 0u;

    易失性浮点 RISE_TIME_s = 0.0f;
    易失性浮点 SETTING_TIME_s = 0.0f;
    易失性浮点 overshooger_pct = 0.0f;

    /*打印触发器(在 ISR 中设置、在 main 中打印)*/
    volatile unsigned int print_metrics = 0U;

    /* main */
    main()

    /*初始化系统*/
    InitSysCtrl();
    DINT;
    IER = 0x0000;
    IFR = 0x0000;
    InitPieCtrl();
    InitPieVectTable();
    EALLOW;
    PieVectTable.ADCINT1 =&CONTROL_ISR;
    EDIS;

    /*配置 ePWM1 */
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;
    InitEPwm();
    EPwm1Regs.TBCTL.BIT.CTRMODE = 3;
    EPwm1Regs.TBCTL.BIT.PRDLD = 1;
    EPwm1Regs.TBCTL.BIT.PHSEN = 0;
    EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;
    EPwm1Regs.TBCTL.BIT.HSPCLKDIV = 0;
    EPwm1Regs.TBCTL.BIT.CLKDIV = 0;
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;
    EPwm1Regs.TBPRD = 0x2328;// 10kHz
    EPwm1Regs.TBPHS.all = 0;
    EPwm1Regs.TBCTR = 0;
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;
    EPwm1Regs.ETSEL.bit.SOCASEL = 1;
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;
    EPwm1Regs.CMPA.HALF.CMPA = 0x0080;
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm1Regs.AQCTLA.bit.ZRO = AQCLEAR;
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;

    /*配置 ADC */
    InitAdc ();
    EALLOW;
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0;
    AdcRegs.INTSEL1N2.bit.INT1E = 1;
    AdcRegs.INTSEL1N2.bit.INT1CONT = 0;
    AdcRegs.INTSEL1N2.bit.INT1SEL = 1;
    AdcRegs.INTSEL1N2.bit.INT2E = 0;
    AdcRegs.INTSEL1N2.bit.INT2CONT = 0;
    AdcRegs.INTSEL1N2.bit.INT2SEL = 0;
    AdcRegs.ADCSOC0CTL.BIT.CHSEL = 0;
    AdcRegs.ADCSOC1CTL.BIT.CHSEL = 8;
    AdcRegs.ADCSOC0CTL.BIT.TRIGSEL = 5;
    AdcRegs.ADCSOC1CTL.BIT.TRIGSEL = 5;
    AdcRegs.ADCSOC0CTL.BIT.ACQPS = 6;
    AdcRegs.ADCSOC1CTL.BIT.ACQPS = 6;
    EDIS;

    /*配置 GPIO */
    InitGpio();
    EALLOW;
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;
    GpioDataRegs.GPBSET.bit.GPIO34 = 1;
    GpioCtrlRegs.GPBMUX1.bit.GPIO39 = 0;
    GpioCtrlRegs.GPBDIR.bit.GPIO39 = 1;
    GpioDataRegs.GPBCLEar.bit.GPIO39 = 1;
    EDIS;

    /*初始化控制器变量*/
    pid1.kp = 9.0f;
    pid1.Ki = 0.015f;
    pid1.kd = 0.35f;
    pid1.kr = 1.0f;
    pid1.c1 = 188.0296600613396f;
    pid1.c2 = 0.880296600613396f;
    pid1.d2 = 0.0f;
    pid1.d3 = 0.0f;
    pid1.i10 = 0.0f;
    pid1.i14 = 1.0f;
    pid1.Umax = 1.0f;
    pid1.Umin =–1.0f;

    RK = 0.25f;//初始参考
    LK = 1.0f;//循环未饱和

    /*启用中断*/
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
    IER |= M_INT1;
    SetDBGIER (0x0001);
    EINT;

    EALLOW;
    EPwm1Regs.TBCTL.BIT.CTRMODE = 0;//启动 PWM
    EDIS;

    /*示例:启动延迟后触发单步执行(可选)*/
    //对于 (volatile uint32_t i = 0;i < 1000000;i++){asm(“ NOP“);}
    // rk = 0.6f;//取消注释以自动生成阶跃

    /*空闲循环*/
    while (1)

    IdleLoopCount++;

    /*每个步骤测试一次打印指标(在 ISR 中设置)*/
    如果 (print_metrics){
    print_metrics = 0U;

    printf(“\n--步骤响应指标--\n“);
    printf(“上升时间:%.6F s\n“、rise_time_s);
    printf(“Overshoot:%.2f %%\n“、overshot_pct);
    printf(“稳定时间:%.6F s\n“、Settleing_time_s);
    Printf(“-------------------------------- \n“);
    }

    asm(“ NOP“);
    }
    }

    /*控制 ISR:由 ADC EOC 触发*/
    中断无效 CONTROL_ISR (void)

    PieCtrlRegs.PIEACK.ALL = PIEACK_GROUP1;
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;

    /*读取输出(ADC 通道)*/
    YK =((float) AdcResult.ADCRESULT0 - 2048.0f)/ 2047.0f;

    /*检测参考步骤*/
    if (fabsf (rk - last_rk)> 1e-6F){
    测量= 1U;
    K_NOW = 0UL;
    K_T10 = 0UL;
    k_t90 = 0UL;
    HAVE_T10 = 0U;
    hase_t90 = 0u;
    稳定= 0U;
    SETTLE_COUNT = 0UL;
    Overshot_pct= 0.0f;

    Y_START = YK;
    Y_final = rk;
    放大器= y_final - y_start;

    y10 = y_start + 0.1f * amp;
    Y90 = y_start + 0.9f * amp;

    Y_max =–1e30f;
    Y_MIN = 1e30f;

    last_rk = rk;
    }

    /*运行 PID */
    UK = DCL_runPID_C4 (&pid1、rk、YK、lk);

    /*防饱和夹具*/
    clampactive = DCL_runClamp_c1 (&UK、upperlim、lowerlim);
    LK =(clampactive == 0U)? 1.0f:0.0f;

    /*对 PWM 的写入控制*/
    占空比=(UK / 2.0f + 0.5f)*(float) EPwm1Regs.TBPRD;
    EPwm1Regs.CMPA.HALF.CMPA =(UINT16) 占空比;

    /*指标跟踪*/
    如果(测量){
    K_NOW++;

    /*过冲角度的极值(可选)*/
    如果 (YK > y_max) y_max = yk;
    如果 (YK < y_MIN) y_MIN = yK;

    /* 10%和 90%交叉(用于上/下台阶)*/
    if(!Have_T10){
    if ((amp >= 0.0f && YK >= Y10)||(amp < 0.0f && YK <= Y10)){
    K_T10 = k_now;
    HASE_T10 = 1U;
    }
    }
    if(!have_t90){
    if ((amp >= 0.0f && YK >= Y90)||(amp < 0.0f && YK <= Y90)){
    k_t90 = k_now;
    hase_t90 = 1U;
    if (Have_T10){
    RISE_TIME_s =((float)(k_t90 - k_t10))* ts;
    }
    }
    }

    /*相对于最终值的过冲百分比*/
    如果 (fabsf (amp)> 1e-12F){
    如果 (amp >= 0.0f && YK > y_final){
    Float OS =(YK - y_final)/fabsf (amp)* 100.0f;
    如果 (OS > overshot_pct) overshot_pct = os;
    } else if (amp < 0.0f && YK < y_final){
    Float OS =(y_final - YK)/fabsf (amp)* 100.0f;
    如果 (OS > overshot_pct) overshot_pct = os;
    }
    }

    /*稳定时间:“SETTLE_HOLD_SAMPLES"必须“必须保持在带内*/
    if(!settleed && fabsf (YK - y_final)<= tol * fabsf (amp)){
    SETTLE_COUNT++;
    if (settle_count >= settlet_hold_samples){
    SETTING_TIME_s =((float)(k_now - SETTLE_HOLD_SAMPLES + 1UL)* TS;
    稳定= 1U;
    print_metrics = 1U;//在主循环中请求打印
    //测量= 0U;//稳定后可选择停止跟踪
    }
    } else if (fabsf(YK - y_final)> tol * fabsf(amp){
    SETTLE_COUNT = 0UL;
    }
    }

    IsrCount++;
    }

    /*文件结尾*/

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

    您可以参考上面提到的应用手册。 如果要实现 DCL 代码、您可以查看 MCSDK 文件夹下的指南。 抱歉、我们无法帮助您测试自己的代码。

    C:\ti\c2000\C2000Ware_6_00_00\libraries\control\DCL\c28\docs