Termostato e sensore di livello con Arduino

Oggi ti racconto il progetto di Stefano: Termostato e sensore di livello con arduino. Tutto ha avuto inizio quando Stefano commentando l’articolo sull’RTC mi ha chiesto una mano per il suo progetto a cui ho risposto ( leggi risposte nei commenti )

Termostato e sensore di livello con arduino e DS18B20

Oggi mi ha scritto per informarmi di aver realizzato quello a cui stava lavorando e la volontà di condividere con altri appassionati il suo lavoro.

Non ho saputo resistere e siccome questo blog è nato anche con lo scopo di diffondere tutti i progetti e le idee che riguardano le passioni che ci accomunano ho voluto dedicare a Stefano questo articolo.

Lo schema del Termostato e sensore di livello con arduino

Lo schema realizzato da Stefano è quello che hai visto in copertina e che ti ripropongo per leggerlo insieme:

Termostato e sensore di livello con arduino e DS18B20

Il Termostato e sensore di livello con Arduino si basa sui seguenti componenti:

  • n.1 arduino UNO
  • n.1 sonda temperatura DS18B20
  • n.1 sonda di livello
  • n.1 Lcd 16×2
  • n.1 relay shield
  • n. 2 pulsanti n.a.
  • n.1 potenziometro da 20Kohm
  • n.3 resistenze di pull-up da 10Kohm ciascuna
  • n.1 resistenza da 4,7Kohm

I collegamenti nello schema sono chiari:

la sonda è connessa al pin 13 di arduino mediante la resistenza da 4,7Kohm;

il display LCD 16×2 è collegato ai pin 2,3,4,10,11 e 12;

la sonda di livello è connessa al pin A3 ( Analogico 3 ) mediante una delle resistenze di pull-up da 10Kohm;

i pulsanti sono connessi al pin A1 ed A2 mediante le altre due resistenza di pull-up da 10Kohm.

Lo sketch del Termostato e sensore di livello con Arduino

Lo sketch lo puoi prelevare direttamente dal sito di Stefano, lo riporto per completezza dell’articolo:

/*
Termostatino antigelo:
Lettura sensore termico ds18b20, visualizzazione su display 16x2,
modifica soglia con 2 pulsanti + e - su ingressi analogici,
visualizzazione soglia durante la modifica,
Sensore di livello ad immersione tramite ingresso analogico e
comando relais.
Pin Analogico 1 = pulsante incremento temperatura soglia
Pin Analogico 2 = pulsante riduzione temperatura soglia
Pin Analogico 3 = sonda di livello
Pin Digitali 2, 3, 4, 10, 11, 12 = lcd DB7, DB6, DB5, DB4, E, RS
Pin digitali 5, 6, 7, 8 = modulo relais
Pin Digital 13 = linea dati sensore DS18B20
Piedinatura DS18B20: pin 1 = GND, pin 2 = DQ, pin 3 = Vdd (Valida tra 3,3V e 5V)
*/

#include <OneWire.h>         //libreria per ds18b20
#include <DallasTemperature.h>      //libreria per conversione valore
#include <swRTC.h>                      //libreria per RTC
#include <LiquidCrystal.h>              //libreria per lcd
#define ONE_WIRE_BUS 13                   // Il terminale data del sensore è connesso alla porta 13 di Arduino

OneWire oneWire(ONE_WIRE_BUS);           // Imposto la comunicazione oneWire per il ds18b20
DallasTemperature sensors(&oneWire);   // Passo le info di oneWire alla DallasTemperature
LiquidCrystal lcd(12, 11, 10, 4, 3, 2); //stabilisco le uscite digitali per lcd 4 bit
swRTC rtc;                              //creo un'istanza della libreria RTC

  int rele_out1 = 5;     //stabilisco l'uscita digitale per il relè 1
  int rele_out2 = 6;     //stabilisco l'uscita digitale per il relè 2
  int rele_out3 = 7;     //stabilisco l'uscita digitale per il relè 3
  int rele_out4 = 8;     //stabilisco l'uscita digitale per il relè 4
  int pulsantepiu;       //pulsante incremento temperatura di soglia
  int pulsantemeno;      //pulsante diminuisco temperatura di soglia
  int tx;                //temperatura di soglia
  int cont;              //contatore usato per ottenere un valore medio di temperatura
  int temperatura;       //temperatura rilevata
  int durata;            //conteggio minuti per temporizzazione
  int livello;       //ingresso sonda livello 170 cm

  byte grado[8] = {      //creo i dati per il carattere °
  0b00010,
  0b00101,
  0b00010,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
};

