Newsgroup: it.hobby.elettronica.digitale
Titolo: Media su N valori

Ciao,
volendo calcolare la media aritmetica a finestra mobile di larghezza N 
(con N grande) che tecnica si può usare?
Non certo la definizione di media: richiederebbe troppe risorse al 
microcontrollore. Pensavo a un'integrazione, ma non è la stessa cosa.
Suggerimenti?
Grazie,
Marco / iw2nzm


Anch'io spesso ho avuto questo problema ma non ho trovato soluzione.
Se devi fare la media mobile su N campioni, c'è bisogno di un buffer di 
N campioni.
Se ti accontenti di avere la media a blocchi ogni N campioni, puoi 
semplicemente sommare e dividere una volta raggiunto N, però non è la 
stessa cosa.
Se qualcuno ha un'idea migliore aiuterebbe anche me.
ciao



 ha scritto nel messaggio
news:GnNUg.134589$zy5.1...@twister1.libero.it...

Quando dici risorse, intendi risorse di tempo/calcolo, capisco bene ? Perchè
se il problema è la memoria il discorso è diverso.
Definizine di media di N valori:
1) sommatoria da 1 a N (o da 0 a N-1),
2) divisione per N.
Genericamente parlando, avendo un insieme di N valori su cui effettuare una
elaborazione, non vedo una operazione più "leggera" della loro somma. Quindi
sulla prima parte della funzione non c'è molto da ottimizzare.
Sulla divisione, ovviamente, si può ottimizzare molto, ma con i soliti
vincoli numerici che N sia una potenza di due. Sulla base di questo, si
potrebbero fare una serie di ragionamenti tipo sottocampionamento, "fill"
del vettore con valori stimati, ecc. ecc.
Sono sicuro che c'ha già pensato qualcuno. Hai cercato su google o su
wikipedia ?
-- 
simone.bern
Mr. Heisemberg is not the only one who can affect a measurement by looking
at it (Robert A. Pease)
zsimone...@zliberoz.it
 (Rimuovere i caratteri di zorro per rispondere
via mail)

 wikipedia ?
Rispondo qui anche per Francesco e mmm.
Per risorse mi riferivo genericamente ai tempi di calcolo e 
all'occupazione di memoria. Senz'altro in caso di divisioni uso il 
solito "trucco" delle potenze di due.
Ma se avessi bisogno di mediare 1024 campioni non vorrei dover tenere un 
buffer lungo 1024 byte! anzi, il doppio visto che l'adc è a 10 bit.
Si potrebbero semplicemente sommare i campioni e dividere per 1024 ma 
così facendo posso avere una media a blocchi lunga al massimo 1024, che 
si "riazzera" alla fine del blocco.
Il segnale pare avere una media piuttosto stabile ma una grande 
varianza, perciò campioni adiacenti possono avere valori abbastanza 
differenti.
Potrebbe andarmi bene anche una media "infinita" ma non ho trovato molto 
con zio google su come calcolarla campione dopo campione.
Marco / iw2nzm

 ha scritto nel messaggio
