Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Filtro passa basso in C

682 views
Skip to first unread message

Giuseppe³

unread,
Apr 10, 2010, 8:21:55 AM4/10/10
to
Salve,
Sto modificando un programma e devo filtrare un valore utilizzando
questa funzione gia' scritta da chi ha fatto il programma:

/*******************************************************************************
*
* Funzione: Filter1
*
* Descrizione: Filtro Passa-basso con costante KF
*
*
* Parametri: unsigned int input: dato in ingresso
* puntatore S_Fil1 *
*
* Return Value:
*
*********************************************************************************/
inline void Filter1 (register unsigned int input, register S_Fil1 *pFil)
{
register int errore;
register int errore2;

errore = (unsigned int)(input) - (unsigned int)(pFil->OutL>>16);
errore2 = errore + pFil->ErrP;
pFil->ErrP = errore;
pFil->OutH = ((long)(errore2)*pFil->KF) << 4;
pFil->OutL += pFil->OutH;
return;
}

In pratica dovrebbe essere un filtro passa basso al quale viene passato
il valore "input" e il puntatore alla struttura pFil la quale contiene i
parametri di lavoro del filtro.

Io ho dichiarato e inizializzato una mia struttura di tipo S_Fill e
passo il valore letto come input e il puntatore alla struttura.
Il risultato dovrebbe essere in OutH moltiplicato per 65536, ma non
riesco ad ottenere valori sensati.

Ho provato a passare un valore costante (diciamo 400) come input e il
risultato e' sempre a 0.
In OutL invece mi ritrovo un valore che diviso per 65536 mi da circa 400.

KF e' il guadagno del filtro ed e' impostato in un'altra parte del
programma a 256.

Non riesco proprio a capire come funziona questa funzione.
C'e' qualcuno che riesce a spiegarmela?

Grazie
Ciao
Giuseppe

FtM

unread,
Apr 10, 2010, 9:24:26 AM4/10/10
to
"var>>16" significherebbe "var/65535"
"var<<4" significherebbe "var*16"
sempre se var è di tipo unsigned, ovviamente ;-)

quindi:


> inline void Filter1 (register unsigned int input, register S_Fil1 *pFil)
> {
> register int errore;
> register int errore2;
>
>     errore      = (unsigned int)(input) - (unsigned int)(pFil->OutL>>16);

sei sicuro che (pFil->OutL>>16) abbia valori sensati? potrebbe essere
sempre 0, a seconda dell'architettura.

>     errore2     = errore + pFil->ErrP;
>     pFil->ErrP  = errore;
>     pFil->OutH  = ((long)(errore2)*pFil->KF) << 4;

di che tipo è pFil->OutH? ha senso fare l'operazione su signed long?
Uno shift su un numero con segno è veramente quello che vuoi?

>     pFil->OutL += pFil->OutH;
>     return;

non c'è bisogno di scrivere "return"

>
> }
>

Senza contare i soliti possibili overflow, etc.etc. (che non scrivo
perché già sono stato accusato di troppa pignoleria, ma visto che
trattiamo di errori numerici controllerei passo passo ogni variabile
per vedere quali valori assume!)

Ciao!

Archaeopteryx

unread,
Apr 10, 2010, 9:33:55 AM4/10/10
to
Il 10/04/2010 15.24, FtM ha scritto:
> Senza contare i soliti possibili overflow,
> etc.etc. (che non scrivo perché già sono stato
> accusato di troppa pignoleria, ma visto che
> trattiamo di errori numerici controllerei passo
> passo ogni variabile per vedere quali valori
> assume!)

Mh come minimo è una funzione un po' mal scritta...
almeno un commento su che tipo di filtro
implementasse... Ma riscriverla da capo non sarebbe
meglio? Se il filtro è nel dominio del tempo si fa
in poco sforzo.

--
http://www.youtube.com/watch?v=N2ENwokc6bs&feature=related
http://www.youtube.com/watch?v=H7GBSeBffnM

Giuseppe³

unread,
Apr 10, 2010, 4:18:33 PM4/10/10
to
Il 10/04/10 15:24, FtM ha scritto:

> "var>>16" significherebbe "var/65535"
> "var<<4" significherebbe "var*16"
> sempre se var è di tipo unsigned, ovviamente ;-)
>
> quindi:
>> inline void Filter1 (register unsigned int input, register S_Fil1 *pFil)
>> {
>> register int errore;
>> register int errore2;
>>
>> errore = (unsigned int)(input) - (unsigned int)(pFil->OutL>>16);
>
> sei sicuro che (pFil->OutL>>16) abbia valori sensati? potrebbe essere
> sempre 0, a seconda dell'architettura.

Ho sperimentato che passando come input 400 fisso e facendo girare il
programma, OutL assume un valore che diviso per 65536 da circa 400.

>
>> errore2 = errore + pFil->ErrP;
>> pFil->ErrP = errore;
>> pFil->OutH = ((long)(errore2)*pFil->KF)<< 4;
>
> di che tipo è pFil->OutH? ha senso fare l'operazione su signed long?
> Uno shift su un numero con segno è veramente quello che vuoi?
>

OutH e' di tipo long (32 bit segnati).
Presumo (ma non sono sicuro) che sia stato preso per assunto che il
valore di ingresso sia sempre positivo.

>> pFil->OutL += pFil->OutH;
>> return;
>
> non c'è bisogno di scrivere "return"
>

Vero.

>>
>> }
>>
>
> Senza contare i soliti possibili overflow, etc.etc. (che non scrivo
> perché già sono stato accusato di troppa pignoleria, ma visto che
> trattiamo di errori numerici controllerei passo passo ogni variabile
> per vedere quali valori assume!)

