Newsgroup: it.hobby.elettronica.digitale
Titolo: FIR e IIR

Ciao!
Prima di reinventare l'acqua calda, sono disponibili dei sorgenti in C 
che implementano un generico filtro FIR e IIR (possibilmente nella II 
forma) ?
Premetto che non utilizzerï¿œ filtri lunghi (a occhio direi che un quarto 
ordine ï¿œ giï¿œ un lusso) ma in giro ho trovato quasi sempre codici 
ottimizzati per una data architettura o per un dato tipo di filtro.
A me invece serve una cosa generica visto anche che le frequenze di 
campionamento su cui devo lavorare sono molto basse (dell'ordine delle 
decine di Hz).
Io ho provato a buttare giï¿œ qualche riga di codice ma non sono riuscito 
a fare qualcosa di generico. Per generico intendo che a seconda 
dell'applicazione definisco l'ordine del filtro, passo la matrice dei 
coefficienti et voilï¿œ :)
Dimenticavo: deve funzionare il real-time, quindi i calcoli devono 
essere effettuati su un campione alla volta.
Marco

 forma) ?
Ciao, tempo fa ho cercato qualcosa del genere e sono riuscito a trovare 
solo questi:
http://www-users.cs.york.ac.uk/~fisher/mkfilter/
http://www.dsptutor.freeuk.com/remez/RemezFIRFilterDesign.html
ma non ho mai provato ad usarli e neanche ad approfondire piï¿œ di tanto. 
Diciamo che sono il risultato di una botta di google, messi da parte per 
riguardarli un giorno con piï¿œ calma. Quel giorno non ï¿œ ancora arrivato :-)
Se scopri che sono utili e interessanti puoi scrivere qui le tue 
impressioni.
-- 
bikerfab
Viaggi in bicicletta, report foto e informazioni
Travelling by bicycle, report, pics and information
http://bikerfab.altervista.org/

 
http://www.dsptutor.freeuk.com/remez/RemezFIRFilterDesign.html
Ciao!
O non mi sono spiegato io oppure non ho guardato bene i tuoi link :)
Non cerco software per progettare i filtri (trovo molto buona la 
versione Lite della Microchip) ma per implementarli nei microcontroller!
Cioï¿œ, dati i coefficienti della H(z), il segnale di ingresso e gli 
accumulatori mi restituisca il campione filtrato.
Io ho scritto questa funzione (non ancora testata) che perï¿œ funziona 
solo per un biquadratico del secondo ordine (*):
float	iir_update(IIR_biquad *iir, float input) {
    float output;
    float w;
    iir->delay[0] = input - iir->den[1] * iir->delay[1] - iir->den[2] * 
iir->delay[2];
    output = iir->num[0] * iir->delay[0] + iir->num[1] * iir->delay[1] + 
iir->num[2] * iir->delay[2];
    iir->delay[2] = iir->delay[1];
    iir->delay[1] = iir->delay[0];
	return output;
}
Ma vorrei qualcosa di piï¿œ generico e non "hard-coded".
Marco
(*) questa volta posso permettermi i float :)

 Ma vorrei qualcosa di piï¿œ generico e non "hard-coded".
scavando nelle profonditï¿œ dei miei ricordi mi sovviene che per la tesi 
di laurea devo aver fatto qualcosa del genere. Se la ritrovo ti faccio 
sapere, ma non garantisco niente :-)



Premetto che di analisi numerica so proprio poco.
Il problema in questo caso ï¿œ solo definire in modo generico un filtro 
IIR. Il design che hai giï¿œ buttato giï¿œ ï¿œ quello ottimale (struttura 
che mantiene lo stato e poi passi per puntatore alla funzione di 
aggiornamento).
Se non ricordo male, per definire un filtro di n-esimo grado nella 
seconda forma hai bisogno di:
- ingresso corrente
- n accumulatori precedenti
- coefficienti per gli ingressi
- coefficienti per le uscite
e con questi calcoli l'uscita attuale.
Tradotto in una struttura C:
struct IIRFilter
{
	float w[IIR_ORDER]; ///< accumulatori
	float a[IIR_ORDER]; ///< coefficienti ingressi
	float b[IIR_ORDER]; ///< coefficienti uscite
}
La funzione di calcolo potrebbe essere un qualcosa tipo:
float iir_update(IIRFilter *iir, float input)
{
   /* Shifta accumulatori */
   for (int i = IIR_FILTER - 1; i > 0; i--)
     iir->w[i] = iir->w[i - 1];
   /* Metti nuovo accumulatore e nuova uscita a 0 */
   iir->w[0] = input;
   float y = 0;
   /* Calcola il nuovo valore dell'accumulatore e dell'uscita*/
   for (int i = IIR_FILTER - 1; i > 0; i--)
   {
     iir->w[0] += iir->w[i] * -iir->a[i];
     y += iir->w[i] * iir->b[i];
   }
   return y + iir->b[0] * iir->w[0];
}
Occhio che non l'ho provata, l'ho scritta di getto in 2 minuti e non 
sono nemmeno sicuro di aver capito quello che chiedi :-P
-- 
  _|/ Francesco Sacchi - Develer S.r.l., R&D dept.
   |\ 
http://www.develer.com/
 - 
http://www.bertos.org

 sono nemmeno sicuro di aver capito quello che chiedi :-P
In effetti guardandola meglio potresti ottimizzarla in:
float iir_update(IIRFilter *iir, float input)
{
   /* Metti nuovo accumulatore e nuova uscita a 0 */
   iir->w[0] = input;
   float y = 0;
   /* Calcola il nuovo valore dell'accumulatore e dell'uscita*/
   for (int i = IIR_ORDER - 1; i > 0; i--)
   {
     iir->w[i] = iir->w[i - 1];
     iir->w[0] += iir->w[i] * -iir->a[i];
     y += iir->w[i] * iir->b[i];
   }
   return y + iir->b[0] * iir->w[0];
}


 }
Ecco, io non sono mai stato capace di fare bene gli algoritmi :)
La procedura mi sembra ottima, la proverï¿œ!
Io sbagliavo approccio perchï¿œ volevo partire "dall'alto" e mi perdevo via...
Marco

 La procedura mi sembra ottima, la proverï¿œ!
Riguardandola a mente fredda mi accorgo che ï¿œ sbagliata, riscrive w[0] 
prima di shiftarlo!
Un implementazione corretta dovrebbe essere:
float iir_update(IIRFilter *iir, float input)
{
   /* Metti nuovo accumulatore e nuova uscita a 0 */
   float w = input;
   float y = 0;
   /* Calcola il nuovo valore dell'accumulatore e dell'uscita */
   for (int i = IIR_ORDER - 1; i > 0; i--)
   {
     iir->w[i] = iir->w[i - 1];
     w += iir->w[i] * -iir->a[i];
     y += iir->w[i] * iir->b[i];
   }
   iir->w[0] = w;
   return y + iir->b[0] * iir->w[0];
}
