简介:本资源是针对2022年全国大学生电子设计竞赛A题“单相交流电子负载”的核心算法实现方案,面向嵌入式参赛学生与电力电子方向实践者,重点解决单相PWM整流系统中高精度、宽频带锁相环(PLL)这一关键难点。工程基于STM32F407VET6主控芯片,采用STM32CubeMX生成底层初始化代码,完整实现了单相DQ坐标系下的锁相环算法,兼顾实时性与鲁棒性,支持45–55Hz动态频率跟踪,可直接适配逆变器或整流器控制场景,亦为其他ARM Cortex-M系列MCU提供可迁移的参考架构。压缩包共191个文件,含28个C源码、55个头文件、29个编译中间文件及工程配置文件(.ioc/.uvprojx等),总大小12.17MB;核心逻辑集中于main.c,配套HAL库驱动(ADC、TIM、UART等)均已集成调试。目前已有215人学习下载,适合需快速掌握单相锁相原理、理解DQ变换在单相系统中的映射方法,并落地到电赛实战平台的中级以上嵌入式开发者。
1. 项目背景与核心挑战:从“电子负载”到“能量回馈”的跨越
如果你参加过电赛,或者搞过电源相关的项目,那你肯定对“电子负载”这个概念不陌生。传统的电子负载,说白了就是个可控的“耗电器”,通过功率器件(比如MOSFET)模拟一个电阻,把电源输出的能量消耗掉,同时测量电压电流。但2022年电赛A题“单相交流电子负载”的要求,直接把难度和含金量都拉满了——它要求实现能量回馈。
这就不再是简单的“烧掉”能量了,而是要把从电网(或交流源)吸收的能量,经过变换,再“还”回电网。题目里提到的“单相PWM整流”就是这个能量回馈功能的核心实现方式。它本质上是一个双向AC-DC变换器:当它作为负载从电网吸收能量时,工作在整流模式(AC to DC);当它需要把直流侧储存的能量回馈给电网时,就工作在逆变模式(DC to AC)。而这一切的控制大脑,题目指定了STM32F407VET6这颗经典的MCU。
所以,这个项目的核心不再是做一个会变阻值的箱子,而是做一个具备网侧电流控制能力、单位功率因数运行、且能实现能量双向流动的并网变换器。这其中的技术核心,就落在了并网同步和电流解耦控制上,也就是标题里提到的DQ锁相环。很多队伍折戟沉沙,不是硬件做不出来,而是软件上的锁相和控制环路没调通,导致回馈时电流波形畸变、相位错乱,甚至直接炸管。
我当年带队做这个题,在锁相环这一块也踩了无数坑。网上能找到的基于STM32的锁相环代码要么是SVPWM的,要么是软件锁相环(SPLL)但没讲清楚在畸变电网下怎么办。今天,我就把基于STM32F407VET6,针对单相PWM整流系统的DQ锁相环(基于二阶广义积分器SOGI)的实现细节、参数整定心得和那些调试中“血与泪”的教训,彻底拆解清楚。无论你是为了备战电赛,还是单纯想搞懂单相并网同步技术,这篇内容都能让你少走至少一个月的弯路。
2. 硬件架构与核心控制思想:为什么是PWM整流和DQ解耦?
在深入代码之前,我们必须先建立起清晰的物理图像和控制框架。很多同学一上来就怼代码,结果连自己的控制对象是什么都没搞清楚。
2.1 单相PWM整流的主拓扑与工作模式
题目要求的单相交流电子负载,其主电路拓扑通常采用单相全桥PWM整流器,也就是常说的H4桥。拓扑结构很简单:交流输入经过滤波电感L,连接到由四个IGBT或MOSFET(Q1-Q4)组成的全桥,桥后是直流侧支撑电容C和负载(或直流源)。
它的核心功能模式有两种:
- 整流模式(消耗能量):模拟一个可控的阻性负载。此时控制目标是让网侧电流(i_ac)跟踪与网压(u_ac)同相位的正弦波。电网能量通过全桥流向直流侧,给电容充电或供给直流负载。此时直流侧电压高于网侧电压峰值。
- 逆变模式(回馈能量):将直流侧储存的能量(比如来自电池或上一阶段储存的电能)逆变成与电网同频同相的正弦电流,回馈给电网。此时控制目标是让网侧电流跟踪与网压反相(相位差180°)的正弦波。直流侧电压需要被控制在一个稳定的值。
无论是哪种模式,对控制器而言,最核心的要求就两个:第一,必须实时、准确地获取电网电压的相位和频率(这就是锁相环PLL的活);第二,必须能独立、快速地控制网侧电流的有功分量和无功分量(这就是DQ变换和解耦控制的活)。
2.2 DQ变换与解耦控制:把交流量变成直流量
交流量(正弦的电压、电流)是时变的,直接设计控制器很麻烦。Park变换(DQ变换)的神奇之处在于,它把一个在静止坐标系(αβ)下旋转的矢量,变换到一个与电网电压矢量同步旋转的坐标系(dq)下。在这个旋转坐标系里,电网电压基波分量就变成了直流量。
对于单相系统,由于缺少自然正交的β相,我们需要先构造一个虚拟的、滞后90度的β相。这就是后面要讲的基于SOGI的正交信号发生器(QSG)的核心任务。
一旦我们得到了在dq坐标系下的电压(Ud, Uq)和电流(Id, Iq),控制意义就非常明确了:
- d轴通常与电网电压矢量对齐。因此,Ud代表电网电压的幅值,Id代表电流的有功分量。控制Id就能直接控制输入或输出的有功功率。
- q轴领先d轴90度。Uq在理想锁相下应为0,Iq代表电流的无功分量。控制Iq就能控制系统的无功功率(功率因数)。
在dq坐标系下,PWM整流器的电压方程可以写为:
Ud = L * dId/dt - ωL * Iq + Ed Uq = L * dIq/dt + ωL * Id + Eq其中,Ed, Eq是电网电压在dq轴的分量(理想锁相下,Ed为电网电压幅值,Eq=0)。看到中间交叉耦合项ωL * Iq和ωL * Id了吗?这就是耦合项,它意味着改变Id会影响到Uq,改变Iq会影响到Ud,直接做PI控制会相互干扰,动态响应差。
解耦控制的目的就是消除这个耦合。我们在PI控制器的输出上,加上一个前馈补偿项:
Vd_ref = (Kp_Id + Ki_Id/s) * (Id_ref - Id) + ωL * Iq + Ed Vq_ref = (Kp_Iq + Ki_Iq/s) * (Iq_ref - Iq) - ωL * Id + Eq这样,ωL * Iq和-ωL * Id就把耦合项抵消了,剩下的就是两个独立的、控制直流量Id和Iq的PI环路。这就是整个电流内环的核心。而外环通常是直流电压环,它的输出作为内环Id的给定值(Id_ref),用于维持直流侧电压稳定或控制有功功率流动。
这一切的前提,都依赖于一个高精度、高动态性能的锁相环,来提供准确的相位sinθ和cosθ,以及电网角频率ω。
3. 单相锁相环的困境与SOGI-QSG的救赎
标准的三相软件锁相环(SPLL)在三相系统里很好用,因为三相自然对称,αβ变换后得到的是完美的两相正交量。但单相系统只有一个物理量,如何得到它的正交分量,是单相锁相环最大的挑战。
3.1 为什么简单的90度延时法不行?
最朴素的想法是:对采集到的电压信号uα进行一个四分之一周期(5ms @ 50Hz)的延时,不就能得到一个滞后的uβ吗?这个方法在电网频率绝对稳定且信号无谐波时理论上可行。但现实很骨感:
- 动态性能差:电网频率是可能波动的。频率一变,固定的延时时间就不再对应90度相移,会引入固定的相位误差,导致锁相精度下降。
- 谐波抑制差:如果网压有畸变(比如含有5次、7次谐波),延时法无法滤除这些谐波,畸变会直接污染构造出的β信号,导致锁相环输出相位抖动。
- 需要缓冲区:实现精确的固定延时需要开辟一个数组做FIFO缓冲,消耗内存和计算资源。
因此,在要求高性能的并网场合,比如我们这个PWM整流项目,90度延时法基本是不可用的。
3.2 二阶广义积分器(SOGI)如何生成完美正交信号?
SOGI-QSG是当前单相锁相环的主流和优选方案。它的本质是一个具有频率自适应能力的带通滤波器。
一个SOGI-QSG的结构框图通常如下(此处用文字描述其传递函数): 对于输入信号v,它同时产生两个输出:v'和qv'。
v'是对输入v中特定频率(ω‘,即锁相环估计的电网角频率)分量的跟踪输出,其传递函数类似于一个带通滤波器:D(s) = kω's / (s² + kω's + ω'²)qv'是v'的积分再乘以ω‘,从而产生一个滞后v'90度的正交信号:Q(s) = kω'² / (s² + kω's + ω'²)
其中,k是阻尼系数,是唯一需要整定的参数。它决定了滤波器的带宽和响应速度。
- k值越大,带宽越宽,对频率变化的跟踪速度越快(动态性好),但对谐波的抑制能力变差。
- k值越小,带宽越窄,滤波效果越好(抗干扰强),但动态响应变慢,对频率阶跃的调节时间变长。
在锁相环中,我们通常使用两个级联的SOGI:第一个用于处理电网电压u,产生正交的uα和uβ;第二个(可选)用于处理网侧电流i,产生正交的iα和iβ,用于DQ变换。
SOGI的核心优势:
- 频率自适应:其中心频率ω‘由锁相环实时更新的频率估计值提供。当电网频率变化时,SOGI能自动调整其中心频率,始终对基波进行最佳提取,这是固定延时法做不到的。
- 谐波抑制:对于偏离中心频率的谐波分量,SOGI有良好的衰减作用,能为锁相环提供更“干净”的正交输入信号。
- 结构简单:离散化后,只需几个差分方程即可实现,计算量适中,非常适合STM32F407这类MCU。
4. 基于STM32F407VET6的软件实现全解析
理论说再多,不如一行代码。下面我们结合STM32F407的硬件特性,将整个系统落地。
4.1 系统外设配置与关键外设选择
STM32F407VET6拥有丰富的定时器和ADC资源,这是我们实现高性能数字电源控制的基础。
ADC采样与触发:
- 关键点:必须保证电压、电流采样的同步性。我们使用一个高级定时器(如TIM1或TIM8)的中心对齐PWM模式生成驱动全桥的互补PWM波。
- 采样时刻:在PWM的计数周期中点(即计数器为0时)触发ADC采样。这个时刻对应功率管桥臂中点电压的平均值,能最大程度减少开关噪声对采样值的影响。
- ADC配置:使用ADC1和ADC2的双ADC同步规则模式。ADC1采样网侧电压和电流,ADC2采样直流侧电压和另一路信号(如预留)。由TIM1的TRGO事件同步触发两组ADC。这样,四个关键模拟量可以在同一个瞬间被捕获,保证了控制算法数据在时间上的一致性。
- DMA传输:为两个ADC配置DMA,将采样结果自动搬运到指定的数组(如
adc_buf[4])中。务必使能DMA的循环模式,并设置好数据宽度(半字)。ADC采样完成中断里不要做复杂计算,只设置一个标志位。
PWM生成:
- 使用TIM1的通道1/2(CH1/CH2)和通道3/4(CH3/CH4)生成两组互补带死区的PWM,分别驱动全桥的上下桥臂。
- 死区时间:根据你选用的IGBT/MOSFET的开关速度来设置,通常1-2us。在TIM1的BDTR寄存器中配置。
- PWM频率:电赛通常要求10kHz或20kHz。10kHz开关损耗小,但电流纹波大;20kHz纹波小,动态响应可能更好,但开关损耗和驱动要求高。我建议用16kHz,在F407上预分频后计数周期为5250(84MHz/16k),分辨率足够,也兼顾了性能和损耗。
- 计数模式:务必选择中心对齐模式1。这样PWM波形是对称的,谐波特性更好,也更方便安排ADC采样点。
控制周期与中断:
- 整个数字控制系统的“心跳”就是PWM周期。我们在TIM1的更新中断(UEV)中执行所有控制算法。
- 中断服务程序(ISR)的流程必须是:读取ADC结果 -> 标幺化/格式化 -> 执行锁相环算法 -> 执行电流环、电压环计算 -> 更新PWM比较寄存器(CCR)。
- 中断优先级:将TIM1更新中断设置为最高优先级(如Preemption=0),确保控制周期绝对准时。ADC采样完成中断的优先级可以低于它。
4.2 SOGI-QSG与锁相环的离散化实现
这是软件的核心。我们首先将连续的SOGI传递函数离散化。采用双线性变换(Tustin)方法,可以得到其离散差分方程。
假设采样周期为Ts,中心频率为ω(即锁相环估计的电网角频率),阻尼系数为k。
我们定义中间变量v为输入,v_alpha和v_beta为输出的正交信号。SOGI的离散化状态空间方程可以这样实现(以下为伪代码逻辑):
// SOGI-QSG 结构体 typedef struct { float omega; // 中心角频率 ω float k; // 阻尼系数 float Ts; // 采样周期 float u_alpha; // 输出:同相分量 float u_beta; // 输出:正交分量 float x1, x2; // 状态变量 } SOGI_QSG; // SOGI-QSG 计算函数 void SOGI_QSG_Update(SOGI_QSG *s, float input) { float k_omega = s->k * s->omega; float omega_sq = s->omega * s->omega; float Ts = s->Ts; // 离散化系数 (使用后向欧拉或双线性变换,此处为示例系数) // 实际系数需要根据离散化方法精确计算 float a11 = 1 - k_omega*Ts - omega_sq*Ts*Ts; float a12 = -omega_sq*Ts; float b1 = k_omega*Ts; // 状态更新 float new_x1 = a11 * s->x1 + a12 * s->x2 + b1 * input; float new_x2 = s->x1 + s->x2; // 假设第二个状态是积分 // 输出计算 s->u_alpha = new_x1; // 或根据实际离散方程调整 s->u_beta = s->omega * s->x2; // 生成正交分量 // 更新状态 s->x1 = new_x1; s->x2 = new_x2; }注意:上面的伪代码仅为示意,离散化系数需要根据你选择的离散化方法(前向欧拉、后向欧拉、双线性变换)精确推导。网上有大量现成的SOGI离散化系数公式,建议直接使用验证过的公式。一个更常见的实现是直接使用两个积分器构成的反馈结构,代码会更直观。
有了正交的uα和uβ后,锁相环就简单了。我们使用基于dq轴的软件锁相环:
// 单相锁相环结构体 typedef struct { float theta; // 输出相位角 (0 to 2π) float omega; // 输出角频率 (rad/s) float omega_nom; // 额定角频率 (314.16 rad/s for 50Hz) float kp_pll; // PI控制器比例系数 float ki_pll; // PI控制器积分系数 float Ts; float pi_integrator; // PI积分项 } SinglePhase_PLL; void SinglePhase_PLL_Update(SinglePhase_PLL *p, float u_alpha, float u_beta) { // Park变换: 将αβ坐标系变换到dq坐标系 (基于当前估计相位theta) float sin_theta, cos_theta; arm_sin_cos_f32(p->theta * RAD_TO_DEG_SCALE, &sin_theta, &cos_theta); // 使用DSP库 float ud = u_alpha * cos_theta + u_beta * sin_theta; float uq = -u_alpha * sin_theta + u_beta * cos_theta; // 注意符号,取决于变换定义 // PI控制器:目标是使uq为0,即d轴与电网电压矢量对齐 float error = 0 - uq; // 我们希望uq为0 float proportional = p->kp_pll * error; p->pi_integrator += p->ki_pll * error * p->Ts; // 限制积分饱和 if (p->pi_integrator > PI_INTEGRATOR_LIMIT) p->pi_integrator = PI_INTEGRATOR_LIMIT; if (p->pi_integrator < -PI_INTEGRATOR_LIMIT) p->pi_integrator = -PI_INTEGRATOR_LIMIT; float output = proportional + p->pi_integrator; // 更新角频率和相位 p->omega = p->omega_nom + output; // 额定频率加上PI调节量 p->theta += p->omega * p->Ts; // 相位角归一化到 [0, 2π) if (p->theta >= TWO_PI) p->theta -= TWO_PI; if (p->theta < 0) p->theta += TWO_PI; }这个锁相环的逻辑是:通过Park变换得到uq,如果相位完全对齐,uq应该为0。如果存在相位差,uq就不为0。PI控制器通过调节角频率ω来驱使uq归零,从而实现对电网相位的跟踪。
4.3 电流内环与电压外环的离散PI实现
锁相环提供了准确的sinθ和cosθ,以及ω。接下来就是实现解耦的电流环。
// 电流PI控制器结构体 (dq轴各一个) typedef struct { float kp; float ki; float Ts; float integrator; float output_limit; } PI_Controller; float PI_Controller_Update(PI_Controller *pi, float error) { float proportional = pi->kp * error; pi->integrator += pi->ki * error * pi->Ts; // 抗积分饱和 (Clamping) float unsaturated_output = proportional + pi->integrator; float final_output; if (unsaturated_output > pi->output_limit) { final_output = pi->output_limit; // 如果输出饱和且误差方向会加剧饱和,则停止积分 if (error > 0) pi->integrator -= pi->ki * error * pi->Ts; } else if (unsaturated_output < -pi->output_limit) { final_output = -pi->output_limit; if (error < 0) pi->integrator -= pi->ki * error * pi->Ts; } else { final_output = unsaturated_output; } return final_output; } // 在定时器中断中执行的核心控制函数 void Control_ISR_Handler(void) { // 1. 读取ADC值并转换为实际物理量 (V, A) float u_grid = ADC_to_Voltage(adc_buf[0]); // 网侧电压 float i_grid = ADC_to_Current(adc_buf[1]); // 网侧电流 float u_dc = ADC_to_Voltage(adc_buf[2]); // 直流侧电压 // 2. 运行SOGI-QSG,得到网压的u_alpha, u_beta SOGI_QSG_Update(&sogi_grid, u_grid); // 3. 运行锁相环,更新theta, sin_theta, cos_theta, omega SinglePhase_PLL_Update(&pll, sogi_grid.u_alpha, sogi_grid.u_beta); arm_sin_cos_f32(pll.theta * RAD_TO_DEG_SCALE, &sin_theta, &cos_theta); // 4. 对网侧电流也进行SOGI处理,得到i_alpha, i_beta (用于DQ变换) SOGI_QSG_Update(&sogi_current, i_grid); // 注意:这个SOGI的中心频率omega应使用锁相环输出的同一个omega // 5. Park变换:将i_alpha, i_beta变换到dq轴 float id = sogi_current.u_alpha * cos_theta + sogi_current.u_beta * sin_theta; float iq = -sogi_current.u_alpha * sin_theta + sogi_current.u_beta * cos_theta; // 6. 电压外环:直流电压PI控制,输出作为有功电流给定Id_ref float vdc_error = Vdc_ref - u_dc; Id_ref = PI_Controller_Update(&pi_vdc, vdc_error); // 无功电流给定Iq_ref通常设为0,以实现单位功率因数 Iq_ref = 0; // 7. 电流内环PI计算 + 前馈解耦 float id_error = Id_ref - id; float iq_error = Iq_ref - iq; float vd_pi = PI_Controller_Update(&pi_id, id_error); float vq_pi = PI_Controller_Update(&pi_iq, iq_error); // 前馈解耦计算 float vd_ff = pll.omega * L * iq + u_grid_amplitude; // u_grid_amplitude 可从ud估算或直接测量幅值 float vq_ff = -pll.omega * L * id; float vd_ref = vd_pi + vd_ff; float vq_ref = vq_pi + vq_ff; // 8. 反Park变换:将dq轴的电压参考值变换回αβ坐标系 float valpha_ref = vd_ref * cos_theta - vq_ref * sin_theta; float vbeta_ref = vd_ref * sin_theta + vq_ref * cos_theta; // 9. 生成PWM驱动信号 (例如使用SVPWM或SPWM) // 对于单相全桥,通常用SPWM即可。valpha_ref即为我们需要的调制波。 // 将其与三角载波比较,生成PWM占空比。 float modulation_wave = valpha_ref / (U_dc / 2.0f); // 标幺化到[-1, 1],U_dc是直流侧电压 // 限制调制比在安全范围内,例如 [-0.9, 0.9] if (modulation_wave > 0.9f) modulation_wave = 0.9f; if (modulation_wave < -0.9f) modulation_wave = -0.9f; // 10. 更新TIM1的CCR寄存器,生成PWM uint16_t ccr_value = (uint16_t)((modulation_wave + 1.0f) * 0.5f * PWM_PERIOD); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, ccr_value); // 互补通道的CCR需要根据调制波极性设置,此处略去细节 }5. 参数整定与调试:从理论到稳定的必经之路
代码写完了,烧进去大概率是一团糟。参数整定是让系统活过来的关键。
5.1 SOGI参数k的整定
阻尼系数k决定了正交信号发生器的性能。我强烈建议从 k = √2 开始尝试,这个值在动态响应和滤波效果之间有一个较好的平衡。你可以通过以下步骤验证:
- 给系统输入一个干净的正弦波(比如用信号发生器),观察SOGI输出的u_alpha和u_beta。
- 它们应该是幅值相等、相位相差90度的正弦波。如果相位差明显不是90度,或者幅值不等,说明离散化可能有问题或k值不合适。
- 然后输入一个含有谐波(比如加一点3次或5次谐波)的信号,观察u_beta的波形是否仍然相对干净。如果谐波含量很高,可以适当减小k值(如取0.8),但要以牺牲一些动态性为代价。
5.2 锁相环PI参数的整定
锁相环本质上是一个跟踪正弦信号相位的闭环系统。其PI参数整定目标是在动态响应速度和抗干扰能力之间取得平衡。
- 比例系数Kp_pll:主要影响锁相环的捕获速度和带宽。Kp越大,对相位阶跃的响应越快,但过大会引起相位超调甚至振荡。可以从
Kp = 2 * ξ * ωn的粗略估算开始,其中ξ取0.7~1,ωn是期望的锁相环自然频率,通常设为电网频率的2~5倍(100~250 rad/s)。所以初始Kp可以设为200左右。 - 积分系数Ki_pll:用于消除稳态相位误差。Ki = ωn²。按照上面的ωn,Ki大概在10000量级。
调试方法:
- 先让系统开环,即锁相环的ω固定为额定值(314.16),只运行SOGI和Park变换。在示波器上观察计算出的uq。如果锁相准确,uq应该是一个接近0的直流信号(可能有少量纹波)。
- 然后闭合锁相环。突然改变输入信号的频率(比如从50Hz跳到51Hz),观察锁相环输出的theta能否平滑地跟踪上,且uq最终能回到0附近。如果跟踪过程振荡,减小Kp;如果跟踪太慢,增大Kp。如果存在稳态误差,适当增大Ki。
5.3 电流环PI参数的整定
电流环是内环,要求响应最快。通常采用零极点对消法或经验法。
- 理论计算:电流环被控对象的传递函数可以近似为
Gp(s) = 1 / (Ls + R)。设计PI控制器Gc(s) = Kp + Ki/s。令控制器零点Ki/Kp抵消对象极点R/L,即Ki/Kp = R/L。然后根据期望的闭环带宽选择Kp。闭环带宽通常取开关频率的1/10到1/5。对于16kHz开关频率,带宽可取1600Hz (约10000 rad/s)。则Kp ≈ L * ω_bandwidth。 - 经验调试(更实用):
- 先将Ki设为0,Kp设一个较小的值。
- 给定一个阶跃的Id_ref(从0到某个小值),观察实际Id的响应。
- 逐渐增大Kp,直到电流响应出现轻微的超调或振荡,然后回调一点,让响应处于临界阻尼状态。
- 然后加入Ki。从小值开始慢慢增加,直到稳态误差被消除,且动态响应没有明显变差。积分项太强会引起低频振荡。
直流电压环参数整定: 电压环是外环,响应必须比电流环慢,通常带宽是电流环的1/5到1/10。整定方法类似,先调Kp,再调Ki。直流侧电容C的大小决定了环路响应。Kp_vdc ≈ C * ω_bandwidth_vdc,其中ω_bandwidth_vdc可取100~200 rad/s。
调试血泪教训1:采样延迟与计算延迟这是最容易导致环路不稳定的“隐形杀手”。从ADC采样到更新PWM占空比,中间经过了采样、转换、DMA传输、算法计算等一系列过程,这会产生至少一个控制周期(Ts)的延迟。在计算PI参数时,必须将这个延迟考虑进去。一个经验法则是,在理论计算得到的Kp基础上,先打一个5到8折,作为初始值进行调试,否则极易振荡。
调试血泪教训2:标幺化与定点数STM32F407虽然有FPU,但大量浮点运算在16kHz中断下仍可能吃力。对于Id/Iq的PI控制器,可以考虑使用定点数运算或标幺化处理。将所有物理量(电压、电流)除以一个基值,转化为标幺值(如-1.0 ~ 1.0)。这样PI参数的范围会变得直观(通常在0~10之间),且运算速度更快。务必在代码中保持单位一致,避免混乱。
6. 实测波形分析与常见问题排查
当所有参数初步调好,系统应该能运行了。用示波器看几个关键波形:
- 网侧电压与电流波形:在整流模式下,两者应同相位,电流正弦度好,THD低。在逆变模式下,两者应反相位。
- 直流侧电压:应稳定在给定值,纹波在可接受范围内。
- dq轴电流Id, Iq:在MATLAB/Simulink仿真中看,或者在MCU里通过串口发送出来看。Id应该能快速跟踪Id_ref,Iq应维持在0附近。
常见问题及排查:
问题:电流环振荡,波形毛刺多。
- 排查:首先检查采样值是否准确、稳定。用示波器测量实际电流,与ADC读取的值对比。其次,检查PWM死区时间是否足够,是否存在上下管直通。最后,大幅降低电流环Kp和Ki,看是否还振荡,如果消失,说明是参数问题,需重新整定。
问题:锁相环在电网电压畸变时(如开机瞬间)失锁,相位乱跳。
- 排查:这是SOGI的k值可能太大了,或者锁相环PI参数太激进。尝试减小SOGI的k值(如从1.414减到0.8),增强其滤波能力。同时适当降低锁相环的Kp,牺牲一点动态性,换取稳定性。也可以在软件中增加一个“锁相状态标志”,当uq连续多次超过阈值时,判断为失锁,此时可以暂时冻结积分器或切换到开环固定频率模式。
问题:模式切换(整流/逆变)时,直流电压或电流冲击大。
- 排查:模式切换本质是改变Id_ref的符号(从正到负)。不要阶跃变化,应该做一个斜坡变化。在软件中,让Id_ref以一定的斜率从当前值变化到目标值,给电流环和系统一个缓冲时间,可以极大减小冲击电流。
问题:轻载时运行正常,加大负载后系统崩溃。
- 排查:检查直流侧电容容量是否足够。负载突变时,需要电容提供或吸收瞬时功率。电容太小会导致直流电压波动剧烈,超过电压环的调节能力。同时,检查电源和功率器件的额定电流、散热是否满足要求。
7. 进阶优化与电赛实战技巧
在基本功能实现后,为了在电赛中取得更好成绩,可以考虑以下优化点:
- 软件锁相环(SPLL)的抗干扰增强:在SOGI之前,加入一个移动平均滤波器或低通滤波器,对原始采样电压进行初步滤波,可以进一步抑制高频噪声。但要注意引入的相位延迟。
- 启动策略:系统上电时,直流侧电容电压为0。如果直接开启PWM和闭环,巨大的电压差会导致冲击电流。标准的做法是:
- 先以不控整流的方式,通过桥臂的反并联二极管给直流电容充电至电网电压峰值。
- 电容电压建立后,再使能PWM输出和闭环控制。
- 闭环启动时,先让电流给定Id_ref从0缓慢增加,实现“软启动”。
- 保护机制:必须在中断服务程序中实现严格的保护。
- 过流保护:实时检测网侧电流和桥臂电流,超过阈值立即封锁PWM输出(将CCR设为0或强制输出无效电平)。
- 过压/欠压保护:监测直流侧电压。
- 软件互锁:确保同一桥臂的上下管驱动信号之间留有足够的死区时间,并且在故障时能同时关闭。
- 效率与功率因数测量:电赛会考核这些指标。效率=输出功率/输入功率。输入输出功率可以通过实时计算电压电流瞬时值的乘积(
u*i)再求平均得到。使用STM32的DSP库中的arm_dot_prod_f32()函数可以高效计算。功率因数可以通过锁相环计算出的电压电流相位差来得到,更简单的方法是PF = 平均功率 / (电压有效值 * 电流有效值)。 - 使用DSP库加速:STM32F407的DSP库(CMSIS-DSP)对三角函数(
arm_sin_cos_f32)、矩阵运算、滤波器等有极大优化。务必在工程中启用FPU,并在编译选项中加入-mfpu=fpv4-sp-d16 -mfloat-abi=hard,并调用DSP库函数,这将显著提升16kHz中断下的计算效率,为更复杂的算法留出余地。
最后,电赛现场环境复杂,干扰强。除了软件稳健,硬件布局布线也至关重要。功率地(强电)和信号地(弱电)要单点连接,电流采样电阻的走线要尽量短且对称,ADC基准电压要干净稳定。多带几块烧写好程序的备用核心板,关键时刻能救命。把这个单相PWM整流系统吃透,不仅仅是完成一道赛题,更是掌握了新能源并网、UPS、变频器等众多电力电子应用的核心基础,这笔经验远比奖项本身更有价值。
本文还有配套的精品资源,点击获取