Termostato con soglia min/max e isteresi di 0,5 gradi [RISOLTO]

Ciao a tutti, tempo fa mi costruii un termostato ma una volta effettuato il progetto definitivo sto riscontrando alcuni problemi che spero voi possiate indicarmi la soluzione.

  1. ho impostato una temperatura di soglia di 25 gradi…il problema è che quando la temperatura si avvicina questo fa accendere e spegnere il led in quanto rileva la temperatura a volte 25 (quindi spento) il secondo dopo di 24,99 (quindi acceso). a tal proposito vorrei inserire nel codice un range di 0,5 gradi in modo da non avere l’effetto di una freccia dell’autovettura.
  2. dopo qualche ora che è in funzione, sul display non visualizzo più le informazioni che ho programmato bensì leggo caratteri strani quindi devo riavviare più volte per tornare alla lettura della temperatura… Potrebbe essere che ho collegato una scheda relè direttamente collegata ad arduino e che gli assorbe troppa corrente? premetto che è solo un problema di DISPLAY perchè il termostato si accende e spegne continuamente (per il problem del punto 1) il che mi fa capire che il codice lavora bene
  3. ho inserito un pulsante per accendere la retroilluminazione del display in modo da non tenerlo perennemente acceso e che al rilascio lo spenga. Non ho messo una resistenza di pulldown, ho fatto male o potrebbe essere il motivo del malfunzionamento del display?
    allego codice per capire dov’è il problema.
#include <OneWire.h>        //libreria Sensore
#include <DallasTemperature.h>    //libreria Lettura sensore gradi Cent
#include <LiquidCrystal.h>    //libreria display LCD


const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;   //LCD connessione
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);    //LCD inizializzazione porte

int LED1=8;    
int LED2=9;
int LED3=6;

#define ONE_WIRE_BUS 10     //sensore PIN 10
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tmp_address;
float temp0=0;  //cambiare variabile in INT se si desidera visualizzare valori interi o FLOAT se lo si vuole con i decimali
float temp1=0;  // originariamente la variabile era INT ma ho modificato in FLOAT
int numberOfDevices;

void setup(){   // SETUP  SETUP   SETUP   SETUP SETUP  SETUP   SETUP   SETUP
 
pinMode (livello, INPUT);    //sensore di livello 5V e l'altro capo al pin assegnato (pin7)
pinMode (LED1, OUTPUT);  
pinMode (LED2, OUTPUT);
pinMode (LED3, OUTPUT);
 
lcd.begin(16, 2);
numberOfDevices = 1;
sensors.begin();
delay(2000);


// LED3 si deve accendere dopo circa 3 minuti

{
delay(90000); // attendi 1 minuto e mezzo dal blackout poi fai partire lo LED3
digitalWrite(skimmer,HIGH); // accendi lo LED3 e lascialo PERENNEMENTE acceso

}
}


void loop(){    // LOOP LOOP  LOOP  LOOP  LOOP  LOOP  LOOP LOOP  LOOP  LOOP  LOOP  LOOP

 
 sensors.requestTemperatures(); // Comando per misurare la temp.
 temp0 = sensors.getTempCByIndex(0);
 lcd.setCursor(0,0); // Colonna 0, Riga 0
 lcd.print("Vasca: ");  //scrivi VASCA:
 lcd.setCursor(7,0); //Colonna 7, Riga 0
 lcd.print(temp0);   //scrivi Temperatura
 lcd.print(char( 223)); // Scrive il pallino dei gradi
 lcd.print("C  ");// Scrive la C di Celsius




 
 //sketch riguardante il TERMOSTATO
 if (temp0 <25) // range temperatura 25  GRADI 
{

   digitalWrite(LED2,LOW);
   lcd.setCursor (0,1);
    lcd.print("LED1:SI ");
 } else {
   digitalWrite(LED2,HIGH);
   lcd.setCursor(0,1);
   lcd.print("LED1:NO");}

   //sketch riguardante il LED3
 if (temp0 >27) // range temperatura 27 GRADI
 {

   digitalWrite(LED2,LOW);
   lcd.setCursor (8,1);
    lcd.print(" LED2:SI ");
 } else {
   digitalWrite(LED2,HIGH);
   lcd.setCursor(8,1);
   lcd.print(" LED2:NO");}
   


}

