我在 LTSPICE 中的 FFT 末尾的垃圾是什么?
这个答案有几个部分。我这个答案基于 FFT 算法的特性。我不熟悉具体的 LTSpice 实现,但您报告的行为正是我所期望的。
最常见的 FFT 实现在 2 个数据点的整数幂上运行。因此,大多数实现会将您的 1,000,000 个数据点填充到 1,048,576 个数据点,然后对其执行 FFT。请注意,此长度不是正弦波的整数。
有替代的傅里叶变换方法可以以不同的方式分解数据。这些通常被称为离散傅里叶变换 (DFT) 方法,实现起来既慢又复杂得多。我几乎从未在实际应用中遇到过它们。FFT 是一种特定的 DFT 实现,它要求数据点的数量是 2 的整数幂(或者有时是 4 的整数幂)。
因此,我假设 LTSpice 将您的数据填充到 1,048,576 个数据点,最后添加的 48,576 个数据值包含一个常数。
现在您可以看到问题:您的 1,048,576 个样本的缓冲区有 1,000 个正弦波,每个 1,000 个样本,后跟 48,576 个常数值。这不能用频率为 1kHz 的正弦波的总和来表示。相反,FFT 结果显示重建信号所需的额外高频值。
要确定这是否是问题所在,请创建一个包含 1,048,576 个样本的缓冲区,其中包含一个周期为 1,024 个样本的正弦波。高频的幅度应该大大降低。
现在,关于应用窗口的效果:
FFT 算法在概念上“包装”数据,因此输入数据的最后一个点之后是输入数据的第一个点。也就是说,FFT 被计算为好像数据是无限的,循环重复,作为具有序列的向量:x[0], x[1], ..., x[1048574], x[1048575], x[ 0], x[1], ...
这种回绕会导致数据缓冲区中的最后一个点和第一个点之间的阶跃转换。此阶跃转换会生成具有来自高频的较大(杂散)贡献的 FFT 结果。窗口的目的是消除这个问题。窗口函数在两端都为零,因此在您的情况下, w[0] 和 w[999999] 都将为零。当数据乘以窗口时,值在开始和结束时都变为零,因此在回绕处没有步进过渡。
您应用的窗口函数会改变缓冲区的频率内容,您可以选择一个可以接受折衷的函数。高斯是一个很好的起点。对于无法精确控制数据频率内容的任何实际应用,您必须应用窗口函数来消除由于数据长度而隐含的阶跃转换。
遗留问题:
FFT 中还有另一个潜在的高频频谱噪声源。效果随着 FFT 长度的增加而增加,在某些情况下您可能会在 1,000,000 个数据点处看到。
FFT 算法内部循环使用复平面中围绕圆的点:e^(i*theta),其中算法以连续更精细的步长从 0 到 2*pi 迭代“theta”,直至达到复平面中的点数快速傅里叶变换。也就是说,如果您在 1,048,576 个样本上计算 FFT,则在外循环的一次迭代中,内循环将计算 e^(i*theta),其中 theta = 2*pi * n/N,其中 N 为 1,048,576 ,将 n 从 0 迭代到 1,048,575。这是通过连续乘以 e^(i*2*pi/N) 的明显方法来完成的。
可以看到问题:随着 N 变大,e^(i*2*pi/N) 变得非常接近 1,并且乘以 N 倍。使用双精度浮点,误差很小,但我认为如果仔细观察,您可以看到产生的本底噪声。对于单精度浮点,在 1,000,000 个数据点处,FFT 计算本身会产生显着的本底噪声。
有计算 e^(i*theta) 的替代技术可以消除这个问题,但实现更复杂。我只需要创建一次这样的实现。
@D.Brown 的回答已经很好了,所以我只会添加一些小东西。LTspice 的算法是自定义的,并且接受非二次幂的点数。这并不意味着分辨率不重要。尽管如此,1s 内的 1kHz 意味着整数个周期,因此不需要加窗或二项式平滑来降低噪声(FFT 窗口中的设置)。不过,@mkeith 提到的是,也就是说,默认情况下,LTspice 使用波形压缩(每个显示器 300 点,IIRC),这意味着任何其他点都会减少并且波形的分辨率会受到影响。对此的解决方案要么是更紧凑的时间步长,要么.option plotwinsize=0
是最后一个消除波形压缩的方法。以下是添加此选项但未强加时间步长时发生的情况:
这可能是你看到的,或多或少,那么有什么选择呢?您正在模拟1s时间段内的1 kHz波形。电路,如果可以这么说的话,是一个简单的源和负载,源是s谐波,对于矩阵求解器来说是一项轻而易举的任务,所以LTspice和所有的SPICE引擎一样,如果它觉得导数是平滑的,它将使其时间步长加倍以不减慢模拟速度,并将继续加倍直到达到某个内部限制,此时它将飞越模拟。结果是一个粗糙的波形,甚至不能改善太多。plotwinsize
现在需要另一种解决方法,即强制时间步长,以提高分辨率。这是 1 μs 时间步长的:
更好,但是您正在执行 100 万个点的 FFT,这可能并不奇怪,需要 100 万个时间点,因此最大时间步长应设置为 1。此外,该选项设置为大于 7 的值,根据本书,它启用双精度:numdgt
本底噪声仍然略微不稳定,但现在低于 -250dB。这接近机器精度。将时间步长设为 1/1048576 (2^-20) 并不能改善结果(您可以自己检查)。
最后,这取决于您愿意接受多少本底噪声。@Tony Stewart 的评论很有实际意义,低于 100~120dB 意味着小于 1~10 μV1V,这是一个相当大的成就。
可能的原因:-
当您在模拟器中绘制瞬态波时,它会在实际计算之间进行插值,以最大限度地减少正在完成的艰苦工作并允许更快地在屏幕上显示结果。
LTSpice 中最大时间步长的默认设置可能是 100 us,因此在这些点之间您有插值结果,即它们并不完美,并且会导致在 FFT 中被视为谐波的失真。
尝试将您的最大时间步长设置为比当前小得多,然后看看会发生什么。