ESP32 for a greenhouse that disconnects regularly from the cloud

Hello everyone (French below),

Here's my current situation. I've created a small system consisting of 2 boxes. Each box contains an ESP32 connected to the arduino Cloud.
The system has several purposes:

  1. To enable the greenhouse to be watered (via a choice of solenoid valves) either physically on the box in the greenhouse or via the cloud application.
  2. Monitor the temperature of the greenhouse continuously and alert me (and wake me up) if the temperature drops below a critical threshold OR if the connection has been lost for some time, which could indicate either a power cut in the greenhouse or a wifi problem.

The system works: both watering and monitoring and wakes me up via a buzzer.

However, I'm regularly woken up by the buzzer during the night because either it's the greenhouse box that disconnects (see the 1st screenshot showing the connection/disconnection times), or it's the one in the bedroom.

The one in the nursery disconnects at more or less regular times when it does (often between 2 and 3 in the morning), whereas the one in the bedroom is more random.


NB: I apologise in advance for the level and possible "simple" errors, I'm a beginner :slight_smile:

Here's the code for the nursery box :

/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled"
  https://create.arduino.cc/cloud/things/380e36ea-1c54-427d-a5b2-5b437254252c 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  CloudElectricCurrent courant;
  int cold_threshold;
  int error_sensorT;
  int problem;
  int status_wifiPep;
  int uptime;
  CloudRelativeHumidity humid_DHT;
  bool button_cloud1;
  bool button_cloud2;
  bool button_cloud3;
  bool button_cloud4;
  bool ev1_state;
  bool ev2_state;
  bool ev3_state;
  bool ev4_state;
  CloudTemperature temp_DHT;
  CloudTemperature temp_DS1;
  CloudTemperature temp_DS2;
  CloudTemperature temp_DS3;
  CloudTemperature temp_DS4;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"

// (1) : Partie T°

#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Arduino.h>
#define ONE_WIRE_BUS 27 

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DHT dht1(23, DHT22); 

const int Led_error_sensorT = 4;
const int Led_problem = 16;

int No_adresse = 0;

int blink_error_sensorT = 0;
int blink_problem = 0;

DeviceAddress tempDeviceAddresses[4]; // Tableau pour stocker les adresses des capteurs
int numSensors = 0; // Nombre de capteurs trouvés

float tempC[4];


// (2) : Partie électrovannes :

// Déclaration des leds des électrovannes :
const int ledEv1 = 18;
const int ledEv2 = 19;
const int ledEv3 = 21;
const int ledEv4 = 22;

//Déclaration des sorties des électrovannes : 
const int Ev1 = 26;
const int Ev2 = 25;
const int Ev3 = 33;
const int Ev4 = 32;

// Déclaration du pin des boutons physiques des électrovannes + la valeur défaut :
const int button_pin = 36;
int button_value = 0;

// Déclaration des états des boutons physiques des ev :
bool button_phys1_state = false;
bool button_phys2_state = false;
bool button_phys3_state = false;
bool button_phys4_state = false;

// Déclaration des états des boutons cloud des ev :
bool button_cloud1_state = false;
bool button_cloud2_state = false;
bool button_cloud3_state = false;
bool button_cloud4_state = false;

unsigned long ev1StartTime = 0; // Temps de début pour électrovanne 1
unsigned long ev2StartTime = 0; // Temps de début pour électrovanne 2
unsigned long ev3StartTime = 0; // Temps de début pour électrovanne 3
unsigned long ev4StartTime = 0; // Temps de début pour électrovanne 4

const long irrigation_time = 300000; //Temps d'irrigation

