锁相环这玩意儿在并网逆变器里就像老司机的方向盘,没它系统分分钟跑偏。今儿咱们扒一扒SOGIDQ这个锁相方案,直接上干货代码,手把手教你从仿真玩到STM32实战
调参时有个骚操作:先把PI参数设为0,用信号发生器给50Hz正弦波,看q_error能否收敛到0。若跟踪速度慢,适当增大Ki。特别注意_SSAT这个饱和指令,防止运算溢出,这是嵌入式开发经常埋雷的地方。采样频率设置为10kHz时,Ts=0.0001需要换算成Q15的系数,具体数值得用matlab提前算好。这段代码藏着两个关键点:SOGI的微分方程实现用了前向欧拉法,注意这里的状态变量x1、x2要持
单相逆变并网的学习代码SOGIDQ锁相, 纯代码仿真,锁相环,并网,stm32代码
先扔个Matlab仿真代码镇楼:
% SOGI正交信号生成
function [alpha, beta] = SOGI(v_grid, w0, Ts)
persistent x1 x2;
if isempty(x1)
x1 = 0; x2 = 0;
end
k = 1.414;
x1_new = x1 + Ts*(v_grid*k*w0 - x2*w0^2 - x1*2*k*w0);
x2 = x2 + Ts*x1;
alpha = x1_new;
beta = x2;
x1 = x1_new;
end
% DQ变换核心
theta = cumsum(w*Ts); % 相位积分
[d, q] = [cos(theta), sin(theta);
-sin(theta), cos(theta)] * [alpha; beta];
这段代码藏着两个关键点:SOGI的微分方程实现用了前向欧拉法,注意这里的状态变量x1、x2要持久化保存。系数k取根号2可不是随便拍的脑袋,这个值能让正交信号生成达到最佳动态响应。

硬件实战时得注意定点数处理,看STM32的ADC中断服务函数:
// 在stm32f4xx_it.c里
void ADC_IRQHandler(void){
static int32_t x1=0, x2=0;
int16_t adc_val = ADC1->DR; // 读取电网电压采样值
// 定点数运算(Q15格式)
int32_t input = adc_val * 2896; // 2896=1.414*2048(12位ADC量程)
int32_t temp = _SSAT((x1*7258 - x2*268435) >> 15, 16); // 7258=2*k*w0*Ts
x1 = x1 + ((input - temp) >> 4);
x2 = x2 + (x1 >> 4);
// 更新全局变量
pll_alpha = x1 >> 12; // 降回实际量纲
pll_beta = x2 >> 12;
}
这里用Q15格式处理小数运算,右移操作代替除法。特别注意_SSAT这个饱和指令,防止运算溢出,这是嵌入式开发经常埋雷的地方。采样频率设置为10kHz时,Ts=0.0001需要换算成Q15的系数,具体数值得用matlab提前算好。
锁相环闭环调节部分才是灵魂:
void TIM6_DAC_IRQHandler(void){ // 10kHz定时器中断
static float pi_out = 0.0f;
float q_error = pll_beta * cos_theta - pll_alpha * sin_theta;
// 抗饱和PI控制器
pi_out += 0.003f * q_error; // Ki=0.003
float output = 314.16f + 0.5f * q_error + pi_out; // Kp=0.5
// 更新相位
theta += output * 0.0001f; // Ts=0.0001
theta = fmod(theta, 6.283185307f);
// 更新正余弦表
cos_theta = arm_cos_f32(theta);
sin_theta = arm_sin_f32(theta);
}
这里用了CMSIS的DSP库加速三角函数计算,实测在72MHz主频下耗时约1.2us。注意PI控制器的抗饱和处理——当q_error持续过大时需要限制积分项,这里简化为系数调节。相位变量theta必须做模运算,否则跑几天就会溢出。

调参时有个骚操作:先把PI参数设为0,用信号发生器给50Hz正弦波,看q_error能否收敛到0。若出现相位来回震荡,把Kp调小;若跟踪速度慢,适当增大Ki。实际调试中发现电网电压谐波会影响锁相精度,这时在SOGI后加个移动平均滤波器有奇效。
最后来个并网同步的判断逻辑:
if(fabs(grid_freq - 50.0f) < 0.5f &&
fabs(grid_phase - inverter_phase) < 0.087f) { // 5度相位差
GRID_SYNC_LED_ON();
enable_inverter();
} else {
trigger_soft_start();
}
这个阈值设置要结合具体硬件响应速度,曾有个兄弟设了0.1度相位差,结果继电器噼里啪啦乱跳。实测在相位差3度、频差0.3Hz内并网,电流冲击最小。

更多推荐
所有评论(0)