I sensori di temperatura analogici MCP9700 e MCP9701
L’ultima volta di cui ho parlato di un sensore di temperatura analogico forse è stato nel 2010 in cui ho presentato su questo blog un progetto di un termostato, a dire il vero non perfetto, ma che serviva per dare un esempio di utilizzo del modulo convertitore A/D. In quel progetto facevo uso di un sensore di temperatura analogico LM35.
L’LM35 è un sensore molto comune, esiste da anni, si trova in formato TO92 (che a noi che continuiamo ad utilizzare millefori, breadboard e componentistica through-hole piace un sacco), ed è uno dei più utilizzati ma… ha un difetto: se ricordate, per leggere e misurare le temperature negative bisogna barcamenarsi tra soluzioni hardware e software dal momento che per andare sotto lo zero è necessario utilizzare un riferimento di tensione negativa…insomma le difficoltà sono tante al punto che io stesso ho desistito passando a soluzioni più facili come le sonde digitali DS18x20 sfruttando il bus One-Wire.
Dato che sto aggiornando il vecchio corso di programmazione PICmicro in C per fare esempi con il nuovo IDE MPLAB X ho pensato, questa volta, per introdurre il nuovo modulo ADCC o ADC2 (ADC with Computation, che sarà oggetto di un prossimo articolo) dei PICmicro, di utilizzare sempre un sensore di temperatura analogico, con caratteristiche simili al vecchio LM35, ma prodotto dalla stessa Microchip: l’MCP9700 e l’MCP9701.
Perchè ho scelto questi due sensori al posto dell’LM35? Il motivo principale è che leggono le temperature negative in maniera semplice, senza bisogno di dover fornire una tensione di riferimento negativa. L’LM35 difatti a 0°C fornisce 0V, per cui, per leggere una temperatura negativa, c’è bisogno di un riferimento di tensione inferiore a 0V, mentre i sensori MCP970x a 0°C restituiscono un valore superiore a 0V, il che vuol dire che possiamo scendere sotto lo zero avendo in uscita un valore di tensione positivo, hanno in pratica un offset a 0°C. In aggiunta anche i sensori Microchip si trovano in formato TO92.
Elenco qui, brevemente, le caratteristiche e le differenze dei due sensori:
Parametro | MCP9700 | MCP9701 | MCP9700A | MCP9701A |
---|---|---|---|---|
Range di Temperatura | -40 ÷ 125°C | -40 ÷ 125°C | -40 ÷ 125°C | -40 ÷ 125°C |
Vdd | 2.3 ÷ 5.5V | 3.1 ÷ 5.5V | 2.3 ÷ 5.5V | 3.1 ÷ 5.5V |
Coefficiente di Temperatura | 10mV/°C | 19.5mv/°C | 10mV/°C | 19.5mv/°C |
Output a 0°C | 500mV | 400mV | 500mV | 400mV |
Accuratezza massima (nel range 0÷70°) | ±4°C | ±4°C | ±2°C | ±2°C |
Come vedete le varianti con la A finale sono uguali in tutto e per tutto a quelle senza la A tranne che per avere una migliore accuratezza (hanno un errore più basso) ma in realtà il datasheet dice che se il sensore parte da 25°C, l’accuratezza tipica fino a 70°C è di ±1°C, ma si parla sempre di valori limite il che vuol dire che in applicazioni reali possono essere più accurati ancora. Chiaramente non sono sensori fatti per costruire termometri di precisione bensì per utilizzi “ambientali” ovvero sistemi di regolazione vari.
L’LM35 da questo punto di vista è migliore dato che ha un’accuratezza 0.5°C. Anche sulla non linearità l’LM35 ha un punto a favore: ±0.35°C vs ±0.5°C dei sensori MCP970x. Non volendo prendere in considerazione altre caratteristiche che per la maggior parte delle applicazioni possono essere trascurabili, dato che, al confronto, siamo pari (1 punto per gli MCP970x dovuto alla questione temperatura negativa, 1 punto per l’LM35 per tutti i parametri relativi a precisione e accuratezza) non rimane che fare il confronto sull’ultima cosa rimasta: il prezzo. Prendendo come riferimento il formato TO92 e lo stesso negozio on-line (Mouser), l’LM35 costa €1,74 mentre l’MCP9700A costa 27 centesimi.
Torniamo alla tabella: il coefficiente di Temperatura dell’MCP9700, ad esempio, mi dice che per ogni grado centigrado, il sensore in uscita mi fornisce 10mV a partire da 500mV che rappresentano lo zero (quindi 510mV rappresentano 1°C e così via). Il perchè la Microchip abbia scelto di costruire dei sensori con quei coefficienti di Temperatura è presto detto.
L’uscita dell’MCP9700 è ottimizzata per fornire 1°C/bit qualora venga utilizzato su moduli ADC ad 8 bit aventi una tensione di riferimento di 2.5V. Un ADC ad 8 bit che ha una tensione di riferimento di 2.5V fornisce un valore da 0 a 255 per un range di tensioni da 0 a 2.5V per cui l’incremento di 1 unità del valore digitale letto corrisponde ad un incremento di tensione sull’ingresso analogico pari a : 2500mV/255 = 9.8mV che è vicinissimo al coefficiente di 10mV/°C dell’MCP9700, per cui, in questo caso specifico, 1 unità letta sul modulo AD corrisponde ad un incremento di 1°C. Se il modulo A/D restituisce un valore di 25 ecco che la temperatura esterna è 25°C. Tutto questo ammesso di aver fornito una tensione di riferimento di 2.5V (che sui PICmicro si può fare utilizzando il pin Vref+) e che il modulo sia ad 8bit, altrimenti bisogna fare qualche calcolo in più, ma nulla di complicato: questa semplificazione è stata fatta dalla Microchip per chi non vuole perdere tempo.
Allo stesso modo l’uscita dell’MCP9701 è stata ottimizzata per fornire 1°C/bit per i moduli ADC ad 8bit aventi una tensione di riferimento di 5V. In queste condizioni l’aumento di una unità del valore digitale corrisponde ad un aumento di tensione pari a: 5000mV/255=19.6mV.
Indice dei contenuti
Appunti di utilizzo
MCP9701 con modulo A/D a 12bit
Perchè faccio questo esempio? Perchè di recente la Microchip mi ha inviato una scheda PIC16F18446 Sensor Board Demonstration che, tra le svariate, interessantissime, cose, utilizza un PIC16F18446 montato su una Xpress Board e ha un sensore MCP9701. Quel PIC ha un modulo ADCC a ben 12bit (non male per un microcontrollore ad 8 bit!), questo vuol dire che la lettura di un valore analogico può fornire un numero da 0 a 4095. Nell’esempio stock di quella scheda, il modulo utilizza una tensione di riferimento di 1024mV che viene fornita dal modulo FVR (Fixed Voltage Reference), questo vuol dire che, a parte che l’ingresso analogico potrà misurare fino a 1.024V, avremo una risoluzione del modulo A/D di:
l’FVR andrebbe sempre utilizzato come riferimento per un modulo A/D perchè fornisce una tensione stabile che non subisce le fluttuazioni della Vdd. Ovviamente nel caso in cui abbiamo bisogno di diversi range di tensione di riferimento possiamo sempre usare la Vdd o un riferimento esterno.
In questo caso, dato che l’MCP9701 restituisce 400mV a 0°C, la lettura del modulo viene riportata a zero per cui dal numero restituito dal modulo viene sottratto il valore (400mV/0.25mV)=1600.
Poi, per convertire in temperatura il valore letto dall’ADC, dato che questo sensore fornisce 19.5mV/°C si divide il valore per 19.5/0.25 = 78
Questo spezzone di codice è estratto dagli esempi per la scheda in questione (modulo temperature.c):
48 49 50 | temp12bit = res - 1600; temp12bit *= 100; temp12bit /= 78; |
Come vedete dal valore res, che è la lettura dal convertitore AD, viene dapprima sottratto il valore 1600, che è determinato dall’offset a 0°C di 400mV come dicevamo prima, c’è quindi una moltiplicazione per 100 che serve per non perdere i decimali durante l’operazione successiva e recuperarli all’atto del mostrarli sul display con una divisione per 100, e c’è infine la divisione per 78 che è il fattore di conversione per trasformare la lettura dell’ADC in gradi centigradi. Alla fine il valore temp12bit contiene il valore di temperatura in gradi moltiplicato 100.
Per mostrarlo sul display, dato che nell’esempio non hanno previsto una funzione per scrivere numeri ma solo per scrivere stringhe (array) viene usato il classico sistema di creare un array (“st” nell’esempio, che hanno sovradimensionato a 16 elementi, non capisco il perchè) e riempirlo con i numeri convertiti in caratteri ASCII aggiungendo a loro il valore ‘0’ che equivale ad aggiungere 48. Le operazioni di divisione e MOD dovremmo già averle imparate perchè ne faccio uso massiccio anche io (ad esempio nell’esempio del cronometro con i display a 7 segmenti per estrarre le singole cifre):
55 56 57 58 59 60 61 62 63 64 65 66 67 | uint8_t st[16]; st[ 0] = ((temp12bit / 1000) % 10) + '0'; st[ 1] = ((temp12bit / 100) % 10) + '0'; st[ 2] = '.'; st[ 3] = ((temp12bit / 10) % 10) + '0'; st[ 4] = ((temp12bit / 1) % 10) + '0'; st[ 5] = 0; if (temp12bit < 1000) { st[0] = ' '; } |
Il codice dalla riga 64 capirete che serve per non mostrare lo zero non significativo davanti al valore (ovvero quando la temperatura è inferiore a 10°C e deve essere quindi mostrata una cifra sola per il valore intero di temperatura).
MCP9700 con modulo A/D a 10bit
Perchè faccio quest’altro esempio? Perchè ho dei campioni di MCP9700, che ha l’uscita da 10mV/°C come il vecchio LM35, e sto aggiornando il corso utilizzando il PIC16F18877 (nuovo sostituto del vecchio PIC16F877A) e questo PICmicro ha un modulo A/D a 10bit.
Se siete interessati, la sigla completa del sensore che sto utilizzando io, in tormato TO92, è MCP9700A-E/TO. La A indica il modello più accurato, la E indica il range “Extended” ovvero quello standard da -40 a 125°C e TO indica il formato TO92.
Come dicevo sopra nel caso in cui è presente il modulo FVR, che mi fornisce una tensione di riferimento stabile, è sempre meglio utilizzarlo ma questo determina anche la tensione massima che può essere misurata.
Anche io utilizzerò l’FVR impostato a 1024mV perchè con il modulo A/D a 10bit mi fornisce un’ottima risoluzione di 1mV/bit (1024mV/2^10) che abbinato all’uscita del sensore di 10mV/°C, mi si traduce in una risoluzione di 0.1°C/bit (ogni 10 unità rappresentano un grado) per cui posso leggere le temperature con una precisione di 0.1°C (ammesso che il sensore in questione sia così preciso!).
Utilizzando un riferimento di 1024mV vuol dire che potrò leggere max 1024mV su un ingresso analogico, che sull’MCP9700 corrispondono ad una temperatura di:
dove 1024mV è la tensione massima che posso mettere in ingresso con il riferimento a 1024mV, 500mV rappresenta 0°C del sensore e 10mV/°C è il coefficiente di temperatura. La temperatura massima di 52.4°C per applicazioni domestiche è più che sufficiente. Nel caso in cui volessi sfruttare l’intero range del sensore, posso impostare il riferimento a 2048mV (che è un altro settaggio del modulo FVR) che mi consentirebbe di leggere fino a 154.8°C
Noi stiamo prendendo in esame le varianti standard dei sensori MCP970x, che arrivano fino a 125°C ma esiste la variante “High Temperature” che arriva fino a 150°C ma c’è solo per l’MCP9700 e NO nel formato TO92
Usando il riferimento di 2048mV la risoluzione scende a 0.2°C/bit dato che ogni bit adesso corrisponde a 2mV.
Bene, e la temperatura negativa? Abbiamo detto che 500mV corrispondono a 0°C, per cui mi aspetto che una lettura da 0 a 500mV corrisponda a temperature negative. Dato che la temperatura minima a cui possono arrivare questi sensori è -40°C, questo valore corrisponde ad una tensione di:
che con il modulo A/D a 10bit con riferimento di 1024mV corrispondono ad un valore numerico di 100 per cui sappiamo già che, nel caso avessimo un valore restituito dal modulo A/D compreso tra 100 e 499, ci troviamo di fronte ad una temperatura negativa, 500 corrisponde allo zero e da 501 a salire la temperatura è positiva.
Questo è tutto, prossimamente parleremo del modulo ADCC dei nuovi PICmicro ad 8bit e di un esempio di lettura dell’MCP9700 (ma potete usare anche l’LM35 dato che ha la stessa uscita di 10mV/°C facendo gli opportuni aggiustamenti dovuti allo 0°C)
Downloads