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

 
 
 
Reply to this topicStart new topic
> Реализация БИХ фильтра, что делать с С-Header из MATLAB ?
sysel
сообщение Apr 26 2010, 08:49
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 3-07-07
Пользователь №: 28 852



Здравсвуйте!
Столкнулся со следующей проблемой:
Разрабатываю IIR (БИХ) фильтр в MATLAB (fdatool), получаю коэффиециенты фильтра (Direct-Form II, Second-Order Sections), (Order = 6, Sections = 3).
Делаю С-header с этими самыми коэффиециентами (Targets -> Generate C header).
Получаю некие массивы.

Как мне теперь реализовать этот фильтр на языке C ?

Следую принципу каскадной реализации и реализации Direct Form II - но фигня какая-то выходит.

Поделитесь, пожалуйста, рабочим кодом.
Go to the top of the page
 
+Quote Post
bahurin
сообщение Apr 26 2010, 10:05
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347



Цитата(sysel @ Apr 26 2010, 11:49) *
Поделитесь, пожалуйста, рабочим кодом.


Код
typedef struct structIIR{    
    double*    b;
    int        lb;
    double* a;
    int        la;
}IIR, *PIIR;


int conv(double *a, int la, double *b, int lb, double *c){
    if((!a)||(!b)||(!c)||(!la)||(!lb))
        return 0;
    memset(c, 0, (la+lb-1)*sizeof(double));
    for(int i = 0; i < la; i++){
        for(int j = 0; j < lb; j++)
            c[i+j] += a[i]*b[j];
    }
    return 1;
}

int iir_filter(PIIR piir, double *s, int n){
    double* c = (double*)malloc(piir->la*sizeof(double));
    double* d = (double*)malloc(piir->lb*sizeof(double));
    double* v = (double*)malloc((piir->lb+n-1)*sizeof(double));

    for(int i =0; i<piir->la; i++)
        c[i] = piir->a[i]/piir->a[0];
    for(int i =0; i<piir->lb; i++)
        d[i] = piir->b[i]/piir->a[0];
    conv(d,piir->lb,s,n,v);
    s[0] = v[0];
    
    for(int i = 1; i<n; i++){
        int k = 1;
        s[i] = v[i];
        while(((i-k)>=0)&&(k<piir->la)){
            s[i]-=c[k]*s[i-k];
            k++;
        }
    }
    free(c);
    free(d);
    free(v);
    return 1;
}


Коэффициенты пишем в структуру IIR и указатель на нее в функцию фильтрации. А вообще вот dll весит 20 кБ умеет считать фильтры аналогично матлабу. Есть документация с примерами.

Сообщение отредактировал bahurin - Apr 26 2010, 10:07
Go to the top of the page
 
+Quote Post
sysel
сообщение Apr 26 2010, 12:46
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 3-07-07
Пользователь №: 28 852



Разобрался сам.
Добавлю свои результаты в фонд будущих поколений:

Пусть нам FDATOOL выдала следующий C-header:
Код
/*
* Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool
*
* Generated by MATLAB(R) 7.8 and the Signal Processing Toolbox 6.11.
*
* Generated on: 26-Apr-2010 15:26:51
*
*/

/*
* Discrete-Time IIR Filter (real)
* -------------------------------
* Filter Structure    : Direct-Form II, Second-Order Sections
* Number of Sections  : 3
* Stable              : Yes
* Linear Phase        : No
*/

/* General type conversion for MATLAB generated C-code  */
#include "tmwtypes.h"
/*
* Expected path to tmwtypes.h
* C:\Program Files\MATLAB\R2009a\extern\include\tmwtypes.h
*/
#define MWSPT_NSEC 7
const int NL[MWSPT_NSEC] = { 1,3,1,3,1,2,1 };
const real64_T NUM[MWSPT_NSEC][3] = {
  {
   0.001582012905215,                 0,                 0
  },
  {
                   1,   -1.997425031815,                 1
  },
  {
    0.06078064837324,                 0,                 0
  },
  {
                   1,   -1.998996713475,                 1
  },
  {
   0.007688806860118,                 0,                 0
  },
  {
                   1,                 1,                 0
  },
  {
                   1,                 0,                 0
  }
};
const int DL[MWSPT_NSEC] = { 1,3,1,3,1,2,1 };
const real64_T DEN[MWSPT_NSEC][3] = {
  {
                   1,                 0,                 0
  },
  {
                   1,   -1.996305874613,   0.9963329403565
  },
  {
                   1,                 0,                 0
  },
  {
                   1,   -1.998581806418,   0.9986427868237
  },
  {
                   1,                 0,                 0
  },
  {
                   1,  -0.9976855336623,                 0
  },
  {
                   1,                 0,                 0
  }
};


