Blocco del codice random

Buongiorno a tutti,
mi trovo di nuovo a chiedere aiuto per un progetto sul quale avevo già aperto un argomento qui sul forum. faccio un recap del progetto:

DESCRIZIONE DEL PROGETTO:
serra completamente automatizzata con regolazione di : temperatura, umidità, e cicli di areazione.
in base ai parametri impostati, Arduino mantiene costanti le condizioni all'interno della serra e
sul display è possibile visualizzare: i valori attuali, i valori registrati in Arduino, dei checkbox che mostrano in tempo reale quale attuatore è attivo ed infine è possibile selezionare tramite i rispettivi pulsanti il funzionamento in manuale di ogni singolo attuatore ed escluderlo cosi dal ciclo automatico.

il tutto è indicizzato in modo da poter cambiare i parametri a proprio piacimento, soprattutto in base alla tipologia di coltura in serra, tramite un display Nextion "nx4827t043_011" ed un Arduino uno.
Il display è programmato con la libreria ufficiale (modificata in modo da essere compatibile con arduino)

a banco tutto funzionava, dopodiché mi sono concentrato sulla creazione fisica della mia bellissima serra.
ora che anche la serra è pronta ho installato arduino e tutta la componentistica ed ho provato il tutto. Ma mi è sorto un problema che non riesco a capire da cosa sia dovuto.

Il problema è il seguente:
Arduino fa ciò che deve idem il Display Nextion quindi il mantenimento della temperatura sulla base dei valori impostati e la gestione dei vari cicli di aereazione, solo che dopo qualche ora di corretto funzionamento il tutto si blocca....non mantenendo più i parametri impostati.

il Display continua a funzionare mostrando i valori attuali e se provo ad attivare gli attuatori in manuale tramite gli appositi bottoni singolarmente funzionano, ma se li lascio in automatico la gestione della temperatura e dell'umidità non funziona quindi non mantiene i valori impostati....

Magari c'è qualche dettaglio che mi sfugge......quindi chiedo aiuto.

#include <Nextion.h>    //includo la libreria per il display
#include <SimpleDHT.h>  //includo libreria per il sensore DHT22
/*definisco tutti i campi con cui bisogna interagire nel dispay
*ogni campo è contraddistinto da:
*-tipo di oggetto (pulsante,campo di testo,campo numerico,check box)
*-coordinare di posizione sulle pagine (numero pagina, ID, "nome") questi valori sono sul programma del pannello. */
//-------PAGINA 0---HOME
NexText Temperatura_Letta = NexText(0, 7, "t50");
NexText Umidita_Letta = NexText(0, 8, "t51");
NexCheckbox Presenza_Luce = NexCheckbox(0, 12, "c8");
//-------PAGINA 1---TEMPERATURA
NexNumber Temperatura_Max_Giorno = NexNumber(1, 5, "n50");
NexNumber Temperatura_Min_Giorno = NexNumber(1, 6, "n51");
NexNumber Temperatura_Max_Notte = NexNumber(1, 20, "n54");
NexNumber Temperatura_Min_Notte = NexNumber(1, 21, "n55");
NexNumber Umidita_Max = NexNumber(1, 13, "n52");
NexNumber Umidita_Min = NexNumber(1, 14, "n53");

NexButton Pulsante_Invio_Temp = NexButton(1, 7, "i0");
//-------PAGINA 2---ARIA
NexNumber Ventilatore_Ton_Set = NexNumber(2, 8, "n58");
NexNumber Ventilatore_Toff_Set = NexNumber(2, 9, "n59");
NexNumber Ventilatore_Ton_Arduino = NexNumber(2, 20, "n60");
NexNumber Ventilatore_Toff_Arduino = NexNumber(2, 21, "n61");

NexNumber Estrattore_Ton_Set = NexNumber(2, 14, "n62");
NexNumber Estrattore_Toff_Set = NexNumber(2, 15, "n63");
NexNumber Estrattore_Ton_Arduino = NexNumber(2, 24, "n64");
NexNumber Estrattore_Toff_Arduino = NexNumber(2, 25, "n65");

NexButton Pulsante_Invio_Aria = NexButton(2, 16, "i1");
//-------PAGINA 3---MANUALI
NexButton Pulsante_On_Tenda_Mano = NexButton(3, 6, "b10");
NexButton Pulsante_Off_Tenda_Mano = NexButton(3, 7, "b11");
NexText Txt_Tenda_Mano = NexText(3, 20, "t53");

NexButton Pulsante_On_Estrattore_Mano = NexButton(3, 10, "b12");
NexButton Pulsante_Off_Estrattore_Mano = NexButton(3, 11, "b13");
NexText Txt_Estrattore_Mano = NexText(3, 21, "t54");

NexButton Pulsante_On_Ventilatore_Mano = NexButton(3, 13, "b14");
NexButton Pulsante_Off_Ventilatore_Mano = NexButton(3, 14, "b15");
NexText Txt_Ventilatore_Mano = NexText(3, 18, "t55");

NexButton Pulsante_On_Umidificatore_Mano = NexButton(3, 16, "b16");
NexButton Pulsante_Off_Umidificatore_Mano = NexButton(3, 17, "b17");
NexText Txt_Umidificatore_Mano = NexText(3, 19, "t56");

NexButton Pulsante_Leggi_Manuali = NexButton(3, 22, "i4");
//-------PAGINA 4---STS_ATTUATORI
NexCheckbox Checkbox_Tenda_On = NexCheckbox(4, 7, "c4");
NexCheckbox Checkbox_Estrattore_On = NexCheckbox(4, 5, "c5");
NexCheckbox Checkbox_Ventilatore_On = NexCheckbox(4, 3, "c6");
NexCheckbox Checkbox_Umidificatore_On = NexCheckbox(4, 1, "c7");
//-------PAGINA 5---ARDUINO
NexNumber Temp_Giorno_Max_Set = NexNumber(5, 5, "n70");
NexNumber Temp_Giorno_Min_Set = NexNumber(5, 6, "n71");
NexNumber Temp_Notte_Max_Set = NexNumber(5, 19, "n74");
NexNumber Temp_Notte_Min_Set = NexNumber(5, 20, "n75");
NexNumber Umi_Max_Set = NexNumber(5, 12, "n72");
NexNumber Umi_Min_Set = NexNumber(5, 13, "n73");

NexButton Pulsante_Leggi_Dati = NexButton(5, 23, "i2");

/*con questa istruzione dichiaro quali sono gli oggetti del display che
*devono inviare dei segnali ad Arduino, in questo caso tutti i pulsanti.*/
NexTouch *nex_list[] = {
  &Pulsante_Invio_Temp, &Pulsante_Invio_Aria, &Pulsante_Leggi_Manuali, &Pulsante_Leggi_Dati,
  &Pulsante_On_Tenda_Mano, &Pulsante_Off_Tenda_Mano,
  &Pulsante_On_Estrattore_Mano, &Pulsante_Off_Estrattore_Mano,
  &Pulsante_On_Ventilatore_Mano, &Pulsante_Off_Ventilatore_Mano,
  &Pulsante_On_Umidificatore_Mano, &Pulsante_Off_Umidificatore_Mano,
  NULL
};

SimpleDHT22 dht22(5);  //definisco oggetto dht22 e lo assegno al pin 5
float temp = 0;        //definisco la variabile "temp" con la virgola
float umi = 0;         //definisco la viriabile "umi" con la virgola
unsigned int lux;      //definisco variabile per la lettura analogica della fotoresistenza

const int tenda = 8;          //definisco la tenda e la assegno al pin 8
const int umidificatore = 9;  //definisco l'umidificatore e lo assegno al pin 9
const int ventilatore = 10;   //definisco il ventilatore e lo assegno al pin 10
const int estrattore = 11;    //definisco l'estrattore e lo assegno al pin 11
//variabili che gestiscono i checkbox degli attutori
bool t = false;
bool u = false;
bool v = false;
bool e = false;
//variabili che gestiscono i manuali
bool t_mano = false;
bool u_mano = false;
bool v_mano = false;
bool e_mano = false;

//variabili dove vengono salvati i valori impostati dal HMI per temperatura ed umidità
unsigned long Temp_Max_Giorno = 25;
unsigned long Temp_Min_Giorno = 20;
unsigned long Temp_Max_Notte = 25;
unsigned long Temp_Min_Notte = 20;
unsigned long Umi_Max = 60;
unsigned long Umi_Min = 40;

//variabili per il timer che aggiornerà i dati inviati al display
unsigned long HMI_t1, HMI_dt;
unsigned long xt1, xdt;
//variabili per il timer che gestirà il ventilatore
unsigned long V_t1, V_dt1;        //dichiaro due variabili "t1 = conteggio tempo" ; "dt1 = differenza"
bool VENT = LOW;                  //inizializzo uno stato per il ventilatore "ON"
unsigned long tempoVent = 0;      //inizializzo la variabile che conterrà il tempo di ON/OFF
unsigned long tempoVent_ON = 1;   //inizializzo un valore iniziale di bakup
unsigned long tempoVent_OFF = 4;  //inizializzo un valore iniziale di bakup
unsigned long bk_V_ON;            //inizializzo la variabile che conterrà il valore di "ON" da visualizzare dul HMI
unsigned long bk_V_OFF;           //inizializzo la variabile che conterrà il valore di "OFF" da visualizzare dul HMI
//variabili per il timer che gestirà l'estrattore
unsigned long E_t1, E_dt1;       //dichiaro due variabili "t1 = conteggio tempo" ; "dt1 = differenza"
bool EST = LOW;                  //inizializzo uno stato per l'estrattore "ON"
unsigned long tempoEst = 0;      //inizializzo la variabile che conterrà il tempo di ON/OFF
unsigned long tempoEst_ON = 1;   //inizializzo un valore iniziale di bakup
unsigned long tempoEst_OFF = 9;  //inizializzo un valore iniziale di bakup
unsigned long bk_E_ON;           //inizializzo la variabile che conterrà il valore di "ON" da visualizzare dul HMI
unsigned long bk_E_OFF;          //inizializzo la variabile che conterrà il valore di "OFF" da visualizzare dul HMI

unsigned long h = 60000;

void setup() {
  Serial.begin(9600);  //definisco la seriale
  nexInit();           //inizzializzo il display

  Pulsante_Leggi_Manuali.attachPop(Leggi_Manuali, &Pulsante_Leggi_Manuali);
  Pulsante_Leggi_Dati.attachPop(Leggi_Dati, &Pulsante_Leggi_Dati);

  Pulsante_Invio_Temp.attachPop(Inviadati_Temperatura, &Pulsante_Invio_Temp);
  Pulsante_Invio_Aria.attachPop(Timer, &Pulsante_Invio_Aria);

  Pulsante_On_Tenda_Mano.attachPop(manu_tenda_on, &Pulsante_On_Tenda_Mano);     //associo una funzione specifica per il bottone corrispondente
  Pulsante_Off_Tenda_Mano.attachPop(manu_tenda_off, &Pulsante_Off_Tenda_Mano);  //("nome funzione", "&oggetto corrispondente")

  Pulsante_On_Estrattore_Mano.attachPop(manu_estrattore_on, &Pulsante_On_Estrattore_Mano);
  Pulsante_Off_Estrattore_Mano.attachPop(manu_estrattore_off, &Pulsante_Off_Estrattore_Mano);

  Pulsante_On_Ventilatore_Mano.attachPop(manu_ventilatore_on, &Pulsante_On_Ventilatore_Mano);
  Pulsante_Off_Ventilatore_Mano.attachPop(manu_ventilatore_off, &Pulsante_Off_Ventilatore_Mano);

  Pulsante_On_Umidificatore_Mano.attachPop(manu_umidificatore_on, &Pulsante_On_Umidificatore_Mano);
  Pulsante_Off_Umidificatore_Mano.attachPop(manu_umidificatore_off, &Pulsante_Off_Umidificatore_Mano);

  pinMode(tenda, OUTPUT);             //definisco la tenda come un output
  pinMode(umidificatore, OUTPUT);     //definisco l'umidificatore come un output
  pinMode(ventilatore, OUTPUT);       //definisco il ventilatore come un output
  pinMode(estrattore, OUTPUT);        //definisco l'estrattore come un output
  digitalWrite(tenda, HIGH);          //spengo la tenda
  digitalWrite(umidificatore, HIGH);  //spengo l'umidificatore
  digitalWrite(ventilatore, HIGH);    //spengo il ventilatore
  digitalWrite(estrattore, HIGH);     //spengo l'estrattore
}

void loop() {
  nexLoop(nex_list); /*metto in loop gli elementi del display da monitorare (i pulsanti)
                      quando uno degli elementi della lista invia un segnale si eseguirà la sua funzione*/
  Ciclo();           //metto in loop la funzione "Ciclo"

  HMI_dt = millis() - HMI_t1;  //ogni 500ms richiamo la funzione "Lettura_Temp_Umi_Luce"
  if (HMI_dt > 500) {
    Lettura_Temp_Umi_Luce();
    HMI_t1 = millis();
  }
  xdt = millis() - xt1;  //ogni 2secondi richiamo la funzione "Attuatori"
  if (xdt > 2000) {
    Attuatori();
    xt1 = millis();
  }
}

void Ciclo() {
  if (lux > 100) {  //se la fotoresistenza rileva luce controllo i parametri settatati per il giorno
    //////////////////--CONTROLLO TEMPERATURA--//////////////
    if (t_mano == false) {
      if (temp <= Temp_Min_Giorno) {  //se la variabile "temperature" è <= a "Temp_Min_Giorno"
        digitalWrite(tenda, LOW);     //accendo la tenda
        t = true;
      } else if (temp >= Temp_Max_Giorno) {  //altrimenti se la variabile "temperature" è >= a "Temp_Max_Giorno"
        digitalWrite(tenda, HIGH);           //spengo la tenda
        t = false;
      }
    }
  }
  //__
  else if (lux < 60) {  //se la fotoresistenza NON rileva luce controllo i parametri settatati per la notte
    /////////////////--CONTROLLO TEMPERATURA--///////////////
    if (t_mano == false) {
      if (temp <= (Temp_Min_Notte)) {  //se la variabile "temperature" è <= a "Temp_Min_Giorno"
        digitalWrite(tenda, LOW);      //accendo la tenda
        t = true;
      } else if (temp >= Temp_Max_Notte) {  //altrimenti se la variabile "temperature" è >= a "Temp_Max_Giorno"
        digitalWrite(tenda, HIGH);          //spengo la tenda
        t = false;
      }
    }
  }
  if (temp > 30.00) {                   //se la variabile "temperature" è > 30°C
    digitalWrite(estrattore, LOW);      //accendo estrattore
    digitalWrite(ventilatore, LOW);     //accendo ventilatore
    digitalWrite(umidificatore, HIGH);  //spengo umidificatore
    e = true;
    v = true;
    u = false;
  } else if (temp <= 30.00) {
    //////////////////--CONTROLLO UMIDITà--/////////////////
    if (u_mano == false) {
      if (umi >= Umi_Max) {                 //se la variabile "humidity" è >= a "Umi_Max"
        digitalWrite(umidificatore, HIGH);  //spengo l'umidificatore
        u = false;
      } else if (umi <= Umi_Min) {         //altrimenti se la variabile "humidity" è <= a "Umi_Min"
        digitalWrite(umidificatore, LOW);  //accendo l'umidificatore
        u = true;
      }
    }
    /////////////////--TIMER VENTILATORE--///////////////
    if (v_mano == false) {
      V_dt1 = millis() - V_t1;             //calcolo la differenza di tempo (primo ciclo vale 0)
      if (V_dt1 >= tempoVent) {            //se la differenza è maggiore della variabile tempoVent
        V_t1 = millis();                   //assegno a "t1" il valore corrente di "millis()"
        VENT = !VENT;                      //assegno allo stato del ventilatore il suo stato negato
        digitalWrite(ventilatore, !VENT);  //assegno all'uscita del ventilatore lo stato appena calcolato

        if (VENT) {                                       //verifico lo stato del ventilatore se =1
          bk_V_ON = tempoVent = (tempoVent_ON * h);       //assegno a "bk_V_ON" e "tempoVent" il valore di "tempoVent_ON" moltiplicato per h (per ottenere i millisec.)
          Ventilatore_Ton_Arduino.setValue(bk_V_ON / h);  //scrivo nel campo di testo "Ventilatore_Ton_Arduino" il valore di "bk_V_ON" diviso per h (per ottenere i minuti)
          v = true;
        } else {                                            //verifico lo stato del ventilatore se =0
          bk_V_OFF = tempoVent = (tempoVent_OFF * h);       //assegno alle due varibili "bk_V_OFF" e "tempoVent" il valore di "tempoVent_OFF"
          Ventilatore_Toff_Arduino.setValue(bk_V_OFF / h);  //scrivo nel campo di testo "Ventilatore_Toff_Arduino" il valore di "bk_V_OFF"
          v = false;
        }
      }
    }
    /////////////////--TIMER ESTRATTORE--///////////////
    if (e_mano == false) {
      E_dt1 = millis() - E_t1;
      if (E_dt1 >= tempoEst) {
        E_t1 = millis();
        EST = !EST;
        digitalWrite(estrattore, !EST);

        if (EST) {
          bk_E_ON = tempoEst = (tempoEst_ON * h);
          Estrattore_Ton_Arduino.setValue(bk_E_ON / h);
          e = true;
        } else {
          bk_E_OFF = tempoEst = (tempoEst_OFF * h);
          Estrattore_Toff_Arduino.setValue(bk_E_OFF / h);
          e = false;
        }
      }
    }
  }
}

void Lettura_Temp_Umi_Luce() {  //definisco la funzione

  lux = analogRead(A1);
  dht22.read2(&temp, &umi, NULL);  //leggo le 2 variabili di temperature e humidity

  if (lux > 100) {                            //se la fotoresistenza rileva luce accendo il checkbox
    Presenza_Luce.Set_font_color_pco(1024);   //assegno il colore "1024" (verde) al quadratino del checkbox
  } else if (lux < 60) {                      //se la fotoresistenza NON rileva luce spengo il checkbox
    Presenza_Luce.Set_font_color_pco(65535);  //assegno il colore "65535" (bianco) al quadratino del checkbox
  }

  String command = "t50.txt=\"" + String(temp, 1) + "\"";  //comando in C invio una stringa contenente la variabile "temp"
  Serial.print(command);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);

  String command2 = "t51.txt=\"" + String(umi, 1) + "\"";
  Serial.print(command2);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

void Attuatori() {
  if (t) {                                       //se ho la variabile "t" vuol dite che la tenda è accesa
    Checkbox_Tenda_On.Set_font_color_pco(1024);  //coloro il corrispondente Checkbox di verde
  } else {                                       //se non la ho la tenda è spenta
    Checkbox_Tenda_On.Set_font_color_pco(0);     //coloro il corrispondente Checkbox di verde
  }
  if (e) {
    Checkbox_Estrattore_On.Set_font_color_pco(1024);
  } else {
    Checkbox_Estrattore_On.Set_font_color_pco(0);
  }
  if (v) {
    Checkbox_Ventilatore_On.Set_font_color_pco(1024);
  } else {
    Checkbox_Ventilatore_On.Set_font_color_pco(0);
  }
  if (u) {
    Checkbox_Umidificatore_On.Set_font_color_pco(1024);
  } else {
    Checkbox_Umidificatore_On.Set_font_color_pco(0);
  }
}

void Timer(void *ptr) {
  Ventilatore_Ton_Set.getValue(&tempoVent_ON);  //scrivo il valore contenuto nel campo numerico "T_ON_Vent" nella variabile "tempoVent_ON"
  Ventilatore_Toff_Set.getValue(&tempoVent_OFF);
  Estrattore_Ton_Set.getValue(&tempoEst_ON);
  Estrattore_Toff_Set.getValue(&tempoEst_OFF);

  Ventilatore_Ton_Arduino.setValue(tempoVent_ON);  //leggo il valore nella variabile "tempoVent_ON" e lo scrivo nel campo di testo "Ventilatore_Ton_Arduino"
  Ventilatore_Toff_Arduino.setValue(tempoVent_OFF);
  Estrattore_Ton_Arduino.setValue(tempoEst_ON);
  Estrattore_Toff_Arduino.setValue(tempoEst_OFF);
}

void Inviadati_Temperatura(void *ptr) {
  Temperatura_Max_Giorno.getValue(&Temp_Max_Giorno);  //leggo il valore che è contenuto nel campo numerico "Temperatura_Max_Giorno" e lo scrivo in "Temp_Max_Giorno"
  Temperatura_Min_Giorno.getValue(&Temp_Min_Giorno);
  Temperatura_Max_Notte.getValue(&Temp_Max_Notte);
  Temperatura_Min_Notte.getValue(&Temp_Min_Notte);
  Umidita_Max.getValue(&Umi_Max);
  Umidita_Min.getValue(&Umi_Min);
}

void manu_tenda_on(void *ptr) {                   //se premo il pusante "ON" che attiva il funzionamento manuale
  t_mano = true;                                  //setto a true il bit che uso nel "Ciclo"
  digitalWrite(tenda, LOW);                       //accendo la tenda
  t = true;                                       //setto a true il bit che colora il checkbox degli attuatori
  Txt_Tenda_Mano.setText("Manuale");              //scrivo nel campo di testo corrispondente sul display "manuale"
  Txt_Tenda_Mano.Set_background_color_bco(1024);  //coloro il campo di testo corrispondente di verde
}
void manu_tenda_off(void *ptr) {                   //se premo il pulsante "OFF" che disattiva il funzionamento manuale
  t_mano = false;                                  //resetto il bit
  digitalWrite(tenda, HIGH);                       //spengo la tenda
  t = false;                                       //resetto il bit
  Txt_Tenda_Mano.setText("Automatico");            //scrivo nel campo di testo corrispondente sul display "automatico"
  Txt_Tenda_Mano.Set_background_color_bco(63488);  //coloro il campo di testo corrispondente di grigio
}
void manu_estrattore_on(void *ptr) {
  e_mano = true;
  digitalWrite(estrattore, LOW);
  e = true;
  Txt_Estrattore_Mano.setText("Manuale");
  Txt_Estrattore_Mano.Set_background_color_bco(1024);
}
void manu_estrattore_off(void *ptr) {
  e_mano = false;
  digitalWrite(estrattore, HIGH);
  e = false;
  Txt_Estrattore_Mano.setText("Automatico");
  Txt_Estrattore_Mano.Set_background_color_bco(63488);
}
void manu_ventilatore_on(void *ptr) {
  v_mano = true;
  digitalWrite(ventilatore, LOW);
  v = true;
  Txt_Ventilatore_Mano.setText("Manuale");
  Txt_Ventilatore_Mano.Set_background_color_bco(1024);
}
void manu_ventilatore_off(void *ptr) {
  v_mano = false;
  digitalWrite(ventilatore, HIGH);
  v = false;
  Txt_Ventilatore_Mano.setText("Automatico");
  Txt_Ventilatore_Mano.Set_background_color_bco(63488);
}
void manu_umidificatore_on(void *ptr) {
  u_mano = true;
  digitalWrite(umidificatore, LOW);
  u = true;
  Txt_Umidificatore_Mano.setText("Manuale");
  Txt_Umidificatore_Mano.Set_background_color_bco(1024);
}
void manu_umidificatore_off(void *ptr) {
  u_mano = false;
  digitalWrite(umidificatore, HIGH);
  u = false;
  Txt_Umidificatore_Mano.setText("Automatico");
  Txt_Umidificatore_Mano.Set_background_color_bco(63488);
}

void Leggi_Manuali(void *ptr) {
  if (t_mano == true) {                              //se "t_mano" è vero vuol dire che il pulsante di abilitazione manuale è stato premuto
    Txt_Tenda_Mano.setText("Manuale");               //scrivo nel campo di testo corrispondente sul display "manuale"
    Txt_Tenda_Mano.Set_background_color_bco(1024);   //coloro il campo di testo corrispondente di verde
  } else {                                           //se non ho "t_mano" il funzionamento prosegue in autmoatico
    Txt_Tenda_Mano.setText("Automatico");            //scrivo nel campo di testo corrispondente sul display "automatico"
    Txt_Tenda_Mano.Set_background_color_bco(63488);  //coloro il campo di testo corrispondente di rosso
  }
  if (e_mano == true) {
    Txt_Estrattore_Mano.setText("Manuale");
    Txt_Estrattore_Mano.Set_background_color_bco(1024);
  } else {
    Txt_Estrattore_Mano.setText("Automatico");
    Txt_Estrattore_Mano.Set_background_color_bco(63488);
  }
  if (v_mano == true) {
    Txt_Ventilatore_Mano.setText("Manuale");
    Txt_Ventilatore_Mano.Set_background_color_bco(1024);
  } else {
    Txt_Ventilatore_Mano.setText("Automatico");
    Txt_Ventilatore_Mano.Set_background_color_bco(63488);
  }
  if (u_mano == true) {
    Txt_Umidificatore_Mano.setText("Manuale");
    Txt_Umidificatore_Mano.Set_background_color_bco(1024);
  } else {
    Txt_Umidificatore_Mano.setText("Automatico");
    Txt_Umidificatore_Mano.Set_background_color_bco(63488);
  }
}

