☰
同步相量计算深度解析:FFT、小波与HHT实战
2026/9/29 23:32:27 网站建设 项目流程

做电力系统同步相量计算这几年,我最大的感受是:一个看似“测个幅值、算个相角”的活儿,真正较真起来能把人磨到怀疑人生。拿标准的50Hz工频信号来说,系统名义频率是50Hz,但实际运行中会有0.01到0.1Hz量级的偏移,更别说振荡、谐波和噪声全混在一起。用FFT去算,频率一旦偏离设计值,频谱泄露马上就会让幅值和相角读数漂移;用窗函数法能缓解一部分,但窗长、窗型怎么选又是一堆讲究;再往上走,小波变换、希尔伯特-黄变换(HHT)这些更复杂的工具也被陆续引入到同步相量计算里。这篇内容,我就把自己在这条路上踩过的坑、试过的方案、写过的Matlab实现,从头到尾梳理一遍,希望对正在做PMU相量算法、电能质量分析或者电力信号处理的朋友有点帮助。

1. 同步相量到底要算什么:先厘清问题再动手

1.1 同步相量不只是“幅值和相角”

我们通常说的相量,其实就是复数的幅值和相位角。但同步相量的关键在“同步”二字:所有测量装置采用统一的时间基准,通常通过卫星对时信号做授时,然后在这个全局时间基准下测得的基波电压或者电流相量,才能叫同步相量。

这里有个容易被新手忽略的点:相角不是相对于自己装置内部起点的角度,而是相对于全球统一时间参考点的角度。一台装置内部眼里看到的是“这个波形比我的晶振时钟提前了0.3毫秒”,这没有意义;只有把所有装置的角度放到同一个时间轴上比对,才能算出厂站之间的功角差、判断系统是否稳定、评估潮流走向。

除了幅值和相角,同步相量还顺带派生两个重要量:频率和频率变化率(ROCOF)。这四个量合起来,构成电力系统动态监测的基础数据。广域测量系统(WAMS)、低频振荡在线识别、扰动源定位,都是从这组数据开始往上建的。我最早接触这个方向时,以为同步相量就是个简化版的“交流电表读数”,深入之后才发现它背后牵着一整套时频分析理论。

1.2 为什么单一方法搞不定同步相量计算

道理说起来很直白:交流信号无非是幅值A、频率f、相位φ三个参数,FFT算一下不就有了?可实际的电网信号远比教科书复杂。频率不是恒定50Hz,负荷波动、发电机调速都会让频率在49.8到50.2Hz之间漂移;线路谐波(3次、5次、7次)、间谐波、白噪声、探头噪声叠在一起;再加上故障时的电压跌落、振荡时的幅值调制,这些非平稳变化让“稳态假设”经常站不住脚。

所以就有了各种方法。FFT和窗函数法解决“稳态但频率不准”的问题;小波变换引入时频分析,能追踪动态变化;HHT走的是完全不同的路子,不依赖预定义的基函数,靠数据本身自适应分解。我实际跑下来发现,这些方法不是互相替代的关系,而是各自对应不同场景的痛点。下面挨个说清楚,最后给一套能复现的Matlab对比框架。

2. FFT与窗函数法:同步相量计算的“地基”

2.1 DFT基础与“非整周期截断”麻烦

DFT的核心思想,是把一段N点离散序列分解成N个不同频率的余弦成分。对于信号x(t)=A·cos(2πf0t+φ),采样N点做DFT,如果f0正好落在某条离散谱线上,该谱线处幅值|X(k0)|=N·A/2,相位angle(X(k0))=φ,直接反算就得到相量。

问题就出在“如果”两个字上。电网频率稍微一偏,f0不再等于k0·fs/N,DFT谱线就不再是干净的单根谱线,而是把能量“泄”到周围一堆谱线上。

我实测过:50Hz信号、窗长80个采样点(采样率4000Hz)时,频率偏移0.5Hz,纯FFT的幅值误差就能超过3%,相位误差接近1度。这在很多工程场景下已经不可接受了,尤其是在做同步相量测量时,IEEE C37.118里稳态情况下的TVE要求通常在1%以内,纯FFT直接超限。

这里多解释一句TVE(总向量误差),它把幅值误差和相位误差揉成一个指标,公式是:

TVE = sqrt((Xr_est - Xr)^2 + (Xi_est - Xi)^2) / sqrt(Xr^2 + Xi^2)

Xr和Xi是理论相量的实部和虚部,带est下标的是估计值。我后面所有对比实验都会算TVE曲线,因为单看一个点的误差很容易被偶然性误导。

2.2 窗函数怎么选:一个表格看清楚

