Come utilizzare il sensore di temperatura TMP36

La conversione di grandezze fisiche in elettriche è un aspetto che prima o poi viene affrontato quando iniziamo a realizzare piccoli esperimenti con Arduino. Oggi la sensoristica è ricca di dispositivi capaci di svolgere questa conversione (come il sensore di temperatura TMP36).

Nello specifico, per quanto riguarda la misura della temperatura abbiamo in commercio dispositivi di ogni sorta, da quelli ultrasensibili a quelli con precisioni dell’ordine del centesimo di grado, dai costi contenuti ai costi esorbitanti. A tal proposito ho in precedenza utilizzato sia il sensore di temperatura analogico MCP9700 sia il sensore digitale MCP9803.

Il segnale di conversione di questi sensori può essere sia analogico (variazione di tensione in funzione della variazione della temperatura) sia digitale (con convertitore analogico digitale ed invio dei dati su linea I2C, SPI o 1Wire).

Per i nostri esperimenti ci accontenteremmo di un sensore molto diffuso, dal costo contenuto e dal semplice utilizzo, il sensore TMP36 prodotto da Analog Device.

Il TMP36 permette di acquisire temperature comprese nell’intervallo tra -40°C e +125°C restituendo in uscita valori di tensione lineari tra circa 0.1Vdc e 1.7Vdc. Una variazione di grado produce una variazione della tensione di uscita pari a 10mV; alla temperatura di 0°C il sensore eroga una tensione di 500mV.

Il circuito che ho realizzato è molto banale, si limita a collegare il sensore direttamente ad Arduino UNO tramite la porta analogica A0:

Sensore Temperatura TMP36 con Arduino

guardando frontalmente il TMP36 troviamo sul lato sinistro il pin di alimentazione, sul pin centrale il segnale in uscita e sul pin destro il collegamento a massa.

Il primo sketch di esempio legge dalla porta analogica A0 il valore di tensione che eroga il TMP36:

void setup()
{
  //Init Seriale
  Serial.begin(9600);
}

void loop()
{
  delay(500);
  int val_ADC = analogRead(0);
  //invio il dato acquisito al pc
  Serial.println(val_ADC);
}

Il codice precedente non fa altro che convertire in forma digitale la tensione presente sul piedino A0, generata dal TMP36. Questo valore deve essere ora interpretato in modo da ottenere direttamente il valore in °C. Per far ciò abbiamo bisogno del datasheet del componente, e precisamente il grafico di conversione °C/Vdc, rappresentato anche nella figura seguente:

TMp36 Grafico conversione °C in Vdc

come possiamo osservare dal grafico (per il TMP36 la linea b evidenziata in rosso) per una tensione di uscita di 0.5Vdc il sensore rileva la temperatura di 0°C. Questo dato ci permette subito di intuire che tensioni inferiori a 0.5Vdc indicano una temperatura sotto lo zero. Inoltre sapiamo che una variazione di grado si ripercuote con una variazione di tensione di 10mV. Quindi, passando agli esempi, se sul pin A0 sono presenti 510mV significa che il sensore sta rilevando una temperatura di 1°C (510mV – 500mV = 10 mV variazione di 1°C).

Non ci resta che interpretare i dati a nostra disposizione e scrivere uno sketch che restituisca il valore in °C:

//variabili globali
int val_Adc = 0;
float temp = 0;

void setup()
{
  //init seriale
  Serial.begin(9600);
}

void loop()
{
  //leggo dalla porta A0
  val_Adc = analogRead(0);
  //converto il segnale acquisito in un valore
  //espresso in gradi centigradi
  temp = ((val_Adc * 0.00488) - 0.5) / 0.01;
  //invio il dato sulla seriale
  Serial.println(temp);
  //ritardo di mezzo secondo
  delay(500);
}

la formula che converte il valore acquisito in gradi centigradi è la seguente

°C = ((valoreADC * PrecisioneADC) – TensioneZeroGradi) / stepGradoTensione

dove

°C = valore della temperatura in gradi centigradi
valoreADC = valore della conversione analogico digitale restituito da analogRead
PrecisioneADC = questo valore è ottenuto dividendo la tensione di riferimento dell’ADC (default 5Vdc) e il numero massimo restituito dalla conversione (1024). (5Vdc /1024 = 0.00488)
TensioneZeroGradi = indica la tensione di uscita dal sensore quando rileva una temperatura di 0°C
stepGradoTensione = indica la variazione di tensione per ogni variazione di grado (0.01 = 10 mV)

Come aumentare la risoluzione nelle letture del TMP36

Eseguendo l’ultimo sketch ci accorgiamo che i valori di temperatura non sono proprio quelli che ci aspettiamo. Considerando la precisione del sensore TMP36 che si attesta a +/- 2°C per tutta la scala, otteniamo comunque dei valori che differiscono di circa 5-7°C dal valore reale. Questo ‘errore’ dipende da diversi fattori tra cui imprecisione dell’ADC, rumore del segnale e approssimazione dei valori nei calcoli.
Per limitare questi errori possiamo adottare due tecniche, la prima è quella di usare il pin AREF dell’Arduino UNO per dare al convertitore analogico digitale dell’ATmega328 un riferimento di tensione più basso (di default è 5Vdc), l’altra tecnica è quella di effettuare diverse letture ed eseguire una media dei valori letti.

Nello schema seguente viene indicato come collegare il pin AREF al pin power di 3.3Vdc:

Arduino tutorial pin AREF

Anche via software dobbiamo indicare al microcontrollore che intendiamo usare il pin AREF per le operazioni di conversione A-D. l’istruzione è la analogReference() e viene impiegata in questo modo:

//variabili globali
int val_Adc = 0;
float temp = 0;

void setup()
{
 //init seriale
 Serial.begin(9600);
 //utilizzando l'istruzione analogReference
 //indico al convertitore AD che deve impiegare
 //la tensione presente sul pin AREF come
 //valore di riferimento per la conversione
 analogReference(EXTERNAL);
}

Usando la tensione di 3.3Vdc come riferimento per la conversione analogico digitale otteniamo che il valore PrecisioneADC nella formula precedente cambia da 0.00488 a 0.0032 (3.3Vdc / 1024 = 0.0032), aumentando così la precisione della formula.
Impieghiamo anche la lettura multipla di valori per cercare di minimizzare le fluttuazioni, come descritto nel codice seguente:

int val_Adc = 0;
float temp = 0;

void setup()
{
 //init seriale
 Serial.begin(9600);
 //utilizzando l istruzione analogReference
 //indico al convertitore AD che deve impiegare
 //la tensione presente sul pin AREF come
 //valore di riferimento per la conversione
 analogReference(EXTERNAL);
}

void loop()
{
 //ritardo di mezzo secondo
 delay(500);
 //init variabile
 val_Adc = 0;
 //eseguo un ciclo
 for(byte Ciclo = 0; Ciclo < 100; Ciclo++)
 {
  //acquisisco il valore e lo sommo alla
  //variabile
  val_Adc += analogRead(0);
  //questo ritardo serve per dare il tempo
  //all ADC di eseguire correttamente
  //la prossima acquisizione
  delay(10);
 }

 //eseguo la media dei 100 valori letti
 val_Adc /= 100;
 //calcolo la temperatura in °C
 temp = ((val_Adc * 0.0032) - 0.5) / 0.01;
 //invio i dati al computer
 Serial.println(temp);
}

in questo modo otterremmo delle misure di temperatura che si avvicineranno molto al valore reale.