Tutorials - PIC - Corso A&C

 

Esercitazioni PIC Baseline


22A - Misura della temperatura


Lo scopo dell' esercitazione è la realizzazione di un termometro utilizzando un sensore lineare.


Per la misura della temperatura sono disponibili numerosi tipi di sensori, tra cui quelli con uscita lineare in tensione che hanno raggiunto costi molto bassi e, data la linearità dell'uscita, sono di impiego più gradevole delle semplici resistenze PTC o NTC.  

Qui, vogliamo verificare il funzionamento di uno dei sensori termici integrati MCP970x, prodotti da Microchip, in particolare MCP9701.

E' simile a quello dei più noti (perché più anziani) LM34 o LM35: si tratta di un componente a tre pin che fornisce una tensione lineare proporzionale alla temperatura.
E' realizzato nel classico contenitore T0-92 e anche in versioni surface mount. Per ragioni di praticità, nelle prove utilizziamo il primo.

Occorre un convertitore analogico-digitale per permettere al microcontroller di elaborare il valore della temperatura, ma, adifferenza di altri sensori, non occorre alcun condizionamento del segnale in uscita, che può essere inviato direttamente nell' I/O analogico del microcontroller
Il circuito applicativo che ne risulta è semplicissimo, dato che sensore e PIC condividono la stessa Vdd/Vss.

In particolare, l' uscita del sensore è ampiamente immune agli effetti delle capacità parassite del collegamento, che può essere realizzato senza problemi sul circuito stampato o posto a (ragionevole) distanza dal microcontroller. Una capacità tra uscita e massa non è indispensabile, ma può essere utile ad annullare i problemi dovuti a transienti sulla connessione.

MCP9700 può essere alimentato tra 2.3 e 5.5V, con una deviazione massima di ±2°C tra 0° e 70°C. 
MCP9701
tra 3.3 e 5.5V, con un ±4°C.  L' accuratezza può essere portata a ±1°C o migliore con una opportuna taratura.

Possono lavorare tra -40 e *125°C (+150°C per i modelli con suffisso A) e consumano solamente 6uA.

MCP9701 ha una tensione in uscita di 19.53 mV per °C, mentre MCP9700 rende 10.00mV per °C; entrambi hanno un offset a 0°C per consentire la misurazione temperature negative. Per MCP9701 si tratta di 0.400V.
La tensione in uscita dal sensore MCP9701, per una determinata temperatura, sarà data da:

      Vt = (Tc * 0,01953) + 0.400

Così, se Tc è –10°C, 0.0°C o 30°C, le tensioni corrispondenti sono 0.204V, 0.400V e 0.985V rispettivamente.

Quando l’uscita è misurata con un ADC a 8 bit, come quelli presenti nei Baseline, con una tensione di riferimento Vref = 5V abbiamo:

      Vout = Vref / 256 * ADC = 5.0 / 256 * ADVAL = 0.01953 * ADC 

dato che la risoluzione di uno step è:

Vstep = Vref / 256  = 5.0 / 256  = 0.01953V 

Risulta evidente come Microchip abbia scelto il valore di 19,5 mV come coefficiente, dato che è precisamente l'ampiezza di uno step della conversione AD a 8 bit con riferimento a 5V e 4 volte quella di un AD a 10bit, il che rende molto semplice la valutazione della temperatura. 
E va considerato che i Baseline sono obbligati ad usare la tensione di alimentazione come riferimento, quindi Vdd = Vref.

Possiamo, allora, semplificare i calcoli relativi alla temperatura alla sola valutazione che :

ADC = Vt / 0.0195

Data la bassa risoluzione dell'ADC, i risultati sono frazionari. Ad esempio:

ADC_0°C = 0.4 / 0.0195 = 20.48

che deve essere approssimato a 20 (o 21).  La risoluzione generale sarà:

risoluzione della misura = V_per_step / V_per_°C = 0.0195 / 0.0195 = 1°C_per_step