频谱泄露的本质是时域截断——把无限长的信号乘以一个矩形窗,在频域就相当于卷积一个sinc函数。sinc函数的主瓣宽、旁瓣高,就是频谱泄漏的根源。既然问题出在“矩形窗”,解决思路也很直接:换旁瓣更低的窗,让能量不往远端泄露。

但加窗的代价是主瓣变宽,频率分辨率下降。选窗本质就是在主瓣宽度和旁瓣衰减之间取舍。我把常用的几类窗参数整理成一张表:

窗类型主瓣宽度(相对矩形窗倍数)第一旁瓣衰减适用场景
矩形窗1-13 dB频率分辨率要求最高,但允许频谱泄露
汉宁窗2-31 dB工程最常用,相量计算首选
海明窗2-41 dB第一旁瓣低,但远端衰减慢
布莱克曼窗3-58 dB旁瓣极低,但主瓣明显变宽
凯塞窗可调β可调需要定制主瓣/旁瓣平衡时

实践里我用汉宁窗最多。电力同步相量计算一般取一个工频周期(20ms)或两个周期(40ms)作为窗长,用汉宁窗加权,再配合双谱线插值算法,能把频率偏移造成的误差压到非常低。海明窗虽然第一旁瓣比汉宁低,但旁瓣衰减慢,对远端谐波压制不彻底。布莱克曼窗主瓣太宽,稳态没问题,动态响应变差。凯塞窗效果好但多了一个β参数要调,落地时麻烦一些。

2.3 加窗FFT提取相量的Matlab实现

下面这段是我做对比测试时反复用到的最小实现。以采样率4000Hz(每工频周期80点)、窗长80点为例,展示从加窗到幅值恢复的完整流程:

fs = 4000; % 采样率 4000Hz N = 80; % 一个工频周期 f0 = 50; % 额定频率 n = (0:N-1)'; t = n / fs; % 模拟:幅值1.2,相角30°,频率偏移到50.5Hz A0 = 1.2; ph0 = 30*pi/180; f_dev = 50.5; x = A0 * cos(2*pi*f_dev*t + ph0); % 汉宁窗 + FFT w = hanning(N); xw = x .* w; X = fft(xw); % 找最大谱线(跳过直流分量) [~, kmax] = max(abs(X(2:end-1))); kmax = kmax + 1; % 幅值和相位恢复 A_est = 2 * abs(X(kmax)) / sum(w); ph_est = angle(X(kmax)); fprintf('估计幅值: %.4f,相位: %.2f°\n', A_est, ph_est*180/pi);

注意,这段代码在“频率正好对准谱线”时效果不错,但频率偏移到50.5Hz时,幅值误差仍有几个百分点。要压得更狠,就得用双谱线插值加窗FFT:取最大谱线kmax和相邻较大谱线kmax±1的比值,反推出实际频率偏移量,再对幅值相位做修正。或者也可以用锁相环先把频率稳到基频再重采样,后者在工程上同样很实用。

这里要提醒一句:加窗后相位不能直接取angle就完事。非对称窗会引入额外相移,用对称窗并把数据对齐到窗中心能省很多麻烦,否则得在相位上减掉一个固定偏移量。我在第一次实现时就在这个细节上吃过亏,算出来的相位总是差一个恒定角度,排查了半天才发现是窗函数对齐的问题。

现在我做FFT类相量计算,默认加窗、默认做插值,坚决不裸奔。当年直接拿fft丢进去算,频率偏了也不管,TVE一路飙到5%以上,那种“明明逻辑都对就是结果不对”的痛苦,经历过的人都懂。

3. 小波变换:把“变焦镜头”装到相量提取上

3.1 STFT的“固定窗”困境与小波思路

FFT类方法只能给出一个窗口内的“平均”频谱,相当于用固定焦距的镜头拍照——你选了20ms窗口,就注定看不清窗口内更快的细节变化;选了5ms窗口,频率分辨率又不够。短时傅里叶变换(STFT)也解决不了这个问题,因为它的窗宽是全局固定的,想同时得到高频处的时间分辨率和低频处的频率分辨率,做不到。

小波变换的思路则完全不同:它给信号配了一个“变焦镜头”,通过一个可伸缩的母小波函数对信号做内积。尺度小的时候,小波被压缩,时间分辨率高、频率分辨率低,适合看瞬态;尺度大的时候,小波被拉长,频率分辨率高、时间分辨率低,适合看慢变分量。这个性质对电力信号特别友好——谐波、故障暂态要看高频细节,基波相量变化要看长时间演化,一次小波变换都能照顾到。

3.2 复小波系数与瞬时相量的关系

