Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Ridurre instabilità ADC

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

4
voti

[21] Re: Ridurre instabilità ADC

Messaggioda Foto UtenteDirtyDeeds » 17 lug 2012, 21:14

dimaios ha scritto:Preferisco sempre realizzare il filtro digitale impostando un notch sulla frequenza di rete e poi un IIR passa basso per ridurre i tempi di calcolo mantenendo una buona selettività della banda.
Se non ci sono particolari richieste concordo sulla tecnica di filtrare con una media mobile su 20 ms o un suo multiplo.


Fermo restando che mi sembra che i problemi dell'op non abbiano molto a che fare con il 50 Hz di rete, vorrei espandere un po' sulla discussione del filtraggio che mi sembra interessasse anche Foto UtenteTardoFreak:

1) Quanti campioni per periodo della frequenza di rete? In [2] Foto UtenteTardoFreak suggeriva di campionare ogni 20 ms per eliminare i disturbi a 50 Hz. In ogni sistema campionato, però, bisogna ricordarsi dell'aliasing: campionando a 50 Hz, la frequenza di Nyquist è di 25 Hz e un disturbo a 50 Hz viene mappato in 0 Hz, cioè in una componente continua che va ad aggiungersi al segnale misurando generando un errore sistematico. Quindi, se voglio rimuovere un disturbo a 50 Hz, devo campionare ad almeno 100 Hz. Se poi voglio anche limitare l'effetto delle armoniche di ordine m, dovrò campionare ad almeno 100m\,\text{Hz}.

2) Il notch suggerito da Foto Utentedimaios potrebbe anche andare bene, ma bisogna anche ricordarsi delle armoniche del 50 Hz: tipicamente i disturbi maggiori si incontrano a 50 Hz, 100 Hz (il ripple degli alimentatori e, per i sistemi ottici, lo sfarfallio delle lampade ad incandescenza), 150 Hz e 200 Hz. Quindi bisogna fare un notch su più frequenze.

Tanto per giocare un po' con l'analisi dei segnali, immaginiamo di avere un segnale Y_t a tempo discreto t = 0,\pm 1,\pm 2,\ldots e di farne la media mobile su N campioni,

\bar{Y}_t = \frac{1}{N}\sum_{u=0}^{N-1}Y_{t-u}

La media mobile è equivalente a un filtro con risposta all'impulso

h_u = 
\begin{cases}
1/N & \text{per}\ 0\le u < N \\
0 &\text{altrimenti}
\end{cases}

Il quadrato della funzione di trasferimento vale quindi (con |f|\le 1/2)

\begin{align}
\mathcal{H}(f) &= |H(f)|^2 \\
&= \left|\sum_{u=-\infty}^{\infty} h_u\text{e}^{-\text{j} 2\pi f u} \right|^2 \\
&= \frac{1}{N^2}\left|\sum_{u=0}^{N-1} \text{e}^{-\text{j} 2\pi f u} \right|^2 \\
&= \frac{1}{N^2}\left|\frac{1-\text{e}^{-\text{j} 2\pi f N}}{1-\text{e}^{-\text{j} 2\pi f}} \right|^2 \\
&= \frac{1}{N^2}\left|\frac{\text{e}^{\text{j}\pi f N}-\text{e}^{-\text{j}\pi f N}}{\text{e}^{\text{j}\pi f}-\text{e}^{-\text{j} \pi f}} \right|^2 \\
&= \frac{1}{N^2}\frac{\sin^2(\pi f N)}{\sin^2(\pi f)}
\end{align}

La funzione \mathcal{H}(f) si annulla per \pi f N = m\pi con m = 1,2,\ldots,N/2 (per f=0, \mathcal{H}(0) = 1 -meno male!), cioè per

f = \frac{m}{N}

Qui f non rappresenta la frequenza reale, ma il rapporto tra la frequenza reale e la frequenza di campionamento f_\text{s}. Tornando alle frequenze reali si vede che la media mobile rigetta le frequenze

f_m = \frac{m}{N}f_\text{s}
It's a sin to write sin instead of \sin (Anonimo).
...'cos you know that cos ain't \cos, right?
You won't get a sexy tan if you write tan in lieu of \tan.
Take a log for a fireplace, but don't take log for \logarithm.
Avatar utente
Foto UtenteDirtyDeeds
55,9k 7 11 13
G.Master EY
G.Master EY
 
Messaggi: 7012
Iscritto il: 13 apr 2010, 16:13
Località: Somewhere in nowhere

0
voti

[22] Re: Ridurre instabilità ADC

