conflitto di programmazione blocca arduino in funzione da ore,a random

Salve a tutti,
ho costruito una piccola centralina che regola i parametri ambientali in una serra,molto elementare ai più,un po meno per un neofita di elettronica e programmazione come me,essendo la meccanica il mio ambiente di studi e lavoro.Ad ogni modo con ricerche letture e prove,senza troppe pretese in un paio di mesi ho dato vita di programma e corpo hardware al progettino in questione,risolvendo man mano tutte le problematiche incontrate,utilizzando molto il forum da osservatore,tutte tranne una,che non riesco a trovare.Premetto che non conoscendo il linguaggio C,non mi sono addentrato nella studio per impararlo,non ne ho avuto minimamente il tempo,mi sono limitato a cercare di capire come è costruito e come credo molti alle prime esperienze copiato parti di codice qua e la capendo almeno come sistemarli per il proprio scopo,e qui devo aver compiuto alcuni errori,che fanno in modo che la centralina si avvii,funzioni correttamente per a volte 2 giorni,a volte 2 ore e dico due per dire un numero,insomma si blocca apparentemente a random,accesa e funzionante nell’ultima istruzione letta,ho un display e un modulo rtc e vedo il blocco dello scorrere dei secondi,temperatura e umidà fisse,e relay con quindi attuatori fissi sull’ultimo stato letto.tutto freezzato insomma.
il funzionamento consiste nella rilevazione di temp. e umidità con sensore DHT22,un display 20x4 per la lettura dei dati,un modulo rtc ds1307 per visualizzare ora e data (doveva servire anche per temporizzare duè relays,ma ho trovato più comodo usare la libreria “Metro” elaborata qui da un maestro).Arduino UNO quindi elabora i dati letti e attiva un modulo da 4 relay collegati ad una ciabatta opportunamente modificata che comanda un umidificatore in base ai dati del sensore,un estrattore e un ventilatore con altri 2 relays accesi e spenti a intervalli regolari con “metro”.relay e processore sono optoisolati e alimentati separatemente,tutto funziona alla perfezione le soglie con isteresi azionano il relay umidificatore quando serve,gli altri due si alternano simultaneamente,non ho mai più di due realy accesi contemporaneamente,fattostà che ogni tanto senza motivo a me visibile si blocca tutto,acceso nell’ultimo stato,e a volte la data e ora rimangono un pò indietro.
ora posto il codice,nel caso qualche volenteroso che ne capisce più di me voglia evidenziarmi l’errore principale.Chiedo scusa in anticipo degli strafalcioni inseriti nel codice,alcune cose insensate o non utili son sicuro di averle copiate e incollate erroneamente,qualcuno potrebbe anche ridere,ci stà…spero comunque di poter risolvere il problema,perchè manca poco,ma le mie enormi lacune non mi permettono di vederlo…grazie a tutti in anticipo…

//ciclo vegetativa estrazione 5on/20off
//umidificatore relay1-estrattore relay3-ventilatore relay4
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <RTClib.h>
#include <Metro.h> //Includi Metro library
#define relay3pin  10 // definire il pin relay3
#define relay4pin  9 // definire il pin relay4

RTC_DS1307 RTC;

//Create a variable to hold theled's current state
int state = LOW;
// Instanciate a metro object and set the interval to 250 milliseconds (0.25 seconds).
Metro relay3Metro = Metro(250); //tempo delay dallo start HIGHT
Metro relay4Metro = Metro(250); //tempo delay dallo start HIGHT


DHT dht(2, DHT22); //Imposta il modello di sensore e il pin di Arduino a cui è collegato
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // indirizzo 0x27 seriale del i2c



const int relay1Pin = 11;
int umidMAX = 75; //valori di umidità da cambiare a piacimento
int umidMIN = 73;
float x=(3.0); //isteresi

void setup()
{
 
  pinMode(relay1Pin, OUTPUT);   //relay umidificatore
  pinMode(relay3pin,OUTPUT);    //relay estrattore
  pinMode(relay4pin,OUTPUT);    //relay ventilatore
  
  dht.begin();
  lcd.begin(20,4);// imposto il numer di righe e colonne del display
  lcd.backlight();
  
  //creo il carattere ‘°’ per poter scrivere °C dopo il valore della temperatura
  byte deg[8] =
  {
    0b00011,
    0b00011,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000
  };
  lcd.createChar(4,deg);
  digitalWrite(relay3pin,state);
  digitalWrite(relay4pin,state);
  
  //Serial.begin(9600);
  Wire.begin();
  RTC.begin(); 

 //RTC.adjust(DateTime(__DATE__, __TIME__));
 if (! RTC.isrunning()) {
   Serial.println("RTC is NOT running!");
   // following line sets the RTC to the date & time this sketch was compiled
     RTC.adjust(DateTime(__DATE__, __TIME__));
 }
}

