Dic 012015
 

Oggi vediamo un articolo semplice semplice, ossia vedremo come utilizzare un sensore LM35 per misurare la temperatura ambiente. Qualche giorno fa cercando di riordinare i miei scatoloni con il materiale elettronico ho trovato una bustina con due sensori LM35, comprati molto tempo fa e mai usati. Ho pensato di scriverci un breve articolo così, dopo aver provato i DS18B20 e i DHT11 oggi completiamo con questo sensore in questo modo abbiamo visto ben 3 modi diversi di misurare la temperatura con Arduino. Le caratteristiche principali di questo sensore sono la calibrazione direttamente in gradi Celsius, la precisione da ¼° (a 25°) a ¾° (agli estremi di scala), il range da -55 a 150 e la risposta lineare di 10mV/C. Fate attenzione che ci sono diverse versioni (LM35 A,C,D) con diversi gradi di accuratezza e range di temperatura, come indicato nella figura sottostante. L’alimentazione deve essere fra i 5 e 30V, l’interfaccia è di tipo analogico e l’assorbimento massimo di 60μA. Tradurre tutto questo in aspetti pratici con il nostro Arduino è piuttosto semplice.

lm35-temp

 

Il sensorelm35

Il sensore ha l’aspetto di un classico transistor (package TO-92), esteriormente è sovrapponibile ad un DS18B20 e come quest’ultimo presenta 3 soli pin: VCC, uscita analogica e GND. Con Arduino UNO non dobbiamo far altro che alimentare il sensore con la linea a 5V, collegare la terra ed il pin analogico in uno degli ingressi analogici di Arduino. Già perché questo sensore a differenza del DS18B20 e il DHT11 non è digitale per cui non bisogna instaurare nessun tipo di comunicazione digitale. E’ sufficiente leggere l’uscita analogica per ricavare la temperatura. Semplice no? Talmente semplice da chiederci perché esistano sensori più complessi come quelli visti in precedenza. Capirlo in realtà è facile, basta che analizziamo il funzionamento del sensore. Esso ci restituisce un valore analogico che varia di 10mV per ogni grado Celsius per cui leggendo il voltaggio possiamo ricavare la temperatura. Se però usiamo un cavo di collegamento molto lungo, questo fornisce una resistenza al passaggio della corrente per cui la tensione letta da Arduino in parte è alterata dalla resistenza del cavo il che determina un errore di lettura. Certo possiamo pensare a una routine di calibrazione ma le cose si fanno più complesse per cui se l’esigenza è quella di porre un sensore molto lontano da Arduino la scelta dovrebbe ricadere su un sensore digitale. Un altro limite è dato dal fatto che per ogni sensore dobbiamo occupare un nuovo ingresso analogico, è impensabile usare questi sensori ad esempio per monitorare 20 valori di temperatura in contemporanea, cosa agilmente fattibile con i DS18B20. Inoltre come vedremo ci sono piccoli grandi problemi che riducono la precisione di lettura del sensore, tutti fattori che vengono eliminati alla fonte con i sensori digitali.

Collegamenti e calcoliUNO_LM35

Il collegamento con Arduino UNO lo potete vedere nella figura qui accanto, ma come dicevamo è estremamente semplice. E’ sufficiente collegare VCC, GND ai rispettivi pin di Arduino e l’uscita ad uno degli ingressi analogici, io ho scelto lo zero solo perché era il più vicino. Diciamo subito che anche se troverete questo tipo di configurazione nel 90% dei tutorial “copia e incolla” che trovate in rete, in questo modo non sarete in grado di sfruttare appieno le capacità di questo sensore. Intanto l’accuratezza scende a mezzo grado a temperatura ambiente e un grado agli estremi, inoltre lo stesso range di temperatura misurabili cambia, infatti sarete in grado di misurare temperature da 2 a 150 gradi. Vediamo di fare due calcoli:

Arduino UNO permette di campionare segnali analogici a 10 bit, ossia 1024  possibili valori. Se l’ingresso va da 0 a 5V significa che abbiamo 5/1023=0.0048875 ossia Arduino UNO riesce a misurare tensioni a passi di circa 5mV (4.88). Dato che l’LM35 fornisce una variazione di 10mV/C diventa evidente che Arduino avrà una precisione di lettura di circa mezzo grado (5/10=0.5), indipendentemente da quella che è la reale precisione del sensore. Se il sensore fornisce 10mV a grado e la temperatura massima è di 150°C significa che il sensore produrrà in uscita una tensione da 0 a 1.5V. Dalla proporzione 1.5:x=5:1024 otteniamo circa 307 il che significa che il nostro Arduino andrà a leggere valori compresi fra 0 e 307 per cui i restanti 716, per raggiungere i 1024, saranno del tutto inutilizzati cosa che riduce ovviamente la precisione della misura.

Ora vediamo come convertire la lettura in temperatura. Facciamo finta che Arduino in un determinato momento legge un segnale analogico pari a 43. Sappiamo che ogni unità letta corrisponde a 4.88mV per cui 43×4.88 fanno 210mV. Se il sensore fornisce 10mV/C otteniamo 21 gradi (210/10), di fatto è sufficiente moltiplicare il valore della lettura per 0.48875. Partendo da questo presupposto lo sketch necessario a leggere la temperatura è quasi banale:

#define potPin  A0
void setup()
{
  Serial.begin(9600);
}

void loop ()                             
{
  int aRead = 0;
  aRead = analogRead(potPin);

  Serial.print("Analog = ");
  Serial.print(aRead);
 
  float tempC = aRead * 0.48875;
 
  Serial.print("     Temp = ");
  Serial.println(tempC);
  delay(1000);
}

Come vedete il listato non fa altro che leggere l’ingresso analogico e stamparne il valore sulla porta seriale, sia come dato grezzo che come conversione in lm35-basictemperatura, operazioni che ripete ogni secondo. Quanto visto sinora corrisponde al tipo di connessione mostrato qui a fianco e ripreso direttamente dal datasheet. Si legge che la precisione è di 0.5 gradi a temperatura ambiente e 1° agli estremi oltre al fatto che il range di funzionamento è da 2 a 150 gradi. Purtroppo i miei LM35 sono della serie D per cui possono utilizzare solamente questo tipo di schema e misurare unicamente temperatura positive. Per questo motivo non mi è possibile testare  ulteriori configurazioni, in particolare per la misura delle temperature negative. Volevo comunque sottolineare che con questo tipo di configurazione indipendentemente dal sensore in vostro possesso non riuscirete mai a misurare temperature al di sotto dello zero per cui nel caso di termometri esterni, celle frigorifere o quant’altro questo sistema così come ve l’ho presentato non funzionerà. Una piccola nota sulle board che funzionano a 3.3V come la DUE ad esempio. In questo caso, essendo la tensione in ingresso non superiore a 1.5V e quindi rientrante nei 3.3V, è possibile usare questo sistema andando solo a modificare la costante 0.48875 in 0.32258.

AREF

Visto che il tipo di sensore in mio possesso non mi permette ulteriori esperimenti, ho pensato di illustrarvi alcuni spunti sulla misurazione dei segnali analogici. Sinora vi ho sempre raccontato che Arduino UNO può leggere segnali analogici compresi fra 0 e 5V. Beh, non è del tutto vero, legge segnali analogici fra 0 e una soglia di riferimento. Questa soglia di base è impostata a 5V, ma la cosa interessante è che è modificabile. Per farlo si utilizza la funzione analogReference e, se non altrimenti specificato, è sottintesa la funzione analogReference(DEFAULT) all’avvio di Arduino, infatti questa funzione pone il riferimento a 5V, cosa che avviene non tanto all’accensione di Arduino, quanto alla prima lettura su un pin analogico o digitale. Attenzione che se intendete usare questa funzione, essa deve essere usata PRIMA della analogRead(). Con Arduino UNO (schede diverse hanno parametri diversi!) possono essere passati altri due valori a questa funzione, il primo è INTERNAL. Usando la funzione analogReference(INTERNAL) il riferimento viene impostato a 1.1V perciò da quel punto Arduino dividerà in 1024 parti gli 1.1V ottenendo una risoluzione di 0,00107421875V, ossia 1,07mV, notevolmente meglio dei quasi 5mV che otteniamo di base. Attenzione però che una volta impostata questa funzionalità dovrà essere assolutamente evitato di portare sugli ingressi analogici un voltaggio superiore a 1.1V pena la possibilità di danneggiare irreparabilmente Arduino. Nell’articolo odierno avremmo potuto usare anche questo trucco, infatti gli 1.1V corrisponderebbero a 110°C per cui se non vi fosse la necessità di leggere temperature superiori si sarebbe potuto ottenere un miglioramento della precisione di lettura. Ovviamente il listato necessita di alcune piccole modifiche:

void setup()
{
  Serial.begin(9600);
  analogReference(INTERNAL); 
}

void loop ()                             
{
  int aRead = 0;
  float ref=1.1;
  aRead = analogRead(A0);
  Serial.print("Analog = ");
  Serial.print(aRead);
  float tempC = aRead * ref/1023*100;
  float volt = aRead*ref/1023;
  Serial.print(" V = ");
  Serial.print(volt);
  Serial.print(" - Temp = ");
  Serial.println(tempC);
  delay(1000);
}

Questo trucchetto può essere usato tutte le volte in cui abbiamo la certezza di non superare gli 1.1V in ingresso al fine di migliorare la risoluzione della misura, il tutto MMA_partitore_LM35senza nessuna modifica hardware ma solamente software. C’è una seconda opzione, analogReference(EXTERNAL) che permette di settare un voltaggio di riferimento esterno attraverso il pin AREF. Molti ora penseranno: bene, se voglio porre un riferimento di 2.5V non devo far altro che prendere la tensione 5V, dividerla in due con un partitore di tensione e collegare la 2.5V ad AREF. Magari!! In realtà collegato al pin AREF c’è un resistore da 32KΩ per cui per settare la giusta soglia dobbiamo utilizzare un resistore esterno che vada a formare un partitore di tensione assieme a quello interno. Qui vicino potete vedere un esempio di calcolo fatto con la mia App per Android in cui potete osservare come R2 è settato a 32K. Per fare i test ho utilizzato un resistore esterno da 10K, solo perché è il primo che ho trovato, e come potete osservare dalla figura otteniamo una tensione di 3.81V che sarà la nostra tensione di riferimento. Avremmo potuto usare questo sistema per migliorare la precisione della misura anche negli articoli sul monitoraggio del consumo energetico, infatti, se ricordate, in quel caso avevamo una tensione massima di 3.5V.

Una cosa molto importante da sapere è che il resistore da 32K viene “attivato” solamente al momento in cui utilizziamo la funzione analogReference(EXTERNAL), in caso contrario alla prima lettura di un valore analogico o digitale, di default verrà “creato” un collegamento diretto a massa, ciò significa che se applichiamo un carico al pin AREF non ci sarà nulla a limitare la corrente con conseguente frittura dell’ATMega di Arduino. Per questo motivo se volete usare il pin AREF per settare una tensione di riferimento, è obbligatorio usare un resistore che limiti la corrente e il cui valore sia settato correttamente per ottenere il voltaggio voluto attraverso il partitore di tensione che si viene a formare. Potreste pensare “beh, sto molto attento, scrivo bene il codice affinché venga impostata analogReference(EXTERNAL) per avere la protezione del resistore interno, discorso corretto, ma basta una piccola svista sul versante software per fare un piccolo disastro per cui non posso che invitarvi caldamente ad inserire sempre un resistore sul pin AREF nel caso vogliate utilizzarlo per impostare una precisa tensione di riferimento. Se volete usare un partitore esterno anziché il singolo resistore, potete usare la mia app impostando a 32K il valore di RL andando poi a settare i valori R1 ed R2 del partitore; in questo caso il voltaggio ottenuto sarà dato da V2L. Potete anche partire dal voltaggio e far calcolare alla mia App il valore di R1. Una domanda cruciale è quale sia il valore minimo del resistore esterno.  Non ho trovato un dato certo nel datasheet dell’ATMega328p, forse anche perché sono 650 pagine e potrebbe essermi sfuggito,  ma pare, da tutta la documentazione che ho letto, che il valore minimo del resistore sia di 5K il che permette di ottenere una tensione di 4.32V. Aumentando la resistenza del resistore si riduce il valore di tensione per cui possiamo dire che tramite l’utilizzo del pin AREF posso modificare la tensione di riferimento da 4.32 a 1.1V.

Considerazioni finali

Abbiamo visto che tutto sommato è abbastanza semplice collegare questo sensore ad Arduino, ma ci sono tutta una serie di piccole imprecisioni ed insidie dietro l’angolo. Diciamo che se dovete usare un singolo sensore, vicino ad Arduino,  misurare temperature non inferiori a 2 gradi e vi accontentate di un piccolo margine d’errore, allora questo sensore può fare al caso vostro. In caso contrario è preferibile l’uso di un sensore digitale, è vero che questo è estremamente più difficile da pilotare, ma ci sono le librerie già pronte all’uso per cui la differenza per che non è un esperto è davvero minima. Un altro caso che mi viene in mente poter far pendere la bilancia verso il sensore analogico, è quello in cui abbiamo uno sketch particolarmente complesso che non ci lascia spazio per le librerie che controllano i sensori digitali, in tal caso una semplice lettura analogica può fare al caso nostro. Per finire ho fatto un piccolo test comparativo fra l’LM35 ed il DS18B20. Ho lasciato “acclimatare” i sensori per una quindicina di minuti e poi ho guardato i valori letti: il DS18B20 mi segna 19.0°C mentre l’LM35 19.8 circa, con una differenza perciò di circa 8 decimi di grado. Paradossalmente se invece di usare il riferimento di 1.1V uso i 5V ottengo 19.55, con una misura persino più stabile nel tempo e una differenza dal DS18B20 di circa 4.5 decimi (anche se lo scatto successivo è stato a 20.04 quando il DS18B20 era a 19.2 con uno scarto di 8 decimi). Ovviamente senza uno strumento di misura di precisione non ho la possibilità di dire dove stia la verità, ma il mio personale parere è che questi LM35 non siano poi così precisi.