Messaggioda Foto Utentedany192 » 17 lug 2012, 22:03

DirtyDeeds ha scritto:Perché? Il PIC 18F4550 ha un ADC a 10 bit, quindi i valori dovrebbero andare da 0 a 1023. Credo che tu abbia copiato il dato a 10 bit su un registro a 16 bit dal lato "alto" invece che da quello "basso", ovvero il bit 0 del registro a 10 bit è finito nel bit 6 del registro a 16. Il risultato è che una variazione dell'ingresso dell'ADC di 1 LSB ti fa variare il valore letto di 64 (2^6). I bit da 0 a 5 del registro a 16 bit, poi, sembrerebbero messi a 1, così che hai un offset di 63. Insomma, mi sembra che l'acquisizione dei valori necessiti di un'aggiustatina ;-)


Dunque, la vera lettura viene eseguita su un range che va da 0 a 1023. Le directx che si occupano di "interpretrare" i dati raw, lavorano su un range che va da 0 a 65535...in questo post viene descritto l'intero processo un po' meglio di come ho fatto io.
L'acquisizione dei dati avviene quindi in maniera corretta. Ti porto l'esempio di un joystick con adc a 8 bit con questo screenshot: i dati raw sono quelli che realmente il micro "sputa fuori" sul buffer USB, i dati sotto il campo value sono quelli interpretati ;-)
In sostanza, come puoi vedere dai file delle misure, l'intervallo tra un campione e l'altro è di +/- 64 ovvero di +/-1 in dato raw.

DirtyDeeds ha scritto:sulla base del programma che hai fatto, ogni quanto viene chiamata adc_read?


Nella versione del firmware con la media, l'adc_read la chiamo in questo modo all'interno di un ciclo for:

Codice: Seleziona tutto
while(1){
for(count=0;count<=255;count++){
                   ch1 += Adc_Read(4);
                   ch2 += Adc_Read(0);
                   ch3 += Adc_Read(1);
                   ch4 += Adc_Read(2);
                   ch5 += Adc_Read(3);
       }
       ch1 /= count;
       ch2 /= count;
       ch3 /= count;
       ch4 /= count;
       ch5 /= count;
....
....
}


Ma ad ogni modo, lo stesso problema del +/-1 ce l'ho sia nella versione con la media che in quella senza: l'unica cosa che cambia è che nella versione con la media le variazioni dovute a questo fantomatico rumore sono meno frequenti.

Adesso con calma mi leggo l'ultimo tuo post, che la mia pancia piena e le formule non vanno molto d'accordo :mrgreen:
Avatar utente
Foto Utentedany192
20 6
Frequentatore
Frequentatore
 
Messaggi: 123
Iscritto il: 1 ago 2011, 13:32
Località: everywhere

1
voti

[23] Re: Ridurre instabilità ADC

Messaggioda Foto UtenteDirtyDeeds » 17 lug 2012, 22:26

dany192 ha scritto:Nella versione del firmware con la media, l'adc_read la chiamo in questo modo all'interno di un ciclo for:


1) Fai il conto di quanto tempo intercorre tra un'acquisizione e l'altra. Ti conviene far riferimento all'assembly generato dal compilatore e al data sheet per ottenere i tempi delle singole istruzioni. Altrimenti, prendi un oscilloscopio e misuralo ;-) (Anche se continuo a dire che l'acquisizione sarebbe meglio agganciarla ad un interrupt).

2) Ma le variabili ch1, ch2 ecc. a quanti bit sono? Tu hai una serie di numeri a 10 bit (immagazzinato "fintamente" a 16 bit), anche immaginando che ci sia sufficiente rumore per avere dithering, se poi fai una divisione a 10 bit, l'operazione di media non serve a nulla :!:
It's a sin to write sin instead of \sin (Anonimo).
...'cos you know that cos ain't \cos, right?
You won't get a sexy tan if you write tan in lieu of \tan.
Take a log for a fireplace, but don't take log for \logarithm.
Avatar utente
Foto UtenteDirtyDeeds
55,9k 7 11 13
G.Master EY
G.Master EY
 
Messaggi: 7012
Iscritto il: 13 apr 2010, 16:13
Località: Somewhere in nowhere

0
voti

[24] Re: Ridurre instabilità ADC

Messaggioda Foto UtenteCandy » 17 lug 2012, 23:30

