Я пытаюсь реализовать быстрое преобразование Фурье со связанной функцией комплексной величины на плате разработчика STM32F411RE Nucleo. Моя цель - разделить объединенный сигнал с несколькими синусоидальными элементами на отдельные частотные компоненты с правильной амплитудой.
Моя проблема в том, что я не могу правильно выровнять результаты частотных подборок из функции комплексной величины с частотами. Я также начинаю сомневаться в обоснованности этих результатов как таковых.
Я пытался использовать несколько различных реализаций, опубликованных людьми для алгоритма FFT с фиксированной величиной, в частности, примеры, перечисленные в StackoverFlow от SleuthEye и Блог от LB9MG .
AFAIK У меня похожий подход, но как-то их подходы дают желаемые результаты, а мой - нет. Ниже приведен мой код, который я изменил для работы с помощью реализации, созданной 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[]
.
![results](https://i.imgur.com/g9Y4wH5.png)
Кто-нибудь имеет представление о том, почему это происходит? Как и многие из моих ошибок, это, вероятно, действительно тривиальная и глупая вещь, но я не могу понять для себя, почему это происходит.
РЕДАКТИРОВАТЬ: благодаря помощи SleuthEye поиск частот теперь возможен, поскольку первоначальный подход к генерации сигнала sin () был выполнен неправильно.
Появились некоторые новые проблемы, поскольку БПФ, по-видимому, дает только правильные частоты для 32 выборок, несмотря на соответствующее масштабирование размера ячейки для приспособления к скорректированному размеру выборки.
Я также не могу реализовать алгоритм фиксации амплитуды: согласно Ссылка SleuthEye с примером кода 2*(1/N)*abs(X(k))^2
Я сделал собственную реализацию 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);
}
}