news:ElQUg.135046$_J1.8...@twister2.libero.it...
ok, la mia risposta era imprecisa, pensavo ad una media con un numero
elevato di campioni, non ad una media mobile...
Mi viene in mente una possibile soluzione, provo a ragionarci con voi.
Supponendo di avere una memoria di 1024 campioni, dividiamo l'intervallo in
16 intervalli di 64 campioni.
|----1----|----2----|----3----| . . . .|---16---|
A parte gli intervalli estremi n. 1 e n. 16 quelli centrali non cambiano
durante le prime 64 iterazioni, quindi se immagini di fare le media
intervallo per intervallo e metterle in memoria,. hai bisogno di un vettore
di sole 64 misure. Le medie le chiamo M1, M2, ...,M16. Puoi fare
successivamente una media di queste, effettuando solo 16 somme e una
divisione per 16.
Man mano che aquisisci un nuovo campione, lo memorizzi nell'intervallo 17°.
Chiamo M17(i), la media che tu puoi calcolare sul 17° intervallo, riempito
solo di 'i' campioni, i<64. La media M1 relativa all'intervallo n.1,
campionato indietro nel tempo, perde importanza ad ogni passo, mentre
l'intervallo 17° si riempie con i nuovi campioni in arrivo.
Puoi a questo punto fare una media pesata M1_17(i) al passo "i" tra M1 e
M17(i), dovrebbe essere qualcosa tipo questa, come suggeriva mmm:
M1_17(i) = [M1 * (64-i) + M17(i) * i]/64
Le medie parziali restano comunque 16, da 2 a 15, più M1_17(i)..
Al 64° nuovo campione scorri di un posto tutte le medie, M2 va in M1, M3 va
in M2, ecc. ecc, calcoli la media finale M17 (anzi, l'hai già calcolata) e
la metti in M16. E ricominci.
Modulando il numero e l'ampiezza dei sottointervalli, probabilmente si trova
un valore ottimo.
Spero di aver reso l'idea,
saluti,
-- 
simone.bern
Mr. Heisemberg is not the only one who can affect a measurement by looking
at it (Robert A. Pease)
zsimone...@zliberoz.it
 (Rimuovere i caratteri di zorro per rispondere
via mail)


 microcontrollore. Pensavo a un'integrazione, ma non č la stessa cosa.
Se il tuo fine č quello di filtrare (solitamente la media mobile č 
utilizzata per questo scopo) allora puoi realizzare un filtro IIR con poche 
operazioni. Io ho realizzato con un 16F877 un filtro da 60Db/Dec che lavora 
ad un 1Khz senza grossi problemi, ovviamente ci sono dentro un bel po di 
trucchi...
Fammi sapere se č questo il tuo caso,
Emiliano. 

 Emiliano. 
Esattamente questo. Parlare di banda risulta meno agevole in questo 
caso. Diciamo che si tratta di (provare) a filtrare detto segnale con 
una finestra lunga un migliaio di campioni, ogni campione arriva ogni 
250 ms (nel frattempo però il micro deve gestire altre cose, quindi 
anche se sembra un'enormità non ho 250 ms di tempo per i calcoli!).
Ciao!
Marco / iw2nzm

 saluti,
Interessante anche questo approccio. Se oggi ho una mezz'oretta libera 
provo a fare qualche simulazione con un foglio di calcolo e vediamo come 
si comporta.
Grazie!
Marco / iw2nzm

 anche se sembra un'enormità non ho 250 ms di tempo per i calcoli!).
Anche se sembra una cosa enorme, fare una somma e una divisione di 1000 
valori ti prenderanno solo pochi millisecondi; il problema principale 
secondo me è la memoria, perchè 1k da dedicare solo ai campioni è 
veramente tanto.
Che CPU è? Quanta memoria hai a disposizione e quanto veloce va?
Ciao

 Diciamo che si tratta di (provare) a filtrare detto segnale con
Prova ad usare un filtro IIR Bessel di primo ordine, devi risolvere con il 
micro questo algoritmo:
Y(n) = Y(n-1) * 15/16 + X(n) /16
Che diventa :
Y(n) = Y(n-1) - Y(n-1)/16 + X(n)/16
In evidenza:
Y(n) = Y(n-1) - (Y(n-1) + X(n))/16
Come puoi vedere ti servono degli shift (divisioni) 1 sottrazione e una 
addizzione. E cosa piu importate ti basta una sola locazione di memoria per 
memorizzare il risultato precedente (Y(n-1).
Ciao Emiliano. 

 Ciao Emiliano. 
Quanto mi piacciono gli IIR :)
Ci provo subito!
Grazie della dritta!
Marco / iw2nzm

 Che CPU è? Quanta memoria hai a disposizione e quanto veloce va?
Niente di che... un banale PIC16F917 a 20 MHz (quindi 5 MHz di clock 
CPU) con 352 byte, ma più della metà sono impegnati in LUT.
Proverò a simulare il filtro proposto da Emiliano. Chissà che si riveli 
una manna :)
Marco / iw2nzm

 Y(n) = Y(n-1) - (Y(n-1) + X(n))/16
Credo che l'ultima riga debba essere:
Y(n) = Y(n-1) - (Y(n-1) - X(n))/16
Ho provato con un foglio di calcolo a generare 100 numeri "casuali" e a 
calcolare per ognuno la media aritmetica nel modo classico e con il 
filtro IIR.
Qui si può vedere l'errore percentuale commesso dal filtro rispetto alla 
media aritmetica:
http://i12.tinypic.com/44i2psk.jpg
Nota: ho inizializzato y[-1] = y[0] = x[0] per ridurre l'overshoot 
iniziale. si può fare di meglio a questo proposito?
Parlavo di "errore": non significa che sia sbagliato visto che fanno due 
cose diverse! Ora devo capire - ed eventualmente provare sulla macchina 
- se può andare bene.
Di certo è comodissimo davvero, leggero e rapido!
Marco / iw2nzm
ps. tra tutte le potenze di 2, 16 è quella che più fa avvicinare 
l'uscita del filtro alla media aritmetica... mi spieghi perché? Come hai 
fatto a stabilirlo? Scusa ma sono (ancora) ignorantissimo sui filtri 
digitali!

 digitali!
Rettifico: non è vero. Più si alza la potenza di 2 più converge al 
"valore atteso". Si vede meglio valutandolo su 1000 campioni anziché 100.
Riciao,
Marco / iw2nzm

 atteso". Si vede meglio valutandolo su 1000 campioni anziché 100.
Aumentando la pontenza di due stai semplicemente abbassando la frequenza di 
taglio, ovviamente i due filtri fanno due cose completamente diverse, le 
funzioni di trasferimento sono completamente diverse, il filtro IIR però è 
piu semplice da realizzare ed ha un risposta all'impulso infinita, si 
comporta come un RC per capirci dove la potenza di due è il tau. Prova a 
farne piu di uno in cascata, le cose migliorano ulteriormente.
Ciao Emiliano. 

> Y(n) = Y(n-1) - (Y(n-1) - X(n))/16
Si giusto, mi è sfuggito il segno, hai fatto bene a correggere.
Ciao Emiliano.

 iniziale. si può fare di meglio a questo proposito?
Non si può fare di meglio se non conoscendo l'uscita precedente, cosa 
evidentemente impossibile da fare.
Questo dei valori iniziali è un problema vecchio come il mondo, per filtri 
piu complessi puoi utilizzare alcune funzioni di matlab che ti aiutano a 
calcolare i valori iniziali.
Emiliano. 

 Ciao Emiliano. 
Si giusto, hai ragione.
Ho infatti implementato in Octave il filtro e ho giocato filtrando 
segnali casuali variando il coefficiente: veramente molto interessante!
Mi permetto di aggiungere qualche spunto di discussione, il thread è 
molto utile, almeno per il sottoscritto :)
+ In un filtro semplice come questo come si calcola quantitativamente la 
frequenza di taglio o meglio la costante di tempo? Cioè, il coefficiente 
2^n che uso nel filtro si può valutare in "costante di tempo espressa in 
numero di campioni" senza dover ricorrere alla funzione di trasferimento?
+ Mi alletta molto il software Microchip per il 
progetto/analisi/implementazione di filtri digitali:
http://tinyurl.com/nfsys
La versione Lite (che limita i FIR a 64 tap e gli IIR a 4 oltre a non 
avere il supporto per MatLab) costa poche decine di euro.
Conosci (o conoscete) altri software interessanti freeware o low cost 
analoghi?
Ciao!
Marco / iw2nzm

 Quanto mi piacciono gli IIR :)