Una domanda: hai anche tenuto conto del fatto che quando commuti il multipledxer del convertitore ADC, c'è una capacità all'interno del micor che si deve stabilizzare? Ovvero, dopo ogni commutazione è bene attendere un adeguato tempo, (calcolabile), per essere certi che il riferimento analogico sia corretto.
Anzi, due domande: hai tenuto conto delle regolazioni sulla velocità di conversione? Se troppo elevata ed il quarzo "basso", il convertitore butta i dadi...
Avatar utente
Foto UtenteCandy
32,5k 7 10 13
CRU - Account cancellato su Richiesta utente
 
Messaggi: 10123
Iscritto il: 14 giu 2010, 22:54

0
voti

[25] Re: Ridurre instabilità ADC

Messaggioda Foto UtenteCandy » 17 lug 2012, 23:32

Ancora una cosa: in ogni caso, +/- 1 digit su qualunque valore, è nulla!
Avatar utente
Foto UtenteCandy
32,5k 7 10 13
CRU - Account cancellato su Richiesta utente
 
Messaggi: 10123
Iscritto il: 14 giu 2010, 22:54

0
voti

[26] Re: Ridurre instabilità ADC

Messaggioda Foto UtenteCandy » 17 lug 2012, 23:35

La media, in questo caso, non serve a nulla.
Io faccio cose più semplici:
1) media di pochi valori e fisso un riferimento.
2) successivamente se il valore mediato oscilla di poco, non correggo nulla, ossia considero il precedente ancora valido.
3) se la variazione è invece molta, allora il nuovo valore, dopo le medie del caso, è vero...

Non so come si chiami tutto questo, e che equazione lo rappresenti, ma è molto efficacie.
Avatar utente
Foto UtenteCandy
32,5k 7 10 13
CRU - Account cancellato su Richiesta utente
 
Messaggi: 10123
Iscritto il: 14 giu 2010, 22:54

0
voti

[27] Re: Ridurre instabilità ADC

Messaggioda Foto UtenteDirtyDeeds » 18 lug 2012, 7:16

:-M
It's a sin to write sin instead of \sin (Anonimo).
...'cos you know that cos ain't \cos, right?
You won't get a sexy tan if you write tan in lieu of \tan.
Take a log for a fireplace, but don't take log for \logarithm.
Avatar utente
Foto UtenteDirtyDeeds
55,9k 7 11 13
G.Master EY
G.Master EY
 
Messaggi: 7012
Iscritto il: 13 apr 2010, 16:13
Località: Somewhere in nowhere

0
voti

[28] Re: Ridurre instabilità ADC

Messaggioda Foto Utentefalessi » 18 lug 2012, 8:43

Hai messo delle capacità (generalmente 100nF) in prossimità del PIC?
Che errore di conversione ha il PIC (ho letto molto velocemente i Datasheet e non ho visto questo dato)?
Come hai accoppiato gli ingressi?
internamente il PIC ha un condensatore da 25pF che deve essere scaricato prima di ogni campionamento, e prima di effettuare la lettura deve essere "carico" (ma questo è gia stato detto)...
Avatar utente
Foto Utentefalessi
30 3
New entry
New entry
 
Messaggi: 69
Iscritto il: 16 nov 2011, 14:08

0
voti

[29] Re: Ridurre instabilità ADC

Messaggioda Foto Utentedany192 » 18 lug 2012, 22:11

DirtyDeeds ha scritto:1) Fai il conto di quanto tempo intercorre tra un'acquisizione e l'altra. Ti conviene far riferimento all'assembly generato dal compilatore e al data sheet per ottenere i tempi delle singole istruzioni. Altrimenti, prendi un oscilloscopio e misuralo ;-) (Anche se continuo a dire che l'acquisizione sarebbe meglio agganciarla ad un interrupt).


Nella versione senza media, faccio l'acquisizione (ovviamente senza ciclo for) una sola volta ed ottengo comunque quei valori che variano comunque. Se era un problema di tempi, credo che in questa versione non avrei avuto questo comportamento...almeno credo :D

DirtyDeeds ha scritto:2) Ma le variabili ch1, ch2 ecc. a quanti bit sono? Tu hai una serie di numeri a 10 bit (immagazzinato "fintamente" a 16 bit), anche immaginando che ci sia sufficiente rumore per avere dithering, se poi fai una divisione a 10 bit, l'operazione di media non serve a nulla :!:


Sono variabili long, 2 byte quindi.

Candy ha scritto:Una domanda: hai anche tenuto conto del fatto che quando commuti il multipledxer del convertitore ADC, c'è una capacità all'interno del micor che si deve stabilizzare? Ovvero, dopo ogni commutazione è bene attendere un adeguato tempo, (calcolabile), per essere certi che il riferimento analogico sia corretto.
Anzi, due domande: hai tenuto conto delle regolazioni sulla velocità di conversione? Se troppo elevata ed il quarzo "basso", il convertitore butta i dadi...


Per quanto riguarda la velocità, utilizzando la funzione adc_read di mikroc, viene impostato l'oscillatore interno che, vado a memoria, dovrebbe essere a 31 kHz...abbastanza lento quindi e non dovrebbero esserci problemi. Io comunque utilizzo un quarzo a 20 MHz come oscillatore esterno.

Candy ha scritto:La media, in questo caso, non serve a nulla.
2) successivamente se il valore mediato oscilla di poco, non correggo nulla, ossia considero il precedente ancora valido.
3) se la variazione è invece molta, allora il nuovo valore, dopo le medie del caso, è vero...


Cosa intendi per poco o molto?

falessi ha scritto:Hai messo delle capacità (generalmente 100nF) in prossimità del PIC?
Che errore di conversione ha il PIC (ho letto molto velocemente i Datasheet e non ho visto questo dato)?
Come hai accoppiato gli ingressi?
internamente il PIC ha un condensatore da 25pF che deve essere scaricato prima di ogni campionamento, e prima di effettuare la lettura deve essere "carico" (ma questo è gia stato detto)...


Si, ho messo un condensatore da 100 nF tra vdd e vss molto vicino al PIC.
L'errore di conversione da datasheet: "The 1/2 LSb error is the maximum error allowed for the A/D to meet its specified resolution."
Gli ingressi sono collegati con il cursore di ogni pot direttamente sul pin dell'adc. Ho provato anche a mettere una capacità tra cursore e gnd ma nulla.
Il condensatore, leggendo sempre il datasheet, si scarica in Tad1 ovvero 4 mS e considerando che la libreria di mikroc setta il registro per 12Tad dovremmo starci dentro. Ad ogni modo, appena ho un po' di tempo, scriverò una funzione dedicata a parte per inizializzare ed utilizzare l'adc impostando manualmente tutti i registri e auementando un po' i tempi.
Avatar utente
Foto Utentedany192
20 6
Frequentatore
Frequentatore
 
Messaggi: 123
Iscritto il: 1 ago 2011, 13:32
Località: everywhere

1
voti

[30] Re: Ridurre instabilità ADC

Messaggioda Foto UtenteCandy » 18 lug 2012, 22:43

Cosa intendi per poco o molto?

E' relativo all'applicazione. Ad esempio: una variazione di 0,1 % sul fondo scala è poco o molto? Dipenderà dal fatto che sia o meno un dato significativo. Io non lo posso sapere da qui.
Ma, se tu individui che, ad esempio, una oscillazione nell'intorno di un valore, entro una certa percuntuale non è un deto significativo, puoi introdurre unabanda morta tale per cui, se l'oscillazione rientra in questa percentuale, il dato di uscita non viene aggiornato.

Esempio praticissimo:
- ADC a 10 bit, risoluzione 1024 punti.
- ci interessa fare una misura percentuale, con risoluzione di una unità percentuale.
- valore di uscita uguale al valore misurato diviso 10.
- i restanti 24 punti dell'ADC, (oltre il 999 quindi), sono definiti come fuori scala.

1) conversione a tempo costante e bufferizzazione dei dati;
2) media di un numero di campioni significatico, (pochi, tanti, dipende...);
3) prima inizializzazione? punto 3.1, altrimenti punto 3.2;
3.1) il risultato della media diventa valore di uscita. Si torna al punto 1).
3.2) il risultato è uguale al precedente valore di uscita, o nella tolleranza del +/- 0,5% di f.s., (+/- 5 punti per farla breve)? il risultato della media diventa valore di uscita, si torna al punto 1; altrimenti il valore di uscita non cambia e si torna al punto 1.

In questo modo hai introdotto una banda morta entro il quale il valore qcquisito può variare senza alterare l'uscita. E' chiaro che bisogna disporre di ADC con un numero di punti adeguatamente elevato, altrimenti è meglio non passare per la conversione ADC...

Tempo fa mi ero studiato alcuni ADC per via di un progetto che stavo facendo e, in ogni caso, un certo errore di ripetibilità c'è sempre, sopratutto per bassi valori. Qualche filtro è sempre meglio introdurlo.
Avatar utente
Foto UtenteCandy
32,5k 7 10 13
CRU - Account cancellato su Richiesta utente
 
Messaggi: 10123
Iscritto il: 14 giu 2010, 22:54

PrecedenteProssimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 5 ospiti