大多数讲小波的文章只讲小波分解、去噪和重构,很少讲怎么用小波系数直接提取相量。其实如果选用解析型复小波(如复Morlet小波),小波系数本身就是复数,它的幅值和相位可以对应到信号的局部幅值和相位,只是需要按小波的中心频率和归一化方式做标定。

具体做法是:对采样信号做连续小波变换(CWT),得到“时间—频率—幅值”的系数矩阵,在50Hz对应的频率位置取出一条系数序列。这条序列每个时刻的幅值反映基波的瞬时幅值,每个时刻的角度反映基波的瞬时相位。相比FFT只能给出一个窗口内的单点估计,CWT能给出一条随时间变化的相量轨迹,这在分析低频振荡、幅值调制等场景下非常有用。

3.3 Matlab中cwt/dwt的使用要点与边界问题

Matlab的连续小波变换函数cwt用起来很方便,默认解析Morlet小波(amor),一行调用直接返回系数矩阵和频率向量:

[coef, frq] = cwt(x, fs, 'amor'); % x是信号序列,fs是采样率 % 找最接近50Hz的频率索引 [~, idx] = min(abs(frq - 50)); base_coef = coef(idx, :); % 50Hz附近小波系数随时间的变化 % 标定:用单位幅值、零相位的50Hz纯信号计算校正系数 x_cal = cos(2*pi*50*t); [coef_cal, ~] = cwt(x_cal, fs, 'amor'); [~, idx_cal] = min(abs(frq - 50)); cal_factor = abs(coef_cal(idx_cal, 1)); cal_phase = angle(coef_cal(idx_cal, 1)); A_est = abs(base_coef) / cal_factor; ph_est = angle(base_coef) - cal_phase;

这里我坚持用“标定法”而不是直接除以某个解析常数,原因是cwt的归一化方式、小波臂长、频率网格疏密都会影响系数幅值,标定法最保险,也最容易跟实际系统对接。实测下来,用单位幅值信号标定后,50Hz稳频信号的幅值误差可以控制到0.5%以内,但数据边界处误差会急剧增大。处理办法有两种:要么在信号前后各加一段缓冲数据,算完再裁掉;要么干脆丢弃两端各约5%的数据。工程上我倾向于后者,简单直接,虽然损失了一点观测长度,但换来了干净的有效区间。

另一个要注意的点是离散小波变换(dwt/wavedec)和连续小波变换的区别。DWT主要用于多分辨率分解、去噪和暂态特征提取,比如把信号分解成d1、d2、d3等细节层,用来定位扰动发生的时刻和频段。但DWT的系数相位特性不如CWT干净,还伴有平移不变性问题——信号时间轴稍微平移,小波系数幅值就会变化,这在相量计算里很致命。所以提取相量时我基本用CWT,DWT留着做特征分析和去噪。

4. 希尔伯特-黄变换:用数据本身的节奏说话

4.1 EMD分解:把混合信号拆成“零件”

希尔伯特-黄变换(HHT)是黄锷提出的一套方法,核心分两步:先用经验模态分解(EMD)把信号分解成若干个固有模态函数(IMF),再对选定的IMF做Hilbert变换,得到瞬时频率和瞬时幅值。

EMD和FFT、小波最大的不同,在于它没有固定的基函数。你去问它“信号里有什么成分”,它不预设答案,而是通过筛选过程从数据里自学习。筛选过程大致是这样:

  1. 找信号的全部局部极大值和极小值;
  2. 用三次样条分别拟合上包络和下包络;
  3. 取上下包络的均值,从原信号中减掉,得到一个去掉低频趋势的剩余信号;
  4. 重复以上步骤,直到剩余信号满足IMF条件(极值点数和过零点数相等或最多差1,且上下包络均值近似为0)。

每个IMF代表一种“瞬时频率有意义”的单分量信号。对电力系统信号来说,基波分量通常分解出来得非常靠前(IMF1或IMF2),谐波次之,趋势项和噪声留在残差里。这就提供了另一种提取基波相量的思路——先EMD筛出基波IMF,再做Hilbert变换。

4.2 希尔伯特变换如何给出瞬时幅值相位

对一个实信号s(t),Hilbert变换构造出解析信号z(t)=s(t)+jH{s(t)}。解析信号的模就是瞬时幅值,辐角就是瞬时相位,瞬时频率则由相位对时间求导再除以2π得到。

这个“瞬时”的定义,看起来美好,用起来有讲究。它只对单分量信号有意义——如果信号里同时有基波、谐波、噪声,拿原始信号直接做Hilbert变换,相位就不是清晰的主值,瞬时频率波动得厉害。所以必须先EMD把各分量拆开,只对选定的IMF做Hilbert变换。这也是HHT和EMD深度绑定的根本原因。

