Conseils pour programme de gestion de climat

Bonjour,

Je me suis lancé dans un projet qui au final se complexifie au fur et a mesure et je souhaite avoir des avis sur la structure globale a donner au programme.

Je joint le programme actuel sur lequel j’ai un problème de temporisation bloquante ( la fonction arrosage bloque les autres pour le moment, normal j’ai des delay dessus je suis en train de m’entrainer sur la fonction millis et je vais rajouter un module RTC DS3231), et les valeurs ne se mettent a jours qu’une fois la 1ere fonction effectuée.
Je vais potasser cela dans le week end mais je suis preneur de conseils sur l’organisation d’un tel programme ou des pistes vers lesquels m’orienter.
A terme je pense faire prendre les mesures x fois par jour , pas de besoin de precision extreme et je vais rajouter de l’hystereris pour avoir une souplesse sur les declenchements des relais.
Mais avant de développer plus loin je souhaite avoir vos avis sur la façon dont j’ai coder, j’hésite a utiliser les fichiers ( ou onglets) mais je ne trouve pas beaucoup de tuto précis donc pour le moment j’ai fait comme ca :

Merci a ceux qui prendrons le temps :slight_smile:

#include <LiquidCrystal_I2C.h>   //librairie de l'ecran adresse apres scan 0x27
#include <Wire.h>
#include <Adafruit_Sensor.h>    //librairies des capteurs tst sur DHT22
#include <DHT.h>
#include <DHT_U.h>

