реклама на сайте
подробности

 
 
> FFT stm32f407 лишние гармоники в выходном массиве
yanvasiij
сообщение Aug 19 2015, 10:48
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



Доброго времени суток!

Процессор stm32f407, библиотека DSP от Stm32CubeMx. Делаю выборку из 1024 отсчетов встроенного АЦП (12 бит) с частотой 1024 Гц. Когда набирается 1024 отсчета отправляю данные в функции быстрого преобразования Фурье из либы DSP.

Код в более приятном виде можно посмотреть ЗДЕСЬ.

CODE
arm_cfft_radix2_instance_q15 fftInstance;
static u32 curInputCursor=0;
static u32 dataIsReady = 0; /**< Флаг для начала преобразования фурье */
static q15_t input [2048]; /**< входной массив данных */
static q15_t output [1024]; /**< выходной массив данных */

/** @brief прерывание по таймеру с частотой 1024 Гц */
extern "C" void timerInterrupt (void)
{
input[curInputCursor++]=uhADCxConvertedValue; /**< Набираю 1024 замера */
if (curInputCursor>=1024)
{
curInputCursor = 0;
dataIsReady = 1; /**< Флаг, сигнализирующий, что выборка готова */
HAL_TIM_Base_DeInit(&htim1); /**< Как только набралось отключаю таймер, чтобы остановить забор замеров */
}
invertLed(); /**< Инвертирую ногу, чтобы на осциллографе проверить действительно ли частота дискретизации 1024 Гц (да, именно так) */
}

/** @brief задача, которая занимается преобразованием фурье */
static void fftTask (void *p)
{
q15_t maxValue; /* Max FFT value is stored here */
uint32_t maxIndex; /* Index in Output array where max value is */

while(1)
{
if (dataIsReady)
{
dataIsReady = 0;

arm_cfft_radix2_init_q15 (&fftInstance, 1024, 0, 1);
arm_cfft_radix2_q15(&fftInstance, input);
arm_cmplx_mag_q15 (input, output, 1024);
u32 index;
saveFft();
timInit(); /**< Снова запускаю таймер для подготовки следующих 1024 замеров */
}
vTaskDelay(5000);
}
}


Если я все правильно понимаю то в массиве output[] должна получиться частотная характеристика с шагом 1 Гц. При этом output[0] - это постоянная составляющая, все остальное гармоники.
Подаю синусоидальный сигнал 50 Гц с амплитудой 1 вольт, смещенный на 1 вольт. Ожидаю, что в output[0] будет значение постоянной составляющей, а в output[50] амплитуда 50-ой гармоники.
Однако в результате output[0] всегда равен нулю, в output[1] некоторое значение очень похожее на постоянную составлющую, в output[3] тоже непонятно какое значение (181), а в output[50] как и ожидалось значение гармоники (оно смещается если изменить частоту синусоидального сигнала). Вдобавок нет нет да и появятся непонятные значения в разных гармониках (то output[200], то output[511] и т.п. совершенно случайным образом). Добавил RC-цепочку на вход - не помогло.

Буду очень признателен, если кто растолкует, что я делаю неправильно.

Вот здесь картинка с характеристикой (строю на графике массив output[])

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
prig
сообщение Aug 27 2015, 10:59
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 869
Регистрация: 30-01-08
Из: СПб
Пользователь №: 34 595



Цитата(Krys @ Aug 25 2015, 07:52) *
...
Ну я Вам про форматы пытался выше объяснить. Если что - спрашивайте конкретные вопросы, поясню более детально.
В рамках конкретной функции такие форматы можно объяснить: если каждую квадратуру выхода БПФ считать пронормированным к 1, то амплитуда в корень из 2 будет больше 1, поэтому при сохранении входного формата возникнет переполнение, следовательно положение точки нужно сдвинуть.
Но на самом деле этого не требуется конкретно для БПФ, т.к. заранее известно, что комплексные числа - это вращающиеся вектора, которые не могут выходить за единичную окружность, тогда и модуль не может превышать 1.
...


