Для анализа фазы FFT rFFT cFFT задействовал следующую вещь:
Ещё раз сравнил выход FFT с простой реализацией на компьютере. Судя по всему выход arm_cmplx_mag_q15 нормализуется делением на количество точек в преобразовании. В данном случае на 1024. При подаче на вход 12-битной синусоиды, на выходе наблюдаю амплитуду максимум 12 бит. Т.е то же самое, что в компьютерном варианте / 1024.
Для анализа фазы задействовал следующую вещь:
int16_t atan2_fp(int16_t y_fp, int16_t x_fp)
{
int32_t coeff_1 = 45;
int32_t coeff_1b = -56; // 56.24;
int32_t coeff_1c = 11; // 11.25
int16_t coeff_2 = 135;
int16_t angle = 0;
int32_t r;
int32_t r3;
int16_t y_abs_fp = y_fp;
if (y_abs_fp < 0)
y_abs_fp = -y_abs_fp;
if (y_fp == 0)
{
if (x_fp >= 0)
{
angle = 0;
}
else
{
angle = 180;
}
}
else if (x_fp >= 0)
{
r = (((int32_t)(x_fp - y_abs_fp)) << MULTIPLY_FP_RESOLUTION_BITS) /
((int32_t)(x_fp + y_abs_fp));
r3 = r * r;
r3 = r3 >> MULTIPLY_FP_RESOLUTION_BITS;
r3 *= r;
r3 = r3 >> MULTIPLY_FP_RESOLUTION_BITS;
r3 *= coeff_1c;
angle = (int16_t) ( coeff_1 + ((coeff_1b * r + r3) >>
MULTIPLY_FP_RESOLUTION_BITS) );
}
else
{
r = (((int32_t)(x_fp + y_abs_fp)) << MULTIPLY_FP_RESOLUTION_BITS) /
((int32_t)(y_abs_fp - x_fp));
r3 = r * r;
r3 = r3 >> MULTIPLY_FP_RESOLUTION_BITS;
r3 *= r;
r3 = r3 >> MULTIPLY_FP_RESOLUTION_BITS;
r3 *= coeff_1c;
angle = coeff_2 + ((int16_t) (((coeff_1b * r + r3) >>
MULTIPLY_FP_RESOLUTION_BITS)) );
}
if (y_fp < 0)
return (-angle); // negate if in quad III or IV
else
return (angle);
}
взял отсюда http://www.dsprelated.com/showthread/co ... 8979-1.php
работает очень быстро (stm32f103), выдаёт угол фазы в градусах с учётом квадрантов (т.е. полный диапазон, а не простой arctan 0..90deg).
Единственная медленная часть - это квадратный корень для подсчёта финальной амплитуды. Пока что не нашёл удовлетворительного по скорости решения.
Обратная связь
Интересуют вопросы реализации алгоритмов, программирования, выбора электроники и прочая информация, постараюсь осветить в отдельных статьях
пишите мне на netdm@mail.ru
Добавить комментарий