Aumentare la risoluzione analogica di Arduino, un parere

Salve,
l'idea nasce dall'esigenza di avere una risoluzione migliore di quella attuale (1/1024 di VRef), se interessa la problematica posso esporla a richiesta. Lo schema concettuale (manuale :~) è molto semplice:
Con un banale partitore mi ricavo la metà della tensione massima, che applico, mediante la posizione di riposo dello switch (per semplicità ho messo un relé a doppio scambio) al pin ARef; sempre nella stessa condizione di switch invio la tensione da misurare al pin analogico A0.
Il comparatore, nel momento in cui rileva che la tensione è >VMax/2 cambia lo stato dello switch, di conseguenza su ARef ora viene applicata la VMax e la tensione da misurare va al pin A1.
In questo modo la risoluzione raddoppia, diventando di circa 2,4mV; inoltre il metodo si potrebbe estendere contemporaneamente a tutti i 5 pin analogici ottenendo una risoluzione di circa 1mV che non sarebbe male, non vi pare?
Non ho fatto prove, ho fatto qualche ricerca ma non sono riuscito a trovare niente che mi servisse, concettualmente dovrebbe andare, ma non so come la prende Arduino..., ecco perché, per non perdere tempo inutilmente, chiedo il vostro parere.
Se la cosa è fattibile avrò bisogno di un paio di dritte su Arduino e sulla parte elettronica, se non è fattibile consideratela un'occasione per augurarvi buona domenica.
Quindi, parafrasando il grande Gassman ne "L'armata Brancaleone", vi dico: «Miei prodi, sequitatemi o sputazzatemi!"

A parte il fatto che l'ATmega 328p non ha la possibilità di inserire un offset per l'ADC, cioè ha solo Aref e non Aref+ e Aref-, col tuo sistema al massimo "raddoppi" la sensibilità per i primi 2.5V, mentre quando vai a misurare tensioni maggiori rimane quella solita.
Per raddoppiare la sensibilità degli ADC si ricorre a tecniche di oversampling, questa è una application note di Atmel che spiega come portare la risoluzione dell'ADC a 11 o 12 bit tramite questa tecnica, è consigliabile non superare i 12 bit anche se in teoria si può andare oltre.

Ciao astrobeed, grazie per la risposta, ho capito quanto mi dici sulla mia idea, in effetti sul pin 1A arriverebbe una tensione tra 2,5 e 5V, con riferimento a 5V, quindi in ogni caso userei solo i secondi 512 punti della scala.
Ho dato una prima occhiata al link, non ho grandissima dimestichezza con l'inglese, mi pare d'aver capito che il contatore, generato da un pwm di Arduino, serve per regolare la tensione sull'ARef.
Quindi realizzando questo semplice circuitino e modulando via software il duty cicle del contatore, in base alla lettura della tensione sotto test, posso ottenere quello che mi serve?
Da cosa dipende l'impostazione dei bit?
Ti chiedo gentilmente qualche indicazione tecnica sulla realizzazione, se non devi perderci troppo tempo, o altrimenti qualche chiarimento teorico in modo che mi faccio un minimo di idea prima di tentare di tradurre questa cosa.
Mi andrebbero benissimo 13 bit, ma anche a 12 potrei ottenere il mio scopo.
Grazie!

menniti:
Ho dato una prima occhiata al link, non ho grandissima dimestichezza con l'inglese, mi pare d'aver capito che il contatore, generato da un pwm di Arduino, serve per regolare la tensione sull'ARef.

Sei totalmente fuori strada, il circuito che immette il pwm sull'Aref tramite un filtro passa basso serve per simulare del rumore bianco se il segnale da campionare è purissimo.
La tecnica dell'oversampling per poter funzionare richiede la presenza del rumore sul segnale da analizzare, condizione normale visto che un segnale di grande purezza normalmente si ottiene solo da costosissimi generatori di laboratorio.
Concettualmente l'oversampling sfrutta l'incertezza stocastica della lettura effettuata dall'ADC per creare i bit mancanti, non ti sto ad elencare tutta la teoria (tanta) matematica che c'è dietro, trovi tutta la documentazione che vuoi con google, però prendi per buono (dimostrabile) che per ogni bit di incremento devi campionare 4 volte più veloce.
Esempio pratico se per il segnale che analizzi ti basta prelevare un campione al secondo per elevare la risoluzione a 11 bit devi campionare 4 volte al secondo, per elevare di due bit devi campionare 16 volte al secondo e così via.
Se vuoi ottenere 12 bit, e ti consiglio di non andare oltre, prendi 16 campioni consecutivi, li sommi tra loro e poi dividi il tutto per 4, in questo modo ottieni un valore compreso tra 0 e 4095 pari a 12 bit.
Per ottenere 11 bit acquisisci 4 campioni consecutivi, li sommi tra loro e dividi per 2.
Ovviamente l'oversampling impatta sulla massima velocità di campionamento, però se si utilizza la tecnica del roll average (buffer circolare per i campioni) è possibile fruttare la massima velocità di campionamento dell'ADC anche con l'oversampling, in questo caso si ha una perdita, accettabile, di precisione.

