Déclenchement VMC

Bonjour,

Je fais appelle à votre aide car à chaque projet que je réalise vous me permettez de bien comprendre et progresser.
Mon projet consiste à déclencher une VMC que je vais installer à l'envers afin de tempérer une partie de la maison lorsque l'on ne peux pas ouvrir les fenêtres (absences...). Bien entendu c'est juste pour pouvoir gagner quelques degrés en inter saison. Et l'été de pouvoir faire rentrer du frais la nuit sans avoir les portes ouvertes.

J'utilise des capteurs de température DS18B20. J'ai trouvé les adresses des capteurs via un scanner de bus one wire.
Je souhaite allumer la VMC en fonction de la différence de température intérieure et extérieure. Un interrupteur doit contrôler si on veux "rafraichir" ou "chauffer" la pièce en fonction de la saison.

Je me suis aidé de plusieurs sites et morceaux de code que j'ai essayé d'assembler correctement mais il doit y avoir encore des erreurs pour que cela fonctionne correctement.

Merci pour votre aide et temps que vous m'apportez !


```cpp
#include <arduino.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Bounce2.h>

#define INTER 3
Bounce inter;

OneWire oneWire(2);

DallasTemperature sensors(&oneWire); 
DeviceAddress SondeInterieure = {0x28, 0xDF, 0xBD, 0x45, 0x92, 0x19, 0x02, 0xB9}; 
DeviceAddress SondeExterieure = {0x28, 0x2C, 0x2F, 0x45, 0x92, 0x16, 0x02, 0xBE};

int RelaisVMC = 4;

void setup() {
  
  Serial.begin(9600);
  sensors.begin();
  sensors.setResolution(SondeInterieure, 2); 
  sensors.setResolution(SondeExterieure, 2);
  pinMode(RelaisVMC, OUTPUT);
  digitalWrite(RelaisVMC, HIGH);
  
  pinMode(INTER, INPUT_PULLUP);
  inter.attach(INTER);
  inter.interval(5);
}
int courant = -1;

void loop() {

sensors.requestTemperatures();
 float SondeInterieure = sensors.getTempFByIndex(SondeInterieure);
 float SondeExterieure = sensors.getTempFByIndex(SondeExterieure);  


  inter.update();
  int valeur = inter.read();
  if (valeur == courant)
    return;

if ( valeur == LOW) // si l'inter est sur LOW on doit prendre le paramètre de  
     {(RAFFRAICHIR);}//car on est en été et il faut rafraîchir la nuit quand l'air se refroidit

else                           //si l'inter est sur HIGH on doit prendre le paramètre de  
   {(RECHAUFFER);}//car on est en printemps automne hiver et il faut chauffer quand il fait soleil et que l'air est plus chaud

  courant = valeur;
 
}

void RAFFRAICHIR(){

if (SondeExterieure < SondeInterieure )
 {digitalWrite (RelaisVMC, LOW);}

else
 {digitalWrite (RelaisVMC, HIGH);}
}

void RECHAUFFER(){
if (SondeExterieure > SondeInterieure )
 {digitalWrite (RelaisVMC, LOW);}

else
 {digitalWrite (RelaisVMC, HIGH);}

}

Bonjour guillaume07230

Il faut dire ce qui ne va pas.

Quelques remarques à propos de ton usage de la bibliothèque Bounce2.h, tout d'abord:
pinMode(INTER, INPUT_PULLUP);
Ne sert à rien et ne doit pas être, c'est la bibliothèque qui "s'occupe" de ça, ainsi:
inter.attach(INTER, INPUT_PULLUP);

Pour lire le bouton, inter.read(); n'est pas très efficace et n'utilise pas les avantages de la bibliothèque, ça ne fait qu'un digitalRead(INTER); il faut, pour lire le bouton, inter.pressed(); par exemple, qui a les avantages de la bibliothèque. comme l'antirebond

Cordialement
jpbbricole

Ton code ne semble pas être indenté, ca à l'air négligeable, mais cela impact sur la compréhension du code, même pour toi.

En générale on utilise soit le camel case, soit le pascal case.
Donc les noms majuscules sont réservé pour les macros ou les constantes, pas pour les fonctions.

Ton programme risque de bagotter, c'est à dire alterner rafraichissement et réchauffement très rapidement.
En général on met en place une hystérésis, c'est à dire que le point de rafraichissement, n'est pas le même que celui du réchauffement.

Petit loupé dans l'envoi du message je présume?

Pourquoi ?

En effet :confused:, c'est corrigé.

Bonjour.
L'idée est séduisante en effet, mais la mise en pratique peut s'avérer complexe pour être efficace. Avant de consolider le code, peux-tu nous préciser le type de VMC que tu souhaites utiliser (simple/double flux ?) et le principe général du projet ?
Pour ma part, je travaille à la mise en oeuvre d'un système similaire basé sur l'utilisation d'une VMC double flux. Il y aura deux fonctions principales : VMC double flux "classique" toute l'année et système de rafraichissement l'été, lorsque la ressource en air frais est disponible.
Pour l'instant, le système n'est pas en service, il est simplement doté de capteurs de température dont les données (mesurées toutes les 6 secondes) sont mémorisées dans une carte SD. Ci-joint un enregistrement d'une semaine au début de l'été.


On peut voir que les capteurs DS18B20 répodent très bien à la température et nécessitent de traiter leurs données pour bien gérer le démmarage du système afin d'éviter les ordres/contre-ordres.

On voit également que la ressource en air frais (dans le centre de la France) n'est pas très importante.
La VMC fonctionne de façon nominale, mais le système de rafraichissement n'est pas encore réglé, la saison de s'y prête plus désormais, mais j'ai mis plusieurs DS18B20 (qui répondent très bien, même au bout de 15 m de câble en diminuant la résistance de pull-up) qui me permettent de savoir qu'il faut bien isoler le caisson de la VMC car des échanges thermiques (entre l'air extérieur et l'air du local dans lequel se trouve le caisson) se font à cet endroit, même en neutralisant l'échangeur thermique.
L'expérience montre aussi que la turbine qui pousse l'air dans la maison n'a pas un rendement parfait et réchauffe l'air d'environ 1° par effet Joule.
A ta disposition si tu veux partager des idées sur ce projet :wink:

Salut,
merci, pour votre aide et conseil !

Il y a déjà une vmc simple flux que je mets en route uniquement lorsque l'on utilise la douche. L'été elle marche tout le temps. L'intérieur de la maison régule très bien naturellement l'hygrométrie grâce à l'utilisation du chanvre en cloison et isolation toiture, les murs en monobrique de 37.5mm, enduit extérieur à la chaux et intérieur plâtre offre un déphasage très intéressant, on arrive à avoir une différence de plus de dix degrés entre l'intérieur et l'extérieur. C'est très appréciable l'été surtout en cas de forte chaleur, à condition que les nuits soit en dessous de 20°. Lors de canicule, on ne peux plus rafraîchir la maison après 2-3jours car elle n'a plus d'inertie.

un inter détermine en fonction de sa position que le système rafraîchit en été ou réchauffe au printemps/automne/hiver.

if ( valeur == LOW) // si l'inter est sur LOW on doit prendre le paramètre de
{(RAFFRAICHIR);}//car on est en été et il faut rafraîchir la nuit quand l'air se refroidit

else //si l'inter est sur HIGH on doit prendre le paramètre de
{(RECHAUFFER);}//car on est en printemps automne hiver et il faut chauffer quand il fait soleil et que l'air est plus chaud

Les deux conditions ne rentre donc pas en conflit.

Guillaume

Pour être plus exacte, tu appels la fonction RAFFRAICHIR, sinon la fonction RECHAUFFER
Hormis mes indications sur une convention de nommage particulière et non standard, cela n''empêche pas tes fonction de bagoter lorsque SondeExterieure et SondeInterieure on des valeurs proches.

Bonjour,

On peut penser qu'il y a une certaine inertie, mais dans ces cas là, un hystéresis est conseillé je pense, genre

SI température< température consigne - Delta
J'arrête de refroidir
Et
SI température> température consigne + Delta
je refroidi

pour éviter les bagottements

oui, quand je dis bagote, c'est à relativiser :slight_smile:
Je pensais plus a un delta sur le temps

J'avais pas vu cela sous cet angle, effectivement, donc tu ne prend par exemple des mesures que tous les "Delta t" pour éviter les changement d'états trop fréquents?

Oui c'est une façon de faire, tu peux aussi faire un truc du genre


long randExt, randInt;
bool chauffe = true;
bool chauffe2 = true;
long nextchange = 0;
long timer = 5000;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello, ESP32!");
  randomSeed(analogRead(0));
}

void loop() {
  randExt = 20 + random(6);
  randInt = 20 + random(6);

  if (randExt > randInt) {
    if (!chauffe) {
      Serial.println("changement!");
    }
    chauffe = true;

    if (!chauffe2 && millis() > nextchange) {
      Serial.print("changement 2!");
      chauffe2 = true;
      nextchange = millis() + timer;
    }
  } else {
    if (chauffe) {
      Serial.println("changement!");
    }
    chauffe = false;

    if (chauffe2 && millis() > nextchange) {
      Serial.println("changement 2!");
      chauffe2 = false;
      nextchange = millis() + timer;
    }
  }
  // put your main code here, to run repeatedly:
  delay(300); // this speeds up the simulation
}

Je ne suis pas sûr d'avoir bien compris la façon dont laquelle tu penses rafraichir ... S'agit-il d'inverser le sens de la circulation de l'air dans la VMC ? La turbine est-elle capable de fonctionner de cette manière ?
Pour ma part, les conditions à satisfaire pour prendre la décision de rafraichir sont les suivantes

  1. condition de température absolue sur la température intérieure (programmable). En effet, nul besoin de faire déclencher le système si la température intérieure est de 20° par exemple.
  2. condition d'écart de température relative entre l'air intérieur et l'air extérieur (également programmable) sur la base de l'algo suivant . Je fais une mesure de température toutes les 6 secondes et je compte le nombre de tests successifs qui donnent l'air extérieur plus frais que l'air intérieur pour décider de démarrer les opérations à effectuer pour rafraichir. J'ai paramétré à 5 ce nombre ce qui prend 30 secondes pour être sûr qu'il n'y aura pas de contre-ordre. Le codage de cet algo fonctionne et est robuste.
    On fait l'opération symétrique avec le comptage des tests successifs pour lesquels le résultat du test est inversé.
    Pour l'instant, le test est fait à égalité des températures, mais il faudra sans doute prendre 1° de marge car la turbine réchauffe l'air insuflé d'environ 1° (selon sa puissance, bien sûr).

Bonjour à tous !

Effectivement cela serait mieux de partir sur un seuil de 20°C pour déclencher ou pas la VMC. Reste à prendre en compte le réchauffement de l'air par le moteur (je ne l'avais pas pris en compte). Je voudrais utiliser une VMC ou une turbine mais installé dans le sens inverse qu'une vmc traditionnelle.
Voici les modifications que j'ai apporté, j'ai fait apparaitre les valeurs des deux sondes dans le serial monitor afin de vérifier si les sondes mesurent correctement et de voir la température.

Je voudrais que lorsque l'inter 2 positions est HIGH les paramètres du void ete s'applique et que quand l'inter est LOW, que les paramètres du void hiver s'applique.

Merci de vos remaraques, elles me permettent de mieux afiner l'idée !


```cpp
#include <OneWire.h>
#include <arduino.h>

