Отсутствует точность измерения уровня библиотеки CMSIS DSP FFT

Я пробовал использовать библиотеку CMSIS DSP для реализации БПФ на STM32F407. Я основывал свой проект на Тилен Майерле библиотека. Я отбираю данные с помощью встроенного АЦП и заполняю входной буфер функцией 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 (…) и получил тот же результат.

Моя проблема - точность расчета величины. Моя задача предполагает получение точных расчетов уровня заданных гармоник. Я измеряю чистый синусоидальный сигнал переменного тока со смещением постоянного тока на входе АЦП с помощью вольтметра. Затем я измеряю частоту сигнала с помощью FFT lib и получаю ухудшение уровня сигнала с увеличением частоты. Я принимаю во внимание ограничения относительно максимальной измеряемой частоты для данной частоты дискретизации, и тот факт, что я не могу использовать более 4096 отсчетов с CMSIS DSP FFT. Мне также нужен небольшой шаг частоты, например, 1 Гц для диапазона от 100 до 1000 Гц.

На данной картинке я показываю вам результаты. Кстати, частота измеряется с некоторой погрешностью. 100 Гц определяется как 101 Гц, 800 Гц - как 808 Гц. Но меня это не сильно смущает.

Синяя линия измеряется вольтметром переменного тока. Красная линия - мои измерения с использованием библиотеки БПФ. Частота дискретизации 4096 Гц, количество отсчетов - 4096

Такая же картина наблюдается и для других частотных диапазонов и частот дискретизации.

Теперь я вижу, что единственное прямое решение - это математически привести мои результаты в соответствие с реальными измеренными значениями. Но это не изящное решение. Очень вероятно, что я пренебрегаю некоторыми важными особенностями анализа DSP FFT и не понимаю математический алгоритм. Другие реализации БПФ мне не так понятны. И действительно ли имеет смысл использовать другие библиотеки, например kissFFT и так далее? Кто имеет опыт работы с другими библиотеками и будет рад поделиться им со мной? Любой совет приветствуется.


person Atken    schedule 10.10.2019    source источник
comment
2.0*0.7071067812/(float)(FFT->FFT_Size); Здесь вы смешиваете float и double. Какова точность double в вашей системе и что происходит, когда вы усекаете его до float?   -  person Lundin    schedule 10.10.2019
comment
@Lundin, моя система - ARM Keil, и, насколько мне известно, ее основные типы соответствуют описано здесь. Кстати, я пытался скомпилировать без этой строки и использования coeff. Но результат тот же.   -  person Atken    schedule 10.10.2019
comment
Хорошо, тогда у вас есть ошибка там, и, вероятно, в других местах тоже. Замените все двойные константы, такие как 2.0, на константы с плавающей запятой 2.0f. Если вы вызываете стандартные библиотеки C, убедитесь, что вы вызываете функции с плавающей запятой, а не двойные.   -  person Lundin    schedule 10.10.2019


Ответы (1)


Большое спасибо за ваши ответы. Но, наконец, я сам боролся со своей проблемой. И около полугода я села и написала здесь про решение.

Что касается меня, то это было ошибочное представление о том, как работает БПФ. Есть особенность, заключающаяся в том, что энергия данного сигнала распределяется между заданной частотой и некоторыми близкими частотами. Таким образом, если мы возьмем величину сигнала на данной частоте из результатов расчета Фурье библиотеки DSP, то, конечно, мы получим потери сигнала, которые увеличиваются с увеличением рабочей частоты при данной частоте дискретизации. Но если мы возьмем среднеквадратичное значение величин данной частоты и некоторых близких частот, мы не получим потери сигнала.

Я изучал возможности точности DSP на практике - для разных частот дискретизации и для диапазона частот от 30 Гц до 32 кГц. Существует вычисляемая частотная дисперсия, в которой мы должны вычислять величину нашего сигнала как среднеквадратичное значение величин частот внутри дисперсии. И есть вычисляемая ошибка определения частоты. Чем выше частота дискретизации, тем дальше рассчитывается значение частоты сигнала. Под рассчитанной частотой сигнала мы понимаем частоту, для которой мы видим максимум амплитуды (при наблюдении четкого синусоидального сигнала). Но частотный сдвиг предсказуем и не создает никаких проблем. Более важным свойством является распространение сигнала. Если мы примем это во внимание и посчитаем величину сигнала более тщательно, это даст нам отличные результаты. Мои расчеты теперь точно совпадают с измерениями GVT вольтметра в дБм. Разница не более 2% в диапазоне -40… +22 дБмВт, для частот (30 Гц… 32 кГц).

Здесь представлены некоторые результаты расчета амплитуды в широком диапазоне частот с уровнем напряжения 0,2Vrms. Синяя линия измеряется вольтметром переменного тока. Красная линия - мои измерения с использованием библиотеки БПФ. Количество отсчетов - 4096, частота дискретизации различается для отдельных частотных поддиапазонов. Это 4096 Гц для F = (30… 1024) Гц, 20480 Гц для F = (1024… 4096) Гц, 40960 Гц для F = (4096… 8192) Гц и 81920 Гц для F = (8192… 32000) Гц. Как видите, результаты очень удовлетворительные.

Среднеквадратичное значение в зависимости от частоты

Я считаю, что для людей, которые в совершенстве владеют математическими основами преобразования Фурье, мой случай - довольно простая задача. Но, может быть, я не сразу понял основы и слишком много рассчитывал на вычислительные возможности библиотеки DSP, поэтому я потерял время и нервные ресурсы по описанной проблеме. Но теперь все в порядке, и я очень доволен реализацией DSP FFT.

person Atken    schedule 21.04.2020