我正尝试在STM32F411RE Nucleo开发板上实现一个具有相关复数幅度函数的快速傅立叶变换。我的目标是将具有多个正弦元素的组合信号分离为具有正确幅度的独立频率分量。
我的问题是,我不能正确地将复数量级函数的频率桶结果与频率对齐。我也开始质疑这些结果的有效性。
我尝试使用人们发布的一些不同的实现来修复幅度,最著名的例子是StackoverFlow by SleuthEye和Blog by LB9MG上列出的例子。
AFAIK I有一个类似的方法,但不知何故,他们的方法产生了预期的结果,而我的方法没有。下面是我的代码,我已经通过SleuthEye创建的实现进行了修改。
int main(void)
{
fftLen = 32; // can be 32, 64, 128, 256, 512, 1024, 2048, 4096
half_fftLen = fftLen/2;
volatile float32_t sampleFreq = 50 * fftLen; // Fs = binsize * fft length, desired binsize = 50 hz
arm_rfft_fast_instance_f32 inst;
arm_status status;
status = arm_rfft_fast_init_f32(&inst, fftLen);
float32_t signalCombined[fftLen] = {0};
float32_t fftCombined[fftLen] = {0};
float32_t fftMagnitude[fftLen] = {0};
volatile float32_t fftFreq[fftLen] = {0};
float32_t maxAmp;
uint32_t maxAmpInd;
while (1)
{
for (int i = 0; i< fftLen; i++)
{
signalCombined[i] = 40 * arm_sin_f32(450 * i); // 450 frequency at 40 amplitude
}
arm_rfft_fast_f32(&inst, signalCombined, fftCombined, 0); // perhaps switch to complex transform to allow for negative frequencies?
arm_cmplx_mag_f32(fftCombined, fftMagnitude, half_fftLen);
fftMagnitude[0] = fftCombined[0];
fftMagnitude[half_fftLen] = fftCombined[1];
arm_max_f32(fftMagnitude, half_fftLen, &maxAmp, &maxAmpInd); // We need the 3 max values
for (int k = 0; k < fftLen ; k++)
{
fftFreq[k] = ((k*sampleFreq)/fftLen);
}
}
下面是我从上面列出的代码中得到的结果:虽然我确实从算法中获得了一个幅值(在正确的索引12处),但它并不对应于输入阵列signalCombined[]
的频率或振幅。
有谁知道为什么会发生这种情况吗?就像我的许多错误一样,这可能是一件非常琐碎和愚蠢的事情,但我无论如何也弄不明白为什么会发生这种事情。
编辑:多亏了SleuthEye的帮助,现在可以找到频率了,因为最初生成sin()信号的方法是错误的。
出现了一些新问题,因为FFT似乎只为32个样本产生了正确的频率,尽管为了适应调整后的样本大小而相应地调整了bin大小。
我也无法实现振幅固定算法:根据示例代码2*(1/N)*abs(X(k))^2
的SleuthEye's Link,我已经创建了自己的实现2 * powf(fabs(fftMagnitude[j]), 2) / fftLen
,如以下代码所示,但这并不能产生甚至接近正确的结果。
while (1)
{
for (int i = 0; i < fftLen; i++)
{
signalCombined[i] = 400 * arm_sin_f32(2 * PI * 450 * i / sampleFreq); // Sin Alpha, 400 amp at 10 kHz
// 700 * arm_sin_f32(2 * PI * 33000 * i / sampleFreq) + // Sin Bravo, 700 amp at 33 kHz
// 300 * arm_sin_f32(2 * PI * 50000 * i / sampleFreq); // Sin Charlie, 300 amp at 50 kHz
}
arm_rfft_fast_f32(&inst, signalCombined, fftCombined, 0); // calculate the fourier transform of the time domain signal
arm_cmplx_mag_f32(fftCombined, fftMagnitude, half_fftLen); // calculate the magnitude of the fourier transform
fftMagnitude[0] = fftCombined[0];
fftMagnitude[half_fftLen] = fftCombined[1];
for (int j = 0; j < sizeof(fftMagnitude); j++)
{
fftMagnitude[j] = 2 * powf(fabs(fftMagnitude[j]), 2) / fftLen; // Algorithm to fix the amplitude of each unique frequency
}
arm_max_f32(fftMagnitude, half_fftLen, &maxAmp, &maxAmpInd); // We need the 3 max values
for (int k = 0; k < fftLen ; k++)
{
fftFreq[k] = ((k*sampleFreq)/fftLen);
}
}
https://stackoverflow.com/questions/56362696
复制相似问题