>fabiomusicman: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More → Modify che si trova in basso a destra del tuo post) e racchiudere il codice all’interno dei tag CODE (… sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

... dopo di che, del problema dei disturbi dei relè con (e anche senza) LCD si è parlato decine di volte sul forum ... fai un po' di ricerche e vedrai che trovi svariate soluzioni.

Guglielmo

Per risolvere il punto 1 puoi fare una cosa del genere:

temperaturaSoglia = 25;
isteresi = 0.5;
ReleAttivo = (ReleAttivo ? !(temp0 >= temperaturaSoglia + isteresi) : temp0 <= temperaturaSoglia - isteresi );

In pratica se il relè è attivato controlli che la temperatura letta sia superiore o uguale 25 gradi + 0.5, altrimenti controlli che la temperatura letta sia inferiore a 25 - 0.5 in questo modo il relè si attiva a 24.5 gradi e resta attivo fino a 25.5 poi si spegne e resta così fino a che non scende di nuovo a 24.5 gradi.
Per il problema dei display impazzito è sempre la solita storia, non scrivere il display ad ogni ciclo di loop ma aggiornalo solo quando serve, cerca nel forum display impazzito o display caratteri strani, troverai un sacco di risposte, oltre al problema relé che ti ha giustamente indicato Guglielmo

gpb01:
>fabiomusicman: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More → Modify che si trova in basso a destra del tuo post) e racchiudere il codice all’interno dei tag CODE (… sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

perfetto…ho fatto come mi descrivi…Scusatemi ma cercavo questa funzione solo che mi è sfuggita e non sapendo come fare ho (sbagliatamente) aperto un nuovo commento il quale ho provveduto ad eliminare

fabpolli:
Per risolvere il punto 1 puoi fare una cosa del genere:

temperaturaSoglia = 25;

isteresi = 0.5;
ReleAttivo = (ReleAttivo ? !(temp0 >= temperaturaSoglia + isteresi) : temp0 <= temperaturaSoglia - isteresi );



In pratica se il relè è attivato controlli che la temperatura letta sia superiore o uguale 25 gradi + 0.5, altrimenti controlli che la temperatura letta sia inferiore a 25 - 0.5 in questo modo il relè si attiva a 24.5 gradi e resta attivo fino a 25.5 poi si spegne e resta così fino a che non scende di nuovo a 24.5 gradi.
Per il problema dei display impazzito è sempre la solita storia, non scrivere il display ad ogni ciclo di loop ma aggiornalo solo quando serve, cerca nel forum display impazzito o display caratteri strani, troverai un sacco di risposte, oltre al problema relé che ti ha giustamente indicato Guglielmo

dove posso documentarmi sulla programmazione dell’isteresi? cercando in altri forum non riesco a venirne a capo

metti un po' a posto i nomi dei piedini, sembra che tu usi lo stesso piedino sia nel ramo 25 gradi che in quello 27

fabiomusicman: dove posso documentarmi sulla programmazione dell'isteresi? cercando in altri forum non riesco a venirne a capo

Non capisco la domanda il codice che ho scritto nel post è utilizzabile su Arduino

Standardoil: metti un po' a posto i nomi dei piedini, sembra che tu usi lo stesso piedino sia nel ramo 25 gradi che in quello 27

??

fabpolli: Non capisco la domanda il codice che ho scritto nel post è utilizzabile su Arduino

le variabili ISTERESI e TEMPERATURA SOGLIA non devono essere dichiarate nel setup? Hai messo dei caratteri come ?! nel codice che mi hai mandato..sono errori? non capisco a cosa servano

fabiomusicman:
??

due sole cose:
usa la formattazione automatica, che senno’ diventa difficile seguirti
secondo:

 if (temp0 <25) // range temperatura 25  GRADI 
{

   digitalWrite(LED2,LOW);
   lcd.setCursor (0,1);
    lcd.print("LED1:SI ");
 } else {
   digitalWrite(LED2,HIGH);
   lcd.setCursor(0,1);
   lcd.print("LED1:NO");}

e

 if (temp0 >27) // range temperatura 27 GRADI
 {

   digitalWrite(LED2,LOW);
   lcd.setCursor (8,1);
    lcd.print(" LED2:SI ");
 } else {
   digitalWrite(LED2,HIGH);
   lcd.setCursor(8,1);
   lcd.print(" LED2:NO");}

lo vedi che per due condizioni differenti usi lo stesso piedino?
ah, e poi
metti il codice che almeno compila, che in quello messo da te ci sono almeno due variabili utilizzate e non dichiarate, sicuramente NON ti compila e NON è quello il codice caricato adesso nell’arduino
io sono dell’idea che se uno ha bisogno di aiuto ci sono, sempre e volentieri, ma almeno un minimo di ordine nelle sue cose lo deve tenerre lui
prima legge di Nelson:
fate ordine e buttate via la spazzatura
non è un consiglio, è una condizione necessaria per ottenere dei risultati

ReleAttivo = (ReleAttivo ? !(temp0 >= temperaturaSoglia + isteresi) : temp0 <= temperaturaSoglia - isteresi );

equivale a

if (ReleAttivo) {
   ReleAttivo = !(tempo>=temperaturaSogli +isteresi);  // ! significa not cioè se è vero scrivi falso e viceversa
} else {
   ReleAttivo = (temp0 <= temperaturaSoglia - isteresi);
}

se non sbaglio :slight_smile:

Patrick_M:

ReleAttivo = (ReleAttivo ? !(temp0 >= temperaturaSoglia + isteresi) : temp0 <= temperaturaSoglia - isteresi );

equivale a

if (ReleAttivo) {

ReleAttivo = !(tempo>=temperaturaSogli +isteresi);  // ! significa not cioè se è vero scrivi falso e viceversa
} else {
  ReleAttivo = (temp0 <= temperaturaSoglia - isteresi);
}




se non sbaglio :)