void setup(){

  Serial.begin(9600);           //inizializzo la seriale
  sensors.begin();      //inizializzo la libreria per leggere il sensore
  lcd.createChar(0, grado);     //associo i dati del ° al carattere custom 0
  lcd.begin(16, 2);             //dichiaro il tipo di lcd
  pinMode(rele_out1, OUTPUT);   //assegno il modo uscita digitale al pin 5
  pinMode(rele_out2, OUTPUT);   //assegno il modo uscita digitale al pin 6
  pinMode(rele_out3, OUTPUT);   //assegno il modo uscita digitale al pin 7
  pinMode(rele_out4, OUTPUT);   //assegno il modo uscita digitale al pin 8

  tx = 1;                       //temperatura di soglia iniziale (valore di sicurezza in caso di interruzioni di alimentazione)
  pulsantepiu = 0;              //assegno valore 0 iniziale al pulsantepiù
  pulsantemeno = 0;             //assegno valore 0 iniziale al pulsantemeno
  livello = 0;         //assegno valore 0 iniziale alla sonda di livello

  rtc.stopRTC();                //blocco RTC per inserire i valori iniziali
  rtc.setTime(0, 00, 00);       //metto valori a zero perché
  rtc.setDate(01, 01, 2012);    //devo usare RTC solo come timer
  rtc.startRTC();               //avvio RTC

}

void loop() {

   sensors.requestTemperatures();    // Invia il comando di lettura delle temperatura
   int durata = rtc.getMinutes();    //acquisisco i minuti 

   if (durata > 10){                       //se durata è maggiore di 10 minuti
      rtc.stopRTC();                  //blocco RTC
      rtc.setTime(0, 00, 00);         //azzero i valori
      rtc.setDate(01, 01, 2012);      //per poter riconteggiare da zero
      rtc.startRTC();                 //riavvio rtc
   }

   int pulsantepiu = analogRead(A1);    //lettura ingresso analogico 1 e assegnazione del valore a pulsantepiù
   int pulsantemeno = analogRead(A2);   //lettura ingresso analogico 2 e assegnazione del valore a pulsantemeno

   if (pulsantepiu == 0){                        //se il pulsantepiù vieno premuto verso il negativo
      tx = tx ++;                           //la variabile temperatura di soglia tx incrementa di una unita
      lcd.clear();               //cancello il display
      lcd.print("Temperatura di");         //scrivo un testo
      lcd.setCursor(0, 1);                 //riposiziono il cursore
      lcd.print("soglia: ");            //scrivo di nuovo un testo
      lcd.print(tx,DEC);            //scrivo il valore impostato della temperatura di soglia
      lcd.write((byte)0);            //scrivo il °
      lcd.print ("C");                      //scrivo il C di Celsius
      delay(1000);                          //ritardo di 1 secondi per la lettura
   }

   if (pulsantemeno == 0){                       //se il pulsantemeno vieno premuto verso il negativo
      tx = tx --;                           //la variabile temperatura di soglia tx decrementa di una unità
      lcd.clear();               //cancello il display
      lcd.print("Temperatura di");         //scrivo un testo
      lcd.setCursor(0, 1);                 //riposiziono il cursore
      lcd.print("soglia: ");            //scrivo di nuovo un testo
      lcd.setCursor(10, 1);            //riposiziono il cursore
      lcd.print(tx,DEC);            //scrivo il valore impostato della temperatura di soglia
      lcd.write((byte)0);            //scrivo il °
      lcd.print ("C");                      //scrivo il C di Celsius
      delay(1000);                          //ritardo di 1 secondi per la lettura
   }

    while (analogRead(A3) == 0) {         //lettura ingresso analogico A3 e confronto con valore 0 (CONTATTO CHIUSO)
      lcd.clear();            //con il livello troppo alto avviso su display
      lcd.print ("! Livello Alto !");      //che il livello  è alto e
      lcd.print(" Valvola Aperta ");      //che apro la valvola
      digitalWrite(rele_out1, HIGH);      //comando anche il rele 1 di apertura valvola
      digitalWrite(rele_out2, HIGH);      //comando anche il rele 2 di apertura valvola
      digitalWrite(rele_out3, HIGH);      //comando anche il rele 3 di apertura valvola
      digitalWrite(rele_out4, HIGH);      //comando anche il rele 4 di apertura valvola
   }

/*Lettura temperatura con ds18b20 */
    int temperatura = sensors.getTempCByIndex(0);   //lettura ingresso digitale 13 e assegnazione del valore alla variabile temperatura

   if(temperatura <= tx && durata == 10){           //se la temperatura rilevata è minore o uguale rispetto
      lcd.clear();            //alla temperatura di soglia e il tempo
      lcd.print("Temperatura ");      //trascorso dall'ultimo ciclo è di 10 minutì
      lcd.print(temperatura,DEC);             //scrivo sul display il valore e
      lcd.write((byte)0);                     //avviso che il contatto è chiuso
      lcd.print("C");
      lcd.setCursor(0, 1);                    //con la scritta " Valvola Aperta "
      lcd.print(" Valvola Aperta ");          //per finire
      digitalWrite(rele_out1, HIGH);           //comando anche il rele 1 di apertura valvola
                digitalWrite(rele_out2, HIGH);           //comando anche il rele 2 di apertura valvola
      digitalWrite(rele_out3, HIGH);      //comando anche il rele 3 di apertura valvola
                digitalWrite(rele_out4, HIGH);          //comando anche il rele 4 di apertura valvola
      delay(60000);                           // e comando i relè per un minuto
   }else{                  //altrimenti scrivo
      lcd.clear();            //sempre sul display
      lcd.print("  Temperatura");      //il valore
      lcd.setCursor(0, 1);
      lcd.print("rilevata:  ");
      lcd.print(temperatura,DEC);
      lcd.write((byte)0);
      lcd.print("C");
      digitalWrite(rele_out1, LOW);      //mantengo bassa l'uscita digitale 5
      digitalWrite(rele_out2, LOW);      //mantengo bassa l'uscita digitale 6
      digitalWrite(rele_out3, LOW);      //mantengo bassa l'uscita digitale 7
      digitalWrite(rele_out4, LOW);      //mantengo bassa l'uscita digitale 8

        }
/*invio le inforamazioni anche al serial monitor della IDE*/

        Serial.print ("temperatura di soglia = ");
   Serial.println (tx, DEC);
        Serial.println (" ");
        Serial.print ("Temperatura rilevata = ");
        Serial.println (temperatura, DEC);
        Serial.println (" ");
        Serial.println (" ");
   Serial.println("durata");
   Serial.println(durata,DEC);
   Serial.println(rtc.getSeconds(),DEC);
        Serial.println (" ");
        Serial.println (" ");
}

