Перейти к содержанию
    

Помогите внести ясность в применении фильтра.

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

 

Сразу приношу извинения за нубские вопросы.

Но какую литературу я бы ни читал о ЦОС там высвечиваются только алгоритмы, методы анализа и расчета.

Меня интересуют можно сказать таки детские вопросы, и так по порядку.

 

1. Я рассчитал FIR фильтр в Matlab и получил искомые коэффициенты, фильтр устойчив, порядок фильтра оптимальный.

2. Теперь я хочу применить его для обработки сигнала полученного из АЦП микроконтроллера STM32F103 то есть от 0 до 4096.

3. Для STM32 серии CortexM3 имеется библиотека DSP которая поставляется как отдельная библиотека от ST а так же есть в составе CMSIS например можно задействовать ее в Keil. Так как F103 не содержит DSP - инструкций, как я понимаю все алгоритмы выполняются на стандартной арифметике.

4. И вот тут у меня начинаются вопросы....

5. Я хочу применить FIR фильтр из состава библиотеки. Но какой использовать? Если логически подумать, так как входные данные целочисленные то мне нужна функция arm_fir_fast_q15, но она ругается на коэффициенты. Так как они имеют вид:

-0.0085006295830239147,

-0.039315452455814658,

0.020190437531132147,

0.0076176048595180471, (взял первые парочку чтоб не копировать весь массив.)

Если применять функцию arm_fir_f32 то коэффициенты ей подходят, но ведь данные мы имеем целочисленные и выход нужен целочисленный.

6. И еще один вопрос, в примере из CMSIS FIR фильтр реализован где в функцию arm_fir_f32 передается массив выборок равный 32. Можно ли пользоваться этими фильтрами передавая на вход всего одну выборку соответственно и получая один результат за итерацию чтобы не накапливать массив для постобработки.

 

Может кто пользуется этими библиотеками, расскажите пожалуйста как правильно использовать, если не затруднит.

За ранее благодарен.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

  /**
   * @brief Processing function for the floating-point FIR filter.
   * @param[in] *S points to an instance of the floating-point FIR structure.
   * @param[in] *pSrc points to the block of input data.
   * @param[out] *pDst points to the block of output data.
   * @param[in] blockSize number of samples to process.
   * @return none.
   */
  void arm_fir_f32(
  const arm_fir_instance_f32 * S,
  float32_t * pSrc,
  float32_t * pDst,
  uint32_t blockSize);

 

f32 означает тип данных. Количество передается в blockSize. Заглячнул в код CMSIS... когда увидел цикл,

  /* Copy numTaps number of values */
  tapCnt = numTaps - 1u;

  /* Copy data */
  while(tapCnt > 0u)
  {
    *pStateCurnt++ = *pState++;

    /* Decrement the loop counter */
    tapCnt--;
  }

Смотреть расхотелось навсегда...

 

Фильтр для своей работы в любом случае требует массива значений - предшествующих текущему моменту.

 

Вот такое использую в своих проектах:

// Ограничение алгоритма генерации параметров фильтра - нечётное значение Ntap.
// Кроме того, для функций фильтрации с использованием симметрии коэффициентов, требуется кратность 2 половины Ntap

#define NtapValidate(n)    ((unsigned) (n) / 4 * 4 + 1)
#define NtapCoeffs(n)    ((unsigned) (n) / 2 + 1)

#define Ntap_rx_AUDIO    NtapValidate(241)    // single samples, floating-point implementation

static FLOAT_T FIRCoef_rx_AUDIO [NPROF] [NtapCoeffs(Ntap_rx_AUDIO)] = { { 0 }, { 0 } };
static FLOAT_T FIRScale_rx_AUDIO [NPROF] = { 1, 1 };

static FLOAT_T filter_fir_rx_AUDIO(FLOAT_T NewSample) 
{
    const FLOAT_T * const k = FIRCoef_rx_AUDIO [gwprof];
    enum { Ntap = Ntap_rx_AUDIO, NtapHalf = Ntap / 2 };
    // буфер с сохраненными значениями сэмплов
    static FLOAT_T x [Ntap * 2] = { 0, };
    static uint_fast16_t fir_head = 0;

    // shift the old samples
    fir_head = (fir_head == 0) ? (Ntap - 1) : (fir_head - 1);
    x [fir_head] = x [fir_head + Ntap] = NewSample;

    uint_fast16_t bh = fir_head + NtapHalf;            // Начало обрабатываемой части буфера
    uint_fast16_t bt = bh;    // Позиция за концом обрабатываемого буфера
    // Calculate the new output
    uint_fast16_t n = NtapHalf;
    // Выборка в середине буфера
    register FLOAT_T v = k [NtapHalf] * x [bh];             // sample at middle of buffer
    do
    {    
        {
            const FLOAT_T kv = k [-- n];
            v += kv * x [-- bh];
            v += kv * x [++ bt];
        }
        {
            const FLOAT_T kv = k [-- n];
            v += kv * x [-- bh];
            v += kv * x [++ bt];
        }
    }
    while (n != 0);
    // Обеспечиваем масштабирование к ранее расчитанному усилению фильтра (1.0)
    return v * FIRScale_rx_AUDIO [gwprof];
}

 

Перевести на целочисленный вариант легко. Придется накапливать в 64 битах (для q31), при использовании результата учесть разрядность рассчитанных коэффициентов

 

ругается на коэффициенты. Так как они имеют вид:

-0.0085006295830239147,

-0.039315452455814658,

0.020190437531132147,

0.0076176048595180471

Множите перед использованием на 32768 (в случае Q15). Результат фильтрации делите на 32768

 

Библиотечная функция arm_fir_fast_q15 использует SIMD инструкции для работы с парами 16-ти битных чисел за одну операцию, данные для фильтрации можете располагать как в моей функции (массив двойной длинны, без необходимости копирования массива данных для сдвига).

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Большое спасибо за разъяснение и за пример реализации фильтра.

 

Фильтр для своей работы в любом случае требует массива значений - предшествующих текущему моменту.

 

Да, я понимаю что для работы фильтра нужен массив предшествующих данных который равен порядку фильтра.

Меня интересовал вопрос именно в передаче нового значения в фильтр за раз в виде одной выборки а не пакетно.

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

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...