proverò ad inserire questo codice. Ma la variabile ISTERESI dove andrebbe dichiarata?

per semplicità dichiarale tutte globali (dove hai dichiarato temp0 e le altre).

finalmente sono riuscito a venirne a capo;
ho messo le variabili globali:

int sogliaMin = 25;
int sogliaMax=27;
float isteresi= 0.5;

posto il codice corretto:

if (temp0 <sogliaMin) // soglia minima temperatura 25  GRADI 
  {

    digitalWrite(LED1,LOW);
    lcd.setCursor (0,1);
     lcd.print("Risc:SI ");} 

if(temp0>(sogliaMin+isteresi)) {
    digitalWrite(LED1,HIGH);
    lcd.setCursor(0,1);
    lcd.print("Risc:NO");}

GRAZIE A TUTTI PER LA VOSTRA PREZIOSA COLLABORAZIONE!!

altra piccola considerazione: come mai a volte il display mi rileva una temperatura di -127? secondo voi da cosa dipende? Ovviamente mi fa scattare il relè e pare che questa rilevazione sia sporadica e non ciclica.. avete idea di cosa sia successo?

-127 è la termeratura restituita in caso di errata/mancata comunicazione con la sonda digitale, forse un falso contatto di uno o più pin della sonda. Se sei ancora su breadboard verifica le connessioni, se è già montato su millefori o pcb finale... verifica le connessioni se sono corrette prova a cambiare la sonda, in ogni caso puoi introdurre una spece di controllo errori nel programma, se ti arriva una lettura di -127 la ignori, se te ne arriva più di una lo segnali come errore sonda

per ignorare quel -127 potrei usare una funzione "if"?

si, comunque se ti limiti ad ignorarlo se ti si guasta la sonda non te ne accorgi, potresti pensare di fare una cosa di questo tipo:

if(temperatura==-127)
{
  contatoreErroreLetturaSonda++;
  if(contatoreErroreLetturaSonda>5)
  {
     ..scrivi sull'lcd errore lettura temperatura
  }
}
else
{
  contatoreErroreLetturaSonda = 0;
  ...il tuo codice attuale...
}

Chiaramente se dopo alcune letture andate male la sonda viene letta bene l'errore ti scomparirebbe dall'lcd, valuta tu se, e te lo consiglio caldamente, lasciare traccia sull'lcd dell'avvenuto errore

Per la precisione comunque if non è una funzione ma un costrutto o istruzione (se preferisci) ;)

fabpolli: Per la precisione comunque if non è una funzione ma un costrutto o istruzione (se preferisci) ;)

hai ragione....intendevo che se mettessi come istruzione quella di ignorare il -127 ovvero quando rilevato non deve far scattare il relè e non deve essere visualizzato nulla sull'LCD.

inoltre il problema che avevo sull' LCD che mi dava caratteri strani al momento pare non lo faccia. Prima lo faceva spesso perchè ho collegato la scheda relè direttamente all'arduino e, non avendo impostata l'isteresi, scattava continuamente quindi presumo, assorbendo troppa corrente, ne veniva meno all'LCD restituendomi quei caratteri. Per come l'ho programmato la scheda non va mai a far funzionare più di un relè alla volta...spero basti per non farmi scrivere quelle cose sull'LCD