void setup() {
  Serial.begin(9600);
  delay(1500); 
  
  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  Serial.println("V2 Programme surveillance pepiniere");
  Serial.println("==========================");
  Serial.println();
  
  // Initialisation du DHT22-1;
  dht1.begin();
  
  pinMode(Led_error_sensorT, OUTPUT);
  pinMode(Led_problem, OUTPUT);
  pinMode(ledEv1, OUTPUT);
  pinMode(ledEv2, OUTPUT);
  pinMode(ledEv3, OUTPUT);
  pinMode(ledEv4, OUTPUT);
  pinMode(Ev1, OUTPUT);
  pinMode(Ev2, OUTPUT);
  pinMode(Ev3, OUTPUT);
  pinMode(Ev4, OUTPUT);
  
  /*
    The following function allows you to obtain more information
    related to the state of network and IoT Cloud connection and errors
    the higher number the more granular information you’ll get.
   The default is 0 (only errors).
    Maximum is 4
  */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
  
  cold_threshold = 10; // Modifier ICI le seuil de froid.
  
  error_sensorT = 0;
/* Liste : 
1 : Si temp DS = -127 sur 1-3 capteurs : erreur branchement (voir blink pour déterminer lequel/lesquels)
2 : Si temp DS = -127 sur TOUS les capteurs : erreur branchement
3 :

*/

problem = 0;
/* Liste : 
1 : Température seuil (cold_threshold) dépassée
2 : Problème de connexion Wifi
3 : Problème de connexion Cloud
4 : 
5 : 
6 : 

*/

 ev1_state = false;
 ev2_state = false;
 ev3_state = false;
 ev4_state = false;
 
 digitalWrite(Ev1, HIGH);
 digitalWrite(Ev2, HIGH);
 digitalWrite(Ev3, HIGH);
 digitalWrite(Ev4, HIGH);

  /* Initialisation des adresses des DS18B20 */ 
  Init_and_TDS(); // Appel de la fonction d'initialisation des adresses DS18B20
  ArduinoCloud.update();
  delay(500);
  digitalWrite(Led_problem, HIGH); // Allume la LED
  delay(500);
  digitalWrite(Led_error_sensorT, HIGH);
  delay(500);
  digitalWrite(ledEv1, HIGH); // Allume la LED
  delay(500);
  digitalWrite(ledEv2, HIGH);
  delay(500);
  digitalWrite(ledEv3, HIGH);
  delay(500);
  digitalWrite(ledEv4, HIGH);
  Serial.println("Test leds allumées");
  delay(3000);
  digitalWrite(Led_problem, LOW); // Allume la LED
  delay(500);
  digitalWrite(Led_error_sensorT, LOW);
  delay(500);
  digitalWrite(ledEv1, LOW); // Éteind la LED
  delay(500);
  digitalWrite(ledEv2, LOW); 
  delay(500);
  digitalWrite(ledEv3, LOW);
  delay(500);
  digitalWrite(ledEv4, LOW);
  Serial.println("Test leds éteintes");
  delay(500);
  delay(20000);
}

void loop() {
  ArduinoCloud.update();
  Serial.println("Début loop : ");
  //Verif si connecté au cloud, si non et + de 5min, restart ESP32
  unsigned long timeMillis = millis();
  static unsigned long timeMillisAntCon = timeMillis;

  if (ArduinoCloud.connected()) {
    timeMillisAntCon = timeMillis;
  } else if (timeMillis - timeMillisAntCon > 300000) {
    ESP.restart();
  }
  Verif_C_W();
  lireTemperatures(); // Appel de la fonction de demande des températures DS18B20
  Init_and_TDHT(); // Appel de la fonction d'initialisation du DHT22
  VerifTDS_TDHT_C_W();
  LedDisplay();
  ButtonTest();
  ButtonCloudTest();
  NormalActivation();
  delay(100);
}

void Verif_C_W() {
  //Verif courant

  
  // Verif Wifi 
  Serial.println("Wifi status =");
  Serial.print(WiFi.status());
  if (WiFi.status() != 3) {
    status_wifiPep = 0;
    Serial.println("status_wifiPep =");
    Serial.print(status_wifiPep);
    Serial.println("Pas de connexion Wifi");
  } 
  else {
    status_wifiPep = 1;
    Serial.println("Connexion Wifi OK");
  }
  
  //Verif connexion au cloud
  if (ArduinoCloud.connected() != 1) {
    status_wifiPep = 2;
    Serial.println("Pas de connexion au cloud");
  }
  
  //Lien de sécurité cloud 
  uptime = uptime + 1;
  Serial.println("uptime =");
  Serial.print(uptime);
  if (uptime >= 10000) {
    uptime = 0;
  }
}


void Init_and_TDS() {
  // Recherche des adresses des capteurs DS18B20
  sensors.begin(); // Réinitialise la recherche
  for (int i = 0; i < 4; i++) {
    if (sensors.getAddress(tempDeviceAddresses[i], i)) {
      // Vérification que l'adresse n'a pas déjà été détectée
      bool addressDuplicate = false;
      for (int j = 0; j < i; j++) {
        if (memcmp(tempDeviceAddresses[i], tempDeviceAddresses[j], 8) == 0) {
          addressDuplicate = true;
          break;
        }
      }
      if (!addressDuplicate) {
        Serial.print("Adresse du capteur ");
        Serial.print(i + 1);
        Serial.print(": ");
        for (int j = 0; j < 8; j++) {
          Serial.print(tempDeviceAddresses[i][j], HEX);
          if (j < 7) {
            Serial.print(":");
          }
        }
        Serial.println();
        numSensors++;
      }
    }
  }

  if (numSensors == 4) {
    Serial.println("Toutes les adresses ont été trouvées.");
    sensors.setWaitForConversion(true);
  } else {
    Serial.println("Certaines adresses n'ont pas été trouvées.");
    digitalWrite(Led_error_sensorT, HIGH);
    while (1); // Bloque le programme en cas de problème
  }
}

void lireTemperatures() {
  // Demande des températures
  sensors.requestTemperatures();
  Serial.println("Lecture des températures :");
  for (int i = 0; i < numSensors; i++) {
    float tempC = sensors.getTempC(tempDeviceAddresses[i]);
    switch (i) {
      case 0:
        temp_DS1 = tempC;
        break;
      case 1:
        temp_DS2 = tempC;
        break;
      case 2:
        temp_DS3 = tempC;
        break;
      case 3:
        temp_DS4 = tempC;
        break;
    }
    Serial.print("Capteur ");
    Serial.print(i + 1);
    Serial.print(" (Adresse : ");
    for (int j = 0; j < 8; j++) {
      if (tempDeviceAddresses[i][j] < 16) {
        Serial.print("0");
      }
      Serial.print(tempDeviceAddresses[i][j], HEX);
      if (j < 7) {
        Serial.print(":");
      }
    }
    Serial.print("): ");
    Serial.print(tempC);
    Serial.println(" °C");
  }
}

void Init_and_TDHT() {
  humid_DHT = dht1.readHumidity(); // Lecture du taux d'humidité (en %)
  temp_DHT = dht1.readTemperature();   // Lecture de la température, exprimée en degrés Celsius
  Serial.println("=============");
  Serial.println("Humid et temp DHT :");
  Serial.print(humid_DHT);
  Serial.print(" / ");
  Serial.print(temp_DHT);
  Serial.println("=============");
}


int VerifTDS_TDHT_C_W() {
  Serial.println("cold_threshold = ");
  Serial.println(cold_threshold);
  /* Blink définit le capteur défaillant et error_sensorT le type de défaut */
  //Si aucun capteurs DS18B20 détecté sur le BUS : 
  //Si temp DS = -127 : erreur branchement
  if (temp_DS1 <= -100) {
    error_sensorT = 1;
    blink_error_sensorT = 1;
    Serial.println("Erreur branchement capteur 1");
  }
  else if (temp_DS2 <= -100) {
    error_sensorT = 1;
    blink_error_sensorT = 2;
    Serial.println("Erreur branchement capteur 2");
  }
  else if (temp_DS3 <= -100) {
    error_sensorT = 1;
    blink_error_sensorT = 3;
    Serial.println("Erreur branchement capteur 3");
  }
  else if (temp_DS4 <= -100) {
    error_sensorT = 1;
    blink_error_sensorT = 4;
    Serial.println("Erreur branchement capteur 4");
  }
  else if ((temp_DS1 <= -100) && (temp_DS2 <= -100) && (temp_DS3 <= -100) && (temp_DS4 <= -100)) {
    error_sensorT = 2;
    blink_error_sensorT = 1;
    Serial.println("Erreur branchement tous les capteurs DS");
  }
  else if (temp_DS1 <= cold_threshold || temp_DS2 <= cold_threshold || temp_DS3 <= cold_threshold || temp_DS4 <= cold_threshold || temp_DHT <= cold_threshold) { 
    problem = 1;
    blink_problem = 1;
    Serial.println("Un des capteurs DS obtient une temp inférieure au seuil défini");
  } 
    else {
    problem = 0;
    blink_problem = 0;
    error_sensorT = 0;
    }
  //Vérif WiFi
  if (status_wifiPep == 0) {
    Serial.println("Problème de Wifi");
    problem = 2;
    blink_problem = 2;
  }
  //Vérif connexion Cloud
  if (status_wifiPep == 2) {
    Serial.println("Problème de connexion au cloud");
    problem = 2;
    blink_problem = 3;
  }
  return (blink_error_sensorT);
  return (blink_problem);
}

void LedDisplay() {
  Serial.print("Blink_error_sensorT = ");
  Serial.print(blink_error_sensorT);
  //Affichage led error sensor T
  for (int a = 0; a < blink_error_sensorT; a++) {
    digitalWrite(Led_error_sensorT, HIGH);
    delay(500);
    digitalWrite(Led_error_sensorT, LOW);
    delay(500);
  }
  blink_error_sensorT = 0;
  
  //Affichage led probleme
  for (int b = 0; b < blink_problem; b++) {
    digitalWrite(Led_problem, HIGH);
    delay(500);
    digitalWrite(Led_problem, LOW);
    delay(500);
    blink_problem = 0;
  }
}

void ButtonTest() {
  button_value = analogRead(button_pin);
  Serial.println(button_value);
  
  if(button_value >=3500) {
    Serial.println("Tous les boutons sont lachés");
  } 
  else if (button_value >= 2803) {
    Serial.println("Le bouton 4 est enfoncé");
    button_phys4_state = true;
  }
  else if (button_value >= 2460) {
    Serial.println("Le bouton 3 est enfoncé");
    button_phys3_state = true;
  }
  else if (button_value >= 1800) {
    Serial.println("Le bouton 2 est enfoncé");
    button_phys2_state = true;
  }
  else if (button_value < 1800) {
    Serial.println("Le bouton 1 est enfoncé");
    button_phys1_state = true;
  }
}

void ButtonCloudTest() {
  if(button_cloud1) {
    Serial.println("Bouton cloud 1 enfoncé");
    button_cloud1_state = true;
  }
  if(button_cloud2) {
    Serial.println("Bouton cloud 2 enfoncé");
    button_cloud2_state = true;
  }
  if(button_cloud3) {
    Serial.println("Bouton cloud 3 enfoncé");
    button_cloud3_state = true;
  }
  if(button_cloud4) {
    Serial.println("Bouton cloud 4 enfoncé");
    button_cloud4_state = true;
  }
}

void NormalActivation() {
  static unsigned long lastButton1PressTime = 0; // Variable pour stocker le temps de la dernière pression du bouton i
  static unsigned long lastButton2PressTime = 0;
  static unsigned long lastButton3PressTime = 0;
  static unsigned long lastButton4PressTime = 0;
  
  //A supprimer normalement (si correction ev 1 fonctionne) :
  static unsigned long button1PressedLastLoop = 0;
  static unsigned long button2PressedLastLoop = 0;
  static unsigned long button3PressedLastLoop = 0;
  static unsigned long button4PressedLastLoop = 0;
  
  // Ev 1 (corrigée) :
  if (button_cloud1_state || button_phys1_state) {
    if (!ev1_state) { // Si l'électrovanne 1 est éteinte
      ev1_state = true; // Active l'électrovanne 1
      digitalWrite(Ev1, LOW);
      digitalWrite(ledEv1, HIGH); // Allume la LED
      ev1StartTime = millis(); // Enregistre le temps de début
      lastButton1PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
      Serial.println("Ev 1 ouverte");
    }  
    if (ev1_state) { // Si l'électrovanne 1 est allumée on regarde si cela fait plus de 2 seconde depuis que le bouton a été enfoncé pour la dernière fois
      // Si + de 2 sec : 
      if (millis() - lastButton1PressTime >= 2000) {
        ev1_state = false; // Désactive l'électrovanne 1
        digitalWrite(Ev1, HIGH);
        digitalWrite(ledEv1, LOW); // Éteint la LED
        Serial.println("Ev 1 fermée manuellement");
      }
      // Si - de 2sec
    } else {
      lastButton1PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
    }

    // Réinitialise le bouton
    button_cloud1_state = false;
    button_phys1_state = false;
  } 
  else if (millis() - ev1StartTime >= irrigation_time) { // Si les 10 secondes se sont écoulées
      ev1_state = false; // Désactive l'électrovanne 1
      digitalWrite(Ev1, HIGH);
      digitalWrite(ledEv1, LOW); // Éteint la LED
      Serial.println("Ev 1 fermée après délai");
    }
    
  // Ev 2 :
  if (button_cloud2_state || button_phys2_state) {
    if (!ev2_state) { // Si l'électrovanne 2 est éteinte
      ev2_state = true; // Active l'électrovanne 2
      digitalWrite(Ev2, LOW);
      digitalWrite(ledEv2, HIGH); // Allume la LED
      ev2StartTime = millis(); // Enregistre le temps de début
      lastButton2PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
      Serial.println("Ev 2 ouverte");
    }  
    if (ev2_state) { // Si l'électrovanne 2 est allumée on regarde si cela fait plus de 2 seconde depuis que le bouton a été enfoncé pour la dernière fois
      // Si + de 2 sec : 
      if (millis() - lastButton2PressTime >= 2000) {
        ev2_state = false; // Désactive l'électrovanne 2
        digitalWrite(Ev2, HIGH);
        digitalWrite(ledEv2, LOW); // Éteint la LED
        Serial.println("Ev 2 fermée manuellement");
      }
      // Si - de 2sec
    } else {
      lastButton2PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
    }

    // Réinitialise le bouton
    button_cloud2_state = false;
    button_phys2_state = false;
  } 
  else if (millis() - ev2StartTime >= irrigation_time) { // Si les 10 secondes se sont écoulées
      ev2_state = false; // Désactive l'électrovanne 2
      digitalWrite(Ev2, HIGH);
      digitalWrite(ledEv2, LOW); // Éteint la LED
      Serial.println("Ev 2 fermée après délai");
    }
    
  // Ev 3 :
  if (button_cloud3_state || button_phys3_state) {
    if (!ev3_state) { // Si l'électrovanne 3 est éteinte
      ev3_state = true; // Active l'électrovanne 3
      digitalWrite(Ev3, LOW);
      digitalWrite(ledEv3, HIGH); // Allume la LED
      ev3StartTime = millis(); // Enregistre le temps de début
      lastButton3PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
      Serial.println("Ev 3 ouverte");
    }  
    if (ev3_state) { // Si l'électrovanne 3 est allumée on regarde si cela fait plus de 2 seconde depuis que le bouton a été enfoncé pour la dernière fois
      // Si + de 2 sec : 
      if (millis() - lastButton3PressTime >= 2000) {
        ev3_state = false; // Désactive l'électrovanne 3
        digitalWrite(Ev3, HIGH);
        digitalWrite(ledEv3, LOW); // Éteint la LED
        Serial.println("Ev 3 fermée manuellement");
      }
      // Si - de 2sec
    } else {
      lastButton3PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
    }

    // Réinitialise le bouton
    button_cloud3_state = false;
    button_phys3_state = false;
  } 
  else if (millis() - ev3StartTime >= irrigation_time) { // Si les 10 secondes se sont écoulées
      ev3_state = false; // Désactive l'électrovanne 3
      digitalWrite(Ev3, HIGH);
      digitalWrite(ledEv3, LOW); // Éteint la LED
      Serial.println("Ev 3 fermée après délai");
    }
  
  // Ev 4 :
  if (button_cloud4_state || button_phys4_state) {
    if (!ev4_state) { // Si l'électrovanne 4 est éteinte
      ev4_state = true; // Active l'électrovanne 4
      digitalWrite(Ev4, LOW);
      digitalWrite(ledEv4, HIGH); // Allume la LED
      ev4StartTime = millis(); // Enregistre le temps de début
      lastButton4PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
      Serial.println("Ev 4 ouverte");
    }  
    if (ev4_state) { // Si l'électrovanne 4 est allumée on regarde si cela fait plus de 2 seconde depuis que le bouton a été enfoncé pour la dernière fois
      // Si + de 2 sec : 
      if (millis() - lastButton4PressTime >= 2000) {
        ev4_state = false; // Désactive l'électrovanne 4
        digitalWrite(Ev4, HIGH);
        digitalWrite(ledEv4, LOW); // Éteint la LED
        Serial.println("Ev 4 fermée manuellement");
      }
      // Si - de 2sec
    } else {
      lastButton4PressTime = millis(); // Met à jour le temps de la dernière pression du bouton
    }

    // Réinitialise le bouton
    button_cloud4_state = false;
    button_phys4_state = false;
  } 
  else if (millis() - ev4StartTime >= irrigation_time) { // Si les 10 secondes se sont écoulées
      ev4_state = false; // Désactive l'électrovanne 4
      digitalWrite(Ev4, HIGH);
      digitalWrite(ledEv4, LOW); // Éteint la LED
      Serial.println("Ev 4 fermée après délai");
    }
}

/*
  Since ErrorSensorT is READ_WRITE variable, onErrorSensorTChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onErrorSensorTChange()  {
  // Add your code here to act upon ErrorSensorT change
}

/*
  Since Problem is READ_WRITE variable, onProblemChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onProblemChange()  {
  // Add your code here to act upon Problem change
}



/*
  Since TempDS2 is READ_WRITE variable, onTempDS2Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onTempDS2Change()  {
  // Add your code here to act upon TempDS2 change
}

/*
  Since TempDHT is READ_WRITE variable, onTempDHTChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onTempDHTChange()  {
  // Add your code here to act upon TempDHT change
}

/*
  Since TempDS3 is READ_WRITE variable, onTempDS3Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onTempDS3Change()  {
  // Add your code here to act upon TempDS3 change
}

/*
  Since TempDS4 is READ_WRITE variable, onTempDS4Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onTempDS4Change()  {
  // Add your code here to act upon TempDS4 change
}


/*
  Since HumidDHT is READ_WRITE variable, onHumidDHTChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onHumidDHTChange()  {
  // Add your code here to act upon HumidDHT change
}


/*
  Since Ev1 is READ_WRITE variable, onEv1Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv1Change()  {
  // Add your code here to act upon Ev1 change
}

/*
  Since Ev2 is READ_WRITE variable, onEv2Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv2Change()  {
  // Add your code here to act upon Ev2 change
}

/*
  Since Ev3 is READ_WRITE variable, onEv3Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv3Change()  {
  // Add your code here to act upon Ev3 change
}

/*
  Since Ev4 is READ_WRITE variable, onEv4Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv4Change()  {
  // Add your code here to act upon Ev4 change
}

/*
  Since ButtonCloud3 is READ_WRITE variable, onButtonCloud3Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onButtonCloud3Change()  {
  // Add your code here to act upon ButtonCloud3 change
}

/*
  Since ButtonCloud2 is READ_WRITE variable, onButtonCloud2Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onButtonCloud2Change()  {
  // Add your code here to act upon ButtonCloud2 change
}

/*
  Since ButtonCloud1 is READ_WRITE variable, onButtonCloud1Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onButtonCloud1Change()  {
  // Add your code here to act upon ButtonCloud1 change
}

/*
  Since ButtonCloud4 is READ_WRITE variable, onButtonCloud4Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onButtonCloud4Change()  {
  // Add your code here to act upon ButtonCloud4 change
}


/*
  Since ColdThreshold is READ_WRITE variable, onColdThresholdChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onColdThresholdChange()  {
  // Add your code here to act upon ColdThreshold change
}

/*
  Since Ev1State is READ_WRITE variable, onEv1StateChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv1StateChange()  {
  // Add your code here to act upon Ev1State change
}

/*
  Since Ev2State is READ_WRITE variable, onEv2StateChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv2StateChange()  {
  // Add your code here to act upon Ev2State change
}

/*
  Since Ev3State is READ_WRITE variable, onEv3StateChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv3StateChange()  {
  // Add your code here to act upon Ev3State change
}

/*
  Since Ev4State is READ_WRITE variable, onEv4StateChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onEv4StateChange()  {
  // Add your code here to act upon Ev4State change
}

/*
  Since Uptime is READ_WRITE variable, onUptimeChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onUptimeChange()  {
  // Add your code here to act upon Uptime change
}

And here's the one for the bedroom box:

/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled"
  https://create.arduino.cc/cloud/things/3da601fe-f49c-49e3-820c-c5f1ef021cd8 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  int error_sensorT_recep;
  int pep_uptime;
  int problem_recep;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

//#include <Preferences.h>
//#include <esp_system.h>
#include "thingProperties.h"

//Preferences preferences;


int Led_problem = 14;
int Led_error_sensorT = 27;
int Led_Wifi = 26;
/* Liste : 
Si éteinte = pas de connexion Wifi
Si fixe = connectée au Wifi et au cloud
Si clignote = connectée au Wifi mais pas au cloud
*/
char Buzzer = 12;

unsigned long previousMillis = 0; // Variable pour stocker le dernier temps en millisecondes
const long interval = 1000; // Intervalle de clignotement en millisecondes (1 seconde)

int last_pep_uptime = 0;
int deconnection_score = 0;

int button_pin = 33;
int button_value = 0;
int mute = 0;
int lap = 0;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();
  
  Serial.println("==========================");
  Serial.println();
  
  // Initialisation des pin des Leds
  pinMode(Led_problem, OUTPUT);
  pinMode(Led_error_sensorT, OUTPUT);
  pinMode(Led_Wifi, OUTPUT);
  pinMode(Buzzer, OUTPUT);
  pinMode(button_pin, INPUT);
  
  void ButtonTest();
  void Verif_C_W();
  void Verif_Connexion_Pepiniere();
  void VerifPepiniere();

  //preferences.begin("myApp", false);
  //deconnection_score = preferences.getUInt("deconnection_score", 0);
  //Serial.println("Initial deconnection_score = ");
  //Serial.print(deconnection_score);
  
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  
  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
 */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();
  ButtonTest();
  Verif_C_W();
  Verif_Connexion_Pepiniere();
  VerifPepiniere();
  //Ajouter la coordination des erreur sensor T.
  delay(5000);
  Serial.println("Hello world");
  Serial.println("WiFi.status =");
  Serial.println(WiFi.status());
  lap++;
}

void ButtonTest() {
  button_value = analogRead(button_pin);
  Serial.println("button_value = ");
  Serial.println(button_value);
  Serial.println("");
  
  if(button_value <= 3000) {
    mute = 1;
  }
  else {
    mute = 0;
    lap = 0;
  }
}

void Verif_C_W() {
  if(WiFi.status() != 3) {
    digitalWrite(Led_Wifi, LOW);
  }
  else {
    digitalWrite(Led_Wifi, HIGH);
    if (ArduinoCloud.connected() != 1) {
      digitalWrite(Led_Wifi, LOW);
      delay(500);
      digitalWrite(Led_Wifi, HIGH);
      delay(500);
      digitalWrite(Led_Wifi, LOW);
      delay(500);
      digitalWrite(Led_Wifi, HIGH);
      delay(500);
      digitalWrite(Led_Wifi, LOW);
      delay(500);
      digitalWrite(Led_Wifi, HIGH);
      delay(500);
      digitalWrite(Led_Wifi, LOW);
      delay(500);
      digitalWrite(Led_Wifi, HIGH);
      delay(500);
      digitalWrite(Led_Wifi, LOW);
    }
  }
}

void Verif_Connexion_Pepiniere() {
  if (pep_uptime == last_pep_uptime) {
    deconnection_score = deconnection_score + 1;
    Serial.println("deconnection_score = ");
    Serial.print(deconnection_score);
  } else {
    deconnection_score = 0;
  }
  if (deconnection_score >= 210) {
    //Si pépinière déconnectée depuis +/- 2 minutes
    if (mute == 0 || lap >= 10) {
    digitalWrite(Led_problem, HIGH);
    tone(Buzzer,1000, 500);
    delay(500);
    tone(Buzzer,800, 600);
    delay(500);
    tone(Buzzer,1000, 500);
    delay(500);
    tone(Buzzer,800, 600);
    delay(500);
    tone(Buzzer,1000, 500);
    delay(500);
    tone(Buzzer,800, 600);
    delay(500);
    }
    //Led problem mais sans le buzzer.
    else {
    digitalWrite(Led_problem, HIGH);
    }
  } 
  else {
    digitalWrite(Led_problem, LOW);
  }
  // Mise à jour de la valeur de deconnection_score dans la mémoire persistante
  //preferences.putUInt("deconnection_score", deconnection_score);
  //Serial.print("Updated deconnection_score in preferences: ");
  //Serial.println(deconnection_score);
  //preferences.end(); // N'oubliez pas d'appeler preferences.end() pour libérer les ressources
  last_pep_uptime = pep_uptime; //Retiens le dernier chiffre de pep_uptime
}

void VerifPepiniere() {
  //Verif T° critique non-dépassée.
  if (problem_recep == 1) {
    Serial.println("Problème seuil critique");
    Serial.println();
    //Seuil critique bas dépassé
    Serial.println("mute =");
    Serial.println(mute);
    Serial.println("lap = ");
    Serial.println(lap);
    if (mute == 0 || lap >= 10) {
    tone(Buzzer,1000, 500);
    digitalWrite(Led_problem, HIGH);
    delay(500);
    tone(Buzzer,600, 600);
    digitalWrite(Led_problem, LOW);
    delay(500);
    tone(Buzzer,1000, 500);
    digitalWrite(Led_problem, HIGH);
    delay(500);
    tone(Buzzer,600, 600);
    digitalWrite(Led_problem, LOW);
    delay(500);
    tone(Buzzer,1000, 500);
    digitalWrite(Led_problem, HIGH);
    delay(500);
    tone(Buzzer,600, 600);
    digitalWrite(Led_problem, LOW);
    delay(500);
    }
    else {
      digitalWrite(Led_problem, HIGH);
      delay(500);
      digitalWrite(Led_problem, LOW);
      delay(500);
      digitalWrite(Led_problem, HIGH);
      delay(500);
      digitalWrite(Led_problem, LOW);
      delay(500);
      digitalWrite(Led_problem, HIGH);
      delay(500);
      digitalWrite(Led_problem, LOW);
      delay(500);
      digitalWrite(Led_problem, HIGH);
      delay(500);
      digitalWrite(Led_problem, LOW);
      delay(500);
      digitalWrite(Led_problem, HIGH);
      delay(500);
      digitalWrite(Led_problem, LOW);
      delay(500);
      digitalWrite(Led_problem, HIGH);
      delay(500);
      digitalWrite(Led_problem, LOW);
      delay(500);
    }
  }
  //Verif si capteurs serres opérationnels
  if (error_sensorT_recep == 1 || error_sensorT_recep == 2) {
    Serial.println("");
    Serial.println("Problème(s) capteurs serres");
    Serial.println("error_sensorT_recep =");
    Serial.print(error_sensorT_recep);
      for (int b = 0; b < error_sensorT_recep; b++) {
        digitalWrite(Led_problem, HIGH);
        delay(500);
        digitalWrite(Led_problem, LOW);
        delay(500);
        tone(Buzzer,600, 600);
        delay(500);
        tone(Buzzer,1000, 500);
        delay(500);
        tone(Buzzer,600, 600);
        delay(500);
        tone(Buzzer,1000, 500);
      }
  }
}


