Corso programmazione PICMicro in C – Lezione 11 (Parte 1/2) – Il convertitore Analogico Digitale – Principi di funzionamento


Scritto da Giovanni Bernardo in data 4 marzo 2010

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.

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, ADCS3, 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 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

  1. Configurare il modulo A/D impostando opportunamente i registri ADCON0 e ADCON1.
  2. Configurare le porte da usare come analogiche portando ad 1 i bit del relativo registro TRIStato.
  3. 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.
  4. Dare un ritardo di almeno 10µS per far caricare correttamente il condensatore di campionamento del modulo AD
  5. Avviare la conversione portando a 1 il bit GO/DONE di ADCON0 (ADGO=1).
  6. 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.

  7. Leggere il valore accedendo ai registri ADRESH e ADRESL
  8. 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

Articoli che potrebbero interessarti:

L'articolo ti è piaciuto o ti è stato utile per risolvere un problema? Supporta e mantieni in vita questo sito, ci basta soltanto un caffè o una birra

  1. #1 da S.D.R. il 4 marzo 2010

    Bel lavoro Giovanni ;-)

  2. #3 da mcgyver86 il 5 marzo 2010

    Spettacolare… Grandissimo Giovanni, veramente ottima lezione.. Grazie per il tuo lavoro, piano piano sto entrando sempre di + nel mondo dei PICmicro!!
    Posso suggerire una lezione? Interfacciare un PICmicro ad un display LCD e tastiera PS/2 (quella dei pc per intenderci!).. Naturalmente è solo una idea!!

    Grazie, saluti

    Alessio.

  3. #5 da S.D.R. il 5 marzo 2010

    Ciao mcgyver86 ,
    Ma a che tipo di LCD vuoi collegarlo ?

  4. #6 da Giovanni Bernardo il 6 marzo 2010

    Penso che collegarlo a un display hd44780 compatibile è la cosa più semplice. Le tastiere PS/2 utilizzano un protocollo di comunicazione seriale sincrono. Hanno una linea di clock e una linea dati. Inviano il bit di start, sul fronte di discesa del clock inviano il bit, 8 bit in totale per il tasto premuto (spero che almeno lettere e numeri seguano in qualche modo il codice ascii, adesso non lo so, mi devo documentare meglio), seguono quindi un bit di parità e un bit di stop. 11bit in totale. Funziona un po’ come l’I2C insomma e non dovrebbe essere difficile usare una tastiera. Proveremo pure questo.

  5. #7 da MayTs il 13 aprile 2010

    Non ho capito esattamente come si calcola il TOSC:
    io per esempio sto usando un quarzo da 8 Mhz(uso un quarzo da 8 mhz, solo perché riesco a far scattare l’interrupt del timer esattamente ogni millisecondo, e per quello che sto facendo preferisco avere delle tempistiche più precise a discapito della velocità di esecuzione).
    quindi usando il quarzo da 8 mhz come calcolo il TOSC e di conseguenza la frequenza ottenuta con tale TOSC?

    Inoltre leggendo il datasheet mi sembra di aver capito che utilizzando un quarzo da 5 Mhz il massimo TOSC utilizzabile sia a 8TOSC, ma visto che nella tabella hai riportato anche il 32 TOSC impostandolo a 32 si rischia qualcosa?(quest’ultima domanda è solo a titolo informativo)

    Grazie in anticipo per le delucidazioni

    • #8 da Giovanni Bernardo il 13 aprile 2010

      TOSC = periodo, FOSC= Frequenza. TOSC=1/FOSC.
      Se esprimi FOSC in Hz TOSC è in secondi.

      Nel tuo caso il quarzo è da 8MHZ? FOSC=8MHz=8000000Hz, quindi TOSC=1/8000000Hz = 125 nanosecondi.

      Se imposti 32Tosc ottieni: 32*125 = 4000 nanosecondi = 4 microsecondi. Quindi per il tuo scopo va bene. 8TOSC ti porterebbe a 1microsecondo ed è troppo poco, 16TOSC a 2microsecondi e pure va bene.

      O si scrive 32TOSC o FOSC/32 è la stessa cosa in quanto TOSC=1/FOSC.

      Con il quarzo da 5MHz, 8 TOSC è il minimo non il massimo, perchè con un valore di TOSC più basso ottieni un tempo troppo rapido, come spiegato nell’articolo. Spero di essere stato chiaro.

  6. #9 da MayTs il 13 aprile 2010

    Chiarissimo e Gentilissimo come sempre.
    Grazie mille.

    Manuel

  7. #11 da Cristianoscr il 22 luglio 2010

    Eccomi che torno all’attacco! Il 12f675 ha porte analogiche? Sul datasheet non trovo niente al riguardo! Se le ha come faccio ad attivarle?

    • #12 da Cristianoscr il 22 luglio 2010

      Dopo lungo penare ho scoperto che avevo tutto sotto gli occhi (dio cos’ho per la testa in questo periodo???) ma nel datasheet del 12f675 la frequenza di conversione A\D la devo impostare in un altro registro?? Precisamente nel registro ANSEL?
      Piano piano sto imparando anch’io a leggere i datasheet…. A breve ti arriverà una cassa di moretti ;)

      • #13 da Giovanni Bernardo il 22 luglio 2010

        Si il registro ANSEL ti permette di impostare singolarmente le porte da usare come analogiche. L’ho spiegato nell’esempio dei relè controllati via wireless in cui faccio uso di un 16F88 che pure ha questa caratteristica

(non verrà pubblicata)
  1. Ancora nessun trackback

Fusion theme by digitalnature | Articoli (RSS) e Commenti (RSS) ^