Però il problema dei filtri IIR è che possono essere instabili se abbiamo
determinati ingressi. Se non ricordo male bisognerebbe andare a guardare i poli
della trasformata Zeta associata al filtro digitali. Il filtro è stabile se
i poli si trovano all'interno della circonferenza di raggio unitario nel
piano complesso. Diciamo che se il filtro IIR è del primo ordine non è difficile
farlo stabile... ma se aumentiamo l'ordine che succede?
Altra domanda. Normalmente nella teoria dell'elaborazione numerica dei segnali
si presuppone che il segnale venga campionato ad un frequenza nota.
Se utilizziamo l'ADC interno ad un uC, molto probabilmente non siamo capaci
a campionare ad un intervallo regolare e costante (molto dipende da quello
che deve fare il uC nel frattempo). Così avremo tanti campioni diluiti sull'asse
temporale ma non equispaziati.
In questo caso, che validità hanno i filtri FIR o IIR? Possono essere studiati
allo stesso modo? Io penso di no...

 allo stesso modo? Io penso di no...
IHMO continuano a valere le analisi se si ragiona in termini di campioni 
e non di tempo. Del resto le operazioni sono svolte all'arrivo di ogni 
campione. Se questi non sono equispaziati non si avrà una perfetta 
relazione con l'asse temporale, ma se sulle ascisse mettiamo i campioni 
allora non cambia nulla. Ovviamente dipende dalle applicazioni se è 
possibile accettare tale compromesso.
Ciao,
Marco / iw2nzm

 numero di campioni" senza dover ricorrere alla funzione di trasferimento?