Possiamo definire una formula generale, escludendo le parti decimali, con:

        t°C =  ADC_t°C + 20      per   ADC >= 20

       t°C =  20 - ADC_t°C         per  ADC =< 20

Con 8 bit di risoluzione non possiamo aspettarci molto di più, oltre al fatto che MCP ha un certa tolleranza propria, dovuta alle tolleranze di costruzione, sui valori nominali, a cui vanno aggiunti quelli prodotti dall’imprecisione della tensione di riferimento, dall’ auto riscaldamento del sensore, ecc. 
Ovviamente, per una ragionevole lettura occorre una altrettanto ragionevole precisione e stabilità della Vdd, che per i Baseline, ricordiamo ancora una volta, è la Vref della conversione: ogni differenza o variazione della Vdd dal valore nominale comporta una variazione del risultato della conversione. 
Ed è evidente che, utilizzando una Vdd diversa dai 5V indicati, occorrerà valutare nuovamente i calcoli. 
Ad esempio, con Vdd=3.0V avremo:

Vstep = Vref / 256  = 3 / 256  = 0.01171V 

Quanto diciamo richiede, quindi, per il microcontroller una alimentazione a 5V precisi, ottenuta almeno con un regolatore lineare (7805 e simili); non è possibile l' uso di batterie, la cui tensione scende col tempo di lavoro, a meno di implementare complessi sistemi di correzione con la misura della Vdd (esercitazione ), cosa che, dati i soli 8 bit della conversione, non darebbe comunque risultati di particolare precisione.
Questi sono ottenibili con un ADC a 10bit o 12bit ed una tensione di riferimento precisa, come è possibile su PIC di fascia superiore ai Baseline; per arrivare a determinare variazioni di ±0.5°C occorre una taratura in relazione al singolo sensore usato e l' applicazione di un algoritmo piece-wise per la correzione delle non linearità del sensore stesso. L’ AN1001 e l' AN981 di Microchip trattano proprio questi problemi.  


L' hardware

Per la nostra applicazione utilizziamo un PIC a 14 pin dotato di ADC, ovvero 16F506 o 526:

Impieghiamo tutti e tre i display a 7 segmenti per indicare temperature positive da 0 a 125°C e negative fino a -20°C.

PORTC e un bit del PORTB sono usati per pilotare i sette segmenti, mentre tre pin sono usati per i gate dei MOSFET del multiplex. Rimane un ingresso analogico (AN2) a cui colleghiamo l'uscita del sensore termico. 
Il pulsante del Reset non viene considerato dal programma.

Come sempre, la LPCuB semplifica le connessioni, limitandole a pochi jumper:

I jumper "gialli" collegano i segmenti da a a f.
Il jumper volante "giallo" collega il segmento g.
I jumper volanti "marrone", "celeste" e "nocciola" collegano i gate dei MOSFET.
Il jumper "verde" collega il display.
il Jumper volante "verde" collega AN2 al sensore.
Il pulsante RES non è utilizzato

Durante la programmazione occorre scollegare A0 e A1, dato il carico collegato renderebbe difficoltosa la comunicazione con il Pickit.

 


Il programma

Si tratta di una applicazione minimale, che non prevede correzioni della lettura, ma punta a dare una idea generale di come si possa realizzare uno strumento con display a sette segmenti pur restando nell' ambito dei Baseline.

Le routines di gestione del multiplex e la lookup table del display sono quelle già viste durante altre esercitazioni.
La lettura del convertitore AD viene effettuata nei "tempi morti"del ciclo del multiplex. 

Il programma principale consiste nella gestione del multiplex per le tre cifre, come abbiamo visto in altre esercitazioni, usando Timer0 in free running per determinare la cadenza. In particolare, usiamo il timer con prescaler 256, che, per un ciclo di clock di 1uS, permette con il test sul bit 3 di identificare tempi di 4ms (4096uS).

