并网逆变器控制需要电网的相角进行功率解耦,而电网相角一般通过锁相环获得,下面介绍三种常用的锁相环-单同步坐标系锁相环(SSRF-PLL)、双同步坐标系锁相环(DDSRF-PLL)、双二阶广义积分器锁相环(DSOGI-PLL)。原理性的比较简单,大家随便翻阅论文或者书籍都可以得到,本篇重点分享m文件deepseek生成经验。
一、结论
1、deepseek网页版使用V3版本模型,足够日常使用,生成m文件基本可以一键运行;
2、生成复杂算法时,第一次生成的脚本可能比较复杂,可以通过多轮对话让他对代码进行精简和优化(如果有移植到嵌入式平台计划);
3、生成的m文件可以"创建触发子系统",可以更真实的模拟嵌入式平台的中断执行效果。因为不同的离散方式受离散周期的影响很大,这里推荐使用双线性变换,如果离散周期很长,可能还要考虑预畸变处理。
二、SSRF-PLL
deepseek:
帮我写一个单同步坐标系锁相环的MATLAB Function函数,输入是三相电压,输出是正序DQ电压以及相角。其中锁相环PI参数,按照带宽50hz和阻尼比为0.707设计。PI的输出需要加上50H的前馈。(小结:指令越清晰,生成结果越准确。如果你告诉AI生成一个xxx功能,没有提具体要求,大概率不会得到想要的结果,我也是经过反复修改,最终告诉他实现xxx功能,参数xxx设计,前馈xxx设计。deepseek还会贴心帮你生成对应的测试脚本,你只需要把代码保存到m文件,测试脚本再保存一个m文件,运行一下函数即可。)
生成代码:
function [Vd, Vq, theta] = SSRF_PLL(Va, Vb, Vc, Ts)
%#codegen
% 单同步坐标系锁相环 (SSRF-PLL)
% 输入:
% Va, Vb, Vc - 三相电压瞬时值
% Ts - 采样时间 (s)
% 输出:
% Vd, Vq - 正序 dq 轴电压分量
% theta - 锁相环输出的相角 (rad)
% 锁相环参数设计 (带宽 50 Hz, 阻尼比 0.707)
fbw = 50; % 带宽 (Hz)
wn = 2*pi*fbw; % 自然角频率 (rad/s)
zeta = 0.707; % 阻尼比
Kp = 2*zeta*wn; % 比例系数
Ki = wn^2; % 积分系数
% 前馈频率 (50 Hz)
w_ff = 2*pi*50; % 前馈角频率 (rad/s)
% 持久变量:保存锁相环内部状态
persistent theta_hat int_error
if isempty(theta_hat)
theta_hat = 0; % 初始相角 (rad)
int_error = 0; % PI 积分项初始值
end
% 1. Clark 变换 (三相 -> αβ)
Valpha = (2/3)*(Va - 0.5*Vb - 0.5*Vc);
Vbeta = (2/3)*((sqrt(3)/2)*(Vb - Vc));
% 2. Park 变换 (αβ -> dq) 使用当前锁相环相角 theta_hat
Vd = Valpha*cos(theta_hat) + Vbeta*sin(theta_hat);
Vq = -Valpha*sin(theta_hat) + Vbeta*cos(theta_hat);
% 3. 锁相环误差信号 (目标 Vq = 0)
error = Vq;
% 4. PI 控制器 (输出角频率增量)
P = Kp * error;
int_error = int_error + Ki * error * Ts; % 积分累加
w_delta = P + int_error; % 角频率增量
% 5. 加入前馈频率,得到总角频率
w_total = w_ff + w_delta;
% 6. 积分得到相角 (模 2π)
theta_hat = theta_hat + w_total * Ts;
theta_hat = mod(theta_hat, 2*pi);
% 输出相角
theta = theta_hat;
end
三、DDSRF-PLL
原理性的东西没有过多好讲的,是目前使用最广泛的锁相环算法,可以解析出正序和负序电压。
deepseek:帮我写一个双同步坐标系锁相环的MATLAB Function函数,输入是三相电压和控制周期,输出是正负序DQ电压以及相角。有以下几点要求:1、锁相环PI参数,按照带宽50hz和阻尼比为0.707设计;2、PI的输出需要加上50H的前馈。3、正负序DQ电压的低通滤波器截止频率为25hz。
生成代码:
function [Vd_pos, Vq_pos, Vd_neg, Vq_neg, theta] = DDSRF_PLL(Va, Vb, Vc, Ts)
%#codegen
% 双同步坐标系锁相环 (DDSRF-PLL)
% 输入:
% Va, Vb, Vc - 三相电压瞬时值 (V)
% Ts - 采样周期 (s)
% 输出:
% Vd_pos, Vq_pos - 正序 dq 轴电压(滤波后)
% Vd_neg, Vq_neg - 负序 dq 轴电压(滤波后)
% theta - 锁相环输出的相角 (rad)
%% 1. 固定参数
% 锁相环 PI 参数 (带宽 50 Hz,阻尼比 0.707)
f_BW = 50; % 带宽 Hz
wn = 2 * pi * f_BW; % 自然角频率 rad/s
zeta = 0.707; % 阻尼比
Kp = 2 * zeta * wn; % 比例系数
Ki = wn^2; % 积分系数
% 前馈角频率 (50 Hz)
w_ff = 2 * pi * 50; % rad/s
% 低通滤波器参数 (一阶,截止频率 25 Hz)
fc_LPF = 25; % Hz
wc_LPF = 2 * pi * fc_LPF; % rad/s
% 采用后向差分法离散化 y[n] = a*x[n] + b*y[n-1]
a_LPF = (Ts * wc_LPF) / (1 + Ts * wc_LPF);
b_LPF = 1 / (1 + Ts * wc_LPF);
%% 2. 持久变量 (状态)
persistent theta % 输出相角
persistent integrator % PI 积分项
% 低通滤波器前一时刻输出 (正序 d/q, 负序 d/q)
persistent lpf_pos_d_prev lpf_pos_q_prev
persistent lpf_neg_d_prev lpf_neg_q_prev
if isempty(theta)
theta = 0;
integrator = 0;
lpf_pos_d_prev = 0;
lpf_pos_q_prev = 0;
lpf_neg_d_prev = 0;
lpf_neg_q_prev = 0;
end
%% 3. Clark 变换 (三相 -> αβ)
Valpha = (2/3) * (Va - 0.5*Vb - 0.5*Vc);
Vbeta = (2/3) * ((sqrt(3)/2) * (Vb - Vc));
%% 4. 三角函数
cos_theta = cos(theta);
sin_theta = sin(theta);
cos_2theta = cos(2*theta);
sin_2theta = sin(2*theta);
%% 5. 瞬时正序 Park 变换 (角度 θ)
Vd_inst_pos = Valpha * cos_theta + Vbeta * sin_theta;
Vq_inst_pos = -Valpha * sin_theta + Vbeta * cos_theta;
%% 6. 瞬时负序 Park 变换 (角度 -θ)
% 负序变换矩阵: [[cosθ, -sinθ], [sinθ, cosθ]]
Vd_inst_neg = Valpha * cos_theta - Vbeta * sin_theta;
Vq_inst_neg = Valpha * sin_theta + Vbeta * cos_theta;
%% 7. 解耦网络 (使用前一时刻低通滤波值)
% 正序解耦项 (来自负序低通滤波值)
Vd_coup_pos = cos_2theta * lpf_neg_d_prev + sin_2theta * lpf_neg_q_prev;
Vq_coup_pos = -sin_2theta * lpf_neg_d_prev + cos_2theta * lpf_neg_q_prev;
% 负序解耦项 (来自正序低通滤波值)
Vd_coup_neg = cos_2theta * lpf_pos_d_prev - sin_2theta * lpf_pos_q_prev;
Vq_coup_neg = sin_2theta * lpf_pos_d_prev + cos_2theta * lpf_pos_q_prev;
% 解耦后的瞬时值
Vd_pos_dec = Vd_inst_pos - Vd_coup_pos;
Vq_pos_dec = Vq_inst_pos - Vq_coup_pos;
Vd_neg_dec = Vd_inst_neg - Vd_coup_neg;
Vq_neg_dec = Vq_inst_neg - Vq_coup_neg;
%% 8. 一阶低通滤波 (更新低通状态)
lpf_pos_d = a_LPF * Vd_pos_dec + b_LPF * lpf_pos_d_prev;
lpf_pos_q = a_LPF * Vq_pos_dec + b_LPF * lpf_pos_q_prev;
lpf_neg_d = a_LPF * Vd_neg_dec + b_LPF * lpf_neg_d_prev;
lpf_neg_q = a_LPF * Vq_neg_dec + b_LPF * lpf_neg_q_prev;
% 输出滤波后的正负序 dq 分量
Vd_pos = lpf_pos_d;
Vq_pos = lpf_pos_q;
Vd_neg = lpf_neg_d;
Vq_neg = lpf_neg_q;
%% 9. 锁相环误差信号 (正序 q 分量)
error = Vq_pos; % 滤波后 Vq_pos 已无 100 Hz 脉动
%% 10. PI 控制器 + 前馈
P = Kp * error;
integrator = integrator + Ki * error * Ts;
w_delta = P + integrator;
w_total = w_ff + w_delta; % 总角频率 (rad/s)
%% 11. 积分得相角 (模 2π)
theta = theta + w_total * Ts;
theta = mod(theta, 2*pi);
%% 12. 更新低通滤波历史值 (供下一周期解耦)
lpf_pos_d_prev = lpf_pos_d;
lpf_pos_q_prev = lpf_pos_q;
lpf_neg_d_prev = lpf_neg_d;
lpf_neg_q_prev = lpf_neg_q;
end
生成的测试脚本
% 测试 DDSRF-PLL
Fs = 10000; % 采样率 10 kHz
Ts = 1/Fs;
t = 0:Ts:0.5; % 0.5 秒
% 三相电压:正序幅值 1,负序幅值 0.2,相位偏移
V_pos_amp = 1;
V_neg_amp = 0.2;
theta_pos = 2*pi*50*t;
theta_neg = -2*pi*50*t + pi/6; % 负序旋转方向相反
Va = V_pos_amp * cos(theta_pos) + V_neg_amp * cos(theta_neg);
Vb = V_pos_amp * cos(theta_pos - 2*pi/3) + V_neg_amp * cos(theta_neg + 2*pi/3);
Vc = V_pos_amp * cos(theta_pos + 2*pi/3) + V_neg_amp * cos(theta_neg - 2*pi/3);
% 初始化输出数组
Vd_pos_arr = zeros(size(t));
Vq_pos_arr = zeros(size(t));
Vd_neg_arr = zeros(size(t));
Vq_neg_arr = zeros(size(t));
theta_arr = zeros(size(t));
% 逐点调用锁相环 (需要重置持久状态,可重新运行函数前 clear 持久变量)
% 为避免状态影响,将函数独立成文件,此处用 "clear DDSRF_PLL" 清空
clear DDSRF_PLL;
for i = 1:length(t)
[Vd_pos_arr(i), Vq_pos_arr(i), Vd_neg_arr(i), Vq_neg_arr(i), theta_arr(i)] = ...
DDSRF_PLL(Va(i), Vb(i), Vc(i), Ts);
end
% 绘图
figure;
subplot(2,2,1);
plot(t, Vd_pos_arr, t, Vq_pos_arr); grid on;
legend('Vd pos','Vq pos'); title('正序 dq 分量');
xlabel('时间 (s)');
subplot(2,2,2);
plot(t, Vd_neg_arr, t, Vq_neg_arr); grid on;
legend('Vd neg','Vq neg'); title('负序 dq 分量');
subplot(2,2,3);
plot(t, theta_arr); grid on;
title('锁相环输出相角 (rad)'); xlabel('时间 (s)');
subplot(2,2,4);
error_rad = mod(theta_arr - theta_pos' + pi, 2*pi) - pi;
plot(t, error_rad*180/pi); grid on;
title('相位误差 (度)'); xlabel('时间 (s)');
MATLAB运行后结果:

四、DSOGI-PLL

deepseek:帮我写一个基于双二阶广义积分器(DSOGI)的正负序分离的matlab function,输入是三相电压和Ts,输出是正负序电压和相角,其中PI调节器参数按照带宽25hz,0.707阻尼比,Vm默认690。且matlab function的输出,不能定义为持久变量。SOGI的中心频率在0-0.1s时用额定值,0.1s后切换到锁相环输出。
(小结:这个过程比较坎坷,有几个注意点:1、如果不指定Vm,按照标幺值设计,kpki会非常大,索性就告诉他Vm是多少。2、前面两个锁相环带宽按照50hz设计,但是DSOGI如果还是按照50hz,SOGI的k系数为推荐值1.414时,运行1s左右后开始发散,把PLL带宽调整为25hz后可以稳定运行,猜测SOGI使用了锁相环输出的w,如果w波动较大会带来SOGI中心频率偏移,最终影响整个环路。3、不能立刻使用锁相环输出的w来闭环,系统无法稳定,所以让他写脚本的时候,先使用开环w,0.1s后切到锁相环输出)

生成代码:
function [Vd_pos, Vq_pos, Vd_neg, Vq_neg, theta] = DSOGI_PLL(Va, Vb, Vc, Ts)
% 基于双二阶广义积分器(DSOGI)的正负序分离锁相环
% 输入:三相电压 Va, Vb, Vc (V),采样周期 Ts (s)
% 输出:正序 dq 电压 (V),负序 dq 电压 (V),锁相环输出相角 (rad)
% PI 参数:带宽 50 Hz,阻尼比 0.707,电压基值 Vm = 690*sqrt(2) V
% SOGI 中心频率:0~0.1s 内使用额定频率 50Hz,之后使用 PLL 输出频率
% ==================== 持久变量(内部状态) ====================
persistent theta_pll % 锁相环输出相角 (rad)
persistent int_error % PI 积分项
persistent freq_pll % 当前 PLL 角频率 (rad/s)
persistent t_elapsed % 累计时间 (s)
% α轴 SOGI 状态: [输入延迟1, 输入延迟2, v'输出延迟1, v'输出延迟2, qv'输出延迟1, qv'输出延迟2]
persistent alpha_state
% β轴 SOGI 状态
persistent beta_state
% 初始化
if isempty(theta_pll)
theta_pll = 0;
int_error = 0;
freq_pll = 2*pi*50; % 初始角频率 100π rad/s
t_elapsed = 0;
alpha_state = zeros(1,6);
beta_state = zeros(1,6);
end
% ==================== 固定参数 ====================
Vm = 690 * sqrt(2); % 电压基值 (峰值) ≈ 975.8 V
f_BW = 25; % 带宽 Hz
wn = 2 * pi * f_BW; % 自然角频率 rad/s
zeta = 0.707;
Kp_unit = 2 * zeta * wn; % 单位幅值下的比例系数
Ki_unit = wn^2; % 单位幅值下的积分系数
Kp = Kp_unit / Vm; % 实际比例系数
Ki = Ki_unit / Vm; % 实际积分系数
w_ff = 2 * pi * 50; % 前馈角频率 (50Hz)
% ==================== Clark 变换 ====================
Valpha = (2/3) * (Va - 0.5*Vb - 0.5*Vc);
Vbeta = (2/3) * ((sqrt(3)/2) * (Vb - Vc));
% ==================== 确定 SOGI 中心频率 ====================
% 累计时间
t_elapsed = t_elapsed + Ts;
if t_elapsed <= 0.1
omega = 2*pi*50; % 0.1s 内使用额定频率
else
omega = freq_pll; % 0.1s 后使用 PLL 输出角频率
end
% ==================== 双线性变换离散化 SOGI ====================
% 输入参数
k = sqrt(2); % 阻尼因子 (ζ = k/2 = 0.707)
T = Ts;
c = 2 / T; % 双线性变换常数
% 分母多项式系数 (共同分母)
den0 = c^2 + k*omega*c + omega^2;
den1 = 2 * (omega^2 - c^2);
den2 = c^2 - k*omega*c + omega^2;
% 归一化分母系数 (a0=1, a1, a2)
a1 = den1 / den0;
a2 = den2 / den0;
% 分子系数 (v' 通道)
b0_v = k * omega * c / den0;
b1_v = 0;
b2_v = -k * omega * c / den0;
% 分子系数 (qv' 通道)
b0_q = k * omega^2 / den0;
b1_q = 2 * k * omega^2 / den0;
b2_q = k * omega^2 / den0;
% ==================== 对 α 轴应用 SOGI ====================
in_alpha = Valpha;
% v' 输出
v_prime_alpha = b0_v * in_alpha + b1_v * alpha_state(1) + b2_v * alpha_state(2) ...
- a1 * alpha_state(3) - a2 * alpha_state(4);
% qv' 输出
qv_prime_alpha = b0_q * in_alpha + b1_q * alpha_state(1) + b2_q * alpha_state(2) ...
- a1 * alpha_state(5) - a2 * alpha_state(6);
% 更新状态 (输入延迟、输出延迟)
alpha_state(2) = alpha_state(1);
alpha_state(1) = in_alpha;
alpha_state(4) = alpha_state(3);
alpha_state(3) = v_prime_alpha;
alpha_state(6) = alpha_state(5);
alpha_state(5) = qv_prime_alpha;
% ==================== 对 β 轴应用 SOGI ====================
in_beta = Vbeta;
v_prime_beta = b0_v * in_beta + b1_v * beta_state(1) + b2_v * beta_state(2) ...
- a1 * beta_state(3) - a2 * beta_state(4);
qv_prime_beta = b0_q * in_beta + b1_q * beta_state(1) + b2_q * beta_state(2) ...
- a1 * beta_state(5) - a2 * beta_state(6);
beta_state(2) = beta_state(1);
beta_state(1) = in_beta;
beta_state(4) = beta_state(3);
beta_state(3) = v_prime_beta;
beta_state(6) = beta_state(5);
beta_state(5) = qv_prime_beta;
% ==================== 正负序分离 (αβ静止坐标系) ====================
% 正序分量
v_alpha_pos = 0.5 * (v_prime_alpha - qv_prime_beta);
v_beta_pos = 0.5 * (qv_prime_alpha + v_prime_beta);
% 负序分量
v_alpha_neg = 0.5 * (v_prime_alpha + qv_prime_beta);
v_beta_neg = 0.5 * (-qv_prime_alpha + v_prime_beta);
% ==================== Park 变换 (得到正负序 dq) ====================
cos_theta = cos(theta_pll);
sin_theta = sin(theta_pll);
Vd_pos = v_alpha_pos * cos_theta + v_beta_pos * sin_theta;
Vq_pos = -v_alpha_pos * sin_theta + v_beta_pos * cos_theta;
Vd_neg = v_alpha_neg * cos_theta + v_beta_neg * sin_theta;
Vq_neg = -v_alpha_neg * sin_theta + v_beta_neg * cos_theta;
% ==================== 锁相环 (基于正序 q 轴分量) ====================
error = Vq_pos; % 误差信号
P = Kp * error;
int_error = int_error + Ki * error * Ts;
w_delta = P + int_error;
w_total = w_ff + w_delta; % 总角频率 (前馈 + PI输出)
% 更新 PLL 输出相角
theta_pll = theta_pll + w_total * Ts;
theta_pll = mod(theta_pll, 2*pi);
theta = theta_pll;
% 更新 PLL 输出角频率 (用于频率自适应)
freq_pll = w_total;
end
运行测试脚本后输出结果:
