Unité de ventilation frigo camping-car

Bonjour la communauté.

Voici les éléments d’une nouvelle réalisation que je viens de terminer.

Il s’agit d’une unité de ventilation pour réfrigérateur de camping-car.

En effet, avec les fortes chaleurs, les frigos des camping-cars ont beaucoup de mal à suivre et à maintenir une température convenable. La solution, est d’ajouter des ventilateurs au niveau de la colonne de ventilation située derrière le frigo. Il existe des unités de ventilation dans le commerce, mais en ce qui me concerne, il n’y a pas de place pour en installer une (Camping-car Pilote avec frigo Dometic). Alors, j’ai pris l’option de me fabriquer ma propre unité en utilisant des ventilateurs 12V prévus pour le refroidissement de boîtiers d’ordinateur.

J’ai donc acheté 6 ventilateurs 12V PWM (4fils) de marque Artic, que je commande à partir d’un microcontrôleur Arduino Nano (Atmega 328P). Le montage comporte un mode manuel permettant le réglage de la vitesse (duty cycle PWM) de 0 à 100% (1800T/Mn), et un mode manuel où la vitesse est régulée à partir d’un thermomètre (type DS18B20) entre 20° et 30°. En dessous de 20° les ventilateurs tournent à vitesse mini, et au dessus de 30° on est au maxi.

J’ai eu du mal avec la sortie tachymétrique des ventilateurs, je n’arrivais pas à obtenir une vitesse stable, alors j’ai installé deux mini aimants néodyme sur l’un des ventilateurs, et un détecteur à effet hall (type KY-003) pour mesurer la vitesse de rotation. Lors de mes essais, tout allait bien, puis quand j’ai fait l’intégration finale, plus rien ne marchait, sauf avec un duty cycle de 100%. En fait, dans le montage final, les fils ne sont plus volants, mais réunis dans un toron, et du coup il y a des inductions parasites qui altèrent le signal tachymétrique. Le problème a été résolu en mettant un filtre passe bas composé d’une résistance de 2,7K et une capa de 47nF sur l’entrée tachymétrique.

L’intégration mécanique est plus difficile, j’étais parti sur la mauvaise idée de faire un montage extérieur, mais cette solution n’est pas top, et finalement j’ai intégré les ventilateurs à la place de la grille de ventilation supérieure où ils tiennent tout juste. Et j’ajoute un grille par-dessus, qui est maintenue par des aimants. L’ensemble doit être démonté pour rouler, d’où l’utilisation d’un connecteur sur l’unité de ventilation.

Le résultat est plutôt satisfaisant : avec une température extérieure à l’ombre de 35° (11 juin), et le frigo chargé avec 9 grandes bouteilles d’eau, la température dans la colonne de refroidissement se stabilise à 30°, et la température à l’intérieur du frigo est OK. Dans cette situation la vitesse de rotation des ventilateurs est de 1714 T/Mn.

Je joins quelques photos, le programme et le schéma à ce post.

/* Programme Ventilateurs V2.0.1 01/06/2025 18H59
Syphil le 01/06/2025
Ce montage est une unité de ventilation pour frigo de camping car. */

#include <OneWire.h> // Librairie pour la gestion interface OneWire
#include <LiquidCrystal_I2C.h> // Bibliothèque contrôle afficheur LCD via liaison I2C
#include <DallasTemperature.h> // Librairie pour la gestion de température
# include <SoftwareSerial.h> // Librairie pour liaison série
# include <Wire.h>

#define BusOW 4 // L'entrée du Bus One Wire est sur la broche 4

//Constantes pour PWM et ventilateurs
int CSorPWM = 9; // Sortie data N°9
long CFrqProc = 16000000; // Fréquence processeur
long CFrqPWM = 25000; // Fréquence du signal PWM