- Подчёркнутое утверждение неверно. Вращающиеся вектора - неправильное объяснение. Правильный вариант:
На самом деле, для конкретной реализации БПФ этого может не потребоваться.
В зависимости от используемых целочисленных операций, сдвиг (нормализация) может осуществляться в процессе вычисления "бабочки" БПФ.

Вероятно, Вы пыталисьсь обобщить частный случай реализации целочисленного БПФ и сделали ошибку.


Цитата(Krys @ Aug 26 2015, 06:50) *
...
Тут теперь уже Ваши объяснения очень тяжело понять, так что даже дискутировать не могу. Единственно результат сдвигать надо вправо в последнем предложении, а округлить надо до сдвига.
К стати: вопрос на засыпку для разминки мозгов: почему при умножении двух 16-разрядных знаковых чисел в допкоде результат получается 32-разрядным, когда по казалось бы очевидной логике должен быть 31 разряд? )))
...


- Речь была о реализации функции умножения 1.15*1.15 -> 1.15 с помощью целочисленного умножения со знаком (ADI ещё используют описание типа 16.0*16.0 -> 32.0):

"Результат операции целочисленного умножения со знаком аргументов в формате 1.15 имеет тот же порядок диапазона - 2^31. Диапазон значений результата укладывается в -1...1.
Формат результата - 2.30. Порядок диапазона формата 2.30 - 2^32. Диапазон значений формата 2.30 укладывается в -2...2.
Т.е., два старших бита результата умножения 1.15*1.15 в формате 2.30 будут всегда знаковыми. Т.о., для получения операции 1.15*1.15 -> 1.15 можно арифметически сдвинуть влево результат 2.30 и потом округлить."

А вот как говорят в ADI о реализации этой функции для одной из инструкций Блэкфина:
Signed fraction. Multiply 1.15 * 1.15 to produce 1.31 results after left-shift correction.
Round 1.31 format value at bit 16. (RND_MOD bit in the ASTAT register controls the rounding.)
Saturate the result to 1.15 precision in destination register half.
Result is between minimum -1 and maximum 1-2-15 (or, expressed in hex, between minimum 0x8000 and maximum 0x7FFF).

Нетрудно заметить что Ваше утверждение о сдвиге вправо и последующем округлении совершенно неверно по отношению к контексту.
Так что да. Скорее всего, Вы просто не поняли о чём вообще речь.

Возможно, Вы пытались поведать о чём-то другом, подразумевая ваше понимание какого-то частного случая.
Аналогично, заданный Вами вопрос о разрядности тоже оказался не слишком корректен.
Для такой детерминированной функции, как целочисленное умножение со знаком (16.0*16.0 -> 32.0), можно говорить о диапазоне значений результата или его порядке, а также о формате результата и диапазоне значений этого формата. И в этой части всё очевидно.


Цитата(Krys @ Aug 26 2015, 06:50) *
...
На приведённом рисунке (моделировал когда-то для своей задачи) сиреневым (power) показана степень того самого масштабирующего коэффициента, про который Вы говорили, в зависимости от стадии обработки. Для блочной плавающей точки. Видно, что, начиная с некоторой стадии, степень возрастает на каждой стадии. А "задержка" начала возрастания степени объясняется тем, что входной сигнал был не на полную шкалу. Если бы на входе была проделана нормализация, то ступеньки бы пошли сразу. Таким образом, из рисунка видно, что блочная плавающая точка не даёт никакого выигрыша для БПФ по сравнению с фиксированной, безусловно устанавливаемой для каждой стадии, т.к. всё равно ступеньки идут на каждой стадии.


- Вероятно, Вы моделировали с табличным синусом или чем-то простеньким. Попробуйте на реальном сигнале типа OFDM. Фиксированная постадийная нормализация (может осуществляется в процессе вычисления бабочки) приведёт к потере гейна и, соответственно, к увеличению шума самого преобразования. И в отдельных случаях потери будут чувствительные (например, для 16-бит 8К БПФ на сигнале DVB-T это уже хорошо заметно, проверялось на реальном же железе, а о 16-ти битах для 32К DVB-T2 даже говорить нечего).

Так что, ваше обобщение касается только частных случаев. В общем случае оно неверно.



П.С. Судя по всему, Вы всё время пытаетесь интерпретировать единственный частный случай реализации целочисленного БПФ.
Это не есть правильно. Таки, лучше подучить матчасть для общего случая.
Go to the top of the page
 
+Quote Post
Krys
сообщение Aug 28 2015, 03:59
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 002
Регистрация: 17-01-06
Из: Томск, Россия
Пользователь №: 13 271



Цитата(prig @ Aug 27 2015, 17:59) *
Цитата(Krys @ Aug 25 2015, 11:52) *

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

- Подчёркнутое утверждение неверно. Вращающиеся вектора - неправильное объяснение.
И что же неправильно во вращающихся векторах?


Цитата(prig @ Aug 27 2015, 17:59) *
В зависимости от используемых целочисленных операций, сдвиг (нормализация) может осуществляться в процессе вычисления "бабочки" БПФ.
Приведите пожалуйста пример, где модуль выхода БПФ больше максимально возможного размаха его квадратур. Для векторов, вращающихся вокруг единичной окружности это невозможно.


Цитата(prig @ Aug 27 2015, 17:59) *
Вероятно, Вы пыталисьсь обобщить частный случай реализации целочисленного БПФ и сделали ошибку.
Я привёл условия типа "если каждую квадратуру выхода БПФ считать пронормированным к 1". Я согласен, что это для частного случая. Но для него я не сделал ошибку.


Цитата(prig @ Aug 27 2015, 17:59) *
Т.е., два старших бита результата умножения 1.15*1.15 в формате 2.30 будут всегда знаковыми. Т.о., для получения операции 1.15*1.15 -> 1.15 можно арифметически сдвинуть влево результат 2.30 и потом округлить."
А вот как говорят в ADI о реализации этой функции для одной из инструкций Блэкфина:
Signed fraction. Multiply 1.15 * 1.15 to produce 1.31 results after left-shift correction.
Round 1.31 format value at bit 16. (RND_MOD bit in the ASTAT register controls the rounding.)
Saturate the result to 1.15 precision in destination register half.
Result is between minimum -1 and maximum 1-2-15 (or, expressed in hex, between minimum 0x8000 and maximum 0x7FFF).

Нетрудно заметить что Ваше утверждение о сдвиге вправо и последующем округлении совершенно неверно по отношению к контексту.
Согласен, если рассматривать иностранную цитату непогрешимой, то моё утверждение неверно. Но если считать, что цитата не является неоспоримой аксиомой, то ошибся не я, а цитата и Вы вместе с ней. Жирным с подчёркиванием я выделил места под вопросом.

"Всегда" - ошибка. Именно про это был мой "вопрос на засыпку", и засыпка произошла.

"Saturate the result to 1.15" - в рамках предыдущего "всегда" сатурация не требуется, там просто нечего сатурировать.

"after left-shift correction" - мне непонятно, почему влево. Вот пример:
Есть переменная 8 битов с форматом 4.4, её нужно вместить с потерей дробной части в 4-битную переменную 4.0. Что мы делаем:
Код
исходная переменная, физическая разрядность (не так, которую мы
подразумеваем форматом 4.4):
                            7 6 5 4 3 2 1 0

Надо вместить в переменную:         3 2 1 0

Если просто скопировать биты 3..0 в биты 3..0 - сохранится младшая часть

Тогда исходную переменную надо сдвинуть вправо:

                            0 0 0 0 7 6 5 4
                            
А затем просто скопировать биты 3..0 в биты 3..0:
                            
Исходная переменная:        0 0 0 0 7 6 5 4
Копируем:                           | | | |
Конечная переменная:                7 6 5 4


Сдвиг-то вправо.

Цитата(prig @ Aug 27 2015, 17:59) *
Аналогично, заданный Вами вопрос о разрядности тоже оказался не слишком корректен.
Ещё как корректен, просто это нужно прощупать "на своей шкуре".

Цитата(prig @ Aug 27 2015, 17:59) *
Для такой детерминированной функции, как целочисленное умножение со знаком (16.0*16.0 -> 32.0), можно говорить о диапазоне значений результата или его порядке, а также о формате результата и диапазоне значений этого формата. И в этой части всё очевидно.
Очевидно, но первое, что очевидно, оказывается неверным. Вопрос на засыпку был "почему при умножении двух 16-разрядных знаковых чисел в допкоде результат получается 32-разрядным, когда по казалось бы очевидной логике должен быть 31 разряд"? Очевидно это 31 разряд, а не 32. Потому что при умножении полезные данные сосредоточены в младших 15 битах операндов, следовательно 15 * 15 получаем 30 и 1 бит знака. 31 разряд в результате. Откуда 32?


Цитата(prig @ Aug 27 2015, 17:59) *
- Вероятно, Вы моделировали с табличным синусом или чем-то простеньким.
Согласен, тут я сделал свой вывод только для своего сигнала. Он был реальный, но с сильным преобладанием несущей, на фоне которой нужно было обнаружить отражения с допплером.


Цитата(prig @ Aug 27 2015, 17:59) *
П.С. Судя по всему, Вы всё время пытаетесь интерпретировать единственный частный случай реализации целочисленного БПФ.
Это не есть правильно. Таки, лучше подучить матчасть для общего случая.
А Вы уверены, что смогли охватить этот самый общий случай? Он бесконечен. Все случаи учесть невозможно. Так-то хорошо все утверждения парировать, что это не годится, в общем случае работать не обязано. Универсальный козырь.