Grazie Stefano !!!

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/termostato-e-sensore-di-livello-con-arduino.html

33 commenti

Vai al modulo dei commenti

    • Stefano Sforzi il 11 Gennaio 2013 alle 15:54
    • Rispondi

    Ciao Mauro
    Intanto grazie per l’articolo e se qualcuno ha idee o suggerimenti io sono sempre disponibile, non si finisce mai di imparare!

    • maurizio il 13 Gennaio 2013 alle 09:44
    • Rispondi

    Ciao Stefano
    Un articolo interessante , davvero molto curato in tutti gli aspetti,sopratutto nei commenti.
    Complimenti Stefano

    Un ringraziamento anche a Mauro , per lo spazio dedicato a questo articolo

    • idris.cesa il 6 Febbraio 2013 alle 07:52
    • Rispondi

    Caricando il programma su arduino mi da questo errore: ‘ swRTC ‘does not name a type.

    Potresti mandarmi la libreria swRTC.h per cortesia ? Non riesco a trovarla .

    Grazie

    1. Ciao Idris, non ho quelle libreria, il progetto lo ha realizzato Stefano e la libreria é una sua variante alla libreria originale RTCLib.

      Prova a sostituirlo con quella originale che trovi ovunque nel web, e a fare le modifiche necessarie allo sketch, trovi molti miei tutorial sull’RTC nel blog.

      Se non ci riesci puoi provare a scrivere a Stefano sul suo forum, trovi il link nella prima linea dell’articolo.

      Mauro

    • Stefano Sforzi il 7 Febbraio 2013 alle 19:21
    • Rispondi

    Ciao Idris, la libreria puoi trovarla direttamente su arduino.cc ma per semplicità ti posto il link alla discussione sul forum in italiano, dove trovi anche il link per il download:

    http://arduino.cc/forum/index.php/topic,73496.msg552421.html#msg552421

    1. Grazie Stefano per il supporto 🙂

      Mauro

        • Stefano Sforzi il 9 Febbraio 2013 alle 14:28
        • Rispondi

        Mi sembra il minimo che posso fare!

    • mrkrunkle il 18 Febbraio 2013 alle 12:18
    • Rispondi

    Ciao a tutti,
    avevo intenzione di realizzare anch’io un strumento per misurare la temperatura con arduino, ma utilizzando un sensore a immersione ad esempio:
    https://www.adafruit.com/products/381
    In piú mi piacerebbe riuscire a calcolare anche il grado alcolico, ad esempio del vino.
    Pensavo di acquistare arduino 2. Del punto uno sembra non ci siano problemi, ma del secondo non saprei da dove iniziare.
    Se avete qualche consiglio vi sarei gradissimo 🙂
    Grazie
    mrkrunkle

      • Stefano Sforzi il 21 Febbraio 2013 alle 19:38
      • Rispondi

      Ciao, il sensore termico che ho utilizzato io è proprio come quello del link che hai segnalato sopra.
      Secondo me la scelta di quale arduino utilizzare è soggettiva, dipende molto da cosa ci devi fare e di che hardware hai bisogno. Per il sensore alcoolico, da quello che so io ci sono dei sensori, ma rilevano dei gas, non so se possono andare bene per il tuo progetto.

    • Giovanni il 3 Ottobre 2013 alle 09:08
    • Rispondi

    Confesso di essere alle prime armi però mi sembra che nel setup manca la dichiarazione degli ingressi, può essere?
    Il progetto è stato utilissimo. Per me è stata una fortuna trovare una soluzione con il sensore di temperatura. Il problema della PT100 infatti mi tormentava da un po’

    1. Ciao Giovanni,
      sei di certo un attento osservatore, tuttavia per la struttura dello sketch non devi dichiararli nella setup.
      Se avessi dichiarato in alto i pin di input A0,A1 ed A2 sarebbe stato più corretto dichiarare questi pin come pin di INPUT.

      In questo caso il codice arduino è buono e quando utilizzi il comando analogRead provvede a leggere l’ingresso anche senza dichiarazione di modalità.

      Mauro

    • luca il 30 Ottobre 2013 alle 14:34
    • Rispondi

    Salve, sono alle prime armi con arduino, mi piace smanettare, mi interessa il tuo progetto “Termostato e sensore di livello con Arduino “, ma purtroppo sono ancora all’antica , vorrei usare la vecchia sonda lm35, puoi darmi una dritta per modificare il tuo sketch per sudetta sonda, e c’è il problema della temperatura negativa.

    In attesa di una risposta grazie.

    1. Ciao Luca,
      ho acquistato tempo fa la sonda LM35 per fare anche io dei test, tuttavia non l’ho ancora provata.
      Se non ricordo male è una sonda analogica ossia varia il potenziale sul piedino di output in funzione della temperatura rilevata.

      In tal caso ti basta un semplice sketch in grado di leggere il valore analogico sul pin a cui hai collegato la sonda.

      Mauro

    • Giovanni il 30 Ottobre 2013 alle 17:01
    • Rispondi

    Ciao Mauro sono ancora Giovanni, avrei un’altra cosa importante da chiederti.
    Ho notato che la variabile “temperatura” è stata dichiarata come INT.
    Significa che la libreria restituisce solo valori interi?
    Come posso fare se mi servisse un punto decimale?

    Sono quasi pronto per iniziare, la sonda dovrebbe arrivarmi la settimana prossima, un saluto e un grazie anticipato 🙂

    1. Ciao Giovanni,
      questo progetto è stato realizzato da un appassionato lettore del blog che ha voluto condividerlo.
      Io non ho mai testato la sonda utilizzata in questo sketch anche se ho acquistato una sonda con l’intenzione di provarla.

      In ogni caso per aiutarti ho aperto il file DallasTemperature.cpp ed ho trovato la dichiarazione del metodo usato per recuperare la temperatura dalla sonda:

      float DallasTemperature::getTempCByIndex(uint8_t deviceIndex)

      Siccome è dichiarato float deduco che il valore restituito sua un valore decimale.

      Mauro

    • Michele il 22 Gennaio 2014 alle 15:37
    • Rispondi

    Ciao
    Sto cercando di impostare le soglie ma non capisco perchè non riesco a farla decrescere…

    Inoltre mi lampeggianop da una all’altra, mi potresti dare qualche indicazione?
    Grazie

    1. Ciao Michele,
      come leggi in fondo ad ogni articolo è richiesto di non incollare codice degli sketch.
      In particolare per questo progetto lascio che sia l’autore a darti aiuto.

      Mauro

    • Alessandro il 27 Febbraio 2014 alle 19:34
    • Rispondi

    Salve anche io sto cercando di costruire un cronotermoststo per il mio acquario,con un lcd keypad,sensore ds18b20,scheda 8 relè,rtc e arduino mega.
    Io volevo impostare una temperatura in modo che se la temperatura si abbassa mi si accende il riscaldatore,e se si alza mi si accendono le 4 ventole da pc a 12 volt.
    Potete darmi dei consigli?

    1. Ciao Alessandro,
      il progetto che vuoi realizzare non è complesso.
      Ti consiglio di procedere con passi semplici:
      – verifichi la lettura del sensore
      – verifichi di riuscire ad attivare i relè singolarmente
      – controlli la scrittura sul display

      dopo ti sarà più semplice scrivere lo sketch totale.

      Mauro

    • Giovanni il 13 Maggio 2014 alle 19:25
    • Rispondi

    Ciao Mauro,
    compilando il sorgente messo a disposizione ottengo dal compilatore “Errore durante la compilazione”,
    utilizzo l’ultimo IDE Versione 1.0.5-r2
    Puoi darmi qualche consiglio?

    1. Ciao Giovanni,
      senza l’errore è impossibile aiutarti.
      Ho scritto anche un articolo dedicati agli errori che solitamente capitano in fase di compilazione, prova a leggerlo e verificare se tra quelli c’è un errore simile a quello che ti si verifica.

    • Luciano il 20 Giugno 2015 alle 12:46
    • Rispondi

    Bellissimo programma …
    Io volevo sapere se è possibilire regolare tarare il sensore di livello dei liquidi con Arduino .. dato che ho costruito una mini centrale idroelettrica con ripompaggio.. l’unico problema è che il sensore di livello mi fa sfasare l’lcd e il relè che attiva la pompa

    1. Ciao Luciano,
      dipende dal sensore che stai utilizzando, se lo conosco posso aiutarti in caso contrario dovrai chiedere a chi ha utilizzato il modello simile al tuo od al produttore.

    • Gianni il 5 Novembre 2015 alle 20:17
    • Rispondi

    Salve Mauro e Stefano.
    Ho un problema con il codice: premendo i pulsanti non si modifica il valore di tx.
    Ho controllato il corretto collegamento dei pulsanti, con un efficace
    int sensorValue1 = analogRead(A0);
    int sensorValue2 = analogRead(A1);
    Serial.println(sensorValue1);
    Serial.println(sensorValue2);
    che mi danno normalmente il valore di 1021, che diventa 0 con pulsante premuto.
    Tx però rimane sempre quella preimpostata.

    Avete suggerimenti? grazie

      • Gianni il 5 Novembre 2015 alle 21:53
      • Rispondi

      Ho risolto sostituendo il
      tx = tx ++;

      Con invece
      {tx++;}

      1. Ottimo Gianni !!!

          • Gianni il 6 Novembre 2015 alle 22:46
          • Rispondi

          per quale motivo il compilatore preferisce una modalità di scrittura piuttosto che un’altra?
          non dovrebbero essere equivalenti?

          1. Ciao Gianni,
            ti riferisci alla differenza tra scrivere

            tx = tx ++;

            oppure

            tx++;

            Non ne sono certo al 100% ma la prima penso sia sbagliata, lo spazio tra tx e il segno ++ non è accettato come modo per incrementare una variabile.
            Francemente io ho imparato a scrivere tx++; e non saprei dirti cosa accade se distanzi i segni dalla variabile.

            • Gianni il 8 Novembre 2015 alle 19:12

            No, mi riferisco alla differenza tra

            tx = tx++;

            oppure

            {tx++;}

          2. Ciao Gianni,
            a parte le {}, che io non uso, mi sembra che la differenza sia quella che ti ho indicato nella risposta precedente.
            Non essendo un programmatore C lascio a chi è più competente di me chiarirti perché una opzione sia migliore o peggiore dell’altra.

    1. Ciao Gianni,
      lascio a Stefano, autore del progetto, la risposta alla tua osservazione.

    • rosario il 15 Giugno 2021 alle 10:18
    • Rispondi

    Ciao e grazie del progetto. COMPLIMENTI
    Vorrei chiederti …come potrei adattare questo progetto ad un sistema di riempimento di una vasca di acquario, governato da un galleggiante e l’acqua prelevata da una cisterna in cui pesca una pompa uso acquario?

    1. Ciao Rosario,
      questo progetto è molto differente da quello che desidera realizzare.
      Ti consiglierei di iniziare da un progetto più semplice che usi uno o due sensori di livello ed una pompa per il trasferimento dell’acqua dalla cisterna all’acquario.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.