Matlab里的Hilbert变换就是一行代码:

z = hilbert(imf_selected); % imf_selected是选定的基波IMF a_inst = abs(z); % 瞬时幅值序列 phi_inst = angle(z); % 瞬时相位序列

4.3 HHT做相量计算的代码思路与三大坑点

用HHT估算同步相量的整体思路是:原始信号 → EMD分解 → 选出基波IMF → Hilbert变换 → 得到瞬时幅值和相位。我跑过对比测试,在频率偏移、幅值调制的场景下,HHT的幅值跟踪能力确实比加窗FFT强,尤其是能捕捉到幅值突变和相位跳变的时刻。但坑也很多,我踩过的有三类:

端点效应是第一个坑。三次样条在数据两端缺乏约束,包络线在端点处会剧烈摆动,导致IMF两端被“掰弯”、幅值相位在端点处失真。常见解法是端点延拓——把端点附近的极值延拓出去,或者用镜像对称延拓。我一般会在EMD之前把信号首尾各补一小段镜像数据,处理完再裁掉。

模态混叠是第二个坑。当一个IMF里混进了两个频率非常接近的分量(比如50Hz基波和50.5Hz的低频振荡分量),EMD可能拆不彻底,幅值和相位互相污染。解决办法是用EEMD(集合经验模态分解)或CEEMDAN,本质是给信号加白噪声辅助,让不同尺度的成分更容易被筛分出来,代价是计算量暴涨。

参数敏感是第三个坑。EMD的停止准则不同,分解结果差异非常大。过度筛分会把IMF磨成纯正弦波,丢失信号的动态信息;筛分不足又会保留相邻频率的干扰。经验值SD阈值取0.1到0.3,但换信号、换场景都要重新调试。

至少在实际工程落地层面,HHT目前更多是研究工具而不是在线实时算法。计算开销大、结果可重复性受参数影响,在PMU这类要求严格确定性的装置里,我更倾向于FFT类做主体,HHT用于离线的非平稳信号分析、故障特征提取和学术研究。先知道工具的边界,再决定怎么用,这是搞研究最重要的一条经验。

5. 四种方法横向对比:选型看哪些维度

5.1 一张表看透四种方法的优劣

我选型对比时通常关注五个维度:适用信号类型、时间分辨率、频率分辨率、抗噪能力、计算开销。整理成表会直观很多:

方法适用信号时间分辨率频率分辨率抗噪能力计算开销
直接FFT(矩形窗)稳态信号无(单窗单值)最好中(泄露会污染相邻谱线)低
加窗FFT(汉宁+插值)准稳态、频率偏移无好(主瓣略宽)较好低
小波变换(CWT)非平稳、动态跟踪好随尺度变化较好(可取定频带)中
HHT(EMD+Hilbert)强非平稳、暂态突变最好(瞬时量)自适应较弱(噪声易造虚假IMF)高

这张表只是静态对比,实际用的时候还有一个指标很关键:在IEEE C37.118这类相量测量标准下的达标能力。标准里最重要的指标是TVE,稳态测试、动态测试、谐波抗扰测试的阈值不一样。就我的测试经验:纯FFT稳态下很容易达标,动态测试会翻车;加窗+插值能把稳态和准动态压达标;CWT在动态测试里表现好,但需要仔细标定;HHT目前很难在标准要求的时间内完成在线计算,更适合离线分析。

5.2 不同工况下的方法适配思路

选型不是“哪种方法更好”,而是“哪种场景下哪种方法更合适”。我一般按工况分四层:

  • 纯稳态:系统无扰动,频率基本等于50Hz。直接FFT都够用,加窗FFT更稳。
  • 准稳态:频率有偏移,比如49.8到50.2Hz。优先加窗FFT配合插值,或者测频后重采样。
  • 动态过程:低频振荡、幅值调制、频率爬坡。CWT能给出漂亮的瞬时相量轨迹,时间定位能力比加窗FFT强。
  • 强暂态:故障、跳闸、行波类突变。HHT的瞬时频率分析优势明显,但要做EEMD抑制模态混叠,纯离线。

我之前做过一次低压配电网的录波分析:故障发生后100ms内电压幅值从1.0跌到0.85再回升。用加窗FFT追踪,幅值曲线在故障点滞后了20ms左右;换成标定后的CWT,滞后能压到5ms以内。时间分辨率这东西,做动态同步相量分析时真的不能只靠FFT扛。

6. 实操与排坑:可复现的Matlab代码框架

6.1 一套四方法对比代码框架