Si, ho provato, ma seguire una funzione che viene richiamata
continuamente e' un po' estenuante da seguire se non si capisce la
logica che c'e' a monte.
Volevo capire cosa il programmatore ha fatto scrivendo queste 6 righe di
codice e la logica che ha seguito per ottenere il risultato di filtrare
il valore.
Forse (o anche senza forse) mi manca la conoscenza del modello
matematico per cui mi trovo impantanato ad interpretare la funzione nel
suo complesso :)

Ciao e grazie
Giuseppe


Giuseppe³

unread,
Apr 10, 2010, 4:22:29 PM4/10/10
to
Il 10/04/10 15:33, Archaeopteryx ha scritto:

> Il 10/04/2010 15.24, FtM ha scritto:
>> Senza contare i soliti possibili overflow,
>> etc.etc. (che non scrivo perché già sono stato
>> accusato di troppa pignoleria, ma visto che
>> trattiamo di errori numerici controllerei passo
>> passo ogni variabile per vedere quali valori
>> assume!)
>
> Mh come minimo è una funzione un po' mal scritta...
> almeno un commento su che tipo di filtro
> implementasse...

Dovrebbe essere un filtro passa basso IIR.

Ma riscriverla da capo non sarebbe
> meglio? Se il filtro è nel dominio del tempo si fa
> in poco sforzo.

Ci ho pensato, ma visto che c'era gia' questa funzione bella e pronta
volevo sfruttarla tanto per far restare "coerente" il programma.

Alla fine, se non riesco a scardinarla, mi adattero' a scriverne
un'altra da zero.

Ciao
Giuseppe


Pleg

unread,
Apr 11, 2010, 7:04:35 AM4/11/10
to
Non ci ho capito molto di quel codice... ok usare un feedback coll'errore
del ciclo precedente per evitare che si accumuli e faccia divergere
l'uscita, ma non ho capito cosa sta facendo.
Se ho interpretato giusto il codice, lo si puo' scrivere cosi' (in equazioni
a tempo discreto):

e[n] = x[n] - 2^-16 * ol[n-1]
e2[n] = e[n] + errp[n-1]
errp[n] = e[n]
oh[n] = 16*KF * e2[n]
ol[n] = ol[n - 1] + oh[n]

(dove ho chiamato x l'ingresso, e gli altri sono semplicemente abbreviati).

Da cui, in trasformata zeta:

OL = z^-1 * OL + 16*KF * (1 + z^-1) * E
E = X - z^-1 * 2^-16 * OL

e quindi:

OL = X * ( 16*KF * (1 + z^-1) ) / ( 1 - z^-1 + 16*KF*2^-16 * z^-1 +
16*KF*2^-16 * z^-2 )

... che non e' un granche' di filtro passabasso :)

> Ho sperimentato che passando come input 400 fisso e facendo girare il
> programma, OutL assume un valore che diviso per 65536 da circa 400.

Gia': il guadagno statico di quella schifezza e':

OL = X * (2*16*KF) / (2*16*KF*2^-16) = 2^16*X = 65536*X

Ovvero l'uscita e' uguale all'ingresso moltiplicato per 65536, COSTANTE!
(con buona pace di KF, che non fa una pippa).
Il filtro ha anche un paio di poli (e non voglio sapere dove sono... ma a
naso dovrebbero essere vicino a z = 1) e uno zero in z = -1.


Pleg


Giuseppe³

unread,
Apr 11, 2010, 7:18:24 AM4/11/10
to
Il 11/04/10 13:04, Pleg ha scritto:
<cut>

>
> Ovvero l'uscita e' uguale all'ingresso moltiplicato per 65536, COSTANTE!
> (con buona pace di KF, che non fa una pippa).
> Il filtro ha anche un paio di poli (e non voglio sapere dove sono... ma a
> naso dovrebbero essere vicino a z = 1) e uno zero in z = -1.

Ciao e grazie per la risposta.
Ho deciso di abbandonare l'idea di riutilizzare la funzione in oggetto.
Ne scrivo un'altra da zero, forse faccio prima.

Ciao
Giuseppe

Archaeopteryx

unread,
Apr 11, 2010, 11:46:16 AM4/11/10
to
Il 11/04/2010 13.18, Giuseppe³ ha scritto:
> Ciao e grazie per la risposta. Ho deciso di
> abbandonare l'idea di riutilizzare la funzione in
> oggetto. Ne scrivo un'altra da zero, forse faccio
> prima.

Una bella implementazione del filtro di Savitzky
Golay e passa la paura :D

Pleg

unread,
Apr 11, 2010, 12:27:32 PM4/11/10
to
> Una bella implementazione del filtro di Savitzky
> Golay e passa la paura :D

E un "permutohedral lattice" ?
http://graphics.stanford.edu/papers/permutohedral/

:DD


Pleg

Archaeopteryx

unread,
Apr 11, 2010, 1:51:27 PM4/11/10
to
Il 11/04/2010 18.27, Pleg ha scritto:
> E un "permutohedral lattice" ?
> http://graphics.stanford.edu/papers/permutohedral/

My God, quel PDF è mostruoso; è una delle volte che
non capisco nemmeno di che si sta parlando :D

0 new messages