Files
STM32F4-Base/docs/算法/傅氏算法详解.md
T
wandering1 c25baba2f1 对齐 L2-2 实例数口径:规划表 4 → 5 个实例(参考项目 4 个)
- 规划 §3.2 L2-2 行:由"4 个实例:C01 基波 I/U、C02 零序基波、C03 二次、C04 五次"
  改为本项目的 5 个实例(C01-IA-F1 / C02-UA-F1 / C03-UN-F1 / C04-IA-F2 /
  C05-IA-F5),并加注说明 4 → 5 的来历:参考项目为 4 个,本项目按 V0.1 有效通道
  (UA/UN/IA)把 C01 的 I/U 拆为两行,其余顺延。
- 规划 §4.3 相量区 RAM 行:双区 + 4 实例 → 双区 + 5 实例。
- 傅氏算法详解 §7:该处的"4 个实例"标注为参考项目口径(其引用来源是
  APP/CLS100_Dsp/InstCalCell.c),并指向规划 §3.2 的本项目口径。
- 相量层单测说明 §4.3:由"与规划表的一处待对齐"改为"实例数 4 → 5:规划表已对齐"。
- 规划文档补记 L2 相量层落地(sample_ring + phasor + 57 用例主机单测),并显式说明
  §3.2 的 L2 各点状态仍标 ⬜ 的理由:台架 @test 闭环未做、L2-3 判据需标准源。
2026-10-10 18:16:17 +08:00

