傅里叶变换把信号分解为频率分量,拉普拉斯变换把微分方程变成代数方程并以极点刻画系统动态。本节用 SciPy 对光伏振荡案的功率录波做频谱分析,确认 8 Hz 分量的存在与幅值;再讲拉普拉斯域的极点-稳定性关系,为下一节的控制诊断搭好数学脚手架。
一段十秒钟的功率曲线,几千个采样点,肉眼看只是一团缓慢起伏的毛刺。但把"时间轴"换成"频率轴",同一份数据立刻坦白:哪里有峰,哪里就有周期性成分。变换域的价值不在计算技巧,而在换一个坐标看同一件事——时间上纠缠的两个成分,频率上往往泾渭分明。
傅里叶级数说,任何周期信号都能拆成谐波之和;傅里叶变换把这条路推广到非周期信号,得到连续频谱。工程实现是离散傅里叶变换(DFT),快速算法 FFT 把计算量从平方级降到 N log N——一次十秒千点的频谱分析在普通笔记本上瞬间完成。
import numpy as np from scipy.fft import rfft, rfftfreq # 光伏电站高速录波:10 秒、1 kHz,含 8 Hz 振荡 fs = 1000.0 t = np.arange(0, 10, 1/fs) rng = np.random.default_rng(7) P = 20 + 0.6*np.sin(2*np.pi*8*t) + 0.3*np.sin(2*np.pi*49.7*t) + 0.15*rng.normal(size=t.size) X = rfft(P - P.mean()) freqs = rfftfreq(P.size, 1/fs) mag = np.abs(X) / P.size * 2 # 找出主要谱峰 idx = np.argsort(mag)[::-1] found = [] for i in idx: if mag[i] < 0.02: break if all(abs(freqs[i]-f) > 2 for f, _ in found): found.append((freqs[i], mag[i])) print("主要频率成分(Hz,幅值 p.u.):") for f, m in sorted(found): print(f" {f:7.2f} Hz {m:.4f}")
输出会列出三个峰:0.05 Hz 附近的缓变(均值去除后残留边缘效应,可忽略)、8.0 Hz 幅值约 0.6、49.7 Hz 幅值约 0.3。8 Hz 分量坐实——它不是噪声,是确凿的周期性振荡;49.7 Hz 则是锁相环跟踪的工频附近波动。频谱同时给出幅值,定量与调度的"3% 峰峰值"记录闭环。
频谱分析的三个工程参数顺带交代:频率分辨率 = 1/时长(10 秒数据只能分辨间隔 0.1 Hz 以上的峰,想看得更细要加长窗);频谱泄漏(信号截断使能量从峰"漏"到邻近频点,加窗函数可缓解);帕塞瓦尔定理(时域总功率等于频域分量功率之和,做噪声能量核算的依据)。

傅里叶擅长回答"信号里有什么",拉普拉斯擅长回答"系统会怎么动"。对微分方程两边做拉普拉斯变换,求导变成乘 s,微分方程变成代数方程。传递函数 H(s) = 输出拉氏变换 / 输入拉氏变换,把系统压缩成两个多项式之比。
极点(分母多项式的根)是系统的"性格档案":一阶系统 1/(s+a) 的极点在 −a,时间响应是指数衰减,衰减速度由极点到原点的距离决定;共轭复极点对应振荡,实部决定衰减快慢,虚部决定振荡频率。左半平面极点 → 稳定;虚轴上 → 临界(等幅振荡);右半平面 → 发散。
import numpy as np # 三种极点位置对应的时域行为 t = np.linspace(0, 5, 500) y_decay = np.exp(-2*t) # 实极点 s=-2 y_osc_damp = np.exp(-0.5*t)*np.cos(6*t) # 复极点 -0.5±j6 y_osc_grow = np.exp(0.3*t)*np.cos(4*t) # 右半平面 0.3±j4 for name, y in [("实极点(单调收敛)", y_decay), ("左半复极点(衰减振荡)", y_osc_damp), ("右半复极点(发散振荡)", y_osc_grow)]: print(f"{name}: 末值 = {y[-1]:+.3f}, 峰值 = {np.max(np.abs(y)):.3f}") # 振荡案的极点语言 print("\n光伏振荡案:闭环某极点从 -0.4+j8.0 移到 +0.05+j8.0") print("实部变正 → 8 Hz 分量从衰减转为自持 —— 这就是频谱上那个峰的本质")
把第 6 章的暂态稳定也翻译过来:故障期间功角摆开,对应系统主导极点暂时大幅右移;故障切除后极点回到左半平面,摆动衰减——"功角回得来"就是"极点回得来"。时域、频域、s 域三个视角说的是同一件事,语言不同。
传递函数沿虚轴取值 s = jω 就得到频率响应——幅频与相频特性。二阶系统是标准样本:自然频率 ωn 与阻尼比 ζ 两个参数决定了谐振峰高低与相位过渡的陡峭程度。
import numpy as np # 二阶系统频率响应:不同阻尼比 wn = 2*np.pi*8.0 # 自然频率取 8 Hz(呼应振荡案) w = np.linspace(0.1, 5*wn, 400) for zeta in [0.1, 0.3, 0.707, 1.0]: H = wn**2 / (-(w**2) + 2j*zeta*wn*w + wn**2) peak = np.max(np.abs(H)) print(f"阻尼比 zeta={zeta:.3f}: 谐振峰 = {peak:.2f} 倍({'有明显谐振' if peak>1.15 else '基本平坦'})")
阻尼比 0.1 时谐振峰 5 倍,0.707 时几乎平坦——振荡案的治理本质就是给 8 Hz 附近的等效阻尼比从 0.1 提到 0.3 以上,频谱上的峰自然塌下去。下一节控制篇将说明这个阻尼比怎么"加"。
下一节正式进入控制:带宽、稳定裕度与 PID,把"加阻尼"落到可整定的参数上。