--------------------
Зная себе цену, нужно ещё и пользоваться спросом...
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- yanvasiij   FFT stm32f407 лишние гармоники в выходном массиве   Aug 19 2015, 10:48
- - Krys   Одной из причин может быть то, что подаваемая част...   Aug 21 2015, 06:23
- - prig   Цитата(yanvasiij @ Aug 19 2015, 13:48) .....   Aug 21 2015, 07:26
- - Krys   Не умничайте )) Напишите, что конкретно   Aug 21 2015, 09:53
- - Alex11   Конкретно - если не наложить окно на измеренный си...   Aug 21 2015, 10:01
|- - Lmx2315   Цитата(Alex11 @ Aug 21 2015, 14:01) Конкр...   Aug 21 2015, 10:54
|- - prig   Цитата(Lmx2315 @ Aug 21 2015, 13:54) ..по...   Aug 21 2015, 12:23
- - Krys   Ну я что и предлагал - тесты на заранее подготовле...   Aug 21 2015, 11:06
- - yanvasiij   Цитата(Krys @ Aug 21 2015, 11:23) Одной и...   Aug 21 2015, 11:43
|- - Lmx2315   Цитата(yanvasiij @ Aug 21 2015, 15:43) Мн...   Aug 21 2015, 11:57
|- - Krys   Цитата(yanvasiij @ Aug 21 2015, 18:43) Во...   Aug 24 2015, 04:00
- - Alex11   Может быть мне следовало изъясняться тщательнЕе. Е...   Aug 21 2015, 11:44
- - yanvasiij   Цитата(Alex11 @ Aug 21 2015, 16:44) Может...   Aug 21 2015, 11:52
- - yanvasiij   Цитата(Lmx2315 @ Aug 21 2015, 16:57) ..10...   Aug 21 2015, 12:04
|- - Lmx2315   Цитата(yanvasiij @ Aug 21 2015, 16:04) Да...   Aug 21 2015, 12:49
|- - Krys   Цитата(Lmx2315 @ Aug 21 2015, 19:49) Если...   Aug 24 2015, 02:15
- - Alex11   Кроме всего изложенного выше, в спектре для опреде...   Aug 21 2015, 16:03
- - yanvasiij   Цитата(Lmx2315 @ Aug 21 2015, 17:49) ..ну...   Aug 24 2015, 03:39
|- - Krys   Цитата(yanvasiij @ Aug 24 2015, 10:39) Пр...   Aug 24 2015, 06:35
- - yanvasiij   Цитата(Krys @ Aug 24 2015, 09:00) А какую...   Aug 24 2015, 04:56
|- - Krys   Цитата(yanvasiij @ Aug 24 2015, 11:56) А ...   Aug 24 2015, 07:41
- - yanvasiij   Цитата(Krys @ Aug 24 2015, 11:35) Я уже с...   Aug 24 2015, 07:17
- - yanvasiij   Цитата(Krys @ Aug 24 2015, 12:41) Я не пр...   Aug 24 2015, 08:36
- - Krys   Спасибо, теперь всё гораздо понятнее. А входной си...   Aug 24 2015, 09:34
- - yanvasiij   Цитата(Krys @ Aug 24 2015, 14:34) Спасибо...   Aug 24 2015, 12:06
|- - Krys   Цитата(yanvasiij @ Aug 24 2015, 19:06) Фу...   Aug 25 2015, 04:52
|- - Krys   Цитата(Krys @ Aug 25 2015, 11:52) А надо-...   Aug 28 2015, 06:07
|- - prig   Цитата(Krys @ Aug 28 2015, 09:07) Я извин...   Aug 28 2015, 09:10
- - yanvasiij   Цитата(Krys @ Aug 25 2015, 09:52) Мы гово...   Aug 25 2015, 06:42
|- - Krys   Цитата(yanvasiij @ Aug 25 2015, 13:42) По...   Aug 25 2015, 07:28
|- - prig   Цитата(Krys @ Aug 25 2015, 10:28) ... Теп...   Aug 25 2015, 09:00
|- - Krys   Цитата(prig @ Aug 25 2015, 16:00) Звиздец...   Aug 25 2015, 09:47
|- - prig   Цитата(Krys @ Aug 25 2015, 12:47) Осторож...   Aug 25 2015, 11:22
|- - Krys   Цитата(prig @ Aug 25 2015, 18:22) Осторож...   Aug 26 2015, 03:50
- - yanvasiij   Цитата(Krys @ Aug 25 2015, 12:28) ... По...   Aug 25 2015, 08:25
- - Krys   Пожалуйста! А во входном массиве (т.е. на вых...   Aug 25 2015, 08:49
- - Krys   что-то ТС пропал... у Вас всё заработало?   Aug 27 2015, 07:55
- - Krys   куда делся ТС? Мы уже тут со скуки похоливарить ус...   Aug 31 2015, 08:21
- - yanvasiij   Цитата(Krys @ Aug 31 2015, 13:21) куда де...   Sep 1 2015, 08:44
|- - alex2103   Цитата(yanvasiij @ Sep 1 2015, 11:44) Я с...   Feb 9 2016, 12:35
- - yanvasiij   Цитата(alex2103 @ Feb 9 2016, 17:35) Расс...   Feb 15 2016, 04:22
|- - Apparatchik   Цитата(yanvasiij @ Feb 15 2016, 06:22) Ес...   Apr 21 2017, 06:39
- - yanvasiij   Выложу в понедельник - пример у меня на работе   Apr 23 2017, 06:34
- - Apparatchik   Буду ждать   Apr 23 2017, 15:19
- - yanvasiij   Приношу извинения за задержку, не было времени нор...   Apr 27 2017, 07:25


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st August 2025 - 18:26
Рейтинг@Mail.ru


Страница сгенерированна за 0.01456 секунд с 7
ELECTRONIX ©2004-2016