#define ADRESSE_I2C_RTC 0x68    // adresse I2C du module RTC DS3231
// Déclaration des variables de l'horloge
byte seconde, minute, heure, numJourSemaine, numJourMois, mois, annee;
String jourDeLaSemaine[8] = {"","Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};

// declaration des relais
const int Relais_Arrosage =  4; // voir programme arrosage automatique
const int Relais_Chauffage = 5; //voir prog Lcd et relais
const int Relais_Humidite = 6;  //voir prog Lcd et relais
const int Relais_Ventilateur = 7; //declenchement programmée par cycle rtc a faire
const int Alim_Sonde=8;         //alimentation de la sonde humidite sol
// declaration des capteurs
#define DHTPIN 12    //broche du DHT
#define DHTTYPE DHT22      // ou DHT 11 selon le modele utilisé

DHT dht(DHTPIN, DHTTYPE);  // Initialise le capteur DHT22
//capteur d humidite sol de type capacitif calibré sec a 800 et eau a 400
int capteuranalogique = A1;
// declaration de l'ecran
LiquidCrystal_I2C lcd(0x27, 20, 4); // ecran lcd2004

    //partie pour l'arrosage
int sensorValue1 = 0;
int maxi = 1023; // pour avoir toute la fenetre du traceur série
int mini = 0; // pour avoir toute la fenetre du traceur serie

   //test fonction millis
const unsigned long DELAI_POMPE= 10000;
  // gestion des temps de mise en route

void setup() {

  // demarrages des elements
  Wire.begin();
  Serial.begin(9600);                // moniteur série
 lcd.begin ();
 lcd.println("DEMARRAGE SYSTEME");
 lcd.clear();
 dht.begin();
// declaration des sorties

pinMode(Relais_Arrosage, OUTPUT);   // broche d'alimentation du relais action en fonction de la sonde
pinMode(Alim_Sonde, OUTPUT);        // broche d'alimentation de la sonde
pinMode(Relais_Chauffage,OUTPUT);   //Relais pour le chauffage action selon consigne temperature
pinMode(Relais_Humidite,OUTPUT);    //Relais humidité action en focntion de la consigne humidité air
pinMode(Relais_Ventilateur,OUTPUT); // Ventilo fonctionnement periodique (xtemps off/y temps ON)
//etat des sorties
digitalWrite(Relais_Arrosage, HIGH);  // les relais sont en inverse
digitalWrite(Alim_Sonde, LOW); // met la sonde hors tension - protection oxydation
digitalWrite(Relais_Chauffage,HIGH);
digitalWrite(Relais_Humidite,HIGH);
digitalWrite(Relais_Ventilateur,HIGH);

}

void loop() {

  // Réception de l'heure et de la date
Wire.beginTransmission(0x68);
Wire.write(0); // Positionner le pointeur de registre sur 00h
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
// Accède aux données de l'horloge (à partir du registre 00h)
seconde = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
heure = bcdToDec(Wire.read() & 0x3f);
numJourSemaine = bcdToDec(Wire.read());
numJourMois = bcdToDec(Wire.read());
mois = bcdToDec(Wire.read());
annee = bcdToDec(Wire.read());
// Affichage de l'heure (afficheur LCD)
lcd.setCursor(15,0);
if (heure<10){lcd.print("0");}
lcd.print(heure, DEC);
lcd.print(":");
if (minute<10){lcd.print("0");}
lcd.print(minute, DEC);

//appel des fonctions du programmes
affichage();
capteursol();
capteurair();
affichage();
}
// Convertir les nombres décimaux codés binaires en décimaux normaux
byte bcdToDec(byte val){return( (val/16*10) + (val%16));}

void affichage(){

   // releve des capteurs
sensorValue1 = analogRead(capteuranalogique); // mesure humidité
int humi = map(sensorValue1,810,390,0,100);
    byte h = dht.readHumidity();
  // Lit la temperature en degres Celsius (valeur par defaut
  byte t = dht.readTemperature();

  //gestion affichage lcd
  lcd.setCursor(0, 0);
  lcd.print("T.AIR = ");
  lcd.print(t);
  lcd.print(" *C ");
  lcd.setCursor(0, 1);
  lcd.print("H.AIR = ");
  lcd.print(h);
  lcd.print(" % ");
  lcd.setCursor(0, 2);
  lcd.print("H.SOL = ");
  lcd.print(humi);
  lcd.print(" % ");
  } 

void capteursol(){
  digitalWrite(8, HIGH); // met la sonde sous tension
sensorValue1 = analogRead(capteuranalogique); // mesure humidité
int humi = map(sensorValue1,810,390,0,100);
 Serial.print(maxi);
Serial.print(" ; ");
Serial.print(mini);
Serial.print("  ;  VALEUR ANALOGIQUE = ");
Serial.print(sensorValue1); 

 if (sensorValue1 > 600) 
 {
    lcd.setCursor(17,2);
    lcd.print("EAU"); // probleme ici eau ne s'efface pas a corriger
  Serial.println(" TROP SEC - ACTIVATION ARROSAGE ");
  for(int arrosage = 1 ; arrosage <= 10 ; arrosage = arrosage+1) // cycle maxi de 10 tests + arrosage
     {
     sensorValue1 = analogRead(capteuranalogique); 
     if (sensorValue1 > 600) {
        Serial.print(arrosage);
        Serial.print(" arrosage ");
        Serial.print(" ; ");
        Serial.println(sensorValue1);
        digitalWrite(Relais_Arrosage, LOW); 
        delay(2000); // durée fixe activation pompe
        digitalWrite(Relais_Arrosage, HIGH); 
        delay(10000); // pause pompe pour laisser a l'eau le tps de pénétrer la terre  
        }
     }
 }


}
void capteurair(){
    // Lecture de température et de l'humiditer environ 250 millisecondes
  // La durer des capteurs peuvent etre regler jusqu'a 2 secondes (capteur tres lent)
  byte h = dht.readHumidity();
  // Lit la temperature en degres Celsius (valeur par defaut
  byte t = dht.readTemperature();
  byte c = dht.readTemperature(true);

  // Vérifie si toutes les lectures ont échoué et quitte le début (pour réessayer).
  if (isnan(h) || isnan(t) || isnan(c)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  {
 if (h >= 40 && h <= 60) // si hum. est = ou sup. a 75 ET hum infer. ou = a 80 relais ouvert
  {
    digitalWrite(Relais_Humidite, LOW);
    digitalWrite(Relais_Chauffage,HIGH);
  }
  else
  {
    digitalWrite(Relais_Humidite, HIGH);
    digitalWrite(Relais_Chauffage,HIGH);// Sinon relais fermé
  }
  if (t<=27)// si la temperature est inf a X° alors
  {
    digitalWrite (Relais_Chauffage,LOW);
  }
  else
  {
    digitalWrite (Relais_Chauffage,HIGH);
  }
  delay(1000);// Delai d'une seconde entre les mesures
  }

}

Hello
Pas grand chose à dire. Tu as utilisé des fonctions, c'est bien, ça permet de faciliter la lecture et le mise au point.

Pour ton problème de delay, tu peux utiliser une bibliothèque. Par exemple une de celles de Bricoleau

OK, donc pour la structure global de ce que j ai fait c est cohérent.
Je suppose que C est la librairie du mini ordonnance qu il faut que je regarde ? Ça a l air de coller avec mes attentes mais pas sur que je comprenne bien je vais tester dans le week end.
Mais j avou avoir déjà un peu de mal à modifier la partie de mon programme qui concerne l arrosage pour remplacer les delay par du Millis, donc je vais m entraîner sur quelques test de temporisation simple aussi.
Merci pour le lien

Bon et bien après quelques test, pas de probleme pour faire un blink sans delay, par contre je coince pour adapter cela a mon cas, je m’explique:

je souhaite que la sonde prennent x mesures par jours ( entre 2 et 6 j’adapterais quand cela sera fonctionnel)
et en fonction de la valeur mesurée déclenchement du relais arrosage ou non

si le relais passe en LOW ( marche pour moi ) , il se met en fonctionnement pour des cycles de 2 secondes de marche et pause de 10 secondes, contrôle de la valeur humidité et si encore trop basse reprend son cycle.

Je joint le programme en question qui fonctionne mais je souhaite enlever le delay et le remplacer par millis.
et la je coince.
je pensait utiliser ce genre de constante et variables:

// gestion temporisation
unsigned long previousMillis=0;
const unsigned long POMPE_ON=2000;
const unsigned long POMPE_OFF=10000; //duree pour phase test pour usage 6h

Par contre je butte sur la méthode pour l’intégrer dans mon programme, si une ame charitable et patiente pouvait me mettre sur la bonne voie en m expliquant car lors de mes test le relais ne se déclenchait plus ou alors c’était les mesures …

ci-joint le code en question:

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16,2); 
int Relais_Pompe = 4;
int capteuranalogique = A1;
int sensorValue1 = 0;
int maxi = 1023; // pour avoir toute la fenetre du traceur série 
int mini = 0; // pour avoir toute la fenetre du traceur serie
void setup() {
lcd.begin();
pinMode(Relais_Pompe, OUTPUT); // broche d'alimentation du relais
pinMode(8, OUTPUT); // broche d'alimentation de la sonde
Serial.begin(9600); // SI ON VEUT VOIR LE TRACEUR SERIE
digitalWrite(Relais_Pompe, HIGH);
digitalWrite(8, LOW); // met la sonde hors tension - protection oxydation
}
void loop() {
{
delay(10000); // cette boucle for protège la sonde car ne fait qu'une mesure par 24h
}
digitalWrite(8, HIGH); // met la sonde sous tension
delay(1000);
sensorValue1 = analogRead(capteuranalogique); // mesure humidité
int humi = map(sensorValue1,810,390,0,100);
//gestion affichage lcd
 
  lcd.setCursor(0, 0);
  lcd.print("Hum.Sol = ");
  lcd.print(humi);
  lcd.print(" % ");


sensorValue1 = analogRead(capteuranalogique);
Serial.print(maxi);
Serial.print(" ; ");
Serial.print(mini);
Serial.print("  ;  VALEUR ANALOGIQUE = ");
Serial.print(sensorValue1);
//Serial.print("  ; VALEUR NUMERIQUE = " );
//Serial.println(sensorValue2);
// si sensorValue1 est supérieur au seuil sec
  if (sensorValue1 > 600) {
    lcd.setCursor(0,1);
    lcd.print("TROP SEC-ARROSAGE");
  Serial.println(" TROP SEC - ACTIVATION ARROSAGE ");
  for(int arrosage = 1 ; arrosage <= 10 ; arrosage = arrosage+1) // cycle maxi de 10 tests + arrosage
     {
     sensorValue1 = analogRead(capteuranalogique); 
     if (sensorValue1 > 600) {
        Serial.print(arrosage);
        Serial.print(" arrosage ");
        Serial.print(" ; ");
        Serial.println(sensorValue1);
        digitalWrite(Relais_Pompe, LOW); 
        delay(2000); // durée fixe activation pompe
        digitalWrite(Relais_Pompe, HIGH); 
        delay(10000); // pause pompe pour laisser a l'eau le tps de pénétrer la terre  
        }
      else
      {  
        lcd.setCursor(0,1);
        lcd.print("FIN ARROSAGE");   
      Serial.println(" FIN CYCLE ARROSAGE ");    
      }
     }
  }
}

Merci d’avance

A mon avis, tu peux en rester à un code avec des delay, car la dynamique de l'humidité dans les sols ne nécessite pas de surveiller à la milliseconde...

Si tu as des délais vraiment très longs, genre des dizaines de minutes, tu peux les couper en tranches et faire tes mesures entre ces tranches.

Je suis d’accord avec toi, surtout que je ne compte faire prendre qu’une mesure humidité du sol toutes les 6 heures , les prise de mesure pour la température de l’air et l’humidité de l’air je pensait en faire une par heure.

La ce qui me gene c’est que si la boucle de l’arrosage est en cours alors les valeurs ne s’actualisent pas sur l’écran, et après avoir lu plusieurs post il faut que je gère une hystérésis sur les valeurs humidité de l’air et température pour avoir des déclenchement régulier des relais.
en esperant que je comprenne mieux cette notion que les temporisations non bloquante ( je me garde ça sous le coude pour faire évoluer le projet plus tard quand mon niveau aura évolué :slight_smile:

Je voudrais que le système soit sur une page de température comprise entre 22 et 26 degré, si j’ai bien compris il faut une valeur de déclenchement a 22 et d’arrêt a 26.
et pour l’humidité de l’air une plage entre 45 et 60%, donc même système

#include <LiquidCrystal_I2C.h>   //librairie de l'ecran adresse apres scan 0x27
#include <Wire.h>
#include <Adafruit_Sensor.h>    //librairies des capteurs tst sur DHT22
#include <DHT.h>
#include <DHT_U.h>

#define ADRESSE_I2C_RTC 0x68    // adresse I2C du module RTC DS3231
// Déclaration des variables de l'horloge
byte seconde, minute, heure, numJourSemaine, numJourMois, mois, annee;
String jourDeLaSemaine[8] = {"","Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};

// declaration des relais
const int Relais_Arrosage =  4; // voir programme arrosage automatique
const int Relais_Chauffage = 5; //voir prog Lcd et relais
const int Relais_Humidite = 6;  //voir prog Lcd et relais
const int Relais_Ventilateur = 7; //declenchement programmée par cycle rtc a faire
const int Alim_Sonde=8;         //alimentation de la sonde humidite sol
// declaration des capteurs
#define DHTPIN 12    //broche du DHT
#define DHTTYPE DHT22      // ou DHT 11 selon le modele utilisé

DHT dht(DHTPIN, DHTTYPE);  // Initialise le capteur DHT22
//capteur d humidite sol de type capacitif calibré sec a 800 et eau a 400
int capteuranalogique = A1;
// declaration de l'ecran
LiquidCrystal_I2C lcd(0x27, 20, 4); // ecran lcd2004

    //partie pour l'arrosage
int sensorValue1 = 0;
int maxi = 1023; // pour avoir toute la fenetre du traceur série
int mini = 0; // pour avoir toute la fenetre du traceur serie

   //test fonction millis
   unsigned long previousMillis =0;
const unsigned long DELAI_POMPE= 10000;
const unsigned long POMPE_ON=2000;
int tempoActive=0;
unsigned long tempoDepart=0;
  // gestion des temps de mise en route

void setup() {

  // demarrages des elements
  Wire.begin();
  Serial.begin(9600);                // moniteur série
 lcd.begin ();
 lcd.println("DEMARRAGE SYSTEME");
 lcd.clear();
 dht.begin();
// declaration des sorties

pinMode(Relais_Arrosage, OUTPUT);   // broche d'alimentation du relais action en fonction de la sonde
pinMode(Alim_Sonde, OUTPUT);        // broche d'alimentation de la sonde
pinMode(Relais_Chauffage,OUTPUT);   //Relais pour le chauffage action selon consigne temperature
pinMode(Relais_Humidite,OUTPUT);    //Relais humidité action en focntion de la consigne humidité air
pinMode(Relais_Ventilateur,OUTPUT); // Ventilo fonctionnement periodique (xtemps off/y temps ON)
//etat des sorties
digitalWrite(Relais_Arrosage, HIGH);  // les relais sont en inverse
digitalWrite(Alim_Sonde, LOW); // met la sonde hors tension - protection oxydation
digitalWrite(Relais_Chauffage,HIGH);
digitalWrite(Relais_Humidite,HIGH);
digitalWrite(Relais_Ventilateur,HIGH);

}

void loop() {

//test fonction millis
unsigned long currentMillis= millis();
  // Réception de l'heure et de la date
Wire.beginTransmission(0x68);
Wire.write(0); // Positionner le pointeur de registre sur 00h
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
// Accède aux données de l'horloge (à partir du registre 00h)
seconde = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
heure = bcdToDec(Wire.read() & 0x3f);
numJourSemaine = bcdToDec(Wire.read());
numJourMois = bcdToDec(Wire.read());
mois = bcdToDec(Wire.read());
annee = bcdToDec(Wire.read());
// Affichage de l'heure (afficheur LCD)
lcd.setCursor(15,0);
if (heure<10){lcd.print("0");}
lcd.print(heure, DEC);
lcd.print(":");
if (minute<10){lcd.print("0");}
lcd.print(minute, DEC);

//appel des fonctions du programmes
affichage();
capteursol();
capteurair();

}
// Convertir les nombres décimaux codés binaires en décimaux normaux
byte bcdToDec(byte val){return( (val/16*10) + (val%16));}

void affichage(){

   // releve des capteurs
sensorValue1 = analogRead(capteuranalogique); // mesure humidité
int humi = map(sensorValue1,810,390,0,100);
    byte h = dht.readHumidity();
  // Lit la temperature en degres Celsius (valeur par defaut
  byte t = dht.readTemperature();

  //gestion affichage lcd
  lcd.setCursor(0, 0);
  lcd.print("T.AIR = ");
  lcd.print(t);
  lcd.print(" *C ");
  lcd.setCursor(0, 1);
  lcd.print("H.AIR = ");
  lcd.print(h);
  lcd.print(" % ");
  lcd.setCursor(0, 2);
  lcd.print("H.SOL = ");
  lcd.print(humi);
  lcd.print(" % ");
  } 

void capteursol(){

 
  
  digitalWrite(8, HIGH); // met la sonde sous tension
sensorValue1 = analogRead(capteuranalogique); // mesure humidité
int humi = map(sensorValue1,810,390,0,100);
 Serial.print(maxi);
Serial.print(" ; ");
Serial.print(mini);
Serial.print("  ;  VALEUR ANALOGIQUE = ");
Serial.print(sensorValue1); 

 if (sensorValue1 > 600) 
 {
    lcd.setCursor(17,2);
    lcd.print("EAU"); // probleme ici eau ne s'efface pas a corriger
  Serial.println(" TROP SEC - ACTIVATION ARROSAGE ");
  for(int arrosage = 1 ; arrosage <= 10 ; arrosage = arrosage+1) // cycle maxi de 10 tests + arrosage
     {
     sensorValue1 = analogRead(capteuranalogique); 
     if (sensorValue1 > 600) {
        Serial.print(arrosage);
        Serial.print(" arrosage ");
        Serial.print(" ; ");
        Serial.println(sensorValue1);
        digitalWrite(Relais_Arrosage, LOW); 
        delay(2000); // durée fixe activation pompe
        digitalWrite(Relais_Arrosage, HIGH); 
        delay(10000); // pause pompe pour laisser a l'eau le tps de pénétrer la terre  
        }
     }
 }
}

void capteurair(){
    // Lecture de température et de l'humiditer environ 250 millisecondes
  // La durer des capteurs peuvent etre regler jusqu'a 2 secondes (capteur tres lent)
  byte h = dht.readHumidity();
  // Lit la temperature en degres Celsius (valeur par defaut
  byte t = dht.readTemperature();
  byte c = dht.readTemperature(true);

  // Vérifie si toutes les lectures ont échoué et quitte le début (pour réessayer).
  if (isnan(h) || isnan(t) || isnan(c)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  {
 if ( h<=50 &&h <= 60) // si hum. est = ou sup. a 75 ET hum infer. ou = a 80 relais ouvert
  {
    digitalWrite(Relais_Humidite, LOW);
    digitalWrite(Relais_Chauffage,HIGH);
  }
  else
  {
    digitalWrite(Relais_Humidite, HIGH);
    digitalWrite(Relais_Chauffage,HIGH);// Sinon relais fermé
  }
  if (t<=22)// si la temperature est inf a X° alors
  {
    digitalWrite (Relais_Chauffage,LOW);
  }
  else
  {
    digitalWrite (Relais_Chauffage,HIGH);
  }
  delay(1000);// Delai d'une seconde entre les mesures
  }

}

Pas si simple de créer des plages de déclenchement,

objectif:
Temperature de l’air:
une consigne a 25° ( qui conditionnera l’arret du relais chauffage)
une hysteresis de 3° ( ce qui amene la temperature de marche du relais a 22°)

Humidité de l’air:
une consigne a 55% ( qui conditionne l’arret du relais humidificateur/clim)
une hysteresis de 10% ( ce qui la valeur de marche du relais quand la valeur atteint 45)
je viens de tester quelques bout de code mais je dois inverser quelque chose ca ne colle pas

#include <LiquidCrystal_I2C.h>   //librairie de l'ecran adresse apres scan 0x27
#include <Wire.h>
#include <Adafruit_Sensor.h>    //librairies des capteurs tst sur DHT22
#include <DHT.h>
#include <DHT_U.h>

#define ADRESSE_I2C_RTC 0x68    // adresse I2C du module RTC DS3231
// Déclaration des variables de l'horloge
byte seconde, minute, heure, numJourSemaine, numJourMois, mois, annee;
String jourDeLaSemaine[8] = {"","Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};

// declaration des relais
const int Relais_Arrosage =  4; // voir programme arrosage automatique
const int Relais_Chauffage = 5; //voir prog Lcd et relais
const int Relais_Humidite = 6;  //voir prog Lcd et relais
const int Relais_Ventilateur = 7; //declenchement programmée par cycle rtc a faire
const int Alim_Sonde=8;         //alimentation de la sonde humidite sol
// declaration des capteurs
#define DHTPIN 12    //broche du DHT
#define DHTTYPE DHT22      // ou DHT 11 selon le modele utilisé

DHT dht(DHTPIN, DHTTYPE);  // Initialise le capteur DHT22
//capteur d humidite sol de type capacitif calibré sec a 800 et eau a 400
int capteuranalogique = A1;
// declaration de l'ecran
LiquidCrystal_I2C lcd(0x27, 20, 4); // ecran lcd2004

    //partie pour l'arrosage
int sensorValue1 = 0;
int maxi = 1023; // pour avoir toute la fenetre du traceur série
int mini = 0; // pour avoir toute la fenetre du traceur serie

   //test fonction millis
   unsigned long previousMillis =0;
const unsigned long DELAI_POMPE= 10000;
const unsigned long POMPE_ON=2000;
int tempoActive=0;
unsigned long tempoDepart=0;
  // gestion des temps de mise en route

void setup() {

  // demarrages des elements
  Wire.begin();
  Serial.begin(9600);                // moniteur série
 lcd.begin ();
 lcd.println("DEMARRAGE SYSTEME");
 lcd.clear();
 dht.begin();
// declaration des sorties

pinMode(Relais_Arrosage, OUTPUT);   // broche d'alimentation du relais action en fonction de la sonde
pinMode(Alim_Sonde, OUTPUT);        // broche d'alimentation de la sonde
pinMode(Relais_Chauffage,OUTPUT);   //Relais pour le chauffage action selon consigne temperature
pinMode(Relais_Humidite,OUTPUT);    //Relais humidité action en focntion de la consigne humidité air
pinMode(Relais_Ventilateur,OUTPUT); // Ventilo fonctionnement periodique (xtemps off/y temps ON)
//etat des sorties
digitalWrite(Relais_Arrosage, HIGH);  // les relais sont en inverse
digitalWrite(Alim_Sonde, LOW); // met la sonde hors tension - protection oxydation
digitalWrite(Relais_Chauffage,HIGH);
digitalWrite(Relais_Humidite,HIGH);
digitalWrite(Relais_Ventilateur,HIGH);

}

void loop() {

//test fonction millis
unsigned long currentMillis= millis();
  // Réception de l'heure et de la date
Wire.beginTransmission(0x68);
Wire.write(0); // Positionner le pointeur de registre sur 00h
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
// Accède aux données de l'horloge (à partir du registre 00h)
seconde = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
heure = bcdToDec(Wire.read() & 0x3f);
numJourSemaine = bcdToDec(Wire.read());
numJourMois = bcdToDec(Wire.read());
mois = bcdToDec(Wire.read());
annee = bcdToDec(Wire.read());
// Affichage de l'heure (afficheur LCD)
lcd.setCursor(15,0);
if (heure<10){lcd.print("0");}
lcd.print(heure, DEC);
lcd.print(":");
if (minute<10){lcd.print("0");}
lcd.print(minute, DEC);

//appel des fonctions du programmes
affichage();
capteursol();
capteurair();

}
// Convertir les nombres décimaux codés binaires en décimaux normaux
byte bcdToDec(byte val){return( (val/16*10) + (val%16));}

void affichage(){

   // releve des capteurs
sensorValue1 = analogRead(capteuranalogique); // mesure humidité
int humi = map(sensorValue1,810,390,0,100);
    byte h = dht.readHumidity();
  // Lit la temperature en degres Celsius (valeur par defaut
  byte t = dht.readTemperature();

  //gestion affichage lcd
  lcd.setCursor(0, 0);
  lcd.print("T.AIR = ");
  lcd.print(t);
  lcd.print(" *C ");
  lcd.setCursor(0, 1);
  lcd.print("H.AIR = ");
  lcd.print(h);
  lcd.print(" % ");
  lcd.setCursor(0, 2);
  lcd.print("H.SOL = ");
  lcd.print(humi);
  lcd.print(" % ");
  } 

void capteursol(){

 
  
  digitalWrite(8, HIGH); // met la sonde sous tension
sensorValue1 = analogRead(capteuranalogique); // mesure humidité
int humi = map(sensorValue1,810,390,0,100);
 Serial.print(maxi);
Serial.print(" ; ");
Serial.print(mini);
Serial.print("  ;  VALEUR ANALOGIQUE = ");
Serial.print(sensorValue1); 

 if (sensorValue1 > 600) 
 {
    lcd.setCursor(17,2);
    lcd.print("EAU"); // probleme ici eau ne s'efface pas a corriger
  Serial.println(" TROP SEC - ACTIVATION ARROSAGE ");
  for(int arrosage = 1 ; arrosage <= 10 ; arrosage = arrosage+1) // cycle maxi de 10 tests + arrosage
     {
     sensorValue1 = analogRead(capteuranalogique); 
     if (sensorValue1 > 600) {
        Serial.print(arrosage);
        Serial.print(" arrosage ");
        Serial.print(" ; ");
        Serial.println(sensorValue1);
        digitalWrite(Relais_Arrosage, LOW); 
        delay(2000); // durée fixe activation pompe
        digitalWrite(Relais_Arrosage, HIGH); 
        delay(10000); // pause pompe pour laisser a l'eau le tps de pénétrer la terre  
        }
     }
 }
}

void capteurair(){
  const float h_consigne=55;
  const int h_hysteresis=10;
    const float t_consigne = 25; //Donnée de la variable de consigne.
  const int t_hysteresis = 3; //Donnée de la variable de hystérésis .
    // Lecture de température et de l'humiditer environ 250 millisecondes
  // La durer des capteurs peuvent etre regler jusqu'a 2 secondes (capteur tres lent)
  byte h = dht.readHumidity();
  // Lit la temperature en degres Celsius (valeur par defaut
  byte t = dht.readTemperature();
  byte c = dht.readTemperature(true);

  // Vérifie si toutes les lectures ont échoué et quitte le début (pour réessayer).
  if (isnan(h) || isnan(t) || isnan(c)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  {
 if ( h<=h_consigne &&h >= h_consigne-t_hysteresis) // si hum. est = ou sup. a 75 ET hum infer. ou = a 80 relais ouvert
  {
    digitalWrite(Relais_Humidite, LOW);
    digitalWrite(Relais_Chauffage,HIGH);
  }
  else
  {
    digitalWrite(Relais_Humidite, HIGH);
    digitalWrite(Relais_Chauffage,HIGH);// Sinon relais fermé
  }
  if (t<=t_consigne && t<=t_consigne-t_hysteresis )// si la temperature est inf a X° alors
  {
    digitalWrite (Relais_Chauffage,LOW);
  }
  else  if (t> t_consigne && t>t_consigne-t_hysteresis)
  {
    digitalWrite (Relais_Chauffage,HIGH);
  }
  
  delay(1000);// Delai d'une seconde entre les mesures
  }

}

et finalement les delay risque d’être gênant car la si le chauffage de met en route, les autres valeurs se figent aussi et tant que le cycle n’est pas fini le système est en pause ( normal me direz vous avec des temporisation bloquante :slight_smile: )

donc si quelqu’un a un peu de temps pour m’expliquer 2 points de mon programme quitte a me montrer un bout d’exemple :
gestion de l’hysteresis
utilisation de la fonction millis
Je debute ( ca fait un mois que je me suis mis au code et a l’arduino) soyez indulgent :o

Je vais tenter de t'expliquer rapidement. Je suis sur mon portable, donc à la merci du correcteur d'orthographe qui risque de mettre un peu le b... dans l'explication.

Si tu veux surveiller une durée, tu lances un chrono en initialisant une variable déclarée comme

unsigned long chrono;

par

chrono = millis () ;

Pour surveiller tu testes

if (millis () - chrono > duration)

Si le test est vrai tu mets à jour le chrono

chrono = millis () ;

Et tu fais ce que tu dois faire...

Pour l'hysteresis, il faut avoir une variable qui stocks l'état de ton système. Par exemple

bool chauffage = false;

Si le chauffage est en marche tu compares la température mesurée avec la valeur basse de la plage. Sinon avec la valeur haute.

Alors , je viens de refaire des tests ( je pense que pour aujourd’hui ca ira , avant de saturer ou m’énerver :slight_smile: )

Je commence a cerner le fonctionnement pour l’hystérésis mais il me manque surement un truc quelque part, je m’explique:

je teste avec une consigne humidité a 45% ( valeur a 42% dans la piece) le relais se coupe bien arrivé a 50% (consigne + valeur hysteresis) par contre il se remet en route a entre 44% au lieu de 40, ca je ne le comprend pas.
C’est peut etre en rapport avec la variable bool je dois pas bien l’utiliser, j’ai mis ceci avant le setup:

bool chauffage=false;
bool humidite=false;

ci dessous le void concerné ( ne rappelant pas les variables ci dessous ca doit forcement avoir une incidence mais laquelle???)

void capteurair(){
  const float h_consigne=45;
  const int h_hysteresis=5;
    const float t_consigne = 24; //Donnée de la variable de consigne.
  const int t_hysteresis = 1; //Donnée de la variable de hystérésis .
    // Lecture de température et de l'humiditer environ 250 millisecondes
  // La durer des capteurs peuvent etre regler jusqu'a 2 secondes (capteur tres lent)
  byte h = dht.readHumidity();
  // Lit la temperature en degres Celsius (valeur par defaut
  byte t = dht.readTemperature();
  byte c = dht.readTemperature(true);

  // Vérifie si toutes les lectures ont échoué et quitte le début (pour réessayer).
  if (isnan(h) || isnan(t) || isnan(c)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  {
    if (digitalRead(Relais_Humidite)){
 if ( h<=h_consigne-t_hysteresis) // si hum. est = ou sup. a 75 ET hum infer. ou = a 80 relais ouvert
  {
    digitalWrite(Relais_Humidite, LOW);
   
  }
    }
    if (!digitalRead(Relais_Humidite)){
  if (h>h_consigne+h_hysteresis)
    
  {
    digitalWrite(Relais_Humidite, HIGH);
 
  }
  }
  if (digitalRead(Relais_Chauffage)){
  if (t<=t_consigne-t_hysteresis )// si la temperature est inf a X° alors
  {
    digitalWrite (Relais_Chauffage,LOW);
  }
  }
  if (!digitalRead(Relais_Chauffage)){
   if ( t>t_consigne+t_hysteresis)
  {
    digitalWrite (Relais_Chauffage,HIGH);
  }
  
  delay(1000);// Delai d'une seconde entre les mesures
  }
  }
}

Il y a un problème ici :

if ( h<=h_consigne-t_hysteresis)

Ça fait bien 44%…

Mets des else dans ton code…

void capteurair() {
  const float h_consigne = 45;
  const int h_hysteresis = 5;
  const float t_consigne = 24; //Donnée de la variable de consigne.
  const int t_hysteresis = 1;   //Donnée de la variable de hystérésis .
  // Lecture de température et de l'humidité environ 250 millisecondes
  // La durée des capteurs peuvent être réglée jusqu'à 2 secondes (capteur très lent)
  byte h = dht.readHumidity();
  // Lit la température en degrés Celsius (valeur par défaut
  byte t = dht.readTemperature();
  byte c = dht.readTemperature(true);

  // Vérifie si toutes les lectures ont échoué et quitte le début (pour réessayer).
  if (isnan(h) || isnan(t) || isnan(c)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  if (digitalRead(Relais_Humidite)) {
    // si hum. est = ou sup. a 75 ET hum infer. ou = a 80 relais ouvert
    if (h <= h_consigne - h_hysteresis) digitalWrite(Relais_Humidite, LOW);
  } else {
    if (h > h_consigne + h_hysteresis) digitalWrite(Relais_Humidite, HIGH);
  }

  if (digitalRead(Relais_Chauffage)) {
    // si la température est inf a X° alors
    if (t <= t_consigne - t_hysteresis) digitalWrite (Relais_Chauffage, LOW);
  } else {
    if (t > t_consigne + t_hysteresis) digitalWrite (Relais_Chauffage, HIGH);
  }

  delay(1000); // Délai d'une seconde entre les mesures
}

Et bien un grand merci, je viens de refaire des tests et en corrigeant l’erreur ça fonctionne …

et le matin l’esprit reposé ca va mieux , j’avais commencé hier soir a mettre des else comme vous me l’aviez proposé mais je m’étais embrouillé dans les accolades et ça coinçait lors de la compilation.

En tout cas je me note cette façon de coder plus clair et compréhensible que ce que j’avais produit avant.

 if (digitalRead(Relais_Humidite)) {
    // si hum. est = ou sup. a 75 ET hum infer. ou = a 80 relais ouvert
    if (h <= h_consigne - h_hysteresis) digitalWrite(Relais_Humidite, LOW);
  } else {
    if (h > h_consigne + h_hysteresis) digitalWrite(Relais_Humidite, HIGH);
  }

Maintenant je vais attaquer deux autres fonctions pour ce projet:

1 relais pour un ventilateur temporisé ( Xtemps en fonctionnement et y temps en pause), j’espère réussir a le faire sans solliciter votre aide :slight_smile:

1 relais pour l’éclairage la par contre j’hésite sur la méthode:
je souhaite créer 2 cycles d’éclairage , chacun avec un temps en marche différent
exemple:cycle 1 relais on : 10H et off 14h
cycle 2 relais on : 14h et off 10h
Je me demandait si je pouvait utiliser un BP pour le choix du mode, de ce genre:
if Bp high alors cycle 1 ( et une LED qui s’allume pour un contrôle visuel du mode sélectionné)
else if BP low alors cycle 2 ( avec une led de couleur différente)

Je suis ouvert a d’autres suggestion de mise en oeuvre, plus efficace ou plus simple.
Je vais commencé par cette partie.

Ce que tu décris n'est pas un bouton poussoir, c'est un interrupteur. Un BP est LOW (si INPUT_PULLUP) uniquement lorsqu'il est pressé.

Effectivement,

Du coup je vais utiliser 2 BP, un pour chaque cycle,
En mettant une condition de ce type:
Si BP 1high (un appui)alors déclenchement du cycle 1

Et une deuxième partie
Si BP 2 high (un appui) alors arrêt du cycle 1 et début cycle 2.
La ou ça va se compliqué ça va être sur la gestion du temps car si j appui sur le 2eme BP quand le cycle 1 est en phase allumé il va falloir que le cycle 2 démarre après le cycle complet du numéro 1 qui comprendra x heure allumé + y heure éteint en ayant toujours x+y= à 24 heures.
Un bon défi pour moi

je viens de faire quelques recherches et je coince sur une action que j’aimerai coder:

en gros j’ai trouver comment programmer une periode de ce type : 'c 'est juste un extrait du code

const struct Horaire heureDebut1 = { 8, 30, 0}; // heure de départ du programme
const struct Horaire heureFin1   = {20, 30, 0}; // heure de fin du programme
unsigned int startProg1 = 0;
unsigned int endProg1 = 0;

 DateTime now = RTC.now(); // récupere l'heure du module RTC
  float heureActuelle = now.hour() + now.minute() / 60.0 + now.second() / 3600.0;
  digitalWrite(relaisLampe, (heureActuelle >= startProg1 && heureActuelle < endProg1) ? 255 : 0);

maintenant ce que je voudrais c’est mettre un BP et lors de l’appui sur le bouton mettre en route ce cycle mais pas a heure fixe mais a partir de l’heure d’appui sur le BP

Je pense a quelque chose de ce type mais c’est confus :

digitalRead (etatduBP)
if BP high alors j’enregistre l’heure actuelle ( je suppose qu’il va falloir créer une variable de type unsigned long tempsDemarrage ) et demarrage du cycle mais du coup

const struct Horaire heureDebut1 = tempsMemorisé
const struct Horaire heureFin1 = temps memorisé+ X heures

est ce que je prend la bonne direction ou pas tout? (j’espere avoir bien expliqué mon idée)

D'abord, un digitalWrite écrit 0 ou 1, LOW ou HIGH et pas 0 ou 255. Mais je pense que ça marche quand même, car il doit juste vérifier que la valeur écrite est nulle ou non nulle.

Je pense que ce que tu veux faire est correct, bien que je ne comprenne pas ton 'const struct'. Tu ne dois pas utiliser un const puisque cette valeur est inconnue à la compilation. Et pourquoi struct et pas int ou unsigned int ?

Regarde le référence arduino pour savoir ce que tu peux mettre comme valeur maximum dans un unsigned int ou un unsigned long, ça te permettra de choisir le type de variable à utiliser.

Re,

l’extrait du code vient d’un programme trouvé sur le forum pour un eclairage automatique pour des lampes dimmable ( je crois que c’est pour cela la plage 0,255.
je n’avais pas encore modifier.

unsigned debutCycle1 = 0;
unsigned finCycle1 = 0;


void lumiere(){
debutCycle1= now.hour() + now.minute()+now.second();
finCycle1= 
   DateTime now = RTC.now(); // récupere l'heure du module RTC
  float heureActuelle = now.hour() + now.minute() / 60.0 + now.second() / 3600.0;
  digitalWrite(Relais_Lampe, (heureActuelle >= debutCycle1 && heureActuelle < finCycle1));

  //lecture de l'etat du BP1
  etatBP1=digitalRead(BP1);
  //
  if (etatBP1!=etatPrecedentBP1){
if etatBP1=HIGH){
}
  }}

voila le début par contre je sèche sur comment ajuster ma variable debutcycle1
que je voulais faire fonctionner comme un previousmillis qui récupère millis() pour le void et ai remis a millis() a la fin
dans le void lumiere
je voudrais que débutcycle1= temps au moment du changement d’etat du BP (heure et minute)
et que fincycle1 soit = debutcycle1+Xheures (pour mon test je mettrais 12h)

je cherche la fonctiond’appel de lheure actuelle mais je ne trouve pas.

Par contre merci pour le lien reference arduino (je le cherchais depuis un moment mais impossible de le retrouver

Si tu veux mesurer des durées, tu as deux solutions :

  • millis() : c'est adapté à la mesure de durées courtes (quelques secondes) avec une précision de quelques millisecondes. Tu peux aussi l'utiliser pour mesurer des durées longues (plusieurs heures) mais la précision se dégrade très vite (rapidement quelques minutes)
  • utiliser une horloge externe (RTC ou internet) : c'est adapté à la mesure de longues durées (plusieurs jours, voire bien plus), avec une précision de l'ordre de la seconde
    Tu es dans le second cas avec ta DS3231. Donc, tu dois interroger régulièrement la RTC. Quand je dis régulièrement, ça veut dire que tu peux utiliser millis() pour ça : par exemple interroger la RTC toutes les 10 secondes
if (millis() - lastmillis > 10000ul) // interrogation toutes les dix secondes

ça sera précis à mieux qu'une seconde je pense. Tu peux utiliser 60000ul pour une minute.

Lors de l'interrogation, tu fais

now = RTC.now();

Si ta précision requise est d'une minute, tu peux coder l'heure comme suit:

int heure = now.hour()*100 + now.minute();

Ça te donnera par exemple pour 14 heures 35 le chiffre 1435.

Si tu as une action à faire à 16 heures, tu compares ce chiffre à 1600. Lorsque c'est égal, tu lances ton action.

OK, je note ces éléments mais dans mon cas l action n est planifier à heure fixe mais elle débute lors du changement d état du BP,
J essaie du coup de faire une condition qui lors de ce changement d état récupéré l heure et les minute (exemple: j appui à 10h35 donc mon cycle démarre et doit s arrêter 10h plus tard soit à 20h35)
Ma variable de départ sera
DebutCycle1= l'heure de l appui ici 10h35,
Et variable de fin de cycle
finCycle1= debutCycle1+10 heures.
Est ce que en mettant
Debutcycle1=now.hour()*100 + now.minute();
Cela fonctionnera ?
Je vais faire quelques essai ce soir je pense, je vous tient au courant de l avancement

Oui tu fais au début :

Debutcycle1=now.hour()*100 + now.minute();

Puis tu testes régulièrement :

heureCourante = now.hour()*100 + now.minute();
if (heureCourante  - Debutcycle1 > 1000) // action

car 1000 vaut 10 heures

Je viens de me rendre compte que je ne pourrais pas utiliser le système tel quel, je vais devoir revoir l ensemble du système, je m explique:
Je vais avoir 3 cycles différents, 2 avoir des durées d éclairage different et un sans mais pour chaque cycle je vais avoir des plages de températures et humidité différentes.
Si je garde le système tel quel je vais être obligé de televerser le code avec les valeurs de température et humidité à chaque changement de cycle.
Du coup a moins de faire un système de menu chose je ne suis pas capable de coder avec mon niveau actuel.
Je pense utiliser 3 BP un pour chaque cycle et chaque cycle aura les conditions enregistrée pour chaque paramètre.
Je vais recommencer le code en utilisant la fonction switch qui me paraît appropriée dans mon cas.
Cas1: BP1 appuyé
Appel des fonctions température, humidité, et lampe cycle 1
Cas 2 : BP2 appuyé
Appel des fonctions temp, humidité et lampe du cycle 2
Cas 3 : idem avec BP3

Le point sur lequel j ai du mal à voir comment le mettre en œuvre est le passage d un cycle à l autre en respectant les durées
Exemple :
Le système est en cycle 1 avec une période de lampe allumée de 10h, j appui sur le BP2 pour passé sur le cycle 2 mais je voudrai que le changement se passe à la fin du cycle 1 complet( 10h allume+14h éteint puis changement de cycle).
Pensez vous que cela soit à ma portée au vue de ce que j ai produit ? Et si oui vers quelle type de fonction ou condition me tourné?
Merci d avance.