// Autres constantes
int CIMA = 7; //Entrée Interrupteur Auto/Manu
int CIntpin = 2; // Entrée interruption
const unsigned long CTOlcd = 360000; // Time out pour éteindre le LCD = 30 secondes
const byte CNpartour = 2; // Ex 2, Nombre de détections par tour (donc deux encoches dans la roue de détection)
const byte CNbdetec = 1; // Ex 20, Nombre de détections avant réactualisation du nombre de tours
const unsigned long CTempsBoucle = 1000; // Gestion interval de temps lecture température


//Variables pour PWM et ventilateurs
int VIcr; //
int VDutyCycle =0; //
int VPotar = 0; // Valeur potentiomètre 0-100
int VMemDuCy = 0; // Mémorisation dutyclycle

//Variables pour thermomètre
OneWire oneWire(BusOW); // Instance pour communiquer avec les capteurs OneWire
DallasTemperature sensors(&oneWire);
DeviceAddress VThermometre; // Adresse thermomètre sur le bus OneWire
float VTemper; // Température thermomètre
float VTemperpre =0.0; // Température précédente
bool VThermOK = true; // Indique si la présence du thermomètre a été détectée 

// Autres variables
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4); // Declaration écran LCD
volatile byte VCpt = 0; // Entrée comptage nombre inpmpulsions capteur effet Hall
volatile bool VChg = false; // Flag changement de valeur
unsigned long VT0 = 0; // Temps initial
unsigned long VT1; // Temps actuel
unsigned long VTemps = 0; // Temps écoulé entre deux comptages
int VVitesse = 0; // Vitesse ventilateur
bool VStlcd = true; // Etat allumé lcd
byte VNbdetec = 20; // Variable comptage nombre de réactualisations
bool VAM = true; // Etat Auto (true) / Manu (false)
bool VPmode = true; // Etat mode précédent
int Vinter = 0; // Lecture interrupteur Auto/Manu
unsigned long VBoucle = CTempsBoucle; // Variable de décomptage entre deux lectures de températures

void setup() 
{
  Serial.begin(9600);
  pinMode(CSorPWM, OUTPUT);
  pinMode(CIMA, INPUT_PULLUP); // Entrée interrupteur Manu/auto
  sensors.begin();

// Initialisation Timer/Counter 1
  noInterrupts();
  TCCR1A = 0xA2;
  TCCR1B = 0x19;
  TCNT1H = 0x00;
  TCNT1L = 0x00;
  // Configuration de la la fréquence de 25KHz pour les impulsion PWM
  //VIcr = 639; // Valeur pour une fréquence de 25KHz
  VIcr = int(CFrqProc / CFrqPWM) -1;
  ICR1H = VIcr >> 8; //Registre Compteur 1 Haut
  ICR1L = VIcr & 0x00ff; // Registre Compteur 1 Bas 
  interrupts();

// Initialisation afficheur  
  lcd.init(); // Initialisation afficheur
  lcd.clear(); // Effacement afficheur
  lcd.backlight(); // Allumage Afficheur
  lcd.setCursor(0,0); // Positionnement curseur
  lcd.print("Temperature : ");
  lcd.setCursor(0,1); // Positionnement curseur
  lcd.print("Mode : ");
  lcd.setCursor(0,2); // Positionnement curseur
  lcd.print("Vitesse : ");
  lcd.setCursor(0,3); // Positionnement curseur
  lcd.print("Duty cycle : ");

  // Initialisation Thermomètre
  oneWire.reset_search(); // Réinitialisation recherche de capteur
  // affecte la première valeur trouvée à VThermomètre
  if (!oneWire.search(VThermometre)) 
  {
    Serial.println("Adresse introuvable pour le thermomètre");
    VThermOK = false;
    lcd.setCursor(0,0);
    lcd.print("Defaut Thermometre");
  }
  else 
  {
    sensors.setResolution(VThermometre, 12);
    lcd.setCursor(0,0); // Positionnement curseur
    lcd.print("Temperature : "); 
  } 

//Initialisation interruption pour compte tours  
  pinMode(CIntpin, INPUT); // Entrée capteur effet Hall
  attachInterrupt(digitalPinToInterrupt(CIntpin), F_RoutInt, RISING); // déclaration de l'interruption sur l'entrée CIntpin

} //Fin fonction setup()