189 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> 从《项目详细分析-交流采样与有效值计算》中提取扩展,配图讲解傅氏算法(全周波傅里叶算法)的原理与工程实现。
> 工程背景:CLS100 DTU 保护测控装置,每周波 20 点采样(1000Hz @ 50Hz),保护有效值/相量由 `GlobalUnit/CalFFTVecFull.c` 全周傅氏计算。
> 公式为 LaTeX 排版,需 Markdown 预览(VS Code / Typora 等)渲染。
---
## 1. 一句话思想
**把一周波的采样序列分别和"标准正弦、标准余弦"做内积(投影)**:正弦分量投影到正弦上得实部,余弦分量投影到余弦上得虚部——用两根已知相位的"标杆"去量未知信号里基波的幅值和相位。数学上这就是**单频 DFT**(只计算 $k=1$ 那一根谱线)。
![投影原理](https://lsky.bitnasdaq.vip/gqvbns.png)
图中含 20% 五次谐波和 1V 直流的畸变波形,经两次投影后仍精确还原出基波:幅值 57.70V、相角 30.0°——谐波和直流在投影中"自己抵消了",这是傅氏算法的全部魔力,第 3 节用面积图解释为什么。
## 2. 数学推导
### 2.1 连续形式
设周期信号 $x(t)$,基波角频率 $\omega = 2\pi f$,其基波分量:
$$
x_1(t) = A_1\sin(\omega t + \varphi_1) = a_1\sin(\omega t) + b_1\cos(\omega t)
$$
在一个整周波 $T$ 上:
$$
a_1 = \frac{2}{T}\int_0^T x(t)\sin(\omega t)\,\mathrm{d}t
\qquad
b_1 = \frac{2}{T}\int_0^T x(t)\cos(\omega t)\,\mathrm{d}t
$$
### 2.2 离散形式(工程实现)
一个周波采 $N$ 个点 $x(0),\dots,x(N-1)$,积分 → 求和:
$$
a_1 \approx \frac{2}{N}\sum_{k=0}^{N-1} x(k)\,\sin\!\left(\frac{2\pi k}{N}\right)
\qquad
b_1 \approx \frac{2}{N}\sum_{k=0}^{N-1} x(k)\,\cos\!\left(\frac{2\pi k}{N}\right)
$$
幅值、相位、有效值:
$$
A_1 = \sqrt{a_1^2 + b_1^2}
\qquad
\varphi_1 = \arctan\!\frac{b_1}{a_1}
\qquad
U = \frac{A_1}{\sqrt{2}}
$$
### 2.3 本项目的写法:把 $\sqrt{2}$ 藏进系数表
`GIUnit/GLobalFunc.c` L337 的系数表预乘了 $\sqrt{2}/N$:
$$
g\_fFFTSin20[k] = \sin\!\left(\frac{2\pi k}{N}\right)\cdot\frac{\sqrt{2}}{N}
$$
于是累加结果直接是**有效值相量**分量:
$$
f_{Re} = \sum_{k=0}^{N-1} x(k)\,\sin\!\left(\frac{2\pi k}{N}\right)\frac{\sqrt{2}}{N} = \frac{a_1}{\sqrt{2}}
\qquad
f_{Im} = \frac{b_1}{\sqrt{2}}
$$
$$
f_{AmSQ} = \sqrt{f_{Re}^2 + f_{Im}^2} = \frac{A_1}{\sqrt{2}} = U
\quad (\text{直接就是有效值,无需再除}\ \sqrt{2})
$$
## 3. 为什么能滤除直流和谐波 —— 正交性
整周波上三角函数系正交:
$$
\int_0^T \sin(\omega t)\,\mathrm{d}t = 0,
\qquad
\int_0^T \sin(m\omega t)\sin(\omega t)\,\mathrm{d}t = 0 \quad (m \in \mathbb{Z},\ m \neq 1)
$$
![正交性](https://lsky.bitnasdaq.vip/BGNWjf.png)
看图最直观:**蓝=正面积,红=负面积**。
| 信号成分 × sinθ | 面积结果 | 结论 |
| --------------- | ------------ | ----------- |
| 直流 1V | 红蓝完全抵消 | **完全滤除** |
| 3、5、…次整数谐波 | 红蓝完全抵消 | **完全滤除** |
| 基波 | 正面积占优,净值 ≠ 0 | **被提取** |
| 衰减直流(非严格周期) | 近似抵消,有残余 | 大部分滤除 |
| 非整数次谐波(如 2.7 次) | 不严格抵消 | 按"泄漏"比例部分反映 |
**前提是数据窗恰好一个整周波**。窗长偏离整周波(系统频率漂移),正交性被破坏,直流和 2 次谐波就会漏进测量——这就是本工程用"软件测频 + 片内 EHRPWM 调频"严格锁定 20 点/周波的原因。
## 4. 频域视角:一个梳状带通滤波器
把整周数据窗对基波做相关,等效为滤波器,其频率响应:
$$
|H(f)| = \left|\frac{\sin\!\big(\pi (f/f_1 - 1)\big)}{N\,\sin\!\big(\pi (f/f_1 - 1)/N\big)}\right|
$$
![频率响应](https://lsky.bitnasdaq.vip/I67YT9.png)
- 中心 50Hz 通带,增益 1;
- **零点恰好落在 0Hz(直流)和 100、150、200…Hz(全部整数谐波)**;
- 窗越长(周波数越多)主瓣越窄、选择性越好,但时延越大。
"一窗 = 一个整周波"是保护领域在**速度**与**滤波**之间的经典折中,IEC 标准对保护动作时间的考核也按全周波算法进行。
## 5. 滑动窗:每 1ms 一个新有效值
数据窗定义为"以当前时刻为终止的前一周波"。每来一个新采样点(1ms),窗口滑动一格、丢弃最老点、20 点全部重算("暴力法"):
![滑动窗](https://lsky.bitnasdaq.vip/R6a1YN.png)
- **暴力法**:每点重算 20 次乘加 ×2(sin/cos),实现简单、无累积误差;
- **迭代法**(`CalIterFFTVecFull.c`,本工程未启用):增量更新
$$
S_{\text{new}} = S_{\text{old}} - x_{\text{old}}\cdot\sin\!\left(\frac{2\pi k}{N}\right) + x_{\text{new}}\cdot\sin\!\left(\frac{2\pi k}{N}\right)
$$
每次只 2 次乘加,但浮点舍入误差随时间累积,需定期用暴力法清洗。本工程 CPU 余量足够,选暴力法。
## 6. 数值算例:三种算法各测到什么
同一组 20 点采样(57.7V 基波 + 20% 五次谐波 + 1V 直流):
![数值算例](https://lsky.bitnasdaq.vip/A7dnSv.png)
| 算法 | 读数 | 说明 |
| -------------------------------- | ---------------- | ------------------------------------------------ |
| 直流平均 | 1.00 V | 只剩直流 |
| 真有效值 $\sqrt{\overline{x^2}}$ | ≈58.85 V | $\sqrt{57.7^2 + 11.5^2 + 1^2}$,谐波直流全算进去 |
| **全周傅氏** | **57.70 V ∠30°** | 精确回到基波,且给出相位 |
保护要的是"基波有效值 + 相位"(方向元件、同期、功率都要相角),且故障时短路电流含衰减直流——傅氏一个整周波积分把它抹掉,真 RMS 则会虚高导致误动。**这就是保护偏爱傅氏、计量偏爱真 RMS 的根本原因**(方法全景见主文档附录C)。
## 7. 工程实现:本工程数据流
![工程实现流程](https://lsky.bitnasdaq.vip/DFUBED.png)
核心循环只有 6 行(`GlobalUnit/CalFFTVecFull.c` L392-405):
```c
for( dwDot=0; dwDot<dwCalRate; dwDot++) {
fVal = pfCalUse[dwAdr]; // 第n个采样点(已乘通道系数)
fRe += fVal * pfFFTSin[dwFFTCnt]; // Σ x·sin·(√2/N)
fIm += fVal * pfFFTCos[dwFFTCnt]; // Σ x·cos·(√2/N)
dwAdr += dwLen; // 滑到下一个采样点
}
Fun_VectorAmp(ptVecSave); // fAmSQ = √(fRe²+fIm²) = 有效值
```
配套工程细节:
- **任意次谐波**:系数索引步进量从 1 改为 $k$ 即算 $k$ 次谐波相量 $f_{Re}(k)=\sum x(n)\sin\!\big(\tfrac{2\pi k n}{N}\big)\tfrac{\sqrt2}{N}$,同一循环复用于 2 次/5 次谐波(涌流判别、选线);遥测对 $k=1\sim11$ 全算再方和根 $U_{\text{rms}}=\sqrt{\sum_{k=1}^{11}U_k^2}$;
- **双区切换**:结果写入向量区 `tVectorRly[2][N]` 的计算区,算完原子交换"计算区/使用区"指针,保护元件读使用区,无锁并发;
- **4 个实例**(**参考项目**口径):C01 基波 I/U、C02 零序基波、C03 二次谐波、C04 五次谐波(`APP/CLS100_Dsp/InstCalCell.c`)。本项目按 V0.1 有效通道展开为 **5 个**(`C01-IA-F1`/`C02-UA-F1`/`C03-UN-F1`/`C04-IA-F2`/`C05-IA-F5`),见 `docs/算法/继电保护功能复现规划.md` §3.2。
## 8. 全周波 vs 半周波
| | 全周傅氏(本工程用) | 半周傅氏(代码有但未启用) |
| -------- | -------------------- | ---------------------------------- |
| 数据窗 | 1 个周波(20 点) | 半个周波(10 点) |
| 滤波能力 | 直流 + 全部整数谐波 | 半周相减消直流和偶次谐波,奇次保留 |
| 速度 | 1 周波 | 快一倍 |
| 精度 | 高 | 低(受奇次谐波影响) |
本工程 `CN_ANA_DIF=FALSE`,半周波/差分组件全部注释掉——DTU 场景更看重精度和抗衰减直流能力。
## 9. 常见疑问
**Q1:傅氏算的是有效值还是幅值?**
取决于系数表。标准系数 $2/N$ 得幅值 $A_1$;本工程预乘 $\sqrt2/N$ 直接得有效值 $U=A_1/\sqrt2$。看 `GLobalFunc.c` 系数表注释"折算成有效值"即可确认。
**Q2:和 FFT 什么关系?**
傅氏算法 = 只算 $k=1$(或少数几次)谱线的 DFT。FFT 是同时算全部 $N$ 根谱线的快速算法。保护只需要基波(+少数谐波),逐次 DFT 比 FFT 更省算力。
**Q3:频率偏离 50Hz 还准吗?**
本工程靠闭环调频保证窗长恒等于实际周波(20 点/周波随频率微调),所以准。固定 1000Hz 采样不调整的方案,频偏 ±2Hz 时幅值误差约 1~2% 且出现相角偏差。
**Q4:衰减直流滤不干净怎么办?**
整周波对"严格周期"信号才完全正交,衰减直流有残余。对策:加长数据窗(1.5~2 周波)、微分/余弦滤波改进傅氏、或最小二乘把 $A\mathrm{e}^{-t/\tau}$ 作为未知量一并回归。