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 LM35,
AD22100 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.
|