/*******************************************************************************
*
* 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
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!
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
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
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
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
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
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
My God, quel PDF è mostruoso; è una delle volte che
non capisco nemmeno di che si sta parlando :D