void Leggi_Dati(void *ptr) {
  Temp_Giorno_Max_Set.setValue(Temp_Max_Giorno);  //leggo il valore contenuto nella variabile "Temp_Max_Giorno" e lo scrivo nel campo di testo "Temp_Giorno_Max_Set"
  Temp_Giorno_Min_Set.setValue(Temp_Min_Giorno);
  Temp_Notte_Max_Set.setValue(Temp_Max_Notte);
  Temp_Notte_Min_Set.setValue(Temp_Min_Notte);
  Umi_Max_Set.setValue(Umi_Max);
  Umi_Min_Set.setValue(Umi_Min);
}

progetto_serra_copia.ino (19,3 KB)

Partiamo dalle basi. Quale modello di Arduino esattamente?

Ciao, l'ho scritto nel post.
comunque è un Arduino uno (quello vecchio)

Vero, scusa, era un po' "affogato" nel resto del testo. :wink:

Beh, ci sono in genere due aspetti da considerare, entrambi relativi alle stringhe, ossia alle "String" ed alle "stringhe C" ossia "char array".

Per le "stringhe C" il problema può risiedere in errori di puntatori ossia in caso di stringhe non terminate da '\0' entro il limite della dimensione preallocata, il puntatore rischia di "vagare" per codice non legittimo e quindi portare a risultati poco prevedibili.

Ma in questo caso credo il problema sia il secondo. Nel codice vedo che usi variabili della classe "String" e, per farla breve, su UNO (in genere si scrive maiuscolo...) R3 (quello "vecchio") l'uso delle variabili "String" è altamente sconsigliato perché la loro gestione, seppure sia "comoda" per chi programma, può causare malfunzionamenti fino al blocco totale del codice. Il problema avviene perché la gestione della memoria per queste variabili non è ottimizzato e soprattutto non essendoci un "garbage collector" su UNO a furia di creare e modificare "String" la memoria si frammenta eccessivamente, fino a che non si riesce più a far funzionare correttamente lo sketch.

Per ulteriori informazioni su questo problema, puoi leggere in rete ad esempio qui:

o anche questo:

Detto questo, il mio consiglio è quello di evitare il più possibile l'uso di "String" e convertire le variabili in "stringhe C".

Quoto al 100%. Alla peggio c'è la classe Safe string

ok perfetto, intanto ti ringrazio per le precisazioni :sweat_smile:

per quanto riguarda la conversione invece presumo ti stia riferendo a questa parte del codice:

String command = "t50.txt=\"" + String(temp, 1) + "\"";  //comando in C invio una stringa contenente la variabile "temp"
  Serial.print(command);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);

  String command2 = "t51.txt=\"" + String(umi, 1) + "\"";
  Serial.print(command2);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);

questa parte è quella che scrive nel campo di testo sul display la temperatura letta dal sensore DHT22..... parte che ho spudoratamente copiato da un video di YouTube di un ragazzo indiano che utilizzava questo metodo per leggere i valori del sensore.

riusciresti ad indicarmi come fare la conversione in stringhe C?

Un indiano con l'arco e le frecce... :smile:

ciao! ho letto questo post sul Safe string ma è molto tecnico e non credo di aver capito a pieno il concetto...

probabilmente si ahahah :rofl:
ma quantomeno mi ha dato moto di leggere i valori del sensore sul display ma ora sto capendo che non va molto bene questa tipologia di scrittura

A volte non è nemmeno necessario fare quelle cose. Spesso vengono messe insieme più stringhe per fare una sola scrittura sul display, ma non ci si guadagna nulla! Si fa una scrittura per ciascuna stringa o valore numerico e basta. :slight_smile: Anch'io una volta credevo che scrivendo una sola volta tutto insieme sul display fosse conveniente, invece il tempo necessario per il trasferimento dei dati al display è praticamente lo stesso e si aggiunge una possibile fonte di problemi.

Infatti. Se fai 3 serial.print molto meglio

Mai, MAI credere ciecamente ai video di Youtube. :wink:

Quali conoscenze hai tu delle stringhe C?
Comunque se devi solo mandarla via seriale, più semplicemente fare più Serial.print().
Nel tuo caso qualcosa del tipo:

  Serial.print("t50.txt=\""); Serial.print(temp,1); Serial.print("\"");
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff); 

  Serial.print("t51.txt=\""); Serial.print(umi,1); Serial.print("\"");
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff); 

Per la conversione in stringhe C invece, se hai bisogno di creare una stringa formattata si usa in genere una variabile stringa (non "String", quando dico "stringa" intendo "stringa C") come buffer dove copiare l'output con sprintf(). Se hai valori interi puoi fare così:

...
// Buffer temporaneo per le stringhe (impostare dimensione max prevista +1)
char buf[30]; 
...
  sprintf(buf, "t50.txt=\"%d\"", temp);
  Serial.print(buf);

Se hai dei valori float, la sprintf() di Arduino non gestisce i float quindi devi usare un trucchetto per separare la parte intera dal decimale:

...
// Buffer temporaneo per le stringhe (impostare dimensione max prevista +1)
char buf[30]; 
  sprintf(buf, "t50.txt=\"%d.%01d\"", (int)temp, (int)(temp*10)%10));
  Serial.print(buf);
...

grazie innanzi tutto,
le mio conoscenze sono molto a livello scolastico quindi non posso dire di conoscere a pieno l'argomento.

ad ogni modo devo leggere sul display le due variabili "temperatura"e"umidità" entrambe sono con virgola quindi di tipo float.

perciò dovrei sostituire la parte che ho scritto io

  String command = "t50.txt=\"" + String(temp, 1) + "\"";  //comando in C invio una stringa contenente la variabile "temp"
  Serial.print(command);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);

con la terza opzione che mi hai suggerito tu giusto?

// Buffer temporaneo per le stringhe (impostare dimensione max prevista +1)
char buf[30]; 
  sprintf(buf, "t50.txt=\"%d.%01d\"", (int)temp, (int)(temp*10)%10));
  Serial.print(buf);

char buf1[30]; 
  sprintf(buf, "t51.txt=\"%d.%01d\"", (int)umi, (int)(umi*10)%10));
  Serial.print(buf1);

questo dovrebbe essere corretto? chiaramente la variabile "buf" deve avere un nome diverso giusto?

Puoi usare un solo buf, stampato la prima volta è "libero" di essere riusato per la seconda print

Non è necessario, soprattutto perché la variabile che usi per questo scopo è "usa e getta" quindi puoi benissimo sovrascrivere il precedente valore.
Ma se la variabile la imposti come globale (ossia la sua definizione "char buf[30];" la metti in testa al codice, fuori dalle funzioni) per renderla visibile a tutto il codice, ti basta quella. Nel listato che ti ho messo se ci fai caso la definizione l'ho messa tra puntini (ad indicare "qui c'è altro codice") e soprattutto indentata in prima colonna (per dire "non si trova dentro a nessuna funzione").

Potrebbe anche diventare una funzione

void ScriviCmdFloat(byte t,float val)
{ char cmd[15];          // t99="xxx.x"  circa 12 char compreso fine stringa
  spnrintf(cmd,15, "t%d.txt=\"%d.%01d\"", t ,(int)val, (int)(val*10)%10));
  Serial.print(cmd);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

Quindi al posto di:

  Serial.print("t50.txt=\""); Serial.print(temp,1); Serial.print("\"");
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff); 

  Serial.print("t51.txt=\""); Serial.print(umi,1); Serial.print("\"");
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);

Usi

  ScriviCmdFloat(50,temp);   //t50
  ScriviCmdFloat(51,umi);    //t51

allora questa mia domanda è dovuta sicuramente a una poca esperienza nell'argomento.

allora io questo pezzo di codice lo ho inserito in una funzione "Lettura_Temp_Umi_Luce" questa funzione la richiamo nel void loop ogni 500ms di modo che in maniera costante ho una lettura dei sensori sempre visibile a pannello.

quindi dato che la scrivo sempre come è possibile che la variabile buf sia usa e getta? come fa a contenere due valori distinti , temperatura ed umidità nello stesso momento?

Conterrà ciò che ci metterà temporaneamente la funzione di volta in volta.

Non lo fa. Prima conterrà il primo valore, lo spari sulla seriale e quindi... quel buf ora è "sporco" ma libero per usarlo di nuovo per il secondo valore.

Il che depone a favore del problema della frammentazione della memoria causata dall'uso delle "String"... :wink:

Ma veramente chiedi questo? Ma dai, non posso crederci, se hai scritto tutto quel popo' di codice con tanto di puntatori ed array di oggetti, non sai come funziona l'uso di una variabile da usare solo per comporre una stringa e poi riutilizzarla per altro?
Non è che magari quel codice non lo hai scritto tu ma è un lavoro di copia/incolla fatto senza capirci nulla, no, eh?