Corso programmazione PICMicro in C – Lezione 11 (Parte 1/2) – Il convertitore Analogico Digitale – Principi di funzionamento
Il convertitore A/D (Analogico => Digitale) è forse una delle periferiche più interessanti a bordo dei picmicro. Non che sia l’unica periferica interessante, per carità, ma è di sicuro quella che ci può permettere di realizzare dei semplici controlli sull’ambiente circostante (temperatura, umidità, presenza di gas, presenza di luce, suono ecc) in maniera molto semplice e soprattutto procurandoci grandi soddisfazioni.
Tale modulo ha la funzione di acquisire un segnale analogico, ovvero un segnale di tensione variabile nel tempo, dall’esterno e convertirlo in una parola digitale per poterlo quindi processare, effettuarvi dei calcoli o semplicemente visualizzarlo magari su un display o su una barra a led.
L’esempio classico è l’interfacciamento con sonde di temperatura per poter realizzare termometri e termostati. Esistono una varietà di sonde che forniscono segnali analogici: sensori di prossimità ad infrarossi, le LDR (Light Dependent Resistors) utili per realizzare controlli della luminosità ambientale e interruttori crepuscolari, sensori di gas utilizzati in ambito domestico per realizzare allarmi ma anche etilometri ecc.
Le applicazioni sono infinite e l’interfacciamento con un segnale analogico è sicuramente più rapido e semplice da effettuare rispetto a quello di un segnale digitale, sebbene per sua natura sia più soggetto ai disturbi.
Essendo i PIC dispositivi TTL, possono ricevere sugli ingressi del convertitore A/D segnali con tensioni variabili da 0 a 5 volt, non possono quindi accettare tensioni negative e, per tensioni superiori a 5 volt è necessario adottare dei partitori di tensione (realizzati semplicemente con resistenze) in maniera tale da non ricevere mai in ingresso tensioni superiori a 5 volts.
Per ulteriori informazioni su come funziona un partitore di tensione, consultate la voce Partitore di tensione su wikipedia.
In realtà il PIC ha delle protezioni al suo interno per scaricare le tensioni che escono al di fuori di tale range, ma tali protezioni hanno comunque un limite ed è sempre meglio non approfittarne e quindi prevedere già dall’esterno che tali tensioni non vengano superate.
Il 16F877 ha un convertitore A/D a 10bit (in altri pic il convertitore è invece ad 8 bit). Cosa vuol dire? Vuol dire che è capace di convertire un valore di tensione, variabile da 0 a 5 volt, in una parola formata da 10bit, ovvero in valori digitali che spaziano da zero fino al valore 1023 (1024 valori possibili) . Facile farsi due conti per capire qual’è quindi il minimo valore di tensione acquisibile (la sensibilità): 5/1024 = 0.00488V, ovvero circa 5mV. A volte, quando i segnali in ingresso non forniscono almeno 5mV è necessario ricorrere all’utilizzo di amplificatori.
Il convertitore A/D all’interno dei PICMicro è sempre uno solo, ovvero c’è un unico modulo capace di eseguire questa operazione di conversione. Gli ingressi, invece, sono più di uno: i dispositivi a 28pin hanno in genere 5 ingressi analogici, i dispositivi a 40 e 44 pin ne hanno 8. I pin capaci di acquisire un segnale analogico sono quelli contrassegnati sui datasheet con la sigla ANx dove x sta per il numero di porta analogica, il quale non segue la stessa numerazione della porta digitale a cui fa capo.
Alcuni picmicro, come il 16F628A, hanno dei pin contrassegnati come ANx ma in realtà tali pic non possiedono un convertitore A/D vero e proprio bensì un comparatore, che è un qualcosa di leggermente differmente, operante sempre nel campo dell’analogico, ma soltanto in grado di confrontare due valori analogici e di dire quale dei due segnali è più grande dell’altro.
Facile capire che essendoci più di un ingresso analogico ma un solo convertitore, si dovrà fare in modo, ogni volta, di “avvisare” il modulo A/D da quale ingresso analogico prelevare il segnale. Essendo inoltre gli ingressi analogici distribuiti su alcune porte, ci saranno quindi anche dei registri appositi che ci permetterano di dire se una determinata porta, contrassegnata anche come analogica, dovrà comportarsi come un I/O digitale oppure come un ingresso analogico.
I registri che si occupano della conversione analogico/digitale sono soltanto 4, di cui 2 destinati al setup della periferica e 2 che contengono il risultato della conversione.
Indice dei contenuti
ADCON0
E’ il registro che si occupa di controllare le operazioni del modulo convertitore, ovvero: l’accensione/spegnimento, la selezione dell’ingresso dal quale prelevare il segnale, l’avvio delle operazioni di conversione ecc. I bit di tale registro sono:
bit 7,6 (ADCS1:ADCS0) : Servono a selezionare (insieme ad un terzo bit, ADCS2, presente sull’altro registro, ADCON1) la frequenza di clock con la quale far funzionare il convertitore. Vedremo in seguito l’importanza di questa scelta e in base a cosa va fatta. I valori possibili sono i seguenti:
Ricordo ancora una volta che Fosc rappresenta la frequenza di Clock del Picmicro.
bit 5,4,3 (CHS2:CHS0) : Eseguono la selezione dell’ingresso analogico dal quale prelevare il segnale da convertire secondo la tabella:
Sto parlando del pin dal quale prelevare il segnale, non del pin da impostare come ingresso analogico, operazione, quest’ultima, che vedremo tra poco.
bit 2 (ADGO, indicato come GO/DONE) : Portando a 1 tale bit, si avvia il processo di conversione. Tale bit viene riportato a zero dall’hardware nel momento in cui la conversione è terminata.
bit 1 : inutilizzato
bit 0 (ADON) : Accende (1) o Spegne (0) il convertitore A/D. Lo si spegne generalmente per consumare meno corrente e/o e quando il modulo non è utilizzato.
ADCON1
E’ il registro che si occupa del settaggio delle porte analogiche. Tramite questo registro, difatti, possiamo dire al pic quali pin devono comportarsi come ingressi analogici.
bit 7 (ADFM) : Serve a selezionare il formato nel quale il valore digitale, risultato dalla conversione, deve essere memorizzato. Abbiamo difatti detto che il risultato della conversione è un valore a 10bit. Essendo il picmicro in questione un sistema ad 8 bit, il valore digitale proveniente dal modulo A/D sarà per forza di cose memorizzato in due registri ad 8 bit, lasciando quindi inutilizzati 6 bit. Tale bit di configurazione serve in pratica a giustificare verso destra o verso sinistra il risultato della conversione, vedremo tra poco come.
bit 6 (ADCS2) : insieme ai bit 7 e 6 del registro ADCON0, serve a selezionare la frequenza di clock del convertitore A/D come abbiamo già visto prima.
bit 5,4 : inutilizzati
bit 3,0 (PCFG3:PCFG0) : hanno la funzione di impostare quali pin devono comportarsi come ingressi analogici secondo la seguente tabella:
La scelta degli ingressi analogici va ovviamente fatta, oltre che con questi 3 bit, anche con i registri TRIS interessati, in pratica bisognerà settare come ingressi le porte che vogliamo come analogiche.
Come vedete dalla tabella, non tutte le combinazioni di pin sono possibili e seguendo la colonna di destra possiamo scegliere la configurazione più adatta alle nostre esigenze in base al numero di canali analogici che necessitiamo per la nostra applicazione. In pratica il numero di destra indica, per il settaggio dei bit PCFG3:PCFG0, il numero di canali analogici disponibili e il numero di riferimenti di tensione. Il convertitore A/D ha di fatti la possibilità di avere dei riferimenti di tensione esterni con i quali effettuare la conversione, questo nel caso in cui volessimo un’applicazione super precisa (a patto che il segnale di riferimento esterno sia anch’esso super preciso!), altrimenti quando il numero di riferimenti esterni è pari a zero viene preso come riferimento la tensione di alimentazione (Vdd) del pic.
Per poter effettuare la conversione, difatti, è necessario confrontare il segnale con una tensione fissa, o meglio con un riferimento di tensione basso e un riferimento di tensione alto. Nel caso in cui non vengano scelte tensioni di riferimento esterne, il segnale verrà confrontato con VSS e VDD.
Vediamo dalla tabella, ad esempio, che con il settaggio dei bit PCFG3:PCFG0 al valore 011x (dove la x può stare indifferentemente a 0 o 1), le porte capaci di essere ingressi analogici, saranno invece tutte digitali, quindi nessun canale analogico disponibile. Mettendo invece a zero i 4 bit, tutte le porte contrassegnate come AN, saranno tutte ingressi analogici.
Selezionando, infine, una configurazione che prevede riferimenti di tensione esterni, tali riferimenti andranno applicati ai pin del picmicro contrassegnati con le sigle VRef (Vref+ come tensione di riferimento alta e Vref- come tensione di riferimento bassa).
ADRESH e ADRESL
Sono i due registri che contengono il risultato della conversione (nei pic con convertitore ad 8 bit c’è invece un unico registro chiamato soltanto ADRES). A seconda di come abbiamo impostato il bit ADFM, il risultato sarà memorizzato in maniera diversa:
Se abbiamo messo ADFM ad 1, il risultato verrà giustificato verso destra, ovvero gli 8 bit meno significativi del risultato saranno memorizzati in ADRESL e i due bit più significativi (il bit 9 e il 10 del risultato) saranno memorizzati in ADRESH come bit 0 e 1, i rimanenti 6 bit di ADRESH saranno posti a zero. Questa è in genere l’opzione più utilizzata perchè segue lo standard. Se invece ADFM=0, il risultato viene giustificato verso sinistra e verrà in pratica letto al contrario rispetto all’impostazione precedente.
Se utilizziamo quindi l’impostazione ADFM=1, per ottenere il valore a 16 bit sarà necessario sommare il valore del registro ADRESL a quello del registro ADRESH shiftato di 8 posizioni a sinistra, in quanto i bit più significativi del risultato si trovano in posizione 0 e 1 e devono invece trovarsi in posizione 8 e 9:
INT valore; valore=ADRESL + (ADRESH<<8); |
Schema a blocchi del convertitore A/D
Possiamo quindi schematizzare con un diagramma come è costituito il modulo A/D:
Vediamo a destra gli ingressi analogici, tramite l’opportuna impostazione dei bit CHS2:CHS0 decidiamo quale “interruttore” chiudere per far giungere al modulo il segnale da campionare, ci sono quindi gli “interruttori” che, tra le altre cose, permettono di impostare la tensione di riferimento. Per le nostre prove utilizzeremo esclusivamente il riferimento interno, quindi nessuna configurazione che preveda riferimenti di tensione esterni.
Principio di funzionamento del convertitore A/D
Vediamo come è costituito il modulo convertitore A/D all’interno del PIC:
Sulla sinistra abbiamo la sorgente che fornisce il segnale analogico da campionare (VAIN), collegata al pin ANx. Tale sorgente ha una sua impedenza (Rs) che non va trascurata. Il datasheet dice difatti che tale impedenza non deve essere superiore a 10KΩ per poter avere una corretta acquisizione. Subito dopo il pin ANx abbiamo quindi un condensatore (Cpin) che ha la funzione di filtrare i disturbi, e due diodi di protezione che scaricano eventuali tensioni superiori a VDD o inferiori a VSS. Segue quindi il vero e proprio circuito di campionamento, preceduto da una leggera perdita di corrente (I leakage) dovuta alle giunzioni interne.
In condizioni normali, lo switch di campionamento SS è chiuso permettendo a CHOLD, di potersi caricare allo stesso livello di tensione presente sull’ingresso analogico da convertire. Lo Switch di campionamento ha anch’esso una propria impedenza (Rss) che è inversamente proporzionale alla tensione VDD di alimentazione del picmicro.
Quando viene avviata la conversione (ADGO=1), SS viene aperto in maniera tale da isolare CHOLD dalla linea e avviare quindi il processo di conversione che permette di tramutare il livello di tensione presente in CHOLD in un valore digitale. La conversione del valore analogico in una parola di 8 o 10 bit viene eseguita tramite un metodo chiamato ad approssimazioni successive.
Al termine della conversione il valore digitale è presente nei registri ADRESH e ADRESL, viene settato il flag di interrupt di fine conversione analogico/digitale (ADIF), ADGO viene rimesso a zero e SS viene richiuso per permettere a CHOLD di ricaricarsi e tenersi quindi pronto per un’altra eventuale conversione.
Per effettuare quindi una corretta acquisizione e conversione del segnale bisogna rispettare alcune tempistiche ben precise: abbiamo un tempo di acquisizione, che è necessario per poter caricare a piena capacità il condensatore di campionamento, ed un tempo di conversione, che inizia quando settiamo ADGO e termina quando viene settato ADIF, e rappresenta il tempo necessario al modulo A/D per poter effettuare l’operazione di conversione. La somma dei due tempi prende il nome di tempo di campionamento.
Le impedenze Rs e Rss influiscono sul tempo di acquisizione in maniera non trascurabile.
Chi ha studiato elettronica sa, difatti, che il tempo di carica di un condensatore è uguale a 5*R*C
Quanto minore è l’impedenza di ingresso del segnale, meno tempo ci vorrà per caricare il condensatore e quindi tanto inferiore sarà il tempo di acquisizione. Con un’impedenza di ingresso di 50Ω si ha un tempo di acquisizione (ripeto: un tempo di carica di CHold) tipico di circa 10.6µS, con un’impedenza di 10KΩ il tempo tipico sale a 19.7µS.
Tale tempo, purtroppo, non viene gestito in maniera automatica dal pic e si capisce, quindi, che, appena finita una conversione non possiamo avviarne immediatamente un’altra perchè non diamo al condensatore di campionamento il tempo necessario per ricaricarsi. Tra una conversione e l’altra, pertanto, dovremo rispettare un’attesa che è ragionevole scegliere tra 10 e 20µS.
Il tempo di conversione, invece, è funzione di un parametro chiamato TAD, che rappresenta il tempo necessario per convertire un unico bit o, in altre parole, il tempo di conversione per bit. La conversione AD richiede un tempo di 12TAD per una conversione completa a 10bit:
TAD rappresenta in pratica la frequenza di clock scelta per il convertitore A/D (impostata tramite i bit ADCS2:ADCS0 nei registri ADCON1 e ADCON0). La scelta del TAD va fatta in maniera accurata per alcuni semplici motivi:
- Bisogna che sia rispettato, per TAD, un valore minimo di 1.6µS. Quindi un clock troppo rapido non potrebbe rispettare tale requisito.
- TAD non deve nemmeno essere troppo elevato: insieme al segnale da campionare viene difatti inevitabilmente acquisito anche del rumore e con tempi maggiori tale fattore aumenta sempre di più in maniera non trascurabile; inoltre potrebbe accadere che il condensatore di campionamento si scarichi prima che la conversione sia terminata. In entrambi i casi il valore restituito dal convertitore è sicuramente corrotto.
Nella seguente tabella possiamo vedere alcuni valori di TAD in funzione del quarzo utilizzato per il clock del pic e del settaggio di ADCS1:ADCS0 (Nota: tale tabella non riporta tutti i valori di clock per il convertitore AD ed assume che ADCS2=0)
Notiamo alcuni valori ombreggiati: tali impostazioni non possono essere utilizzate perchè TAD risulta troppo breve o troppo lungo e causa quindi problemi per quanto detto prima.
Oltre al valore di TAD derivato dal clock è possibile selezionare una modalità in cui TAD viene ricavato da un circuito oscillatore RC interno al convertitore. Nei sistemi in cui il dispositivo entrerà in modalità sleep dopo l’avvio della conversione A/D e contemporaneamente operanti ad un clock superiore ad 1MHz, è richiesto l’utilizzo della sorgente di clock RC. In questo modo, il rumore digitale proveniente dai moduli in SLEEP viene bloccato: questo metodo fornisce l’accuratezza maggiore. Si capisce quindi che il convertitore AD è l’unico capace di continuare a funzionare anche quando tutto il resto del pic è “addormentato”.
La sorgente di clock RC fornisce un TAD tipico di 4µs (oscillante tra 2 e 6µS).
Dalla tabella precedente possiamo quindi vedere che per un pic operante alla frequenza di 20MHz è giusto scegliere la sorgente di clock RC oppure 32Tosc (che fornisce un TAD proprio di 1.6µS). Per altri valori di quarzo, e altre impostazioni fare i calcoli è semplice. Basta calcolare TOSC (che è l’inverso della frequenza del quarzo del picmicro) e quindi moltiplicarlo per 2, per 4, per 8 ecc e vedere quindi qual’è il valore migliore.
Settaggio e avvio del modulo A/D
- Configurare il modulo A/D impostando opportunamente i registri ADCON0 e ADCON1.
- Configurare le porte da usare come analogiche portando ad 1 i bit del relativo registro TRIStato.
- Se si desidera intercettare la fine conversione in una routine di interrupt procedere come segue oppure proseguire dal punto 4:
Portare a 0 il bit ADIF (A/D Interrupt Flag) del registro PIR1.
Portare a 1 il bit ADIE (A/D Interrupt Enable) del registro PIE1, in maniera tale che si possa scatenare un interrupt quando la conversione è terminata.
Portare a 1 il bit PEIE (Peripheral interrupt Enable) del registro INTCON, in maniera tale da attivare gli interrupt provenienti dalle periferiche esterne, quale appunto è il convertitore A/D
Portare a 1 il bit GIE (Global Interrupt Enable) del registro INTCON. - Dare un ritardo di almeno 10µS per far caricare correttamente il condensatore di campionamento del modulo AD
- Avviare la conversione portando a 1 il bit GO/DONE di ADCON0 (ADGO=1).
- Attendere il completamento della conversione A/D:
Aspettando che ADGO=0 nel caso in cui gli interrupt non li abbiamo attivati
oppure, se abbiamo previsto una routine di interrupt e abbiamo abilitato l’interrupt del modulo A/D, intercettando il settaggio di ADIF (ADIF=1).ADIF viene comunque settato anche se il relativo interrupt è disabilitato, ma nel caso in cui non stiamo usando l’interrupt, è più conveniente utilizzare ADGO perchè non ci dobbiamo preoccupare di resettarlo. - Leggere il valore accedendo ai registri ADRESH e ADRESL
- Se stiamo sfruttando l’interrupt, riportare a zero ADIF (ADIF=0)
Il valore ottenuto sarò quindi un valore numerico da 0 a 1023 rappresentativo della tensione in ingresso, sapendo che ogni bit del valore ottenuto vale circa 5mV, fare il calcolo della tensione in ingresso è abbastanza semplice.
Nella prossima parte di questa lezione vedremo come mettere in pratica la teoria.
Ringrazio pubblicamente Andrea Nalesso per la preziosa collaborazione fornita e per l’interessamento