我试图将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。但这并没有使我感到困惑。
对于其他频率范围和采样率,可获得相同的图像。
现在,我看到唯一的正面决定是将数学结果调整为实际测量值。但这不是一个很好的解决方案。我很可能忽略了DSP FFT分析的一些重要功能,并且对数学算法缺乏了解。 其他FFT实现对我来说还不太清楚。使用其他库(例如kissFFT等)真的有意义吗?谁在其他库中拥有丰富的经验,可以与我分享?任何建议都将受到高度赞赏。
答案 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。如您所见,结果非常令人满意。
我相信,对于那些对傅立叶变换的数学基础最精通的人来说,我的案例是一件很简单的任务。但是,也许我没有立即了解这些基础知识,而对DSP库的计算功能却视而不见,因此我在描述的问题上浪费了一些时间和精力。但是现在还可以,我对DSP FFT实现深感满意