void loop() 
{
  //Lecture et mappage de l'entrée analogique A1 correspondant au potentiomètre
  if(!VAM) // Si Mode Manuel
  {
    VPotar = analogRead(A1);
    //map du potentiomètre pour déterminer le DutyCycle 0-100
    VDutyCycle = map(VPotar, 0, 1023, 0, 100);
    if(VDutyCycle != VMemDuCy)
    {
      VMemDuCy = VDutyCycle;
      lcd.setCursor(13,23);
      lcd.print(String(VDutyCycle) + "  " ); // Actualisation duty cycle sur l'afficheur (%)
      noInterrupts();
      OCR1A = VIcr * (VDutyCycle / 100.0); // Rgistre Sortie PWM 1 A
      interrupts();
    }
  }
// Acquisition état interrupteur et allumage Lcd
  Vinter = F_Inter(CIMA); // Acquisition interrupteur
  if (Vinter == 1) VAM = true;
  if (Vinter == 2) VAM = false;
  if (VAM != VPmode) // Si l'interrupteur a été basculé on réactualisse l'affichage du mode
  {
    lcd.backlight();
    lcd.display();
    VStlcd = true;
    VPmode = VAM; // Ancien Mode devient mode actuel
    lcd.setCursor(7,1);
    if(VAM) lcd.print("Auto  "); else lcd.print("Manuel");
  }
// Gestion de la vitesse
  if (VChg)
  {
    if (VT0 == 0) // Première fois
    {
      VT0 = millis();
      VCpt = 0;
      VChg = false;
    } 
    else
    {
      VT1 = millis(); // Initialisation Temps zéro au premier passage d'un cycle
      VTemps = VT1 - VT0; // Calcul interval de temps entre premier et dernier passages
      VVitesse = 60000 / ((VTemps * CNpartour)/VCpt); // Vitesse en tours/minute
      VNbdetec = byte(VVitesse / 8)+20; // Ajustement du nombre de tours à compter en fonction de la vitesse
      lcd.setCursor(10,2); // Positionnement curseur
      lcd.print(String(VVitesse) + "   ");
      VCpt = 0; // Remise à zéro compteur d'impulsions
      VChg = false;
      VT0 = millis();
    }
  }
  --VBoucle;
  if (VBoucle == 0)
  {
    VBoucle = CTempsBoucle;
    sensors.requestTemperatures(); // Interrogation capteur température
  }
// Gestion du mode Manu
  if (VAM == false) // Mode Manu
  {
    if(VThermOK)
    {
      VTemper = sensors.getTempC(VThermometre);
      if (VTemper == DEVICE_DISCONNECTED_C)
      {
        lcd.setCursor(0,0); // Positionnement curseur
        lcd.print("Snd temp deconnectee");
      }
      else if (VTemper != VTemperpre)
      {
        lcd.setCursor(14,0);
        lcd.print(String(VTemper,1) + " ");
        VTemperpre = VTemper; 
      }
    }   
  }
// Gestion du mode Auto
  else if(VThermOK)
  {
    VTemper = sensors.getTempC(VThermometre);
    if (VTemper == DEVICE_DISCONNECTED_C)
    {
      lcd.setCursor(0,0); // Positionnement curseur
      lcd.print("Snd temp deconnectee");
    }
    else if (VTemper != VTemperpre)
    {
      lcd.setCursor(14,0);
      lcd.print(String(VTemper,1) + " ");
      if (VTemper > 30.0) VTemper = 30.0; else if (VTemper < 20.0) VTemper = 20.0; // Limitation de la température lue
      VTemperpre = VTemper;
      VDutyCycle = map(int(VTemper * 100), 2000, 3000, 9, 100); // Mise en forme de DutyCycle selon la température
      VMemDuCy = VDutyCycle;
      lcd.setCursor(13,23);
      lcd.print(String(VDutyCycle) + "  " ); // Actualisation duty cycle sur l'afficheur (%)      
      noInterrupts();
      OCR1A = VIcr * (VDutyCycle / 100.0); // Rgistre Sortie PWM 1 A
      interrupts();
    }
  }
  F_TOlcd();  
} // Fin fonction loop()


