Pb de condition pour le contrôle d'un relai dans un projet de gestion climatique

Bonjour à tous.
Je cale sur mon projet de gestion d’enceinte climatique :
J’aimerais piloter un relai à l’aide d’une sonde de température et d’humidité sht31.
Je me suis inspiré du montage 15 du grand livre d’arduino d’Erik Bartmann pour ceux qui connaisse.
Voici le code qui compile et téléverse correctement.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "Adafruit_SHT31.h"

#define delay1 10
#define delay2 500
#define seuilTemp 24     // Température seuil
#define seuilHum 60      // Humidité seuil
#define hystTemp 2       // Hysteresis Température
#define hystHum 2        // Hysteresis Humidité
#define relai1 4         // broche de commande du relais
const int cycles = 20;   // Nombre de mesures à moyenner
LiquidCrystal_I2C lcd(0x27, 20, 4);
Adafruit_SHT31 sht = Adafruit_SHT31();

void setup() {
  sht.begin(0x44);
  pinMode(relai1, OUTPUT);
  digitalWrite(relai1, HIGH);
  lcd.init();
  lcd.backlight();
  lcd.clear();
}
void loop() {
  float Temp = 0.0;
  float Hum = 0.0;
  float t = sht.readTemperature();
  float h = sht.readHumidity();
  for (int i = 0; i < cycles; i++) {
    Temp += t;                             // somme des températures mesurées
    Hum  += h;                             // somme des humidités mesurées
    delay(delay1);
  }
  Temp /= cycles;                          // moyenne des températures mesurées
  Hum  /= cycles;                          //moyenne des humidités mesurées
  lcd.setCursor(0, 1);
  lcd.print("Temperature: ");
  lcd.print(Temp , 1);
  lcd.write(0xD0 + 15);
  lcd.print("C");
  lcd.setCursor(0, 2);
  lcd.print("Humidite   : ");
  lcd.print(Hum , 1);
  lcd.print("%");
  if  ((Hum > (seuilHum + hystHum)) || (Temp > (seuilTemp + hystTemp)))     // condition + ou pour fermer le relais
    digitalWrite(relai1, LOW);
  else if  ((Hum < (seuilHum - hystHum)) || (Temp < (seuilTemp - hystTemp))) // condition + ou pour ouvrir le relais
    digitalWrite(relai1, HIGH);
  delay (delay2);

Le problème est que seuils et hystérèses sont bien pris en compte individuellement pour la température ou pour l’humidité mais dès que j’associe les deux paramètres dans la condition avec un « ou », seuls les seuils sont pris en compte sans les hystérèses.
Problème de syntaxe ou de logique dans ma condition ?
D’avance merci pour vos conseils et éclaircissements :slight_smile:

Fred

Le problème est que seuils et hystérèses sont bien pris en compte individuellement pour la température ou pour l'humidité mais dès que j'associe les deux paramètres dans la condition avec un « ou », seuls les seuils sont pris en compte sans les hystérèses.

quelle évidence avez vous pour cela?

Lorsque je teste le système en n'incluant dans le code que la condition pour l'humidité ou la température, le changement d'état du relais prend bien en compte les 2°C ou 2% d'hystérèse :
à 26°C relai on, 22°C relai off
ou
à 62% relai on, 58% relai off
mais lorsque je test avec les deux conditions ensemble :

if  ((Hum > (seuilHum + hystHum)) || (Temp > (seuilTemp + hystTemp)))     // condition + ou pour fermer le relais
    digitalWrite(relai1, LOW);
  else if  ((Hum < (seuilHum - hystHum)) || (Temp < (seuilTemp - hystTemp))) // condition + ou pour ouvrir le relais
    digitalWrite(relai1, HIGH)

le changement d’état du relai n'intervient qu'au seuil uniquement sans prendre en compte les 2°C ou 2% d'hystérèse :
basculement de l’état du relai pile à 24°C ou 60%...

c'est louche... le code est assez simple, si l'une des 2 conditions et vraie ça bascule

Essayez d'imprimer ce qui a été vraiment testé (rajoutez Serial.begin(115200); dans le setup())

if  ((Hum > (seuilHum + hystHum)) || (Temp > (seuilTemp + hystTemp))) {     // condition + ou pour fermer le relais
  Serial.println(F("Je ferme le relai"));
  Serial.print(F("Hum = ")); Serial.println(Hum);
  Serial.print(F("Temp = ")); Serial.println(Temp);
  digitalWrite(relai1, LOW);
} else if  ((Hum < (seuilHum - hystHum)) || (Temp < (seuilTemp - hystTemp))) { // condition + ou pour ouvrir le relais
  Serial.println(F("J'ouvre le relai"));
  Serial.print(F("Hum = ")); Serial.println(Hum);
  Serial.print(F("Temp = ")); Serial.println(Temp);
  digitalWrite(relai1, HIGH);
}

d'autre part votre moyenne ne fonctionne pas, vous ne lisez qu'une fois les capteurs..

  float t = sht.readTemperature();
  float h = sht.readHumidity();
  for (int i = 0; i < cycles; i++) {
    Temp += t;                             // somme des températures mesurées
    Hum  += h;                             // somme des humidités mesurées
    delay(delay1);
  }

ça ne va pas. il faut lire le capteur dans la boucle

  for (int i = 0; i < cycles; i++) {
    Temp += sht.readTemperature();                             // somme des températures mesurées
    Hum  += sht.readHumidity();                             // somme des humidités mesurées
    delay(delay1);
  }

ok pour la moyenne, c'est corrigé. Merci :slight_smile:
Cependant, ça se complique :
le moniteur série m'indique à présent le changement d'état du relai à pile (seuiTemp + hysTemp) et (seuilHum + hystHum)

20:29:07.764 -> J'ouvre le relai
20:29:07.764 -> Hum = 57.96
20:29:07.764 -> Temp = 25.05
20:29:09.405 -> J'ouvre le relai
20:29:09.405 -> Hum = 57.73
20:29:09.405 -> Temp = 25.64
20:29:10.999 -> Je ferme le relai
20:29:10.999 -> Hum = 57.34
20:29:10.999 -> Temp = 26.19
20:29:12.593 -> Je ferme le relai
20:29:12.593 -> Hum = 56.84
20:29:12.593 -> Temp = 26.73
20:29:14.182 -> Je ferme le relai
20:29:14.182 -> Hum = 56.22
20:29:14.229 -> Temp = 27.27
20:29:15.823 -> Je ferme le relai
20:29:15.823 -> Hum = 55.30
20:29:15.823 -> Temp = 27.39
20:29:17.416 -> Je ferme le relai
20:29:17.416 -> Hum = 51.36
20:29:17.416 -> Temp = 26.68
20:29:19.010 -> Je ferme le relai
20:29:19.010 -> Hum = 47.22
20:29:19.010 -> Temp = 26.22
20:29:20.651 -> J'ouvre le relai
20:29:20.651 -> Hum = 44.40
20:29:20.651 -> Temp = 25.85
20:29:22.245 -> J'ouvre le relai
20:29:22.245 -> Hum = 42.52
20:29:22.245 -> Temp = 25.49
20:29:23.838 -> J'ouvre le relai
20:34:00.257 -> J'ouvre le relai
20:34:00.257 -> Hum = 60.71
20:34:00.257 -> Temp = 19.32
20:34:01.898 -> Je ferme le relai
20:34:01.898 -> Hum = 63.59
20:34:01.898 -> Temp = 19.27
20:34:03.492 -> Je ferme le relai
20:34:03.492 -> Hum = 64.04
20:34:03.492 -> Temp = 19.25
20:34:05.109 -> J'ouvre le relai
20:34:05.109 -> Hum = 61.72
20:34:05.109 -> Temp = 19.26

le mystère s'épaissit...

Pourquoi ‘juste’ ? C’est à cause du > ? Vous avez mis le seuil à combien ?
Vous imprimez à 2 chiffres après la virgule mais la comparaison est faite avec tout le nombre flottant

Pour la moyenne, n’oubliez pas de remettre à 0 les valeurs avant le prochain tour

Temp = 0;
Hum = 0;
 for (int i = 0; i < cycles; i++) {
    Temp += sht.readTemperature();                             // somme des températures mesurées
    Hum  += sht.readHumidity();                             // somme des humidités mesurées
    delay(delay1);
  }

Pour la moyenne j'ai ceci actuellement : il faut que je déclare Temp et Hum avec float et je les mets à 0 en début de cycle

 float Temp = 0;
  float Hum = 0;
  for (int i = 0; i < cycles; i++) {
    Temp += sht.readTemperature();         // somme des températures mesurées
    Hum  += sht.readHumidity();            // somme des humidités mesurées
    delay(delay1);
  }
  Temp /= cycles;                          // moyenne des températures mesure
  Hum  /= cycles;                          // moyenne des humidités mesurées

Sinon, avec

if  ((Temp > (seuilTemp + hystTemp)) || (Hum > (seuilHum + hystHum))) {   
    digitalWrite(relai1, LOW);
  }
  else if  ((Temp < (seuilTemp - hystTemp)) || (Hum < (seuilHum - hystHum))) { 
    digitalWrite(relai1, HIGH);
  }

changement d’état du relais attendu pour l'humidité ( seuilHum et hystHum sont pris en compte) mais pas pour la température ( seuilTemp est pris en compte pas hystTemp).

Lorsque j’omets la condition pour l'humidité comme ceci :

if  (Temp > (seuilTemp + hystTemp)) { //|| (Hum > (seuilHum + hystHum))) {   
    digitalWrite(relai1, LOW);
  }
  else if  (Temp < (seuilTemp - hystTemp)) { // || (Hum < (seuilHum - hystHum))) { 
    digitalWrite(relai1, HIGH);
  }

changement d'état du relai attendu (seuiTemp et hystTemp sont pris en compte)
C'est à se tirer le peu de cheveux qu'il me reste...

mais pas pour la température ( seuilTemp est pris en compte pas hystTemp).

je n'y crois pas...postez tout le code utilisé

J'y ai ajouté une horloge rtc pour contrôler un autre relai. c'est pas très beau mais ça semble fonctionner.

Pour l'histoire de la condition, je vous assure que je n'ai pas la berlue. C'est comme s'il y avait un chevauchement ou qqch...

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "Adafruit_SHT31.h"
#include "RTClib.h"
#define delay1 10
#define delay2 500
#define seuilTemp 21     // Température seuil
#define seuilHum  60      // Humidité seuil
#define hystTemp  3       // Hysterese Température
#definet hystHum  3        // Hysterese Humidité
#define relai1 4         // broche de commande du relai1
#define relai2 5         // broche de commande du relai2
const int OnH = 12;
const int OnMin = 20;
const int OffH = 12;
const int OffMin = 21;
const int cycles = 20;   // Nombre de mesures à moyenner

LiquidCrystal_I2C lcd(0x27, 20, 4);
Adafruit_SHT31 sht = Adafruit_SHT31();
RTC_DS3231 rtcDS;

void setup() {
  Serial.begin(115200);
  sht.begin(0x44);
  rtcDS.begin();
  pinMode(relai1, OUTPUT);
  pinMode(relai2, OUTPUT);
  digitalWrite(relai1, HIGH);
  digitalWrite(relai2, HIGH);
  lcd.init();
  lcd.backlight();
  lcd.clear();
}
void loop() {
  DateTime now = rtcDS.now();
  lcd.setCursor(0, 0);
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  lcd.print(now.minute(), DEC);
  lcd.print(':');
  lcd.print(now.second(), DEC);

  if (now.hour() == OnH && now.minute() == OnMin) {
    digitalWrite(relai2, LOW);
    lcd.setCursor(10, 0);
    lcd.print("JOUR");
  }
  else if (now.hour() == OffH && now.minute() == OffMin) {
    digitalWrite(relai2, HIGH);
    lcd.setCursor(10, 0);
    lcd.print("NUIT");
  }
  float Temp = 0;
  float Hum = 0;
  for (int i = 0; i < cycles; i++) {
    Temp += sht.readTemperature();         // somme des températures mesurées
    Hum  += sht.readHumidity();            // somme des humidités mesurées
    delay(delay1);
  }
  Temp /= cycles;                          // moyenne des températures mesurées
  Hum  /= cycles;                          //moyenne des humidités mesurées

  lcd.setCursor(0, 1);
  lcd.print("Temperature: ");
  lcd.print(Temp , 1);
  lcd.write(0xD0 + 15);
  lcd.print("C");
  lcd.setCursor(0, 2);
  lcd.print("Humidite   : ");
  lcd.print(Hum , 1);
  lcd.print("%");

  if  ((Hum > (seuilHum + hystHum)) || (Temp > (seuilTemp + hystTemp))) {    // condition + ou pour fermer le relais
    Serial.println(F("Je ferme le relai"));
    Serial.print(F("Hum = ")); Serial.println(Hum);
    Serial.print(F("Temp = ")); Serial.println(Temp);
    digitalWrite(relai1, LOW);
  }
  else if  ((Hum < (seuilHum - hystHum)) || (Temp < (seuilTemp - hystTemp))) { // condition + ou pour ouvrir le relais
    Serial.println(F("J'ouvre le relai"));
    Serial.print(F("Hum = ")); Serial.println(Hum);
    Serial.print(F("Temp = ")); Serial.println(Temp);
    digitalWrite(relai1, HIGH);
  }
  delay (delay2);
}

Et quelles sont les valeurs affichées lors des "faux déclenchements" ?

Je ne suis pas sûre de vous suivre. Les valeurs affichées sont du type de celles de mon 4eme post dans le moniteur série
qui sont, à une décimale près, celles que je peux lire sur le lcd. Le projet tourne sur une nano. Je l'ai fait tourner sur une vraie uno R3: même sentence. ça va pour l'humidité mais pour la température, ça bascule pile au seuil sans prendre en compte l'hystérèse.
Mes delays sont'ils assez long ? dois-je sampler plus pour faire la moyenne ? Je suis à court d'idées...

ça va pour l'humidité mais pour la température, ça bascule pile au seuil sans prendre en compte l'hystérèse.

je voudrais voir cela dans les traces

Éventuellement rajoutez des print pour afficher les valeurs de seuilHum et hystHum ainsi que seuilTemp et hystTemp pour avoir toute l’info

Le délai n’a pas d’importance, ce que vous semblez dire c’est que la comparaison ne fonctionne pas. Ce n’est pas logique.

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