[Conseil] VMC - Extraction automatisée d'humidité

Bonjour,
je me lance dans un nouveau projet qui viens d'un constat: en appartement il n'y a pas de VMC (Ventilation Mécanique Contrôlée) dans mes toilettes et dans ma salle de bain... et cela pour évité les dépots de moisi qui apparaisse régulièrement au plafond >:(

Je veux donc mettre une VMC, alors je cherche ce qui se fait et dans les magasins d'outillage... rien ne me plait complètement :o

Ma petite connaissance en électronique et programmation me dit "hoo... se serait parfait comme projet pour mettre en pratique ce que je sais concernant l'arduino..."
et cela même si c'est plus chère qu'un produit fini, clef en main, manufacturé...

alors je me lance...

le principe: en fonction de l'hygrométrie détecté, un ventilo extrait l'air plus ou moins vite.

cool! "le principe" tient sur une ligne, ça va peut être être simple pour une fois.... :slight_smile:

alors je m'équipe:

  • une carte arduino Uno
  • 2 ventilo de PC en PWM avec 4 fils: BOOGIE BUG - BBFAN120PWM
  • 2 détecteur d'humidité: DHT22/AM2302

Bon dans un premier temps je vais essayer de faire fonctionner tout ça ensemble:

Mais comment un ventilo fonctionne?
des que je reçoit mes ventilos, ma 1ère réaction c'est de brancher le noir sur le noir, le rouge sur du 12v et là... rien
qu'a cela ne tienne je branche le fil de commande sur un "potar" en 5v et la ca tourne!!!!!! mais que au max et quand je descend en dessous d'environ 2v la le ventilo s'arrete....

grrr bon ok je suis neuneu alors maintenant que j'ai joué je consulte le net...

et le secret c'est PWM!!! je constate que sur le ventilo et sur ma carte arduino il y a ces 3 lettres...
je regarde donc sur le net... j'arrive à comprendre ce que les uns et les autres raconte et met en pratique ce que je lit...

le problème suivant est que je doit faire un programme standard qui doit fonctionner avec d'autre ventilos.
Dans la doc technique des ventilos, la fréquence du PWM doit être de 45k Hz.
Hors la sortie PWM de l'arduino fait environ 490Hz

en recherchant sur le net je trouve la bibliothèque: Google Code Archive - Long-term storage for Google Code Project Hosting.... super je vais comme cela attendre les 45k HZ pour le PWM

ce que je m'empresse de faire: Fan ctrl w pwm lib by nicolasb29 Code
hop 1 potar pour le "duty cycle du PWM et un potar pour modifier la fréquence de PWM...
et ça fonctionne!!!! Shémas

et la stupeur! même avec une fréquence de 200Hz j'arrive à contrôler mon ventillo... Super je vais économiser de la mémoire et passer la fréquence du PWM de l'arduino a une fréquence la plus proche des 45K Hz, ce sera donc 31372 Hz!!

je refait le montage en enlevant le potar de changement de fréquence Code
Ca fonctionne encore... je suis content

maintenant j'aimerais des conseils sur le code fait (peut être que j'ai fait des choses aberrantes?...)
et aussi des conseils sur comment utiliser au mieux, dans mon code, le retour tachométrique du ventilo pour qu'il m'alerte lorsque la valeur du cycle du PWM ne correspond pas aux impulsions du tacho....
auriez vous un conseil la dessus?

merci de m'avoir lu et je continuerais à vous montrer mon avancé du projet au fur et à mesure

Salut ..

C'est un projet utile !

Concernant le PWM pour de l'extraction je pense que c'est du luxe ... Mais si tu peux le faire fais-toi plaisir !

Juste un truc, à mon avis, pour les WC, une détection d'humidité ne sera pas efficace, car l'humidité ne varie pas en tirant la chasse ... Un capteur de présence ou un bouton serait plus approprié...

Pour la salle de bain, je suis curieux de voir ta solution de régulation

ton ventilateur est étonnant, normalement les ventilo de PC marchent etre 21 et 25 kHz.

quand j ai manipule des ventilo pour controler la temperature de mon installation home cinema, j ai du faire face au meme probleme de frequence que toi, cela dit mes ventilo (noctua) etant en 3 fils, sans manipuler la frequence PWM au debut je les ai transforme en haut-parleurs stridents assez insuportables, et puis j ai trouve la formule magique TCCR1B = TCCR1B & B11111000 | 0x01; que tu utilises aussi, et elle a regle tous mes problemes!
top moumoute.
j explique mon projet en details ici, tu peux peut etre reprendre quelques bribes de codes eventuellement : Arduino screen lifter and home theatre system - YouTube

apres pour un retour de tachymétrie, honetement je pense que c est du perfectionnisme pas forcement utile dans un cas d extraction d air. A ta place je me contenterai d envoyer les ordres PWM aux ventilos en fonction de l hygrometrie et faire confiance au systeme en ce qui concerne la vitesse.
tu peux aussi installer des LED RGB en tape et faire varier legerement la teinte en fonction de l hygro si tu veux un retour visuel (c est ce que je vais faire dans ma salle de bain).

en revanche il y a quelque chose qui m interpelle un peu plus, c est que je ne sais pas si c est tres bon pour des ventilo de PC d etre dans une hygrometrie elevee en permanence :confused:
je dis ca parce que justement je suis en train de me faire un montage similaire, mais le mien utilisera un ventilateur prevu pour les salle de bain car je flippe un peu de mettre des ventilo de PC au dessus de ma douche..

pour les chiottes, en effet oublie l hygrometrie, et mets un pir sensor pour detecter une presence humaine avec une temporisation pour l eteindre (mettons 2 minutes apres que le capteur ne capte plus personne), et l affaire est dans le sac!
j ai fais ca dans mes chiottes, mais juste pour la lumiere (et la temporisation est de 45 sec...ce qui est un peu short je trouve, car des fois on ne bouge pas pendant plus longtemps que ca sur le trone...)

ce qui pourrait etre super bogoss, cest de detecter si on a affaire a un caca ou un pipi pour ne déclencher le ventilo qu en cas de grosse commission.
généralement un caca prend un peu plus de temps qu une mixion, donc si une présence humaine est detectee pendant plus de 1min45 d affilee, c est a ce moment que le ventilo démarre!
tu peux aussi bloquer la détection lorsque la porte est ouverte, pour eviter que le ventilo se mette a tourner pendant le grand ménage.

merci pour vos conseils

pourquoi je veux en mettre un dans les wc (non je n'ais pas des wc de 100 m² ;D ) c'est parce que je remarque des traces de moisissure sur le plafond dans les coins. (et non ça ne vient pas de l'appartement du dessus)
donc bon vu que le mur est mitoyen avec la salle de bain, je vais m'amuser a concevoir pour les 2...

pour le tachymètre; oui c'est aussi pour me faire plaisir, dans mes tics perfectionnistes... Éventuellement, comme cela, je vais pouvoir faire mes propres courbes de vitesse par rapport au PWM. et me faire mon opinion.
Maintenant ca peut servir aussi par la suite a savoir un mauvais fonctionnement par arrêt du ventilateur...
et l'inconnue effectivement, sera la résistance des ventilo à l'humidité... mais pas grave car

  • il existe des ventilateurs spéciaux, spécial humidité mais avec un rendement nettement moindre
  • le projet est intéressant, et j'affine comme cela mes connaissance 8)

passant au autre chose, j'ai un peut avancé le code justement en intégrant le tachymètre.
mais j'ai un résultat très très bizarre!!!!
En effet la valeur du tachymètre ne cesse de décroître alors que le ventilo tourne toujours à la même vitesse... je ne comprend pas pourquoi?????

voici mon code:

/*juste pour rappel
byte = 0 à 255
int = -32768 à 32767
unsigned int =  0 à 65535
long = -2147483648 à 2147483647 - 32 bits (4 bytes)
unsigned long =  0 à 4294967295 */

//###### Déclaration
const byte pinPwm = 9; //sortie PWM
const byte pinPotarCycle = 0; // Analog In A0

//####### Variables
unsigned int	varUIntPotarCycleMem;
unsigned long	varULngMillisMem;
volatile unsigned long varVULngFanCpt;

//#####################################################
void setup()
{
  delay(2000); //pause pour ouvrir le moniteur série

  Serial.begin(9600); //initialisation du moniteur serie de debugage
  //300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200

  //###### Déclaration Entrées / Sorties
  pinMode(pinPwm, OUTPUT); //PWM en sortie

  //####### Initialisation
  varUIntPotarCycleMem = 0;
  varULngMillisMem = millis();

  /*
  la fréquence par defaut de l'arduino uno sur la sortie 9 est de 490.20 HZ
  cette fréquence passe pour controler certain ventilo mais la norme est 45kHz (45000)
  pour éviter de prendre de la place en mémoire avec la biblioteque PWM.h (arduino-pwm-frequency-library/)
  j'utilise TCCR1B avec un prescaler qui me permet d'approcher le plus des 45kHz
  Pins 9 et 10 pour le "timer 1" de l'arduino Uno:
  Setting 	Divisor Frequency
  0x01 	 	1 	31372.55 Hz <--CHOIX
  0x02 	 	8 	3921.16 Hz
  0x03  	64 	490.20 Hz   <--DEFAULT
  0x04  	256 	122.55 Hz
  0x05 	 	1024 	30.64 Hz
  TCCR1B = TCCR1B & 0b11111000 | <setting>;*/
  TCCR1B = TCCR1B & 0b11111000 | 0x01; // = 31372.55 Hz

  //initialisation du 1er lancement du ventilo
  funPwmCycle(50); //50% de la vitesse

  //au lencement du pgm on fait tourner de ventilo x secondes
  //pour "décrasser"...
  delay(2000);

  Serial.println("**** Fin du Setup ****");
}

//#####################################################
void loop()
{
  funPwmCycleMeca();
  funFanVitesse();
}

//#####################################################
//modification du duty cycle du PWM
void funPwmCycleMeca()
{
  unsigned int	varUIntPotar;
  unsigned int 	varUIntPotarMap;

  varUIntPotar = analogRead(pinPotarCycle); //lecture de l'entrée, de 0 à 1023

  if (varUIntPotar != varUIntPotarCycleMem)
  {
    varUIntPotarCycleMem = varUIntPotar; // enregistrement de la var pour le prochain loop

    //convertion pour le pwm de 0 à 1023 => en 0 à 100%
    varUIntPotarMap = map(varUIntPotar, 0, 1023, 0, 100);

    funPwmCycle(varUIntPotarMap); //set du pwm;
  }
}

//#####################################################
//set du pwm; de 0 à 100
void funPwmCycle(byte varBytVitesse)
{
  //varUIntVitesse = PWM de 0 à 100%
  const byte pinPwm = 9; //pin du PWM sur l'Arduino
  static byte varBytVitesseMem = 0; //Mémorisation de la vitesse
  byte varBytVitesseMap;

  if (varBytVitesseMem != varBytVitesse)
  {
    //on pas de pourcent en 0 à 255 pour analogWrite
    varBytVitesseMap = map(varBytVitesse, 0, 100, 0, 255);

    analogWrite(pinPwm, varBytVitesseMap); //modification du PWM

    varBytVitesseMem = varBytVitesse; //stokage de la vitesse

    //affichage des valeurs sur le moniteur serie
    if (false) { // true / false
      Serial.print("DutyCycle: ");
      Serial.print(varBytVitesse);
      Serial.println("%");
    }
  }
}

//récupère la vitesse du ventillo
unsigned long funFanVitesse ()
{
  const unsigned long cstULngTpsVerif = 1000; //temps d'attente avant la vérification de vitesse
  const unsigned long cstULngTpsTest = 1000; //temps d'attente pour le test de vitesse

  static unsigned long varSULngMillisMem = 0; //mémorisation du tmps de test
  unsigned long varULngMillisTmp; //var de stokage
  unsigned long varULngRpm; //var vitesse par minute

  varULngMillisTmp = millis(); //nombre de millisecondes depuis le début du programme

  //si on a PAS dépassé le débordement de la variable ~ 50 jours
  if (varULngMillisMem < varULngMillisTmp)
  {

    //vérification de la vitesse du ventillo toute les x secondes
    if (varULngMillisTmp - varULngMillisMem >= cstULngTpsVerif)
    {

      //test la vitesse du ventilo
      if (varSULngMillisMem == 0)
      {

        // RàZ du compteur
        varVULngFanCpt = 0;

        //début du chrono pour compter
        varSULngMillisMem = millis();

        // interruption externe n°0 sur la broche numérique 2
        attachInterrupt(0, funFanCpt, RISING);

        //vérif que l'on à pas varSULngMillisMem == 0 (débordement de var)
        if (varSULngMillisMem == 0)
          varSULngMillisMem = 1; // on le met à 1 ms juste au cas ou...
      }

      //au bout de x sec de comptage
      if (varULngMillisTmp - varSULngMillisMem >= cstULngTpsTest)
      {
        //on arrete la récup automatique du compteur
        detachInterrupt(0);

        // calcul du rpm (rotation par minute)
        // [nb tour] * [nb ms durant 1 min (60000)] / [temps écoulé]
        varULngRpm = varVULngFanCpt * 6000 / varULngMillisTmp;

        Serial.print("Rpm:");
        Serial.println(varULngRpm);

        //réinitialisation
        varSULngMillisMem = 0;
        varULngMillisMem = millis();

        return varULngRpm;
      }
    }
  }

  //si on a dépassé le débordement de la variable ~ 50 jours
  else
  {
    //réaffectation de la var de mémoire
    varULngMillisMem = varULngMillisTmp;
  }
}

//#####################################################
//interruption pour compter le nombre de tour du ventillo
void funFanCpt()   // la fonction appelée par l'interruption externe n°0
{
  varVULngFanCpt = varVULngFanCpt + 1;
}

et voici le log:

**** Fin du Setup ****
Rpm:3154
Rpm:3544
Rpm:2542
Rpm:2089
Rpm:1754
Rpm:1681
Rpm:1454
Rpm:1236
Rpm:1157
Rpm:1034
Rpm:936
Rpm:874
Rpm:834
Rpm:754
Rpm:688
Rpm:675
Rpm:633
Rpm:575
Rpm:548
Rpm:556
Rpm:522
Rpm:498
Rpm:474
Rpm:462
Rpm:429
Rpm:436
Rpm:410
Rpm:382
Rpm:374
Rpm:370
Rpm:358
Rpm:328
Rpm:351
Rpm:334
Rpm:303
Rpm:309
Rpm:304
Rpm:285
Rpm:271
Rpm:266
Rpm:270
Rpm:260
Rpm:251
Rpm:240
Rpm:261
Rpm:248
Rpm:241
Rpm:226
Rpm:222
Rpm:214
Rpm:218
Rpm:223
Rpm:210
Rpm:211
Rpm:204
Rpm:194
Rpm:188
Rpm:188
Rpm:192
Rpm:185
Rpm:177
Rpm:185
Rpm:170
Rpm:172
Rpm:170
Rpm:166
Rpm:171
Rpm:173
Rpm:169
Rpm:161
Rpm:155
Rpm:156
Rpm:154
Rpm:143
Rpm:150
Rpm:140
Rpm:152
Rpm:137
Rpm:135
Rpm:146
Rpm:137
Rpm:134
Rpm:131
Rpm:132
Rpm:129
Rpm:128
Rpm:124
Rpm:129
Rpm:131
Rpm:120
Rpm:121
Rpm:116
Rpm:126
Rpm:111
Rpm:107
Rpm:108
Rpm:105
Rpm:103
Rpm:101
Rpm:109
Rpm:98
Rpm:102
Rpm:96
Rpm:101
Rpm:96
Rpm:99
Rpm:99
Rpm:101
Rpm:106
Rpm:101
Rpm:100
Rpm:99
Rpm:100
Rpm:96
Rpm:99
Rpm:96
Rpm:93
Rpm:92
Rpm:89
Rpm:89
Rpm:92
Rpm:91
Rpm:92
Rpm:88
Rpm:90
Rpm:88
Rpm:83
Rpm:85
Rpm:86
Rpm:83
Rpm:86
Rpm:85
Rpm:83
Rpm:84
Rpm:84
Rpm:89
Rpm:83
Rpm:82
Rpm:80
Rpm:77
Rpm:82
Rpm:79
Rpm:78
Rpm:76
Rpm:81
Rpm:78
Rpm:75
Rpm:74
Rpm:74
Rpm:75
Rpm:74
Rpm:76
Rpm:71
Rpm:72
Rpm:72
Rpm:72
Rpm:72
Rpm:73
Rpm:71
Rpm:68
Rpm:69
Rpm:70
Rpm:67
Rpm:67
Rpm:68
Rpm:67
Rpm:66
Rpm:64
Rpm:66
Rpm:64
Rpm:64
Rpm:66
Rpm:65
Rpm:67
Rpm:64
Rpm:63
Rpm:65
Rpm:60
Rpm:64
Rpm:60
Rpm:55
Rpm:57
Rpm:59
Rpm:60
Rpm:59
Rpm:57
Rpm:61
Rpm:37
...

vous auriez une idée du pourquoi?

pour lire le code plus facilement: Fan ctrl 04 by nicolasb29

@Benn j'ais vu ton boulo... super taff d'avoir réussit a mener ton projet...

j'ai une question: tu utilise GitHub pour ton code moi j'ai que trouvé CodeBender...
y a t'il une raison pour préférer GitHub?

dans la formule varULngRpm = varVULngFanCpt * 6000 / varULngMillisTmp;

tu es sur de bien réinitialiser varVvarULngMillisTmp ... sinon elle croît et tu obtiens une valeur décroissante avec le temps

à priori tu devrais diviser par varVvarULngMillisTmp - varSULngMillisMem qui est la durée de comptage ...

PS : disons que le nom de tes variables est un peu difficile à interpreter ...

Bien vu B83s

c'est exactement ca!!

voilà le code de remplacement:

// calcul du rpm (rotation par minute)
// [nb tour] * [nb ms durant 1 min (60000)] / ([temps écoulé] - [temps en mémoire])
varULngRpm = varVULngFanCpt * 6000 / (varULngMillisTmp - varSULngMillisMem);

et j'avoue me regarder bêtement tellement c'est évident que cela vienne de cette formule!!
ça fonctionne maintenant!!!

je m’attelle donc à la détection d'humidité maintenant...

Nicolasb29:
j'ai une question: tu utilise GitHub pour ton code moi j'ai que trouvé CodeBender...
y a t'il une raison pour préférer GitHub?

oui oui il y a une raison, c est que je n avais jamais entendu parler de CodeBender jusqu a maintenant en fait :smiley:

...Et je m y mets de suite ^^

supprimé car en double... voir ici