CMSIS DSP FFT 库电平测量缺乏准确性

CMSIS DSP FFT library level measurement lacks accuracy

我尝试使用 CMSIS DSP 库在 STM32F407 上实现 FFT。我的项目基于 Tilen MaJerle library。我使用板载 ADC 对数据进行采样,并使用函数 TM_FFT_AddToBuffer(TM_FFT_F32_t* FFT, float32_t sampleValue) 填充输入缓冲区。此后我使用函数 TM_FFT_Process_F32(TM_FFT_F32_t* FFT).

处理数据
uint8_t TM_FFT_AddToBuffer(TM_FFT_F32_t* FFT, float32_t sampleValue) {
/* Check if memory available */
if (FFT->Count < FFT->FFT_Size) {
    /* Add to buffer, real part */
    FFT->Input[2 * FFT->Count] = sampleValue;
    /* Imaginary part set to 0 */
    FFT->Input[2 * FFT->Count + 1] = 0;

    /* Increase count */
    FFT->Count++;
}

/* Check if buffer full */
if (FFT->Count >= FFT->FFT_Size) {
    /* Buffer full, samples ready to be calculated */
    return 1;
}

/* Buffer not full yet */
return 0;
}

void TM_FFT_Process_F32(TM_FFT_F32_t* FFT) {
uint16_t iCntr = 0;
float coeff = 2.0*0.7071067812/(float)(FFT->FFT_Size);

/* Process FFT input data */
arm_cfft_f32(FFT->S, FFT->Input, 0, 1);

/* Process the data through the Complex Magniture Module for calculating the magnitude at each bin */
arm_cmplx_mag_f32(FFT->Input, FFT->Output, FFT->FFT_Size);  

for (iCntr = 1; iCntr < (FFT->FFT_Size); iCntr++) 
    FFT->Output[iCntr] *= coeff; //high-order harmonics values - magnitude

FFT->Output[0] /= (float)FFT->FFT_Size; //dc component value 

/* Reset count */   
FFT->Count = 0;
}

我在 TM_FFT_Process_F32(...) 函数中添加了一些简单的变换,旨在调整谐波电平。当然,当我排除它们并使用原始 Tilen 代码时,我得到了相同的结果。

如您所见,我尝试了 arm_cfft_f32(…) 和 arm_cmplx_mag_f32(…) 函数。我还尝试了 arm_rfft_fast_f32(…) 函数用于我的目的并得到了相同的结果。

我的问题是震级计算的准确性。我的任务期望获得预定谐波的准确电平计算。我用电压表在 ADC 输入上测量带有直流偏移的清晰正弦交流信号。然后我用 FFT lib 测量信号频率,并得到随着频率增加信号电平下降。我考虑了关于给定采样率的最大测量频率的限制,事实上,我不能使用超过 4096 个样本的 CMSIS DSP FFT。 我还需要较小的频率步长,例如 100 到 1000 Hz 之间的范围为 1 Hz。

在给出的图片中,我向您展示了结果。顺便说一句,频率测量有一些误差。 100 Hz 定义为 101Hz,800 Hz – 定义为 808Hz。但这并没有让我很困惑。

Blue line is measured with AC voltmeter. Red line is my measurements with FFT library. Sampling rate 4096 Hz, number of samples – 4096

其他频率范围和采样率也得到了相同的图片。

现在我看到唯一的正面决定是在数学上将我的结果调整为实际测量值。但这不是一个优雅的解决方案。我很可能忽略了 DSP FFT 分析的一些重要特性,并且缺乏对数学算法的理解。 其他 FFT 实现对我来说不是很清楚。使用其他库(例如 kissFFT 等)真的有意义吗?谁有其他库的经验并且愿意与我分享?非常感谢任何建议。

非常感谢您的回答。但最后我自己解决了我的问题。我花了大约半年时间坐下来写下解决方案。

就我自己而言,这是对 FFT 工作原理的一种粗心大意的误解。有一个特征在于给定信号的能量分布在给定频率和一些附近的频率之间。因此,如果我们从 DSP 库傅里叶​​计算的结果中获取给定频率下的信号幅度,当然,我们将得到在给定采样率下随着工作频率的增加而增加的信号损失。但是,如果我们对给定频率和一些附近频率的幅度取均方根值,我们将不会丢失信号。

我在实践中研究了 DSP 的精度能力——针对不同的采样率和 30 Hz 到 32 kHz 之间的频率范围。有一个可计算的频率色散,我们应该将信号幅度计算为色散内频率幅度的均方根值。并且存在可计算的频率定义误差。采样率越高,信号频率的计算值就越远。计算出的信号频率是指我们看到幅度最大值的频率(当观察到清晰的正弦信号时)。但是频移是可以预测的,不会造成任何问题。更重要的 属性 是信号传播。如果我们将其考虑在内并更彻底地计算信号幅度,它将为我们提供出色的结果。我的是,现在我的计算与以 dBm 为单位的电压表 GVT 测量值非常吻合。对于频率 (30Hz…32kHz),在 -40 … +22 dBm 范围内差异不超过 2%。

这里有一些幅度计算结果,通过电压水平为 0.2Vrms 的宽频率范围。蓝线是用交流电压表测量的。红线是我使用 FFT 库进行的测量。样本数量 – 4096,采样率因特殊频率子范围而异。 F=(30…1024)Hz 时为 4096 Hz,F=(1024…4096)Hz 时为 20480 Hz,F=(4096…8192)Hz 时为 40960 Hz,F=(8192…32000)Hz 时为 81920 Hz。如您所见,结果非常令人满意。

Vrms vs Frequency

我相信对于那些精通傅立叶变换数学基础的人来说,我的案例是一项非常简单的任务。但可能是我没有一下子掌握基础知识,过于看重DSP库的计算能力,所以在描述的问题上浪费了一些时间和精力。不过现在好了,对DSP的FFT实现深感满意