2023年电赛电源题代码开源——STM32实现SOGI、锁相环和双环控制的电压电流控制方案
1.基于二阶广义积分器的锁相环实现
笔者的锁相环这一环节参考的是知乎的这篇文章:
单相锁相环(一)基于二阶广义积分器的单相锁相环(SOGI-PLL)的matlab/simulink仿真 – 知乎 文章写的非常详细、如果详细阅读必定会有收获,这边笔者就放出自己的代码,并且加以解释。首先,我才用两个函数去实现锁相环,第一个是对输入信号进行二阶广义积分处理,产生两个幅度相同,但是相位相差90度的信号,这两个信号一个相位与原输入信号相同,另外一个与输入信号滞后90度。具体实现见图2,或者对上述链接进行Z变换的推导。
图.一 实现锁相环的代码框架
图.二 二阶广义积分的代码实现
具体不加以解释,然后变量在攥写代码的时候写的并不是很规范,但是大致思路如上,后续整理代码的时候会进行重构。
实现生成两个滞后90度的信号后,我们对这两个信号做一个park变换,合成这两个信号的q轴分量,我们通过PI控制器使该信号的q轴分量趋向于零来实现锁相。该PI控制器输出的结果是信号的频率,所以还需要对该结果进行积分才可以得到信号的相角信息。并且在控制过程中加入了50Hz频率的前馈,因为我们电源题可以确定是对50Hz频率的信号进行控制。具体代码如图三。同时为了防止数据的溢出,每当角度大于2PI时就会对其进行求余处理。
图.三 锁相环控制器代码框架
2.电压外环与电流内环的双环控制框架
该控制方案的优势为负载调整率较小,可以实现不同输出电流的情况下稳定电压输出。缺点是在输出电压较小时所含高次谐波量较大,含有四个PI控制器参数难以整定。
具体思路如下,对输入的电流与电压进行二阶广义积分的处理,各自生成90度相移的信号。一开始对该信号进行park变换,实现q轴与d轴分量的分离。然后使用两个PI控制器,实现q轴分量为零,d轴分量为目标幅值的控制。将电压外环的控制器输出作为电流内环的目标值进行电流内环控制,然后对电流内环输出进行反park变换,生成目标输出电压,代入到SPWM的函数里面进行占空比的调整
总结一下,电源题需要熟悉park变化的使用,不能简单的以电压电流输入为直接的反馈,因为交流电是余弦信号,简单的PI控制器对于余弦信号的跟随能力较弱,需要考虑使用park变化将余弦信号转化成线性信号进行控制,经笔者验证,park变换后的线性跟随能力远超直接对余弦信号进行跟随。
/*******************************************************************
函数名称:Volt_Current_Loop_Control(float des)
函数功能:进行电压外环电流内环控制
备 注:非并网
********************************************************************/
float U_d_feedback=0;
float U_q_feedback=0;
float I_d_feedback=0;
float I_q_feedback=0;
float U_alpha=0;
float sinF=0;
float cosF=0;
CHM_SIGNAL input_volt={.frequence=50,.fpd=0,.fpd_1=0,.fpd_2=0,.fpU=0,.fpU_1=0,.fpU_2=0,.fpq=0,.fpq_1=0,.fpq_2=0,.theta=0};
CHM_SIGNAL input_current={.frequence=50,.fpd=0,.fpd_1=0,.fpd_2=0,.fpU=0,.fpU_1=0,.fpU_2=0,.fpq=0,.fpq_1=0,.fpq_2=0,.theta=0};
void Volt_Current_Loop_Control(float des,float sita)
{
input_volt.fpU=stMotorCtrl.stElecObs.fpPhaAVoltFB;//电压反馈
input_current.fpU=stMotorCtrl.stElecObs.fpPha1CrtFB;//电流反馈
SOGI(&input_volt);
SOGI(&input_current);//进行二阶广义积分
sinF=(float)sin(sita);
cosF=(float)cos(sita);
U_d_feedback=input_volt.fpd*cosF+input_volt.fpq*sinF;
U_q_feedback=input_volt.fpd*(-sinF)+input_volt.fpq*cosF;
I_d_feedback=input_current.fpd*cosF+input_current.fpq*sinF;
I_q_feedback=input_current.fpd*(-sinF)+input_current.fpq*cosF;
U_d_PID.fpDes=des;
U_q_PID.fpDes=0;
U_d_PID.fpFB=U_d_feedback;
U_q_PID.fpFB=U_q_feedback;
PI_Controller(&U_d_PID);
PI_Controller(&U_q_PID);
I_d_PID.fpFB=I_d_feedback;
I_q_PID.fpFB=I_q_feedback;
I_d_PID.fpDes=U_d_PID.fpU;
I_q_PID.fpDes=U_q_PID.fpU;
PI_Controller(&I_d_PID);
PI_Controller(&I_q_PID);
U_alpha=cosF*I_d_PID.fpU-sinF*I_q_PID.fpU;
SPWM_control(U_alpha);
}
图.四 双环控制代码框架