uh... mi sovviene un vecchio ricordo :)
In prima approssimazione, si può stimare(*) la larghezza di banda come 
epsilon, se la posizione del polo è 1-epsilon.
Quindi nel nostro caso epsilon = 1/16 = 0.0625 e corrisponde alla banda 
passante (unilatera) espressa come frequenza normalizzata.
Es. se la frequenza di campionamento fosse fs=1 KHz avrei 
BW=epsilon*fs=62,5 Hz.
E' corretto?
Marco / iw2nzm
(*) non ricordo però in quali casi si può usare tale approssimazione: 
solo per i filtri tutti poli? (ovviamente complessi e coniugati)

 BW=epsilon*fs=62,5 Hz.
No. Non è corretto perchè la trasformazione dei coefficienti dell'equazione 
differenziale è ottenuta tramite la trasformata in Z che non è per niente 
lineare. Genericamente il filtro che ho postato è l'equazione differenziale 
nel dominio digitale di quella piu generica in S.
Tieni conto che per trasformare i coefficienti di una generica funzione di 
trasferimento del dominio di Laplace (s) devi utilizzare come minimo 
l'approssimazione di Tustin e sostituire i poli in s con i relativi poli in 
z:
z = (1 + s/2f) / (1-s/2f) che come vedi non è per nulla lineare con f. 
(controllala questa trasformazione googlando un po con "tustin" o "bilinear 
transformation")
Ciao Emiliano. 

 analoghi?
L'unica che mi viene in mente veramente completa e professionale è il 
toolbox per matlab "signal processing" e il relativo tool per lo sviluppo di 
filtri digitali. Ma è lontano dall'essere free!
Ciao Emiliano. 

 farlo stabile... ma se aumentiamo l'ordine che succede?
In questo caso specifico il filtro è stabile perchè i poli sono molto 
all'interno della circonferenza unitaria, chiaramente per frequenze molto 
basse, intendo per coefficienti 2^n molto alti, conviene utilizzare formati 
numerici a 24 o meglio 32 bit, altrimenti si rischia di perdere sensibilità 
e ti ottenere qualcosa di diverso da quello che ci si aspettava, in certi 
casi anche instabilità.
Emiliano. 

Emiliano ha scritto:

Ok, mi andrò a ripassare le trasformazioni bilineari.
Se hai voglia per favore puoi dare un'occhiata a pag. 71 (79 del file 
pdf) del libro su cui ho studiato:
http://www.elet.polimi.it/dsp/courses/fens/books/rocca-fens.pdf
(sono un paio di MB)
In alto è rappresentata l'approssimazione che ricordavo: ti dice 
qualcosa? Nel senso: è utilizzabile in casi particolari?
Grazie,
Marco / iw2nzm

 (sono un paio di MB)