下面这个框架是我做多方法测试时用的最小可复现结构:生成一段可控测试信号,在循环里分别走FFT和加窗FFT,再对整段信号做CWT,最后用TVE曲线对比。完整代码按自己场景裁剪即可:

clear; clc; fs = 4000; t_total = (0:(8*fs-1)) / fs; f_dev = 50.5; % 测试信号:1.0 p.u.、相角30°、频率偏移50.5Hz、叠加2%白噪声 A0 = 1.0; ph0 = 30*pi/180; sig_true = A0 * cos(2*pi*f_dev*t_total + ph0); sig = sig_true + 0.02 * randn(size(t_total)); % 滑窗参数 win_len = 80; % 两个工频周期 step = 20; % 滑动步长 A_fft = zeros(1, floor((length(sig)-win_len)/step) + 1); ph_fft = zeros(size(A_fft)); A_win = zeros(size(A_fft)); ph_win = zeros(size(A_fft)); for idx = 1 : length(A_fft) seg_start = (idx-1)*step + 1; seg = sig(seg_start : seg_start+win_len-1); % 直接FFT法 X0 = fft(seg); [~, k0] = max(abs(X0(2:end-1))); k0 = k0+1; A_fft(idx) = 2*abs(X0(k0)) / win_len; ph_fft(idx) = angle(X0(k0)); % 加汉宁窗法 w = hanning(win_len); Xw = fft(seg .* w); [~, kw] = max(abs(Xw(2:end-1))); kw = kw+1; A_win(idx) = 2*abs(Xw(kw)) / sum(w); ph_win(idx) = angle(Xw(kw)); end % CWT法(作用于整段信号) [coef, frq] = cwt(sig, fs, 'amor'); [~, idx_f] = min(abs(frq - 50)); base_coef = coef(idx_f, :); % 注意:小波系数幅值不是物理幅值,必须按3.3节标定法校正 % 这里用单位幅值信号预先算好cal_factor和cal_phase A_cwt = abs(base_coef) / cal_factor; ph_cwt = angle(base_coef) - cal_phase; % 最后按TVE公式逐点计算误差并绘图对比

关于这段代码有两点说明。第一,CWT部分我特意用注释标注了标定要求,千万别拿未标定的系数当物理幅值直接用,否则幅值可能差出几倍。第二,滑窗步长要兼顾响应速度和计算量:步长越小曲线越平滑但耗时越大,一般取窗长的1/4到1/2。我实测下来,80点窗、步长20点,对于4000Hz采样率的离线分析是速度和精度的折中。

6.2 常见问题速查表与调试心得

最后把我在实际调试里遇到过的典型问题整理成速查表,这张表是我自己翻得最频繁的东西:

现象根因解决思路
频率偏移后FFT幅值偏小且相位乱跳频谱泄露加窗+双谱线插值,或锁相环测频后重采样
加汉宁窗后幅值整体偏小没除以相干增益用 sum(w)/N 做校正
CWT提取的幅值比真实值差很多小波系数归一化问题用单位幅值纯信号标定
CWT在数据两端幅值猛跳小波边界效应丢弃两端约5%数据,或扩展信号再裁掉
EMD第一个IMF混有基波和高频噪声模态混叠改用EEMD/CEEMDAN
EMD在端点处IMF严重变形端点效应镜像延拓或极值延拓
不同参数下EMD结果差异大停止准则敏感固定SD阈值与最大筛选次数,统一实验条件
HHT计算速度慢迭代筛选耗时缩短信号长度、限制最大IMF数、优化EMD实现

调试经验层面,我最想分享三条。第一,先纯后杂。新方法先用纯正弦信号验证数学部分,确认幅值和相位都对,再加谐波、加噪声、加频率偏移。见过太多人一上来就用真实录波数据调算法,出了问题根本分不清是预处理、参数还是算法本身的毛病。第二,清理基准。做对比实验时理论相量值一定自己算清楚,别拿另一种方法的输出当基准——两个都有误差,结论就全乱了。第三,记录参数。EMD和小波都对参数敏感,每次实验把窗长、阈值、小波类型、尺度范围记录清楚,这些元数据比最后画的图重要得多。

我自己做同步相量研究的路径,是从裸FFT开始,被频率偏移教育过之后老老实实加窗,再被动态分析需求推着去学小波和HHT,一路踩坑一路总结。如果你也是从某个单独的FFT代码开始做相量计算,我的建议是先别急着上复杂方法,把窗函数和插值吃透,它能解决你80%的精度问题;剩下20%的动态和暂态场景,小波和HHT各有用武之地。方法没有绝对的好坏,只有合不合适。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询