Il ciclo comprende 4 frame di 4ms ciascuno, per un totale di 16ms, alla fine dei quali viene acquisita la misura fatta dall' ADC.
L' elaborazione del dato, però, è eseguita solamente una volta al secondo, allo scopo di evitare sfarfallio della cifra delle unità nel caso di scarsa precisione delle letture ADC causate da disturbi i dalla Vdd non ideale.
Dato che un ciclo di 1s comporta 64 cicli, vengono effettuate 64 misurazioni; ad ognuna di esse, il risultato è sommato in un contatore a due bytes:

; avvia conversione
      bsf   ADCON0,GO
adlp  btfsc ADCON0,NOT_DONE
       goto adlp
; somma risultato al precedente
add   movfw ADRES
      addwf adsumL, f
      skpnc
       incf adsumH, f
      retlw 0

Da osservare che movfw non è un opcode del set di istruzioni, ma è uno pseudo opcode di MPASM che equivale a movf file,w .

L' elaborazion dei dati comporta la media della somma; dato che si tratta di 64 somme, la divisione per 64 è ottenuta con 6 shift a destra. Ogni shift a destra divide per 2 e 26=64. Questo permette un ulteriore stabilizzazione dell'ultima cifra, riducendo l'incertezza di 1/2 LSB dovuta alla parte decimale del risultato della conversione e che l'uscita a 8 bit non permette di rendere in valore intero. Questo è a scapito di un rallentamento nella misura, ma va osservato che in genere la variazione di temperatura è un processo lento o molto lento, come nel caso di quella ambiente; in ogni caso, variando il numero dei cicli e quindi delle letture si potranno effettuare più elaborazioni al secondo.

; calcola media delle somme
; per 64 somme, shift 6 posizioni a destra

ADmean rrf   adsumH,f ; bit 0 al carry
      
rrf   adsumL,f ; carry al bit 7
      
rrf   adsumH,f 
      
rrf   adsumL,f 
      
rrf   adsumH,f 
      
rrf   adsumL,f 
      
rrf   adsumH,f 
      
rrf   adsumL,f 
      
rrf   adsumH,f 
      
rrf   adsumL,f 
      
rrf   adsumH,f 
      
rrf   adsumL,f 
       retlw 0

Il risultato della media, a 8 bit, è in adsumL.

L' elaborazione corregge l'offset di 400mV a 0°C e determina se la temperatura è positiva o negativa. 

Viene effettuata anche una valutazione del valore ottenuto dalla misura: se è inferiore ad un minimo o superiore ad un massimo, la cui causa ha ampie probabilità di essere dovuta ad un problema sul collegamento tra microcontroller e sensore (interruzione, corto circuito) o ad un guasto del sensore stesso.  In questi casi il display presenterà le cifre LLL o HHH come indicazione di overflow della misura.

Nel caso di valori sotto 0°C, viene presentato il segno - sulla cifra delle centinaia. La trasposizione del dato sul display richiede anche la conversione da esadecimale a BCD. Per semplificare le operazioni, il dato BCD è su tre bytes (BCD unpacked), in cui l'LSB contiene il valore decimale, mentre l'MSB è a 0.
Ad esempio:

risultato ADC conversione BCD
1 00  00  01
10 00  01  00
15   00  01  05
25  00  00  05
30 00  01  00
145 01  04  05
155 01  05  05

Gli zeri non significativi vengono aboliti, impedendo l' accensione dei segmenti. Così, si avranno letture del genere:

LLL valore troppo basso. Es. ctocto tra Vin e Vss
-10 temperatura sotto 0
- 5 invece di -010
  5 invece di 005
  10 invece di 010
125 massima temperatura positiva
HHH valore troppo alto. Es. ctocto tra Vin e Vdd


Per ottenere le lettere L e H, il segno - e lo spegnimento del display, l'algoritmo inietta quattro possibili valori nei bytes a sostituire i valori originali derivati dalla conversione, e che saranno trasformati dalla lookup table nelle maschere necessarie ai segmenti. Le maschere volute vanno a sostituire 4 posizioni nella tabella:

; segment data table - display catodo comune
segtbl andlw 0x0F        ; solo nibble basso
       addwf PCL,f       ; punta PC
       retlw b'00111111' ; "0" -|-|F|E|D|C|B|A
       retlw b'00000110' ; "1" -|-|-|-|-|C|B|-
       retlw b'01011011' ; "2" -|G|-|E|D|-|B|A
       retlw b'01001111' ; "3" -|G|-|-|D|C|B|A
       retlw b'01100110' ; "4" -|G|F|-|-|C|B|-
       retlw b'01101101' ; "5" -|G|F|-|D|C|-|A
       retlw b'01111101' ; "6" -|G|F|E|D|C|-|A
       retlw b'00000111' ; "7" -|-|-|-|-|C|B|A
       retlw b'01111111' ; "8" -|G|F|E|D|C|B|A
       retlw b'01101111' ; "9" -|G|F|-|D|C|B|A
      ;retlw b'01110111' ; "A" -|G|F|E|-|C|B|A
      ;retlw b'01111100' ; "b" -|G|F|E|D|C|-|-
      ;retlw b'00111001' ; "C" -|-|F|E|D|-|-|A
      ;retlw b'01011110' ; "d" -|G|-|E|D|C|B|-
      ;retlw b'01111001' ; "E" -|G|F|E|D|-|-|A
      ;retlw b'01110001' ; "F" -|G|F|E|-|-|-|A

      retlw b'00111000'  ; Ah -> "L" -|-|F|E|D|-|-|-
      retlw b'01110110'  ; Bh -> "H" -|G|F|E|-|B|C|-
      retlw b'01000000'  ; Ch -> "-" -|G|-|-|-|-|-|-
      retlw 0            ; Dh -> display off

Di conseguenza, con i valori nell' esempio precedente:

risultato media conversione BCD flag dopo la correzione al display
1 00  00  01 negativo 0A  0A  0A LLL
10 00  01  00 negativo  0C  01  00  -10
15   00  01  05 negativo 0C  0D  05 - 5
25  00  00  05 positivo 0D  0D  05   5
30 00  01  00 positivo 0D  01  00   10
145 01  04  05 positivo 01  04  05 125
155 01  05  05 positivo 0B  0B  0B HHH

In fase di verifica, non disponendo di temperature diverse da quella ambiente, si potrà collegare ad AN2 il cursore del potenziometro inserendo l'apposito jumper e verificare il corretto funzionamento: con il cursore verso la posizione min. il display indicherà LLL; per tensioni al di sotto di 0.4V la lettura sarà negativa. Per valori tra 0.4 e  2.85V si avranno letture positive fino a 125. Oltre il display presenterà HHH.

Si potrà avere una immediata variazione della temperatura toccando il sensore, che, come si potrà osservare, è molto sensibile ed ha una rapida risposta.

Dalle prove fatte, un MCP9701 in media rende la temperatura ambiente attorno a 20°C con un errore massimo di 0.5°C. Volendo migliore precisione occorrerà al minimo una taratura del complesso sensore/micro/Vdd, aggiustando il risultato della conversione in funzione della correzione voluta. Una azione grossolana è quella di aggiungere o togliere una unità al risultato delle conversione AD; una azione più fine sarà quella di inserire una maggiore sofisticazione dell' algoritmo di analisi del risultato, con la valutazione dei decimali. Però,  questo richiederebbe o una cifre in più sul display; oppure la riduzione dell' ambito di misura in modo da utilizzare una cifra per gli 0.5 gradi o anche una funzione che dilati la lettura nell' ambito di risultati a due cifre e mezza. Vista però la limitazione della definizione dell'ADC e lo scopo essenzialmente didattico dell' esercitazione, non è parso utile complicare troppo il firmware. 


File compresso contenente il progetto MPLAB.


Si possono usare altri sensori di temperatura come i già citati LM35AD22100 o TMP37, che hanno la stessa piedinatura, ma richiedono una diversa gestione dei risultati della conversione ADC, dato che l'uscita è rispettivamente pari a 10, 22.5 e 20mV/°C.

 


 

 

 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 23/03/15.