Ho dato un'occhiata a questo libro, sinceramente non ho capito cosa 
rappresentino P1 e P2 se intende i poli del filtro mi sembra che non abbiano 
molto a che fare con quelli in Z.
Cmq la tecnica è molto semplice e ti garantisco che una volta studiata la 
trasformata bilineare puoi realizzare qualsiasi tipo di filtro digitale, 
credo però che pochissimi siano implementabili su un PIC.
Emiliano. 

 possibile accettare tale compromesso.
Mah, non so. Sinceramente non sono proprio convinto. Tieni presente che
tutta la teoria matematica DSP (teorema del campionamento, filtri digitali,
ecc. ecc.) parte dal presupposto che i campioni (impulsi matematici) siano
localizzati in punti equispaziati sull'asse x, ad un intervallo pari ad 1/fs
(fs=frequenza di campionamento).
Se non è più così, tutta la teoria DSP va a farsi benedire, a partire dal
teorema del campionamento.

 casi anche instabilità.
Anche qui non ti seguo molto. Che relazione c'è tra "frequenze molto basse"
e il numero n dei campioni? Puoi spiegare meglio?

 analoghi?
Questo e' un programma simile a matlab ma open source:
http://www.scilab.org
Ciao
Paolo

 e il numero n dei campioni? Puoi spiegare meglio?
Io non parlavo di numero di campioni, durante la discussione si era 
sostituito un coefficiente del filtro con un 2^n che nulla ha a che fare con 
il numero di campioni, per chiarire ho sostituito 2^n con 2^k:
Essendo il filtro del tipo: Y(n) = Y(n-1) - (Y(n-1) - X(n))/ 2^k, ovviamente 
per k molto alti la frequenza di taglio diminuisce, ma dividendo per 2^k si 
perdeno un certo numero di bit e si rischia di perdere in risoluzione, per 
questo motivo suggerivo di andarci con cautela o utilizzare formati numerici 
a 24 - 32 bit (si parla sempre di caso specifico = microcontrollori 8 bit)
Emiliano.

 
http://www.scilab.org
Si, lo conosco. Io però uso Octave (anch'esso analogo e open source). Lo 
uso per l'analisi di filtri digitali, ma cercavo qualcosa per la 
progettazione.
Ciao!
Marco / iw2nzm

 credo però che pochissimi siano implementabili su un PIC.
Su un PIC credo anch'io, la cosa ovviamente (spero) cambi con l'uso di 
un dsPIC o meglio archittetture DSP "serie"!
Ciao e grazie degli interventi
Marco /iw2nzm

 Emiliano.
Ciao!
Marco / iw2nzm

 semipiano sinistro del piano s.
Aggiungo per completezza:
"Condizione necessaria e sufficiente per la stabilità è che il modulo 
dei poli della funzione di
trasferimento sia minore di 1: i poli siano cioè interni al cerchio 
unitario.
Questa è la stabilità analitica. In pratica può accadere che un sistema 
analiticamente stabile non
lo sia nella sua implementazione su calcolatore. Ciò può accadere, per 
sistemi complessi con
poli molto vicini all'unità, a causa degli errori di arrotondamento.
Notiamo che i sistemi MA (o FIR), non avendo poli, sono intrinsecamente 
stabili."
(pag. 92 di 
http://tinyurl.com/lujk5
)
Non voglio aver ragione, ci mancherebbe! Voi avete esperienza di queste 
cose, io solo l'infarinatura dai corsi di ingnegneria, ma vorrei capire 
come stanno le cose!
Ciao!
Marco / iw2nzm