int inter =3;
int led = 13;// led sur port 13
OneWire ds(2); // on pin 2
 

byte sondeInt[8] = {0x28, 0xFF, 0x64, 0xE, 0x6F, 0x61, 0x34, 0xE8};
byte sondeExt[8] = {0x28, 0xFF, 0x64, 0xE, 0x75, 0xB, 0x81, 0x78};
int SignBit = 0;
 
void setup(){
Serial.begin(9600);
pinMode(led,OUTPUT);
pinMode(inter, INPUT_PULLUP);

}

 
int tc_100(byte* addr){
int HighByte, LowByte, TReading;
byte data[12];
byte i;
 
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
 
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
 
ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
 
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
return (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
}
 
void mypr(int Tc_100) {
int Whole, Fract;
 
Whole = Tc_100 / 100; // separate off the whole and fractional portions
Fract = Tc_100 % 100;
 
if (SignBit) // If its negative
{
Serial.print("-");
}
Serial.print(Whole);
Serial.print(".");
if (Fract < 10)
{
Serial.print("0");
}
Serial.print(Fract);
 
Serial.print("\n");
}
 
void loop()
{
byte i;
byte data[12];
int Tc_100;

Tc_100 = tc_100(sondeInt);
Serial.print("1: ");
mypr(Tc_100);
 
Tc_100 = tc_100(sondeExt);
Serial.print("2: ");
mypr(Tc_100);

if (inter== HIGH)
     {ete();}
else
     {hiver();}
}

void hiver(){
if (tc_100(sondeInt)<20 && tc_100(sondeExt)>20)
{digitalWrite(led,HIGH);}
else 
{digitalWrite(led,LOW);}
}

void ete(){
if (tc_100(sondeExt)<20 && tc_100(sondeInt)>20)
digitalWrite(led,HIGH);
else 
digitalWrite(led,LOW);
}
 

Bonjour,
OK, je comprends un peu mieux ton idée et voici quelques éléments de réflexion complémentaires qui sont susceptibles de retenir ton attention :

  1. Sur l’aspect logiciel, n’étant pas un « digital native » et n’étant pas un bon connaisseur du C++, c’est toujours difficile pour moi pour rentrer dans un code que je n’ai pas écrit, toutefois, j’ai noté des erreurs dans les adresses des deux capteurs de température qui sont à corriger. Par ailleurs et pour info, j’en questionne cinq avec la fonction suivante et avec un délai de 800 ms par capteur qui couvre le temps de conversion sur 12 bits qui est de 750 ms, le fonctionnement est nominal.
    Je n’insère que le code utile à l’accès aux capteurs :
#include <OneWire.h>       // Appel de la bibliothèque du protocole One-Wire nécessaire à la communication avec les capteurs de température
#define Broche_One_Wire 2  // Définition de la broche de l'Arduino sur laquelle le bus One-Wire est connecté (la broche digitale 2 dans le cas présent)
const byte addrtempint[] = { 0x28, 0x60, 0xA8, 0x57, 0x04, 0xE1, 0x3C, 0xBC };
const byte addrtempVMC[] = { 0x28, 0xEC, 0x22, 0x57, 0x04, 0xE1, 0x3C, 0x5D };
const byte addrtempneuf[] = { 0x28, 0xC6, 0xC8, 0x80, 0xE3, 0xE1, 0x3C, 0x79 };
const byte addrtemprej[] = { 0x28, 0x7E, 0x72, 0x57, 0x04, 0xE1, 0x3C, 0x17 };
const byte addrtempext[] = { 0x28, 0x4B, 0xCD, 0x80, 0xE3, 0xE1, 0x3C, 0x0B };
OneWire oneWire(Broche_One_Wire);  // Création de l'objet OneWire pour utiliser le bus One-Wire

float getTemperature(const byte addr[]) {  // Fonction de lecture de la température sur un capteur DS18B20. addr[] : adresse du module 1-Wire concerné
  byte data[9];                            // data[] : données lues depuis le scratchpad, Le chiffre 9 correspond au nombre d'octets à lire du scratchpad
  oneWire.reset();                         // Reset le bus One-Wire
  oneWire.select(addr);                    // Sélectionne le capteur par son adresse
  oneWire.write(0x44, 1);                  // Lance une conversion de température avec la résolution par défaut à la MST qui est de 12 bits (ce n'est pas une programmation de la résolution)

  delay(800);  // Attente de la fin de la conversion en tenant compte de la résolution de mesure sur 12 Bits pour un capteur (750 ms)

  oneWire.reset();       // Reset le bus One-Wire
  oneWire.select(addr);  // Sélectionne le capteur par son adresse
  oneWire.write(0xBE);   // Envoi d'une demande de lecture du scratchpad

  for (byte i = 0; i < 9; i++) {  // Lecture de tous les octets du scratchpad
    data[i] = oneWire.read();
  }
  return ((data[1] << 8) | data[0]) * 0.0625;  // Calcul de la température en degré Celsius sur la base d'une résolution de 12 bits
}  // Fin de la fonction d'accès aux capteurs

void loop() {

  float temperature[4];  // Définition de la variable "température" mais quid du chiffre entre crochets ? Peut-être parce que 5 capteurs [0, 1, 2, 3, 4, 5]

  // Appel de la fonction de conversion et de récupération de la température pour chacun des capteurs dont les adresses sont spécifiées plus haut
  temperature[0] = getTemperature(addrtempint);   // Appel de la fonction pour le capteur tempint
  temperature[1] = getTemperature(addrtempVMC);   // Appel de la fonction pour le capteur tempVMC
  temperature[2] = getTemperature(addrtempneuf);  // Appel de la fonction pour le capteur tempneuf
  temperature[3] = getTemperature(addrtemprej);   // Appel de la fonction pour le capteur temprej
  temperature[4] = getTemperature(addrtempext);   // Appel de la fonction pour le capteur tempext

  // Alimentation des variables de température utilisées pour l'algorithme
  tempint = temperature[0];
  tempVMC = temperature[1];
  tempneuf = temperature[2];
  temprej = temperature[3];
  tempext = temperature[4];
}

  1. Sur l’aspect fonctionnel du système, je comprends bien l’objectif pour l’été, mais l’objectif recherché pour l’hiver m’échappe complètement, désolé :woozy_face:
    Ci-dessous un schéma simplifié de mon système qui ne sera actif qu’en été et qui correspond au tien. J’ai conçu le système avec un certain nombre de capteurs de température pour aider à la mise au point finale.

    Ci-dessous, les résultats des enregistrements de ce matin qui illustrent le réchauffement de l’air apporté par la turbine en fonction de sa vitesse (1h en mode GV, 1h en mode PV et 1h en mode GV). On voit bien que c’est le mode d’activation de la turbine qui réchauffe l’air au premier ordre. Les pertes dans les gaines (5 cm de laine de roche) ne sont pas mesurables car de l’ordre de 0,5° qui est la précision de mesure du capteur.

Il restera un point majeur à traiter pour espérer que le système soit efficace, c’est de réduire au maximum, le transfert de calories entre l’aire extérieur et l’air ambiant dans les combles car du coup, c’est le caisson de la VMC qui va faire office d’échangeur thermique. Cela n’apparait pas clairement en ce moment car la différence de température entre l’extérieur et les combles n’est pas importante, mais l’été, avec 28°C dans les combles et 18°C dehors la nuit, ce sera moins drôle.

Il y a bien une isolation symbolique avec 1,7 cm de polystyrène dans le caisson (en rose), mais c’est tout à fait insuffisant pour le but recherché, c’est comme pour la nourriture surgelée, il ne faut pas rompre la chaîne du froid. C’est la raison pour laquelle, j’ai acheté des panneaux de fibre de bois de 10 cm d’épaisseur afin de confectionner un caisson isolant.


En espérant que ces éléments te soient utiles !

Merci beaucoup pour tous ces détails et partage d'expériences, je vais pouvoir m'en inspirer.

Pour la période printemps automne plutôt que hiver, je souhaiterais avec le même principe et sans inverser le sens de rotation de la turbine car c'est pas possible, faire entrer de l'air chaud extérieur dans la pièce lorsque le logement n'est pas occupé.

pour cela aimerai utiliser un interrupteur pour sélectionner soit le void rafraichir en été ou bien le void réchauffer en fonction de la saison.

Ça y est, j’ai compris ton projet.

Pour se recentrer sur la question initiale relative au déclenchement de la ventilation, je pense que dans chacun des deux cas (été/hiver), il serait plus judicieux de conditionner ce déclenchement à l’écart de température intérieur/extérieur plutôt que de passer par un seuil en valeur absolue.

L’exemple suivant illustre la perte en ressource d’air « frais » qui est sera perdue avec un seuil à 20°.


De plus, pour l’hiver, la turbine permettra de réchauffer l’air extérieur en fonction de sa perte par effet Joule, mais le réchauffement de l’air extérieur sera à prendre en compte pour l’été comme discuté un peu plus haut.
Par ailleurs, à quel rythme sera effectuée cette comparaison ?
L’échelle de plusieurs minutes serait suffisante, cela éviterait des ordres/contre-ordres intempestifs pouvant nuire à la turbine et à son dispositif de commande.

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