La tecnica dell'oversampling per poter funzionare richiede la presenza del rumore sul segnale da analizzare, condizione normale visto che un segnale di grande purezza normalmente si ottiene solo da costosissimi generatori di laboratorio.
Concettualmente l'oversampling .................... che per ogni bit di incremento devi campionare 4 volte più veloce.
Esempio pratico se per il segnale che analizzi ti basta prelevare un campione al secondo per elevare la risoluzione a 11 bit devi campionare 4 volte al secondo, per elevare di due bit devi campionare 16 volte al secondo e così via.
Se vuoi ottenere 12 bit, e ti consiglio di non andare oltre, prendi 16 campioni consecutivi, li sommi tra loro e poi dividi il tutto per 4, in questo modo ottieni un valore compreso tra 0 e 4095 pari a 12 bit.

Te lo sei scelto perfetto l'alias, sei proprio di un'altra galassia :astonished:
Il concetto mi è chiaro, ma non ho idea di come realizzarlo praticamente :blush: Non so se puoi aiutarmi anche in questo, ma forse ci vuole troppo tempo... La tensione che misuro entra proprio nel range 0-5V con una risoluzione di 1mV (p.es. 2,213 - 2,215 devono essere valori diversi), le variazioni avvengono in un lasso di tempo piuttosto lungo, mediamente ogni 0,5-1 secondo, a volte però capita che da 1,234 passi di colpo a 4,567, anche se sono situazioni rare.
Ti ringrazio in ogni caso!

Non devi fare altro che leggere consecutivamente l'ADC per 16 volte, sommare tra loro i valori e dividere per 4, il risultato finale è un valore a 12 bit (0-4095).
Dato che Arduino campiona in modo fisso a 10ksps e le variazioni sono lente non hai nessun problema di aliasing, però evita di alimentare Arduino da USB e usa una sorgente esterna perché la tensione presente sulla porta USB è tutto fuorché pulita e stabile, non è molto indicata per l'uso con l'ADC.
Tieni presente che lo schema di Arduino collega assieme Vcc e Avcc, sono rispettivamente l'alimentazione di Arduino e l'alimentazione del ADC, il che va bene per quasi tutte le situazioni, ma non per applicare l'oversampling senza usare una tensione di alimentazione precisa e stabile.
In alternativa puoi usare Aref, previa abilatazione tramite "analogReference(EXTERNAL)", collegandolo ad una tensione campione ben filtrata.

OK, ora ho capito cosa devo fare, appena faccio un minimo di progressi, continuo su questo topic.
Grazie ancora, ce la "faremo" anche questa volta; intanto sto imparando ad usare KiCad e sto disegnando il circuito finale del generatore di sequenze a 24 bit, la tua prima opera con me come manovale....
Ciao.

astrobeed ho una piccola domanda.
Attualmente io tengo in memoria la SOMMA(in float) delle ultime 500 letture(circa mezzo secondo di letture), quando leggo un dato dall'ADC calcolo la media (somma/500), poi tolgo da somma la media (somma-media) e aggiungo il valore letto (somma+=valore)

se a questo punto facessi somma/(500-4) otterrei la media a 12 bit... o perderi troppa precisione data dalla sottrazione della media? e quindi devo tenere un'array con le ultime 16 letture a parte?

Non mi è chiaro perché devi fare tutte quelle operazioni comunque non è così che incrementi la risoluzione dell'ADC.
Come ho già spiegato devi prendere 4^x samples ove x è il numero di bit che vuoi incrementare, per 1 bit 4 samples, per 2 bit 16 samples, per 3 bit 64 samples etc, fai la somma dei samples e li dividi per 4^(x-1), quindi 2 per 1 bit, 4 per 2 bit, 16 per tre bit etc.
Però l'operazione sopra descritta deve essere fatta per ogni singola lettura che vuoi ottenere, quindi se devi acquisire y campioni per costruire una curva devi ripetere l'oversampling y volte.
Se non ti basta la banda imposta dall'oversampling puoi ricorrere al ring buffer, cioè ad ogni sample che ricevi applichi l'oversampling usando i 4^x - 1 valori precedenti, però questo comporta una perdita di precisione che potrebbe vanificare il guadagno in risoluzione, è da valutare caso per caso e tocca farsi i conti anche con la densità spettrale del rumore.

son partito da quell'idea perchè è il codice che uso ora (media su 500 valori, per trovare lo "0" del giroscopio "libero" dal drift)..
e dato che arduino non regge un array di 500 elementi, ho sfruttato il trucco della somma :slight_smile:
se già l'array circolare è una perdita di precisione, allora il metodo di togliere dalla somma la media fà perdere ancora più precisione e diviene inutilizzabile