Прячем #include "tmwtypes.h" :
// #include "tmwtypes.h"
И заменяем "real64_T" на "double".

Для получения одного отфильтрованного отсчета сигнала надо вызвать функцию IIR_filt (X), где X - входной отсчет.
Функция возвращает отсчет отфильтрованного сигнала.
Предварительно надо задать начальные значения для массива "ячеек памяти" WHistory. Ну или просто обнулить их.

Код
#include "fdacoefs.h"

double WHistory[MWSPT_NSEC][2];

double IIR_filt (double X){
    for (int i=0; i<MWSPT_NSEC; i++){
        double W;
        W = X;
        for (int j=1; j<DL[i]; j++){
            W-= DEN[i][j]*WHistory[i][j-1];
        };
        W*=1/DEN[i][0];

        X = W * NUM[i][0];
        for (int j=1; j<NL[i]; j++){
            X+=NUM[i][j]*WHistory[i][j-1];
        };
        WHistory[i][1] = WHistory[i][0];
        WHistory[i][0] = W;
    };
    return X;
};


Код не оптимизирован, зато даёт хорошее представление о том, чиго надо делать с хедером из FDATOOL.

Вот схематичное описание того, что далает этот код:
http://ftp.math.hkbu.edu.hk/help/toolbox/s...ilt.df2sos.html
Go to the top of the page
 
+Quote Post
sysel
сообщение Apr 27 2010, 09:21
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 3-07-07
Пользователь №: 28 852



Приведу оптимизированную версию кода, которая "хавает" как floating-point, так и fixed-point IIR из С-Header-ов, сгенерированных FDATOOL из MATLABa

Код
#include "fdacoefs.h"

typedef double    real;

#define Fs        3600    // Частота сэмплирования

#define IIR_hist_size        5    // Кол-во ячеек памяти в реализации фильтра

real History[IIR_hist_size];

real IIR_filter (real X, real* Hist){
    for (int i=0; i<MWSPT_NSEC; i++){
        int jmax = ((NL[i]>DL[i])?(NL[i]):(DL[i]))-1;
        if (jmax>0){
            // Блок фильтра из каскада
            real W = 0;
            for (int j=0; j<jmax; j++){
                W += DEN[i][j+1] * Hist[j];
            };
            W = X - W;
            W *= (1/DEN[i][0]);
    
            X = W * NUM[i][0];
            for (int j=0; j<jmax; j++){
                X += NUM[i][j+1] * Hist[j];
            };
            
            for (int j=1; j<jmax; j++){
                Hist[j] = Hist[j-1];
            };
            Hist[0] = W;
            Hist += jmax;
        } else if (jmax==0){
            // Блок "Gain" между каскадами фильтра
            X *= NUM[i][0] * (1/DEN[i][0]);
        };
    };
    return X;
};

int main(){
    // Обнуляем ячейки памяти
    for (int i=0; i<IIR_hist_size; i++){
        History[i]=0;
    };
    
    real X,Y,F;

    F = 10.0; // 10 Гц

    F=2*CONST_PI*F/(real)Fs;

    for (int i=0; i<1000000; i++){
        X=cos(F*(real)i);
        Y=IIR_filter (X,History);
    };

    return 0;
}
Go to the top of the page
 
+Quote Post
baralgin
сообщение Apr 27 2010, 17:35
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680



Цитата(sysel @ Apr 27 2010, 12:21) *
Код
// Блок "Gain" между каскадами фильтра
X *= NUM[i][0] * (1/DEN[i][0]);

Этот участок кода вызывает подозрение. На fixed-point'е веротно не будет работать(как надо). Наверное лучше разделить: сначала умножение, потом деление.
Да и в целом код не выглядит ни оптимальным ни красивым. Сам начал разбираться этим вопросом в последнии дни. Ваши приведённые примеры значительно помогли(мне smile.gif ). Странно, но в дебрях матлабовского хэлпа ничего не находится по алгоритму вычисления. А в широком поле интернета только стандартная формула (типа y = w-1*y-1+w-2*y-2, wi = ... ), в которой коэффициентов много меньше чем в сабжевом хидере.
Go to the top of the page
 
+Quote Post
sysel
сообщение Apr 28 2010, 06:21
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 3-07-07
Пользователь №: 28 852



Цитата(baralgin @ Apr 27 2010, 21:35) *
Этот участок кода вызывает подозрение. На fixed-point'е веротно не будет работать(как надо). Наверное лучше разделить: сначала умножение, потом деление.

