并网逆变器学习笔记11---并网逆变器学习---SSRF-PLL、DDSRF-PLL、DSOGI-PLL快速上手(结合deepseek脚本快速生成)

并网逆变器控制需要电网的相角进行功率解耦,而电网相角一般通过锁相环获得,下面介绍三种常用的锁相环-单同步坐标系锁相环(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

运行测试脚本后输出结果:

相关推荐
海兰15 小时前
手把手elasticsearch学习之构建 HITL AI 代理
人工智能·学习·elasticsearch
和blue一起变得更好15 小时前
day4 element plus+vue3+vite实现简单学习任务管理
javascript·vue.js·学习
handler0115 小时前
【Linux】五种IO模型详解
linux·运维·服务器·c语言·网络·笔记·php
爱喝水的鱼丶16 小时前
SAP-ABAP:条件判断与循环控制语句(7篇)第七篇:性能优化:条件与循环代码的常见性能瓶颈与优化方案
学习·算法·性能优化·sap·abap
小新同学^O^1 天前
简单学习 --> 模型参数
学习·llm·大模型参数
cdbqss11 天前
VB2026 菜单生成基类 BqGetMenuStrip
数据库·经验分享·学习·oracle·vb
智者知已应修善业1 天前
【51单片机8位数码管动态显示日期小数点风格】2023-11-13
c++·经验分享·笔记·算法·51单片机
智者知已应修善业1 天前
【51单片机有三个LED 分别第一个灯闪三下 再到第二个灯又闪三下 再到第三个灯又闪三下 就这样循环程序】2023-11-16
c++·经验分享·笔记·算法·51单片机
暴躁小师兄数据学院1 天前
【AI大数据工程师特训笔记】第04讲:PostgreSQL 数据库内置函数详解
大数据·数据库·笔记·ai·语言模型