void loop()

{
  
  if (relay3Metro.check() == 1) { // check if the metro has passed its interval .
    if (state==HIGH)  { 
      state=HIGH;
      relay3Metro.interval(1200000); // tempo relay spento
    } 
    else {
      relay3Metro.interval(300000); // tempo ralay acceso
      state=LOW;
    }
    digitalWrite(relay3pin,state);
    
  }
  

  
  if (relay4Metro.check() == 1) { // check if the metro has passed its interval .
    if (state==LOW)  { 
      state=HIGH;
      relay4Metro.interval(300000); // tempo relay spento
    } 
    else {
      relay4Metro.interval(1200000); // tempo ralay acceso
      state=LOW;
    }
    digitalWrite(relay4pin,state);
  }

  

  
  {
    lcd.setCursor(0,0);//metti il cursore sulla terza riga prima colonna
    lcd.print("**CICLO VEGETATIVA**");
    lcd.setCursor(1,1);//metti il cursore sulla terza riga prima colonna
    lcd.print("Estraz. 5on/20off");

    
  }
  float h = dht.readHumidity(); //leggi il valore di temperatura
  float t = dht.readTemperature(); //leggi il valore di umidità
  lcd.setCursor(0,2);//metti il cursore sulla terza riga prima colonna
  lcd.print("T=");
  if(isnan(t))lcd.print("Errore!");//se il valore di temperatura è NaN (Not a Number)
  else //altrimenti
  {
    lcd.print(t);
    lcd.write(4); //scrivi il carattere ‘°’
    lcd.print("C");
  }
  lcd.setCursor(0,3);//metti il cursore sulla quarta riga prima colonna
  lcd.print("H=");
  if(isnan(h))lcd.print("Errore!");//se il valore di umidità è NaN (Not a Number)
  else
  {
    lcd.print(h);
    lcd.print(" %");
     }
    if (h <= umidMIN-x) {
    digitalWrite(relay1Pin, LOW);
    }
    if (h >= umidMAX+x) {
    digitalWrite(relay1Pin, HIGH);
    }
   
 
 
  DateTime now = RTC.now();

   Serial.print(now.year(), DEC);
   Serial.print('/');
   Serial.print(now.month(), DEC);
   Serial.print('/');
   Serial.print(now.day(), DEC);
   Serial.print(' ');
   Serial.print(now.hour(), DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
   Serial.println();
   lcd.setCursor(10,2);
lcd.print(now.day(),DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd.print(now.year(), DEC);
lcd.print(' ');
lcd.setCursor(11,3);
lcd.print(now.hour(),DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);
lcd.print(':');
lcd.print(now.second(), DEC);
lcd.print(' ');
       

   Serial.print(" since 1970 = ");
   Serial.print(now.unixtime());
   Serial.print("s = ");
   Serial.print(now.unixtime() / 86400L);
   Serial.println("d");

   // calculate a date which is 7 days and 30 seconds into the future
   DateTime future (now.unixtime() + 7 * 86400L + 30);

   Serial.print(" now + 7d + 30s: ");
   Serial.print(future.year(), DEC);
   Serial.print('/');
   Serial.print(future.month(), DEC);
   Serial.print('/');
   Serial.print(future.day(), DEC);
   Serial.print(' ');
   Serial.print(future.hour(), DEC);
   Serial.print(':');
   Serial.print(future.minute(), DEC);
   Serial.print(':');
   Serial.print(future.second(), DEC);
   Serial.println();

   Serial.println();
 
   
 
 }

Breve aggiornamento...
ho provato svariati tentativi,nella mia ignoranza andando per esclusioni,unica strada praticabile,ho proceduto quindi togliendo parti di sketch in blocco in maniera ovviamente sensata,cioè escludendo funzioni della centralina in questione...ho da prima escluso libreria e funzione "metro" lasciando lettura sensore e attuazione relay in base a umidità rilevata,e lasciando anche la parte di orologio con rtc...il problema di blocco improvviso e a random è rimasto.
Poi ho tolto anche la parte rtc nel tentativo successivo,lasciando quindi solamente gestione relay umidità in base a lettura sensore...ma purtroppo il problema non si è risolto comunque.
tengo a precisare per completezza che i problemi riscontrati sono:

-blocco delle operazioni programmate,cioè rimane tutto acceso e funzionante all'ultima istruzione(display acceso,realy chiuso quindi umidificaore acceso, ma letture umidità a display fisse e ora data rtc ferma al momento di blocco)

-blocco delle operazioni programmate come sopra ma con display spento (questo solo un paio di volte)

-blocco delle operazioni programmate come sopra ma con display con caratteri illegibili ( anche questo solo un paio di volte)

il tutto senza una logica o tempistica imputabile a qualcosa,apparentemente.

tra le varie prove mi accorsi che la ciabatta alla quale sono collegati i ralay (di cui ne uso soltanto uno ora) e che comanda la 220 v collegata ad una tripla insieme ad una ventola (23W di assobirmento) risentiva dell'accensione o spegnimento di quest'ultima e lo si vedeva dallo sfarfallio di una frazione di secondo dei 4 led della scheda relays (eppure è optoisolata la scheda :o ),per cui ho provveduto a cambiare presa lasciando la centralina alimentata dalla rete da sola,sperando fosse quello il problema,ma non era quello...posto ora lo sketch semplificato e ridotto ma che continua ogni tanto a bloccarsi,almeno per capire se il problema è di programmazione o di hardware.Se qualcuno vede errori sono pronto a bacchettate e rimproveri ...grazie in anticipo a che vi perderà un momento

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>


DHT dht(2, DHT22); //Imposta il modello di sensore e il pin di Arduino a cui è collegato
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // indirizzo 0x27 seriale del i2c



const int relay1Pin = 11;
int umidMAX = 77; //valori di umidità da cambiare a piacimento
int umidMIN = 70;
float x=(3.0); //isteresi

void setup()
{
 
  pinMode(relay1Pin, OUTPUT);
 
  dht.begin();
  lcd.begin(20,4);// imposto il numer di righe e colonne del display
  lcd.backlight();
  
  //creo il carattere ‘°’ per poter scrivere °C dopo il valore della temperatura
  byte deg[8] =
  {
    0b00011,
    0b00011,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000
  };
  lcd.createChar(4,deg);
  
  
}
void loop()

{
{
    lcd.setCursor(0,0);//metti il cursore sulla terza riga prima colonna
    lcd.print("**CICLO VEGETATIVA**");
   

    
  }

  
  float h = dht.readHumidity(); //leggi il valore di temperatura
  float t = dht.readTemperature(); //leggi il valore di umidità
  lcd.setCursor(0,2);//metti il cursore sulla terza riga prima colonna
  lcd.print("T=");
  if(isnan(t))lcd.print("Errore!");//se il valore di temperatura è NaN (Not a Number)
  else //altrimenti
  {
    lcd.print(t);
    lcd.write(4); //scrivi il carattere ‘°’
    lcd.print("C");
  }
  lcd.setCursor(0,3);//metti il cursore sulla quarta riga prima colonna
  lcd.print("H=");
  if(isnan(h))lcd.print("Errore!");//se il valore di umidità è NaN (Not a Number)
  else
  {
    lcd.print(h);
    lcd.print(" %");
     }
    if (h <= umidMIN-x) {
    digitalWrite(relay1Pin, LOW);
    }
    if (h >= umidMAX+x) {
    digitalWrite(relay1Pin, HIGH);
    }
   
 
   Serial.println();
   
 
 }

Hai filtrato e disaccoppiato bene le alimentazioni ed usato per i rele' un'alimentatore a parte rispetto a quello di Arduino ? (o almeno un robusto filtro sul'alimentazione della scheda rele') ... e riguardo ai carichi, come hai connesso il tutto ? ... se ci sono carichi resistivi, li hai dotati di snubber (spegniscintilla) RC ?

Grazie Etemenaki per il passaggio e la risposta...
dunque,arduino e scheda relay sono alimentati separatamente,il primo con alimentatore da 9v 0.7A
i relay con alimentatore 5v 1.0A ,entrambi recuperati da vecchi cellulari.
Separare le alimentazioni però è l'unica accortezza che ho applicato,come dicevo nel primo post,sono abbastanza ignorante in materia,e di tutte le informazioni recuperate in rete non mi ero mai imbattuto in discussioni su filtrare e disaccoppiare le alimentazioni pensando che la scheda relay prestampata avesse già integrati che filtrassero e isolassero il tutto,men che meno gli snubber,che sono andato a cercare ora...per quanto riguarda i carichi sono connessi tramite ciabatta (4 prese schuko) modificata interrompendo la fase in 4 e collegata ai 4 relays in modo normalmente aperto e che quindi ovviamente chiudono il circuito della sola presa corrispondente quando sollecitati da segnale arduino.il carico applicato al relay (relay1 ed unico per ora utilizzato) è un trasformatore da 12 v che alimenta un piccolo umidificatore ad ultrasuoni non ricordo ora di preciso ma direi un consumo attorno alla 20ina di watt...correggimi se sbaglio ma quindi un carico induttivo.
Altra nota,che ho recentemente letto nel forum,è che l'alimentazione scheda relay è posizionata molto vicina ad arduino,ed è sempre acceso ovviamente,non vorrei generasse disturbi.
Da quello che mi scrivi però sembra che il problema sia elettrico-elettronico invece che di programmazione,è così?
se mi date qualche consiglio cerco di studiare ed intervenire per risolvere il problema,tenendo presente che in origine alla ciabatta gestia dai relay dovrei collegarci altri 2 carichi da 18-25w (ventilatore e aspiratore) comandati ad intemittenza con "metro"
grazie ancora per l'interessamento

Il problema potrebbe essere sia software che hardware, ma il fatto che con identiche condizioni ti dia il blocco in modo "random", mai sulle stesse funzioni, fa per lo meno venire il dubbio che potrebbe (condizionale obbligatorio) essere dovuto a qualche disturbo o extratensione generata dal carico (magari quando si chiude o si apre, a volte il disturbo e' sufficente ad impallarti la MCU ed altre volte no) ... per cui la prima cosa da provare mi e' sembrata quella ...

Arduino e' una scheda di prototipazione rapida, non un'hardware pensato per uso industriale, quindi piu di tanti filtri non li ha ... se l'alimentatore e' connesso alla stessa ciabatta o linea (o molto vicino) che alimenta i carichi, c'e' la possibilita' che alcuni disturbi "rientrino" attraverso l'alimentazione della logica ed interferiscano ... supponendo che le masse non siano in comune fra scheda rele' e scheda arduino e che la scheda rele' possieda degli optoisolatori (ma sarebbe meglio se ci dicessi qual'e', per esserne sicuri), gia il fatto di poter mettere gli alimentatori distanti fisicamente (o per lo meno non "attaccati" ad arduino) potrebbe aiutare, come l'aggiungerci un paio di condensatori (tipo, indicativamente, 470uF con 100nF in parallelo) sulla linea di alimentazione che entra nel jack (e se non c'e' problema di spazio, anche sulla linea che alimenta i rele') ...

Poi serve sapere come hai collegato gli ingressi di arduino ... diretti, pullup, pulldown, debounce ? ... se potessi postare uno schema elettrico aiuterebbe parecchio a capire se il problema e' piu hardware o piu software, e magari anche a risolverlo ...

Ciao Etemenanki,la scheda relat in questione è questa: http://www.miniinthebox.com/it/4-modi-rele-modulo-con-fotoaccoppiatore_p407339.html

le masse non sono in comune ed è alimentata come dicevo da alimentatore separato quindi ho tolto il ponticello e collegato il + al jd-vcc e il - al gnd a fianco dei segnali "in"1-2-3-4...

purtroppo a causa della mia ignoranza in materia non sono in grado di disegnare uno schema elettrico degno di essere chiamato tale,ho provato un pò a riprodurre i collegamenti con Fritzing anche se non dispongo di una libreria completa,quindi con qualche nota ho cercato di essere il più completo possibile,allego anche un paio di foto dell'oggetto in questione se dovesse chiarire qualche lacuna...

p.s. nelle foto non si vede l'alimentatore di arduino che è esterno alla scatola-centralina

sempre e comunque grazie!!

allegati…

Il modulo RTC non lo conosco: ha i resistori di pull up sulla linea I2C?

Comunque è possibile che ci sia un disturbo dovuto alla apertura dei contatti sui relè collegato a carichi induttivi.

Prova ad inserire sui contatti uno snubber come ti ha detto Etem.