Dal momento che l'LM35 nel contesto in cui lavora al più potrà generare circa 0,5V (10mV/°C => 50°C) si è usata come tensione di riferimento quella interna (1.1V) del micro ATmega,per avere una risoluzione migliore.
Infatti con Vref=1,1V ed essendo l'ADC da 10bit abbiamo così 1 LSB = 1,074mV il che assicura una risoluzione di circa 0,1 °C migliore di quella propria del sensore.
Nel loop del programma, si è pensato di usare tre funzioni distinte, per tre rispettivi compiti:
- la prima, per la misura della temperatura: readTemp()
esegue 20 letture della tensione fornita dal sensore, per ciascuna ne calcola la temperatura e alla fine ne fa la media aritmetica, questo per avere una migliore stima della misura; questo valore medio costituirà il valore di ritorno della funzione stessa che viene salvato nella variabile temp. - la seconda, per inviare la temperatura alla seriale: sendTempToSerial()
prende come parametro di ingresso la temperatura acquisita mediante readTemp()
e la invia sulla seriale (USB) solo quando arriva un carattere convenzionale (ch)
dal PC - la terza, per inviare la temperatura al LCD: sendTempToLCD()
come la precedente, prende la temperatura acquisita mediante readTemp() e la
manda sul LCD collegato in locale ad Arduino. Il refresh avviene con un tempo di circa 0.5s che si è dimostrato un buon compromesso
Così, se non si è interessati a visualizzare la temperatura sul LCD o viceversa a non usare il lato PC, nel loop potra "commentare" la funzione che non interessa.
N.B. Lo sketch funziona da Arduino release 18
Da questa release,infatti, sono state apportate modifiche all'implementazione dei metodi print()/println() della classe Print, che consentono ora di specificare (nel secondo parametro di ingresso) il numero di cifre dopo la virgola ovviamente per i numeri in virgola mobile. Se si lavora su release precedenti (e non si vuole fare l'upgrade alla 18) si possono sempre copiare i nuovi file di implementazione e interfaccia: Print.cpp e Print.h della release 18 sull'installazione precedente:
http://arduino.googlecode.com/svn/trunk/hardware/arduino/cores/arduino/Print.cpp
http://arduino.googlecode.com/svn/trunk/hardware/arduino/cores/arduino/Print.h
Personalmente, ho seguito questa strada sulla mia release 17 (il path della 17 è ./hardware/cores/arduino) e tutto ha funzionato perfettamente.
Ecco lo sketch:
/*
* Sketch : LM35.PDE
* Motivazione: Misura di una temperatura ambientale (indoor) mediante sensore LM35
* Autore : Francesco Parisi ( fparisi at tiscali dot it ), (fparisi at gmail dot com)
* Ultima rev.: 1.5
* Data: : 09-Feb-2010
* Note : La scala dell'LM 35 è T = K * V,ove:
* K = 100 [°C/V] coeff.angolare della scala
* V è la tensione generata dall'LM35 (10mV/°C)
* T è la temperatura in °C
*/
/* Include la libreria per la gestione del LCD */
#include <LiquidCrystal.h>
/* Corrispondenza pin LCD <-> pin digitali di Arduino */
#define RS 12
#define EN 11
#define D7 2
#define D6 3
#define D5 4
#define D4 5
/* Numero del pin analogico sul quale è collegato l'LM35 */
#define ANALOGPIN 5
/* Definizioni globali */
double vref = 1.1; // Vref dell'ADC (quell'interno è di 1,1V)
LiquidCrystal lcd( RS, EN, D4, D5, D6, D7 ); // 'lcd' è una variabile di tipo LiquidCrystal */
/* Impostazione dell'hardware */
void setup()
{
/* Impostazioni comuni */
analogReference( INTERNAL ); // per l'ADC usiamo il Vref interno da 1,1V (migliore precisione)
analogRead( ANALOGPIN ); // Prima lettura "a vuoto" (cfr. pag. 47 datashett ATmega168)
/* Impostazione per l' LCD (2x16) */
lcd.begin( 2, 16 );
/* Impostazione per l'invio dati alla seriale */
Serial.begin( 9600 ) ; // apriamo uno stream seriale a 9600 bps
}
/* Legge la temperatura */
double readTemp()
{
double temp = 0.0; // valore convertito in temperatura (°C)
int val = 0; // valore quantizzato dall'ADC [0..1023]
int nread = 20; // numero di letture
double somma = 0.0; // somma delle letture
for (int i=0; i<nread; i++)
{
val = analogRead( ANALOGPIN ); // legge il dato della tensione sul pin 'voltagePin'
temp = ( 100.0 * vref * val ) / 1024.0; // lo converte in °C
somma += temp; // aggiunge alla sommaf delle temperature lette
delay(50); // aspetta 50ms
}
return ( somma / nread ); // restituisce la temperatura media
}
/* Invia la temperatura quando sulla seriale arriva il carattere convenuto */
void sendTempToSerial( double temp )
{
char incomingByte = 0; // Primo byte di input dallo stream seriale
char ch = 's'; // carattere convenuto
if ( Serial.available() > 0 )
{
incomingByte = Serial.read(); // Leggi il primo carattere in arrivo dal PC via seriale/USB
if ( incomingByte == ch ) // se è quello convenuto...
Serial.println( temp ); // ...manda la temperatura al PC via seriale/USB
}
}
/* Invia la temperatura su un LCD (modo 4bit) */
void sendTempToLCD( double temp )
{
lcd.clear(); // Pulisce lo schermo
lcd.noBlink(); // No lampeggio cursore
lcd.setCursor( 0, 0 ); // Posiziona cursore a colonna 1, riga 1
lcd.print( temp, 1 ); // Stampa temperatura con una cifra decimale
lcd.print(' ');
lcd.print( (char) 223 ); // Stampa '°'
lcd.print( 'C');
}
/* Esegue ripetutamente... */
void loop()
{
// acquisisci la temperatura e memorizzala nella var. temp.
double temp = readTemp();
// inviala al PC via seriale/USB, quando richiesto
sendTempToSerial( temp );
// inviala al LCD
sendTempToLCD( temp );
}
Codice evidenziato generato con Generator: GNU source-highlight 3.1
by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite
Nessun commento:
Posta un commento