Да, флагом махать я начал раньше времени насчет "fixed-point". В общем, приведённый выше фрагмент кода работает с fixed-point коеффицентами, если в объявлении матриц коэффиециентов изменить тип на "double".
С fixed-point всё не так просто, как мне казалось. FDATOOL выкидывает форматы представления с фиксированной запятой в комментарии, так что породить код, который бы с ходу хавал бы хедер не выйдет.
Цитата(baralgin @ Apr 27 2010, 21:35) *
Да и в целом код не выглядит ни оптимальным ни красивым.

Согласен. Но, думаю, более оптимальный и красивый код можно породить только если вычленить коэффиециенты из матриц NUM и DEN в какие-то другие структуры. И что самое главное, разделить на этапе написания кода блоки "gain" и фильтров.
Цитата(baralgin @ Apr 27 2010, 21:35) *
Сам начал разбираться этим вопросом в последнии дни. Ваши приведённые примеры значительно помогли(мне smile.gif ). Странно, но в дебрях матлабовского хэлпа ничего не находится по алгоритму вычисления. А в широком поле интернета только стандартная формула (типа y = w-1*y-1+w-2*y-2, wi = ... ), в которой коэффициентов много меньше чем в сабжевом хидере.

Была та же проблема. Формул куча, кода шиш. Породил какой-никакой код и выложил тут.
У приведённого выше кода есть большой плюс: он опирается на порождённый fdatool хедером с минимальными изменениями в нём.
Go to the top of the page
 
+Quote Post
bahurin
сообщение Apr 28 2010, 09:57
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347



Цитата(sysel @ Apr 28 2010, 09:21) *
Была та же проблема. Формул куча, кода шиш. Породил какой-никакой код и выложил тут.
У приведённого выше кода есть большой плюс: он опирается на порождённый fdatool хедером с минимальными изменениями в нём.


вот есть такая pdf-ка еще как фильтры считать и куча матлабовского кода к ней. Кому инетересно можете поглядеть. Я по этой доке писал фильтры разные
Прикрепленный файл  ellip.zip ( 831.45 килобайт ) Кол-во скачиваний: 514
Go to the top of the page
 
+Quote Post
avmsystem
сообщение Oct 20 2011, 12:52
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 3-02-05
Пользователь №: 2 399



Цитата(sysel @ Apr 26 2010, 16:46) *
Разобрался сам.
Добавлю свои результаты в фонд будущих поколений:

Пусть нам FDATOOL выдала следующий C-header:
[code]/*


Борюсь с той же проблемой.
Если с хидером для FIR еще как-то разобрался, то для IIR самому разобраться не получается.
Приведенный пример кода тупо вставленный в программу работает не правильно.
Видимо где-то ошибка, где не пойму.

Подскажите плиз где глянуть наглядный алгоритм использования коэф-тов из fdatool.


Go to the top of the page
 
+Quote Post
Vl4ever
сообщение Jan 13 2012, 17:15
Сообщение #9





Группа: Новичок
Сообщений: 2
Регистрация: 13-01-12
Пользователь №: 69 365



столкнулся с похожей проблемой.Нужно реализовать филтер чебишева с данными параметрами на процессоре stm32f101 ( arm cortex m3) .Имеются библиотеки расчёта IIR (ili FIR) филтеров от производителей ARMa (CMSIS - DSP http://www.onarm.com/cmsis/download/).Если кому-то удалось реализовать филтер,используя Матлаб fdatool и исползуя эти библиотеки,поделитесь пожалуста опытом.Спасибо sm.gif
Go to the top of the page
 
+Quote Post
skyv
сообщение Feb 14 2012, 11:17
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 181
Регистрация: 26-07-10
Пользователь №: 58 606



Цитата(Vl4ever @ Jan 13 2012, 21:15) *
столкнулся с похожей проблемой.Нужно реализовать филтер чебишева с данными параметрами на процессоре stm32f101 ( arm cortex m3) .Имеются библиотеки расчёта IIR (ili FIR) филтеров от производителей ARMa (CMSIS - DSP http://www.onarm.com/cmsis/download/).Если кому-то удалось реализовать филтер,используя Матлаб fdatool и исползуя эти библиотеки,поделитесь пожалуста опытом.Спасибо sm.gif


Посмотрите документ "The Scientist and Engineer's Guide to Digital Signal Processing".
Там есть алгоритм расчета коэффициентов фильтра.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 15:30
Рейтинг@Mail.ru


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