/*
  Since ProblemRecep is READ_WRITE variable, onProblemRecepChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onProblemRecepChange()  {
  // Add your code here to act upon ProblemRecep change
}

/*
  Since ErrorSensorTRecep is READ_WRITE variable, onErrorSensorTRecepChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onErrorSensorTRecepChange()  {
  // Add your code here to act upon ErrorSensorTRecep change
}

/*
  Since PepUptime is READ_WRITE variable, onPepUptimeChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPepUptimeChange()  {
  // Add your code here to act upon PepUptime change
}

I've tried to add checks in the code to allow it to restart if it's been disconnected for x amount of time. But the problem persists, even though it restarts fine.

I wondered whether the problem with the greenhouse box might not be the fact that the ESP32 has to "store" the value of "millis()" and that, once a certain number is "too large", it crashes? I don't know, it's just a hypothesis.

Thank you very much in advance for your help (my sleep thanks you too) !

Bonjour à tous et à toutes,
Voici ma situation actuelle, j’ai crée un petit système composé de 2 boitiers. Chaque boitier contient un ESP32 relié au Cloud d’arduino. Le système à plusieurs but :

  1. Permettre l’arrosage de la serre (via un choix d’électrovannes) soit physiquement sur le boitier dans la serre soit via l’application du cloud.
  2. Surveiller la température de la serre en continu et me signaler (et me reveiller) si la température baisse en dessous d’un seuil critique OU que la connexion est perdue depuis x temps ce qui pourrait m’indiquer soit une coupure de courant dans la serre soit un problème de wifi.

Le système est fonctionnel : autant l’arrosage que la surveillance et le réveille via un buzzer.

Cependant, je me fais assez régulièrement réveiller pendant la nuit par le buzzer parce que, soit c’est le boitier de la serre qui se déconnecte (voir la 1ère capture d’écran indiquant les heures de connexions/déconnexion), soit c’est celui de la chambre.

Celui de la pépinière se déconnecte à heures +/- régulières lorsqu’il le fait (entre 2 et 3h du matin souvent) tandis que pour celui de la chambre c’est + aléatoire.

NB : Je m’excuse d’avance pour le niveau et les possibles erreurs « simples », je suis débutant :slight_smile:

Voici le code du boitier de la pépinière :

Voir en haut

Et voici celui du boitier de la chambre :

Voir en haut

J’ai essayé d’ajouter des vérifications dans le code pour lui permettre de se redémarrer s’il est déconnecté depuis x temps. Mais le problème persiste même s'il redémarre bien.

Je me suis demandé si le problème avec la boîte à serres n'était pas que l'ESP32 doit "stocker" la valeur de "millis()" et que dès qu'un certain nombre est "trop grand", il se plante ? Je ne sais pas, c'est juste une hypothèse.

Merci beaucoup d’avance de votre aide (mon sommeil vous remercie aussi :wink: ) !

Without digging too much in your code, I see that you have several delay() in the loop() function.

My suggestion is to remove delays replacing it with a non-blocking approach. You can take a look at the following guides:
https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay/
https://docs.arduino.cc/arduino-cloud/cloud-interface/variables/#cloud-updates

This forum post can also be insightful:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.