Go Down

Topic: termostato semplice... per iniziare (Read 2712 times) previous topic - next topic

marinaio67

Salve a tutti... per cominciare a capire qualcosa di arduino vorrei realizzare un termostato... ho preso una DS18B20 e un display LCD e li ho collegati ad arduino seguendo alcuni schemi che ho trovato , infine ho collegato un led che simula l'attivazione del carico... poi ho trovato alcuni sketch e ne ho tratto uno semplice che fa la lettura della temperatura , me la invia al display e alla temparatura di 20° mi accende il led... tutto ok fin qui , adesso vorrei aggiungere due pulsanti che mi facciano variare la temperatura di accenzione del led... e qui comincio ad avere un pò di difficoltà... vi metto lo sketch che ho fatto , spero che qualcuno riesca ad indirizzarmi... ciao e grazie
Code: [Select]
/*
prova.ino
Misurazione della temperatura
invio a display LCD e accenzione led a 20° C

*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>


int LED=7;                 //Pin7 = LED

// linea dati DS18B20 al pin 10 di Arduino
#define ONE_WIRE_BUS 10

// Imposta la comunicazione oneWire per comunicare
// con un dispositivo compatibile
OneWire oneWire(ONE_WIRE_BUS);

// Passaggio oneWire reference alla Dallas Temperature.
DallasTemperature sensors(&oneWire);

// RS RW EN D4 D5 D6 D7
LiquidCrystal lcd(12, 11, 6, 5, 4, 3, 2);



void setup()

{
  // Start up the library
  sensors.begin();
  // Imposta il valore di righe e colonne del display LCD
  lcd.begin(16, 2);
lcd.clear();
 
 
 
 
  pinMode(LED, OUTPUT);   //LED set to output
   
 
}



void loop(void)
{

 
 
if (sensors.getTempCByIndex(0) >= 20)                        //temperatura maggiore o uguale a 20 led acceso
  {
    digitalWrite (LED, HIGH);         //led acceso
  }
  else if (sensors.getTempCByIndex(0) <= 20)                //temperatura minore o uguale a 20 led spento
  {
    digitalWrite (LED, LOW);      //led spento
   
}

sensors.requestTemperatures(); // Invia il comando di lettura delle temperatura
  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  Temperatura");
  lcd.setCursor(4, 1);
  lcd.print (sensors.getTempCByIndex(0));
  lcd.print (" C");
}

PaoloP

Al posto del valore 20, metti una variabile che chiamerai, ad esempio, soglia.
Aggiungi il codice necessario in modo che la variabile soglia premendo un pulsante incrementi mentre premendo il secondo decrementi.

marinaio67

Qualche chiarimento... Posso dare un valore a questa soglia (ad esempio 20 gradi) in modo che se va via la corrente ritorni l'impostazione di base ? Com'è la sintassi per l'incremento e per il decremento ? Devo aggiungere delle librerie ? Scusa ma sono proprio in confusione...

PaoloP

Si.
Come tutte le variabili, durante l'inizializzazione gli può essere attribuito un valore.
Code: [Select]
int soglia = 20;

Devi leggere i pulsanti con il digitalRead come in questo tutorial --> http://www.arduino.cc/en/Tutorial/Pushbutton
e invece di accendere il led incrementi la variabile semplicemente con
Code: [Select]
soglia++;
o la decrementi con
Code: [Select]
soglia--;

marinaio67

Aggiornamento... sono riuscito a fare ciò che mi ero proposto , però ci sono dei malfunzionamenti... intanto il led si accende e si spegne con un certo ritardo (non so se il delay che ho messo in fondo per LCD può interferire... ho detto una bischerata ? ) e poi anche i pulsanti UP e DOWN non rispondono subito , per fare alzare o abbassare la soglia di 1 grado devo premere i pulsanti ripetutamente... questo il codice... mi sfugge qualcosa ?
Code: [Select]
/*
prova.ino
Misurazione della temperatura
invio a display LCD e accenzione led a 23° C

*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>


int LED=7;                 //Pin7 = LED
int SOGLIA=23;              // imposta la temperatura iniziale a 23°C
const int inPinU = 30;   // Pin30 = pulsante UP
int valU = 0;     
int valUltimoU = 0;   
const int inPinD = 31;   // Pin31 = pulsante DOWN
int valD = 0;   
int valUltimoD = 0;     


// linea dati DS18B20 al pin 10 di Arduino
#define ONE_WIRE_BUS 10

// Imposta la comunicazione oneWire per comunicare
// con un dispositivo compatibile
OneWire oneWire(ONE_WIRE_BUS);

// Passaggio oneWire reference alla Dallas Temperature.
DallasTemperature sensors(&oneWire);

// RS RW EN D4 D5 D6 D7
LiquidCrystal lcd(12, 11, 6, 5, 4, 3, 2);



void setup()

{
  // Start up the library
  sensors.begin();
  // Imposta il valore di righe e colonne del display LCD
  lcd.begin(16, 2);
lcd.clear();
 
 
 
 
  pinMode(LED, OUTPUT);   //LED set to output
  pinMode(inPinU, INPUT);    // dichiaro che il pulsante UP è un ingresso
  pinMode(inPinD, INPUT);    // dichiaro che il pulsante DOWN è un ingresso 
 
}



void loop(void)
{

 
 
if (sensors.getTempCByIndex(0) >= SOGLIA)                        //temperatura maggiore o uguale a SOGLIA led acceso
  {
    digitalWrite (LED, HIGH);         //led acceso
  }
  else if (sensors.getTempCByIndex(0) <= SOGLIA)                //temperatura minore o uguale a SOGLIA led spento
  {
    digitalWrite (LED, LOW);      //led spento
   
}

valUltimoU = valU;
valU = digitalRead(inPinU);  // legge lo stato del pulsante UP
  if(valUltimoU == HIGH && valU == LOW) 
  {
    SOGLIA++;
    Serial.println(SOGLIA);
  }
  valUltimoD = valD;
valD = digitalRead(inPinD);  // legge lo stato del pulsante DOWN
  if(valUltimoD == HIGH && valD == LOW) 
  {
    SOGLIA--;
    Serial.println(SOGLIA);
  }

sensors.requestTemperatures(); // Invia il comando di lettura delle temperatura
  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  Temperatura");
  lcd.setCursor(4, 1);
  lcd.print (sensors.getTempCByIndex(0));
  lcd.print (" C");
  delay(3000); // wait 3000ms
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  Soglia");
  lcd.setCursor(4, 1);
  lcd.print (SOGLIA);
  lcd.print (" C");
  delay(3000); // wait 3000ms
  lcd.clear();
}

PaoloP

Se inserisci un delay di 3000 millisecondi in quel lasso di tempo i pulsanti non vengono controllati.
Dopo il digitalread dei pulsanti aggiungi un delay(15); come sistema antirimbalzo.
Inoltre dovresti mettere le resistenze di pull-down sui pulsanti, se non l'hai fatto.

marinaio67

le resistenze le ho messe da 10K , vanno bene ? poi ho visto che abbassando il delay a 500ms i pulsanti rispondono meglio anche se sono sempre lenti (sembra poco 500ms ma da un pulsante si vorrebbe una risposta quasi immediata)... il problema è che se abbasso ancora il delay l'LCD sembra un albero di natale (già ora le scritte si alternano troppo velocemente)... come posso fare perchè il delay dell'LCD non influisca nel delay dei pulsanti ? allego l'ennesimo codice  :D
Code: [Select]

/*
prova.ino
Misurazione della temperatura
invio a display LCD e accenzione led a 20° C

*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>


int LED=7;                 //Pin7 = LED
int SOGLIA=23;              // imposta la temperatura iniziale a 23°C
int inPinU = 30;   // Pin30 = pulsante UP
int valU = 0;     // variabile per leggere lo stato del Pulsante UP
int inPinD = 31;   // Pin31 = pulsante DOWN
int valD = 0;     // variabile per leggere lo stato del Pulsante DOWN



// linea dati DS18B20 al pin 10 di Arduino
#define ONE_WIRE_BUS 10

// Imposta la comunicazione oneWire per comunicare
// con un dispositivo compatibile
OneWire oneWire(ONE_WIRE_BUS);

// Passaggio oneWire reference alla Dallas Temperature.
DallasTemperature sensors(&oneWire);

// RS RW EN D4 D5 D6 D7
LiquidCrystal lcd(12, 11, 6, 5, 4, 3, 2);



void setup()

{
  // Start up the library
  sensors.begin();
  // Imposta il valore di righe e colonne del display LCD
  lcd.begin(16, 2);
lcd.clear();
 
 
 
 
  pinMode(LED, OUTPUT);   //LED set to output
  pinMode(inPinU, INPUT);    // dichiaro che il pulsante UP è un ingresso
  pinMode(inPinD, INPUT);    // dichiaro che il pulsante DOWN è un ingresso 
 
}



void loop(void)
{

 
 
if (sensors.getTempCByIndex(0) >= SOGLIA)                        //temperatura maggiore o uguale a SOGLIA led acceso
  {
    digitalWrite (LED, HIGH);         //led acceso
  }
  else if (sensors.getTempCByIndex(0) <= SOGLIA)                //temperatura minore o uguale a SOGLIA led spento
  {
    digitalWrite (LED, LOW);      //led spento
   
}

valU = digitalRead(inPinU);  // legge lo stato del pulsante UP
delay(15);

  if(valU == HIGH) 
  {
    SOGLIA++;
    Serial.println(SOGLIA);
  }

valD = digitalRead(inPinD);  // legge lo stato del pulsante DOWN
delay(15);

  if(valD == HIGH) 
  {
    SOGLIA--;
    Serial.println(SOGLIA);
  }

sensors.requestTemperatures(); // Invia il comando di lettura delle temperatura
  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  Temperatura");
  lcd.setCursor(4, 1);
  lcd.print (sensors.getTempCByIndex(0));
  lcd.print (" C");
  delay(500);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  Soglia");
  lcd.setCursor(4, 1);
  lcd.print (SOGLIA);
  lcd.print (" C");
  delay(500);
  lcd.clear();
}

leo72

Il refresh del display non lo devi fare continuamente ma solo se l'utente preme qualche pulsante oppure 1 volta al uno/due secondi nelle condizioni normali.
Metti un controllo basato su millis() per farlo.

marinaio67

Nel frattempo ho modificato ancora... ho tolto del tutto il delay all'LCD mettendo in un'unica schermata i dati che mi interessano... resta la lentezza di risposta dei pulsanti... da cosa può dipendere ? Inoltre ho visto alcuni tutorial dove il pulsante viene definito in "#Define nomepulsante" mentre in altri viene definito come ho fatto io con "int nomepulsante" , cosa cambia ?

leo72

Quel delay(500) influisce non solo sulla visualizzazione dei dati sul display ma sull'esecuzione di tutto il codice per cui anche tra 2 letture differenti dei pulsanti c'è mezzo secondo di ritardo.
E' come percorrere un giro in F1 dove, ad ogni tornata, devi rientrare ai box. Sarai sempre lentissimo.

Devi ristrutturare tutti il programma usando solo e soltanto i millis per impostare l'aggiornamento del display una volta ogni x secondi oppure se il pulsante viene premuto.
Il resto del programma (lettura dello stato dei pulsanti) puoi lasciarlo tranqullamente nel loop principale: "qualcosa" verrà fatto solo quando leggi una pressione.

Il BlinkWithoutDelay contenuto negli esempi dell'IDE ti mostra come fare una certa azione ogni 1000 ms, fa sicuramente al caso tuo  ;)

marinaio67

Ok , grazie di tutti i consigli , domani provo a fare le modifiche... Intanto spiego dove vorrei arrivare , così se avete delle indicazioni su quale esempi seguire , comincio a buttarci un occhio... In pratica vorrei aggiungere altre sonde (almeno tre in modo da gestire stanza per stanza) e aumentando anche il numero dei pulsanti (per esempio UP , DOWN , LEFT , RIGHT , OK) strutturare una specie di menù dove premendo ok entro nella lista delle stanze , con due pulsanti scorro avanti o indietro stanza per stanza e con i restanti due setto la temperatura di accensione... Esiste qualcosa dove prendere degli spunti ?

leo72

C'è una libreria per creare e gestire menu su LCD fatta da un utente del forum.
http://arduino.cc/forum/index.php/topic,115498.0.html

Questa ti può tornare utile per gestire appunto i menu.

marinaio67

Ho visto questa libreria e anche un'altra sempre dedicata ai menù... al momento per me , sono di difficile comprensione (sarà l'inglese o molto probabilmente sarà che son duro...) cosa comporterebbe il fatto di non usare nessuna libreria e strutturare il menù direttamente nello sketch con if e else ?

leo72


Ho visto questa libreria e anche un'altra sempre dedicata ai menù... al momento per me , sono di difficile comprensione (sarà l'inglese o molto probabilmente sarà che son duro...) cosa comporterebbe il fatto di non usare nessuna libreria e strutturare il menù direttamente nello sketch con if e else ?

Nulla di strano. Devi solo scrivere il relativo codice. Anch'io i menu me li faccio da solo, non uso lib.

Go Up