Sensore di Temperatura LM35 con LED

Cosa ho sbagliato?

#include <LiquidCrystal.h>
#define LM35_pin A1 /* Numero del pin analogico sul quale è collegato l'LM35  */
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); /*Inizializzazione della libreria con i pin del display LCD */

float vref = 1.1;      /* Vref dell'ADC (quell'interno è di 1,1V) */
/* Definisco il settaggio della temperatura */
const int caldo = 22; /* Setto il parametro Caldo */
const int freddo = 18; /* Setto il parametro Freddo */

void setup() {
  lcd.begin(16, 2);   /* Imposto di quante colonne e righe è composto il display */
  analogReference( INTERNAL );  /* per l'ADC usiamo il Vref interno da 1,1V (migliore precisione) */
  analogRead( LM35_pin );       /* Prima lettura "a vuoto" (serve per l'assestamento dell'ADC) */
pinMode(6, OUTPUT); /* PIN led BLU */
pinMode(7, OUTPUT); /* PIN led VERDE */
pinMode(8, OUTPUT); /* PIN led ROSSO */
}

void loop() {
  lcd.setCursor(0, 1); /* imposta il cursore sulla colonna 0, riga 1 */
  float temp = readTemp();  /* legge il valore della temperatura e la memorizza nella var. temp. */
  sendTempToLCD( temp );    /* invia il valore al LCD */

int sensor = analogRead(A1);
float voltage = (sensor / 1023.0) * 5.0;
float tempC = (voltage - .5) * 100;
float tempF = (tempC * 1.8) + 32;
if (tempF < freddo) { //freddo
digitalWrite(6, HIGH);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
}
else if (tempF >= caldo) { //caldo
digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(8, HIGH);
}
else { //temperatura perfetta
digitalWrite(6, LOW);
digitalWrite(7, HIGH);
digitalWrite(8, LOW);
}

}


/* Legge la temperatura */
float readTemp()
{
  float temp = 0.0;       // valore convertito in temperatura (°C)
  int val = 0;            // valore quantizzato dall'ADC [0..1023]
  int nread = 5;          // numero di letture (da 5 a 8)
  float somma = 0.0;      // somma delle letture
  for (int i = 0; i < nread; i++)
  {
    val = analogRead( LM35_pin );              // legge il dato della tensione sul pin 'LM35_pin'
    temp = ( 100.0 *  vref * val ) / 1023.0;   // lo converte in °C
    somma += temp;                             // aggiunge alla somma delle temperature lette
  }
  return ( somma / nread );                     // ne calcola il valore medio
}

/* Invia la temperatura su un LCD (modo 4bit) */
void sendTempToLCD( float temp )
{
  lcd.clear();               // Pulisce lo schermo
  lcd.setCursor( 0, 0 );     // Va in posizione di home: colonna 1, riga 1
  lcd.print( "Temperatura di: ");
  lcd.setCursor( 0, 1 );     // Va in posizione di home: colonna 1, riga 2
  lcd.print( temp );         // Stampa solo la parte intera della temp.
  lcd.print( ' ' );          // Stampa uno spazio
  lcd.print( (char) 223 );   // Stampa '°'
  lcd.print( 'C' );
  delay( 1000 );
}

Buonasera,

essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il succitato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nel rispetto del suddetto regolamento nessuno ti risponderà (eventuali risposte verrebbero cancellate), quindi ti consiglio di farla al più presto. :wink:

... e che ne sappiamo se non ci dici che problema riscontri?

Non è che noi possiamo metterci a realizzare e provare ogni codice che viene postato ... tu illustra i problemi, noi cerchiamo una possibile soluzione :wink:

Guglielmo

Hai ragione, scusami... La Temperatura data sul display non è precisa e i led dovrebbero accendersi in base alla temperatura ma resta sempre il rosso acceso

Un problema per volta ...
... relativamente alla temperatura considera che dentro gli LM35 c'è un generatore a corrente costante, usato per la misura, che li rende indipendenti dalla tensione di alimentazione, che può essere compresa tra 4 e 30 V, e anche al rumore sulla stessa se non è troppo alto.

Il problema è l'ADC del micro che richiede un riferimento di tensione preciso e noto, più gli eventuali problemi legati al rumore, su AREF e l'alimentazione del ADC, che possono causare notevoli fluttuazioni nella misura.

Purtroppo la soluzione è solo una, o usare un riferimeto di tensione molto preciso da dare su piedino AREF usando un generatore di tensione di precisione esterno, oppure ... calibrare l'insieme alimentatore/Arduino/sensore introducendo da software una correzione di +/- N gradi.

Guglielmo

Per il secondo problema, onde rendere più leggibile a tutti il codice, potresti cortesemente riprenderlo ed utilizzare la funzione di "formattazione automatica" del codice che offre l'IDE di Arduino? Dopo di che editi il tuo post e metti il codice ben indentato e più leggibile :wink:

Grazie

Guglielmo

P.S.: leggi nel REGOLAMENTO il punto 17.2 :slight_smile:

Ho notato, rileggendo attentamente il codice, che comunque usi il riferimento interno di tensione (che, pur NON essendo esattamente ad 1.1V, è comunque abbastanza stabile) ...

analogReference( INTERNAL ); /* per l'ADC usiamo il Vref interno da 1,1V (migliore precisione) */

... quindi hai il valore massimo misurabile di circa 1.1V.

Ora io vedo strani calcoli iniziali in cui tu invece fai i calcoli, mi sembra, con i 5V ...

float voltage = (sensor / 1023.0) * 5.0;

... e, se è così, sicuramente hai valori errati ... :roll_eyes:

Ah ... la divisione deve essere per 1024 ... hai 1024 valori, da 0 a 1023 :wink:

Guglielmo

Ecco qui formattato e modificato

/*
  Controllo Temperatura con Display Crystal e LM35
  by NunzioTech
*/

#include <LiquidCrystal.h>
#define LM35_pin A1 /* Numero del pin analogico sul quale è collegato l'LM35  */
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); /*Inizializzazione della libreria con i pin del display LCD */

float vref = 1.1;      /* Vref dell'ADC (quell'interno è di 1,1V) */
/* Definisco il settaggio della temperatura */
const int caldo = 22; /* Setto il parametro Caldo */
const int freddo = 19; /* Setto il parametro Freddo */

void setup() {
  lcd.begin(16, 2);   /* Imposto di quante colonne e righe è composto il display */
  analogReference( INTERNAL );  /* per l'ADC usiamo il Vref interno da 1,1V (migliore precisione) */
  analogRead( LM35_pin );       /* Prima lettura "a vuoto" (serve per l'assestamento dell'ADC) */
  Serial.begin(9600);
  pinMode(6, OUTPUT); /* PIN led BLU */
  pinMode(7, OUTPUT); /* PIN led VERDE */
  pinMode(8, OUTPUT); /* PIN led ROSSO */
}

void loop() {
  lcd.setCursor(0, 1); /* imposta il cursore sulla colonna 0, riga 1 */
  float temp = readTemp();  /* legge il valore della temperatura e la memorizza nella var. temp. */
  sendTempToLCD( temp );    /* invia il valore al LCD */

  int sensor = analogRead(A1);
  float voltage = (sensor / 1023.0) * 1.1;
  float tempC = (voltage - .5) * 100;
  float tempF = (tempC * 1.8) + 32;
  if (temp < freddo) { //freddo
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
  }
  else if (temp >= caldo) { //caldo
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH);
  }
  else { //temperatura perfetta
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, LOW);
  }
  Serial.println(temp);             //invia i dati alla seriale

}


/* Legge la temperatura */
float readTemp()
{
  float temp = 0.0;       // valore convertito in temperatura (°C)
  int val = 0;            // valore quantizzato dall'ADC [0..1023]
  int nread = 5;          // numero di letture (da 5 a 8)
  float somma = 0.0;      // somma delle letture
  for (int i = 0; i < nread; i++)
  {
    val = analogRead( LM35_pin );              // legge il dato della tensione sul pin 'LM35_pin'
    temp = ( 100.0 *  vref * val ) / 1023.0;   // lo converte in °C
    somma += temp;                             // aggiunge alla somma delle temperature lette
  }
  return ( somma / nread );                     // ne calcola il valore medio
}

/* Invia la temperatura su un LCD (modo 4bit) */
void sendTempToLCD( float temp )
{
  lcd.clear();               // Pulisce lo schermo
  lcd.setCursor( 0, 0 );     // Va in posizione di home: colonna 1, riga 1
  lcd.print( "Temperatura di: ");
  lcd.setCursor( 0, 1 );     // Va in posizione di home: colonna 1, riga 2
  lcd.print( temp );         // Stampa solo la parte intera della temp.
  lcd.print( ' ' );          // Stampa uno spazio
  lcd.print( (char) 223 );   // Stampa '°'
  lcd.print( 'C' );
  delay( 1000 );
}

Ora funziona perfettamente, devo solo verificare che la temperatura mostrata sia precisissima… Grazie mille per il tuo enorme aiuto...

.... figurati, considera che forse, una piccola calibrazione dovrai comunque farla ... come detto gli 1.1V, pure essendo abbastanza stabili, NON sempre sono esattamente 1.1V e quindi ... la misura potrebbe leggermente cambiare :wink:

Guglielmo

P.S.: ... comunque, senza fare un secondo post, sistemato il codice bastava EDITARE ( con la matitina :pencil2:) il primo post ed inserirlo corretto in quello :grin: