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

时间:2019-10-10 06:09:16

标签: c signal-processing fft stm32f4 cmsis

我试图将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输入上测量具有DC偏移的清晰正弦交流信号。然后,我使用FFT lib测量信号频率,并得到随频率增加而降低的信号电平。考虑到给定采样率下最大测量频率的限制,事实是,CMSIS DSP FFT不能使用超过4096个采样。 我还需要较小的频率步进,例如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等)真的有意义吗?谁在其他库中拥有丰富的经验,可以与我分享?任何建议都将受到高度赞赏。

1 个答案:

答案 0 :(得分:2)

非常感谢您的回答。但是最后我自己在问题上挣扎。大约半年的时间,我才坐下来在这里写下解决方案。

就我个人而言,这是对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实现深感满意