// Routine utilisée pour gérer l'interrupteur
int F_Inter(int PInput)
{
  static int VEtatprec = LOW;
  int VEtatcur = LOW;
  int VRetour = 0;
  static int VNblec = 10; // Nombre de cycles répétitifs, utilisé pour le filtrage des rebonds
  static int Vbout0 = HIGH;
  int Vbout1;
  Vbout1 = digitalRead(PInput); // Acquisition entrée du bouton
  if (Vbout1 == Vbout0) {VNblec -=1;} else // Filtrage rebonds
  {
    VNblec = 10;
    Vbout0 = Vbout1;
  }
  if (VNblec <= 0)
  {
    VNblec = 0;
    VEtatcur = Vbout1; // Validation état bouton après filtrage des rebonds
  }
  if(VEtatcur == LOW) {VEtatcur = HIGH;} else {VEtatcur = LOW;} // Inversion du sens d'action du bouton (à cause de INPUT_PULLUP)
  if(VEtatcur != VEtatprec) // Changement d'état du bouton poussoir
  {
    VEtatprec = VEtatcur;
    if (VEtatcur == HIGH) // Front montant
    {
      VRetour = 1;
    }
    if (VEtatcur == LOW)
    {
      VRetour = 2;
    }
  }
  else {VRetour = 0;}
  return(VRetour);
} // Fin fonction F_Inter()


void F_RoutInt() // Routine de gestion d'interruption
{
  VCpt++; // Incrémentation du compteur
  if(VCpt == VNbdetec) VChg = true; // Flag changement de valeur
  return;
} // Fin fonction F_RoutInt()

void F_TOlcd() // Fonction time out pour éteindre l'écran LCD
{
  static unsigned long VTp = millis(); // Initialisation temps courant et temps actuel
  static unsigned long VTc = VTp;
  VTc = millis();
  if (VTc - VTp > CTOlcd) // Le time out CTOlcd est dépassé
  {
    if (VStlcd == true)
    {
      lcd.noDisplay();
      lcd.noBacklight();
      VStlcd = false;
      VTp = VTc;  
    } 
  }
} // Fin fonction F_TOlcd()

// Fonction F_Timer attente d'un délais en ms, sans interruption du programme
bool F_Timer(unsigned long Ptemps)
{
  static unsigned long VTimeP = millis();
  static unsigned long VTimeC;
  VTimeC = millis();
  if (VTimeC - VTimeP > Ptemps)
  {
    VTimeP = VTimeC;
    return true;
  } else return false;
} // Fin fonction F_Timer

![20250605_144016|281x500](upload://oIWxRCM1HSfE0WWpdXqIMZlZHnq.jpeg)
![20250606_161654|690x388](upload://1M7v2nMv1TF3dZYadBJEb8ZY3xo.jpeg)
![20250606_161724|690x388](upload://jRosdsndxZpp3sb5bAwG8PS8K0Q.jpeg)
![20250608_141733|281x500](upload://eovbCrkIt1heaBeCfx8wMGgK3z0.jpeg)
![20250612_153037|690x388](upload://zRrz5ZxsEF6GSinc6UQrIKzfcGa.jpeg)
[Sch Elec Ventilateurs A0-2.pdf|attachment](upload://x6J0cOuq73iMnV3nmLFvGzjLtcW.pdf) (239,9 Ko)

Joli projet, mais les images ne sont pas passées, tu as dû les mettre dans la zone de code.

Merci, je vais de ce pas y remédier...
Sch Elec Ventilateurs A0-2.pdf (239,9 Ko)





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