Travaux et conseils pratiquesCuve avec précision améliorée

Vous avez trouvé une astuce, vous êtes maintenant aguerri dans telle ou telle manipulation, bricolage, montage, venez partager ici vos trucs et astuces...
Règles du forum
Chers membres, merci de prendre connaissance et respecter les quelques règles de bon sens suivantes avant de poster votre message :
- Vous assurer que vous postez dans la bonne rubrique
- Vérifier qu'il n’existe pas déjà une réponse à votre question ou un sujet identique
- Prendre conscience que vos propos n’engagent que vous et que vous devrez en assumer la paternité
- Vérifier les sources des informations que vous diffusez, en vous assurant le cas échéant de respecter les droits d’auteur qui peuvent être liés aux informations, images ou documents cités
- Prendre soin de respecter vos interlocuteurs et bannir les insultes et autres propos diffamatoires ou dégradants
- Vous assurer de rester autant que faire se peut dans le sujet exposé
- Prendre le temps de vérifier l’orthographe et la grammaire de votre message
Merci par avance de votre contribution à préserver le bon esprit de ce forum.
Avatar de l’utilisateur
Peujton
Arpette
Arpette
Messages : 282
Inscrit depuis : 1 an 9 mois
Mon équipement : Cuve Brewferm 27L achetée d'occasion pilotée par une carte Arduino Uno + sonde de température
Pompe de recirculation IWAKI Magnet Pump MD-6-2
Système de chauffe régulé par un contrôleur STC-1000
Brewbag 30L
Serpentin refroidisseur + pompe + cuve eau froide 500L
Seaux de fermentation 12L et 30L
Seaux de 12L et 30L additionnels pour le stockage du malt concassé, les ingrédients, le transvasement...
Concasseur Brewferm Grizzly
Capsuleuse Corona Pro
Désinfectant Chemipro OXi
Tête, bras, jambes, mains (c'est ce qui me sert le plus :)
Brasseur : Amateur
Localisation : Saint-Jacques-Sur-Darnétal
A remercié : 72 fois
A été remercié : 20 fois

Cuve avec précision améliorée

Message par Peujton »

Je profite d’une vacherie de bronchite qui me bloque enfermée à la maison, pour finaliser un projet que j’ai commencé il y a quelques mois, pour améliorer la qualité de mes paliers de température.
Je dispose d’une cuve chauffante Brewferm de 27 litres avec un robinet inox. Une bonne vieille cuve… Le défaut de ce type de cuve vient de son imprécision au niveau des températures. Le thermostat est un simple potentiomètre gradué de 10 en 10. Lorsque la cuve passe en chauffe, elle chauffe à fond et comme elle a une très forte inertie, généralement, la température est dépassée de 5 à 10 degrés. Même en essayant de regraduer à force d’essais, même en se disant que l’on chauffe 10°C en dessous histoire de pas dépasser, même avec toutes les astuces possibles, disons-le, ça reste une bonne bouilloire de luxe pour grand buveur de thé :jesors4:
Mon projet était de parvenir à gommer ces défauts par une solution simple, pas chère et réutilisable.
Partant du principe que si je pouvais avoir une température précise et piloter plus finement la chauffe que le simple on off du thermostat de la cuve Brewferm, la solution serait plus proche de mes besoins, à savoir, brasser avec… Je suis parti sur l’idée de programmer mon propre programme de contrôle de chauffe.
Ayant déjà une bonne expérience sur l’Arduino Uno et ayant un peu de matériel disponible et quelques composants d’avance à sacrifier pour l’exercice, je suis parti sur cette solution. J’ai cherché le seul composant qu’il me manquait : une sonde précise étanche dans les plages de température.
Ensuite pour afficher la température précise à atteindre et la dernière température lue, il me fallait un afficheur. J’ai opté pour un afficheur 1602 A 2x16 digits que j’avais en stock. Le relai 220V/10A est assuré par un SRD-05-VDC-SL qui du coup trouve sa première et dernière application.
Pour éviter de gérer des entrées clavier, le réglage de la température de chauffe se fait par un potentiomètre dont la valeur va pouvoir être lue par la carte Arduino (valeur 0 à 1023).
S’agissant d’un pilotage d’un courant relativement puissant pour alimenter la cuve, le relai est l’élément qui va le plus être sollicité. J’ai fait un rapide examen des consommations prévues sur le circuit :
- afficheur 1602A : 1.2mA
- sonde DS18B20 : 1.5mA
- relais SRD-05-VDC-SL : 360mW sous 5V -> 72mA, donc au max 80mA
- 2x potentiomètres : 2x 0.5mA
- résistance : 0.25mA


La grosse contrainte sur ce type de projet sur Arduino, c’est la puissance disponible pour piloter les composants du circuit les plus gourmands. La carte Arduino Uno Rev 3 que j’ai utilisée permet de délivrer 40mA par port/plot et 240mA sur le circuit complet. Certains experts indiquent que la carte peut supporter beaucoup plus si la surconsommation est extrêmement ponctuelle et instantanée. Dans mon cas, c'est l’activation du relai pour mettre en chauffe surtout et arrêter la cuve, qui va générer le gros de la charge, qui d’après le datasheet du composant ne devrait pas dépasser 10ms. Un laps de temps assez réduit finalement qui devrait permettre au circuit d'évacuer la chaleur produit, s'il y en a. Il restera donc cependant à surveiller aussi la température du circuit...
Il restait à mettre en musique tout cela sur une plaque d’essai, avec quelques composants périphériques et quelques paquets de nouilles comme il est d’usage😊sur un bon circuit d’essai Arduino.

Le schéma du circuit :

Voir la photo dans la galerie

La partie basse tension en détail :
1x Carte Arduino Uno (25€)
1x afficheur 1602 A ou équivalent
1x relai SRD-05-VDC-SL
1x sonde DB18S20 (13€ht)
2x potentiomètre 4,7kohms (valeurs lues 0 à 1024)
1x résistance de 220ohms


Détail de la partie secteur :

Voir la photo dans la galerie


Programme Arduino version test chauffe eau

Pour ma version de programmation d’essai, je suis parti en mode DEBUG (avec du println) et j’ai évité les tableaux et préféré consommer de la variable, plus simple de mon point de vue pour la mise au point, et ça me permet de mieux ajuster les différents niveaux de chauffe.
A force d’essais, je suis arrivé à la conclusion que pour dompter l’inertie de la cuve, il me fallait découper la chauffe en plusieurs phases et qu’il fallait des cycles de chauffe pas trop long, pour le moment, je suis descendu à 30s par cycle, ce qui semble un bon compromis entre vitesse de chauffe et maitrise de la montée en température :
- prg100 : une première phase où la température est loin d’être atteinte (écart > 15°C) et où on peut s’autoriser à libérer les chevaux caloriques de la cuve à 100%, soit 30s de chauffe sur 30s.
- prg1 : une deuxième phase où la température est loin d’être atteinte (écart > 10°C) et où on l’on doit commencer à couper un peu la chauffe pour incurver la pente de montée en température en coupant la chauffe 5s après 25s d’allumage
- prg2 : une troisième phase où la température est plus proche (écart >5°C) et où il faut commencer à couper un peu la chauffe 20s de chauffe, puis 10s de coupure
-prg3 : une quatrième phase où on est à moins de 2 degrés de la température à atteindre et où il faut fournir un effort de chauffe mais beaucoup plus modéré pour arriver en plateau à la bonne température, et là on allume 10s puis on coupe 20s
- prg4 : une cinquième phase où on est à moins de 1°C ou même à température, et là, on va juste devoir maintenir un effort pour se maintenir à la bonne température. Mes tests ont montré que prg4 devait être adapté en fonction de la température à atteindre : pour 63°C, 2s de chauffe/30s suffisent. Mais il faut compter ensuite pour monter à 75°C, 5s de chauffe et 25s de coupure. Puis pour monter à 100°C, il faut compter 10s de chauffe et 20s de coupure.
- sinon, dans les autres cas, on dépasse et on doit couper (et il y a peut-être quelque chose à revoir donc)
Mes premiers essais pour passer de 10°C à 60°C sont concluants, mais un premier essai de montée à 75°C a plafonné à 73°C. J’ai revu le programme 4 comme suit pour augmenter le temps de chauffe / 30s en conséquence : 5s pour monter à 75°C et 10s pour monter à 100°C.
On peut résumer les programmes comme suit :

chauffe t cible < 64 t cible <76 t cible 100
prg100 30 30 30
prg1 25 25 25
prg2 20 20 20
prg3 10 10 10
prg4 2 5 10


Mes tests à partir de là avec de l’eau ont été concluants. Il restera à voir si cela suffit pour un brassin un peu plus dense.
Il reste à voir comment le pilotage va fonctionner pour différents paliers et comment ça peut tenir dans la durée, car le relai peut engendrer de la surchauffe sur la carte. Sur quelques minutes, ça n’est pas possible à voir, mais en testant des maintient en température 1h, je devrais avoir une idée précise d’un éventuel problème ou de la validité de la solution. J’aviserai ensuite. Il existe des solutions type shield de puissance (https://www.manomano.fr/p/motor-power-s ... d=50562460), mais ça a un coup. Si nécessaire, j’y passerai 😉

Résumé de mes tests :

Graphe montée en température de 9°C à 63°C :

Voir la photo dans la galerie


Graphe montée en température de 63°C à 75°C :

Voir la photo dans la galerie


Graphe montée en température de 75°C à 100°C :

Voir la photo dans la galerie


Programme Arduino

Code : Tout sélectionner

#include "TimerOne.h"
#include <LiquidCrystal.h>
#include <OneWire.h>

//SDHT dht;

OneWire ds(2); // Déclarez un objet OneWire lié à la broche 2

int valeur;
int potentiometre=A0;
double valeur_maxi_potentiometre=1024;
double valeur_mini_potentiometre=3;
double temperature_maxi_cible=100; // 100% est pas mal comme maxi !
double temperature_cible_courante=0;
double t1 = 0;
double tprec=0;
double tccprec=0;

// 
// tableaux de données pour la sonde DS18B20
//
byte data[12]; // Tableau de données pour stocker les données du capteur
byte addr[8]; // Tableau d'adresses pour stocker l'adresse unique du capteur
float TemperatureSum=0;

//
// Initilisation du temps
//
unsigned long time; // lecture de l'incdice de temps du début d'action
unsigned long time1; // lecture du temps écoulé depuis début d'action
int chauffe=0; // 0=chauffe pas activée, 1=chauffe activée
//
// type_chauffe : plus on est proche de la température à atteindre, moins le temps de chauffe sera long, afin d'atténuer l'inertie de la cuve
//
// si t cible <65°C
//
// à + de 15°C sous la température, on active la prise 30s et on coupe 0s
// à + de 10°C sous la température, on active la prise 25s et on coupe 5s
// à + de 5°C sous la température, on active la prise 20s et on coupe 10s
// à + de 2°C sous la température, on active la prise 10s et on coupe 20s
// à + de 1°C sous la température, on active la prise 2s et on coupe 28s
// sinon, si la temp est > l'objectif, on coupe la prise sinon on l'allume
//
// si t cible <80°C
//
// à + de 15°C sous la température, on active la prise 30s et on coupe 0s
// à + de 10°C sous la température, on active la prise 25s et on coupe 5s
// à + de 5°C sous la température, on active la prise 20s et on coupe 10s
// à + de 2°C sous la température, on active la prise 10s et on coupe 20s
// à + de 1°C sous la température, on active la prise 5s et on coupe 25s
// sinon, si la temp est > l'objectif, on coupe la prise sinon on l'allume
//
//
// si t cible <100°C
//
// à + de 15°C sous la température, on active la prise 30s et on coupe 0s
// à + de 10°C sous la température, on active la prise 25s et on coupe 5s
// à + de 5°C sous la température, on active la prise 20s et on coupe 10s
// à + de 2°C sous la température, on active la prise 10s et on coupe 20s
// à + de 1°C sous la température, on active la prise 10s et on coupe 20s
// sinon, si la temp est > l'objectif, on coupe la prise sinon on l'allume
//
int type_chauffe=0; 
int action_chauffe_terminee=0; // 0=non, 1=oui -> on peut repartir sur un type de chauffe différent selon la temp

// initialisation de l'afficheur LCD
// dans l'ordre RS(12), E(11) puis les 4 bits de données D4 à D7 
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
// symbole °
byte degre[8] = {
  B00110,
  B01001,
  B00110,
  B00000,
  B00000,
  B00000,
  B00000,
};




void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  pinMode(A0, INPUT);
  time=millis();
  chauffe=0;
  type_chauffe=0;
  action_chauffe_terminee=0;
 
  //
  // Afficheur 2x16 digits
  //
  // définition de la dimension de l'afficheur (colonnes, lignes)
  lcd.begin(16, 2);    // ATTENTION : malgré les apparences, le modèle 161A possède 2 lignes de 8 caractères ... alignées !
  // lcd.begin(10, 1) // pour un afficheur à 2 lignes de 16 caractères
  // Affichage du message :
  lcd.print("Controle de temp.");     // les 8 premiers caractères ...
  lcd.setCursor(0, 1);       // changement de "ligne"
  lcd.print("Lancement...");  // les 8 derniers caractères
  lcd.createChar(0,degre);
  delay(1000);
  time=millis();

}


//
// BOUCLE PRINCIPAL
//

void loop() {

  valeur = analogRead(potentiometre);
  Serial.print("----->Valeur Potentiometre = ");
  Serial.println(valeur);

 

  //
  // lecture de la température mesurée par la sonde
  //
  lecture_DS18B20();
  t1=trunc(TemperatureSum);
  
  //
  // calcul de la température cible lue
  //
  temperature_cible_courante=trunc(double(valeur*temperature_maxi_cible/(valeur_maxi_potentiometre-valeur_mini_potentiometre)));

  Serial.print("***********>t1=");
  Serial.print(t1);
  Serial.print(", tprec=");
  Serial.println(tprec);
  Serial.print("***********>temperature_cible_courante=");
  Serial.print(temperature_cible_courante);
  Serial.print(", tccprec=");
  Serial.println(tccprec);

    // 
    // dans ce cas actualiser l'affichage LCD
    //
    lcd.clear();
    lcd.print("Temp.:");     // les 8 premiers caractères ...
    lcd.print(int(trunc(t1)));  // les 8 derniers caractères
    lcd.write(byte(0));     // les 8 premiers caractères ...
    lcd.print("C");     // les 8 premiers caractères ...
    if (type_chauffe>0) { 
      if (type_chauffe==100) lcd.print(">*"); else {lcd.print(">");lcd.print(type_chauffe);  } 
      lcd.print(">");
      int sec=trunc((time1-time)/1000);
      lcd.print(sec);
      lcd.print("/30");
    }
    lcd.setCursor(0, 1);       // changement de "ligne"
    lcd.print("Cible:");     // les 8 premiers caractères ...
    lcd.print(int(trunc(temperature_cible_courante)));  // les 8 derniers caractères
    lcd.write(byte(0));     // les 8 premiers caractères ...
    lcd.print("C");     // les 8 premiers caractères ...

    delay(500);

    // 
    // actualiser si une différence est relevée sur une température
    //
    if(t1!=tprec || temperature_cible_courante!=trunc(double(tccprec))) {

      if (temperature_cible_courante!=tccprec) {
        //
        // la température cible a changée -> la prendre en compte
        //
        Serial.print("----->Réglage température cuve sur ");
        Serial.println(temperature_cible_courante);
        tccprec=temperature_cible_courante;

      } else {
        // 
        // la température lue sur la sonde a changé -> la prendre en compte
        //
        Serial.print("----->température cuve sur ");
        Serial.println(t1);
        tprec=t1;

      }

      // 
      // on coupe la chauffe et on arrête l'action en cours pour se caler sur la nouvelle température
      //
      chauffe=0;
      type_chauffe=0;
      action_chauffe_terminee=0;
      tccprec=temperature_cible_courante;

      Serial.println("MODIFICATION D'UNE TEMPERATURE LUE -> ACTION DE CHAUFFE TERMINEE. On coupe !");
      Serial.println("ACTION DE CHAUFFE A DETERMINER !");
      digitalWrite(3, LOW); // normalement le port est déjà LOW
      
    }
    //
    // DANS TOUS LES CAS : CONTROLE DE LA CHAUFFE
    //
    // si une action de chauffe est en cours, on la laisse aller au bout
    //
    Serial.print("action_chauffe_terminee=");
    Serial.print(action_chauffe_terminee);
    Serial.print(",chauffe=");
    Serial.print(chauffe);
    Serial.print(",type_chauffe=");
    Serial.print(type_chauffe);
    Serial.print(",time=");
    Serial.print(time);
    Serial.print(",time1=");
    Serial.println(time1);

    if (action_chauffe_terminee==0 && chauffe==1) {
      time1=millis();
      Serial.print("Lecture time1=");
      Serial.print(float(time1/1000));
      Serial.print(", nb secondes écoulées depuis denier millis() :");
      unsigned long ecoulees=(time1-time)/1000;
      Serial.println(ecoulees);

      // dans tous les cas, si une 30s sont écoulées, on termine l'action en cours, on arrête la prise
      if (time1>=time+30000) {
        action_chauffe_terminee=1;
        chauffe=0;
        type_chauffe=0;
        Serial.println("ACTION DE CHAUFFE TERMINEE. On coupe !");
        digitalWrite(3, LOW); // normalement le port est déjà LOW
      } else { // s'il y a une action de chauffe en cours et elle n'est pas terminée
        // on controle l'action en cours selon son type de chauffe attendu
        switch (type_chauffe) {
          case 0: // on vérifie juste que les 30s ne sont pas passées
            break;
          case 1: // on vérifie que le temps de chauffe n'est pas dépassé
            if (time1>=time+25000) {
              // on coupe la chauffe
              Serial.println("ACTION DE CHAUFFE 1 (25s/5s) TERMINEE. On coupe jusqu'à la fin des 30s !");
              digitalWrite(3, LOW); // normalement le port est déjà LOW
            }
            break;
          case 2: // on vérifie que le temps de chauffe n'est pas dépassé
            if (time1>=time+20000) {
              // on coupe la chauffe
              Serial.println("ACTION DE CHAUFFE 2 (20s/10s) TERMINEE. On coupe jusqu'à la fin des 30s !");
              digitalWrite(3, LOW); // normalement le port est déjà LOW
            }
            break;
          case 3 : // on vérifie que le temps de chauffe n'est pas dépassé (rappel 5s, puis 55s de coupure)
            if (time1>=time+10000) {
              // on coupe la chauffe
              Serial.println("ACTION DE CHAUFFE 3 (10s/20s) TERMINEE. On coupe jusqu'à la fin des 30s !");
              digitalWrite(3, LOW); // normalement le port est déjà LOW
            }
            break;
          case 4 : // on vérifie que le temps de chauffe n'est pas dépassé (rappel 2s, puis 28s de coupure)
            int a=2000;
            if (temperature_cible_courante<65) { a=2000;} 
            else if (temperature_cible_courante<80) { a=5000;}  
            else if (temperature_cible_courante<101) { a=70000;} 
            else { a=10000;}
            if (time1>=time+a) {
              // on coupe la chauffe
              Serial.println("ACTION DE CHAUFFE 4 (2s/28s) TERMINEE. On coupe jusqu'à la fin des 30s !");
              digitalWrite(3, LOW); // normalement le port est déjà LOW
            }
          case 100 : // on vérifie que le temps de chauffe n'est pas dépassé (rappel 30s, puis 0s de coupure)
            if (time1>=time+30000) {
              // on coupe la chauffe
              Serial.println("ACTION DE CHAUFFE 100 (30s/0s) TERMINEE. On coupe jusqu'à la fin des 30s !");
              digitalWrite(3, LOW); // normalement le port est déjà LOW
            }
            break;
          default: // coupé
            // on coupe la chauffe
            Serial.println("ACTION DE CHAUFFE défaut (0s/30s) TERMINEE. On coupe jusqu'à la fin de la minute !");
              digitalWrite(3, LOW); // normalement le port est déjà LOW
            break;
        }
      }
    } else if (chauffe==0 && type_chauffe==0) {
      //
      // si pas d'action en cours ou si action en cours et cette action est terminée, alors on repart sur une nouvelle action
      //
      chauffe=0;
      action_chauffe_terminee=0;
      // on repart pour 1 minute, reste à définir le programme
      time=millis();

      //
      // plus on est proche de la température à atteindre, moins le temps de chauffe sera long, afin d'atténuer l'inertie de la cuve
      // 100 : à + de 15°C sous la température, on active la prise 30s et on coupe 0s 
      // 1: à + de 10°C sous la température, on active la prise 25s et on coupe 5s
      // 2: à + de 5°C sous la température, on active la prise 20s et on coupe 10s
      // 3: à + de 2°C sous la température, on active la prise 10s et on coupe 20s
      // 4: à + de 1°C sous la température, on active la prise 2s et on coupe 28s
      // sinon, si la temp est > l'objectif, on coupe la prise sinon on l'allume

      if (t1+15<temperature_cible_courante) {
        //
        // type_chauffe 100 on allume 30s puis on coupe 0s
        //
        type_chauffe=100;
        chauffe=1;
        action_chauffe_terminee=0;
        digitalWrite(3, HIGH);
        Serial.println("CHOIX TYPE CHAUFFE 100 (30s/0s). On allume !");

      } else if (t1+10<temperature_cible_courante) {
        //
        // type_chauffe 1 on allume 25s puis on coupe 5s
        //
        type_chauffe=1;
        chauffe=1;
        action_chauffe_terminee=0;
        digitalWrite(3, HIGH);
        Serial.println("CHOIX TYPE CHAUFFE 1 (25s/5s). On allume !");

      } else if (t1+5<temperature_cible_courante) {
        //
        // type_chauffe 2 on allume 20s puis on coupe 10s
        //
        type_chauffe=2;
        chauffe=1;
        action_chauffe_terminee=0;
        digitalWrite(3, HIGH);
        Serial.println("CHOIX TYPE CHAUFFE 2 (20s/10s). On allume !");

      } else if (t1+2<temperature_cible_courante) {
        //
        // type_chauffe 3 on allume 10s puis on coupe 20s
        //
        type_chauffe=3;
        chauffe=1;
        action_chauffe_terminee=0;
        digitalWrite(3, HIGH);
        Serial.println("CHOIX TYPE CHAUFFE 3 (10s/20s). On allume !");

      } else if (t1==temperature_cible_courante || t1+1<=temperature_cible_courante ) {
        //
        // type chauffe 4 on allume 2s et on coupe 28s  :maintient en température
        //
        type_chauffe=4;
        chauffe=1;
        action_chauffe_terminee=0;
        digitalWrite(3, HIGH);
        Serial.println("CHOIX TYPE CHAUFFE 4 (2s/28s). On allume !");

      } else if (t1>temperature_cible_courante) {
        Serial.println("=======> Surchauffe !!!!!!!!! On coupe !");
        digitalWrite(3, LOW);
        chauffe=0;
        time=millis();
      }

    }


  tprec=t1;
  tccprec=temperature_cible_courante;

}





void lecture_DS18B20() {

  if ( !ds.search(addr)) {
    Serial.println("Pas de capteur trouvé");
    ds.reset_search();
    delay(250);
    return;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
    Serial.println("CRC incorrect");
    return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1); // Lancez une conversion de température
  delay(1000); // Attendez la fin de la conversion
  byte present = ds.reset();
  ds.select(addr);
  ds.write(0xBE); // Demandez les données de température
  
  for (int i = 0; i < 9; i++) { // Boucle pour lire les données
    data[i] = ds.read();
  }

  ds.reset_search();
  byte MSB = data[1];
  byte LSB = data[0];
  float tempRead = ((MSB << 8) | LSB); // Concaténez les octets pour obtenir la température
  TemperatureSum = tempRead / 16;
  Serial.print("Température : ");
  Serial.print(TemperatureSum);
  Serial.println("°C");
  
}

Il me reste pas mal à faire.
J’ai planqué le tout dans une boite de chaine neige en plastique dur noir, pour évite r l’achat d’un boitier dont le prix aurait multiplié par 10 le cout du prototype.
Mes tests m’ont amené à conserver la partie courant secteur hors de la boite contenant le circuit courant faible, afin de limiter les perturbations du courant secteur sur l’électronique.
Il me restera à fixer tout cela en plus dur soudé sur une plaque quand ce sera au point, et à protéger la partie électronique de l’Arduino des courant forts qui vont circuler dans la partie secteur…
Quelques photos …
Dernière modification par Penn-Maen le 06 mars 2025 14:11, modifié 1 fois.
Raison : Mise en place balise Code pour le programme ;)
--
Peujton
Nombre de brassins : 18
Je débute, le brassage pour moi, c'est encore de la poésie :violin: ... :lol:
Avatar de l’utilisateur
Peujton
Arpette
Arpette
Messages : 282
Inscrit depuis : 1 an 9 mois
Mon équipement : Cuve Brewferm 27L achetée d'occasion pilotée par une carte Arduino Uno + sonde de température
Pompe de recirculation IWAKI Magnet Pump MD-6-2
Système de chauffe régulé par un contrôleur STC-1000
Brewbag 30L
Serpentin refroidisseur + pompe + cuve eau froide 500L
Seaux de fermentation 12L et 30L
Seaux de 12L et 30L additionnels pour le stockage du malt concassé, les ingrédients, le transvasement...
Concasseur Brewferm Grizzly
Capsuleuse Corona Pro
Désinfectant Chemipro OXi
Tête, bras, jambes, mains (c'est ce qui me sert le plus :)
Brasseur : Amateur
Localisation : Saint-Jacques-Sur-Darnétal
A remercié : 72 fois
A été remercié : 20 fois

Re: Cuve avec précision améliorée

Message par Peujton »

--
Peujton
Nombre de brassins : 18
Je débute, le brassage pour moi, c'est encore de la poésie :violin: ... :lol:
Avatar de l’utilisateur
benmince
Brasseur
Brasseur
Messages : 1467
Inscrit depuis : 10 ans 5 mois
Mon équipement : décapsuleur
Brasseur : Amateur
Localisation : Normandie Cailleville
4 recettes partagées
A remercié : 132 fois
A été remercié : 79 fois

Re: Cuve avec précision améliorée

Message par benmince »

:o
Je suis toujours impressionné et également envieux de tout vos montages électroniques .
Je n'y comprends pas grand chose mais c'est passionnant de vous voir cogiter .
Sur l'autre sujet d'hier , ils ont la Wifi , eux ! :lol:

Bon, sinon pour des paliers de température stables , il suffit d'isoler la cuve et d'utiliser un thermomètre . En règle général je perds un degré par demi heure à 10°C de température ambiante .

Bout : Eric974 Abbaye - Imperial Stout Tonka - Belgian Dark Strong
Keg : NEIPA Conan/Mosaic/Sabro - AIPA WLP644 Citra/Mosaic
prim :
Projet : Dextrine-Mash Hopping
Avatar de l’utilisateur
Peujton
Arpette
Arpette
Messages : 282
Inscrit depuis : 1 an 9 mois
Mon équipement : Cuve Brewferm 27L achetée d'occasion pilotée par une carte Arduino Uno + sonde de température
Pompe de recirculation IWAKI Magnet Pump MD-6-2
Système de chauffe régulé par un contrôleur STC-1000
Brewbag 30L
Serpentin refroidisseur + pompe + cuve eau froide 500L
Seaux de fermentation 12L et 30L
Seaux de 12L et 30L additionnels pour le stockage du malt concassé, les ingrédients, le transvasement...
Concasseur Brewferm Grizzly
Capsuleuse Corona Pro
Désinfectant Chemipro OXi
Tête, bras, jambes, mains (c'est ce qui me sert le plus :)
Brasseur : Amateur
Localisation : Saint-Jacques-Sur-Darnétal
A remercié : 72 fois
A été remercié : 20 fois

Re: Cuve avec précision améliorée

Message par Peujton »

Oui, le wifi ce sera bien pour la V2 :D
Je vais regarder cette possibilité d'isoler. ça me fera effectivement gagner du temps :dance:
--
Peujton
Nombre de brassins : 18
Je débute, le brassage pour moi, c'est encore de la poésie :violin: ... :lol:
Avatar de l’utilisateur
Arwen
Ch'ti nouveau
Messages : 148
Inscrit depuis : 2 ans
Mon équipement : Bricolage maison en biab à partir de 2 futs de 30l, chauffage électrique commandé par un arduino, pompe, échangeur à plaques, fermenteur Brico Dépot, frigo régulé par stc1000.
Brasseur : Amateur
Localisation : Brest
2 recettes partagées
A remercié : 2 fois
A été remercié : 22 fois

Re: Cuve avec précision améliorée

Message par Arwen »

bonjour,

Quelques remarques pour aider, simplifier et éviter des problèmes.

- Il n'y a pas de problème au niveau du courant du relais, il est alimenté directement par le 5V et le fil de commande venant d'une des broches du processeur ne consomme que quelques mA, il n'engendrera pas de surchauffe sur la plaque.
- Il existe une bibliothèque pour la gestion de la lecture de la température :

Code : Tout sélectionner

#include <DallasTemperature.h>
int ONE_WIRE_BUS = 4;      //Broche du DS18B20, dépend évidemment de la broche utilisée
et pour une lecture :

Code : Tout sélectionner

DS18B20.requestTemperatures();
temperatureLue0 =  DS18B20.getTempCByIndex(0); // on peut avoir plusieurs sondes, la suivante p.ex. temperatureLue1 =  DS18B20.getTempCByIndex(1);
- Le principe de faire décroitre la puissance de chauffe quand on s'approche de la température désirée est tout à fait correcte MAIS les valeurs choisies dépendent fortement de la température ambiante et risquent de ne plus être valables si celle-ci change.
- Pour l'ébullition, pas de risque de dépasser 100°, on peut continuer plus longtemps à chauffer au max, par contre le choix d'un rapport cyclique jouera sur la puissance de cette ébullition.
- Il est préférable d'utiliser une fonction PID, qui marche un peu selon le même principe mais qui s'adapte aux différences.

Personellement j'aurais utilisé deux boutons poussoirs plutôt qu'n potentiomètre pour le règlage. D'ailleurs à quoi sert le deuxième potentiomètre du schéma ?
Et SURTOUT, j'aurais plutôt mis tout ce qui concerne le 220v dans une boite, c'est quand même une tension qui ne pardonne pas.

Bon courage pour la suite, celà fait plaisir de voir des gens qui péfèrent bricoler plutôt que de s'offrir une installation clefs en mains qui ne permettra pas forcément de faire de meilleures bières ... :clap: :clap: :clap:
Make beer great again (ndt : à bas la kro)
Avatar de l’utilisateur
Penn-Maen
Maître Brasseur
Maître Brasseur
Messages : 12678
Inscrit depuis : 14 ans 2 mois
Je suis tuteur : oui
Mon équipement : viewtopic.php?t=39535
Miss Vilaine ¯\_(ツ)_/¯
Brasseur : Amateur
Localisation : Morbihan centre
1 recettes partagées
A remercié : 777 fois
A été remercié : 1473 fois

Re: Cuve avec précision améliorée

Message par Penn-Maen »

Arwen a écrit : 05 mars 2025 16:02 Et SURTOUT, j'aurais plutôt mis tout ce qui concerne le 220v dans une boite,
TAFDAK
Arwen a écrit : 05 mars 2025 16:02c'est quand même une tension qui ne pardonne pas.
c'est l'intensité qui ne pardonne pas... (juste pour s'en rappeler : les clotûres électriques pour les bestiaux, c'est souvent > 10 000 V. Pourtant personne - humain ou animal - ne meurt de toucher le fil [sauf les poules, qui meurent plus de la peur que du choc] )

PM, chipoteur
Regarde, écoute, questionne, apprend, transmet, recommence sans cesse
Disclaimer : je dis certainement plus de conneries que la moyenne, alors vérifiez !

SE PRESENTER ...et... Guide pour débutants
Avatar de l’utilisateur
neo64
Maître Brasseur
Maître Brasseur
Messages : 2450
Inscrit depuis : 7 ans 2 mois
Brasseur : Amateur
A remercié : 102 fois
A été remercié : 340 fois

Re: Cuve avec précision améliorée

Message par neo64 »

Salut,
Pour parfaire ton montage je te conseille d'acheter une petite pompe pour recirculer la bière comme sur les cuve auto. Avoir une température précise c'est bien, si c'est homogène c'est mieux ;)
"In hop we trust"

Nos petits liens
Avatar de l’utilisateur
Arwen
Ch'ti nouveau
Messages : 148
Inscrit depuis : 2 ans
Mon équipement : Bricolage maison en biab à partir de 2 futs de 30l, chauffage électrique commandé par un arduino, pompe, échangeur à plaques, fermenteur Brico Dépot, frigo régulé par stc1000.
Brasseur : Amateur
Localisation : Brest
2 recettes partagées
A remercié : 2 fois
A été remercié : 22 fois

Re: Cuve avec précision améliorée

Message par Arwen »

Je suppose que la cuve est utilisée en biab. Avec une pompe, attention à ce qu'il reste toujours du moût dans le fond, sinon la résistance risque de ne pas aimer.

P.S. @Penn-Maen
On reparle de la loi d'Ohm ? Quand on dit 220V, on parle implicitement d'une source avec une impédance quasi nulle, les clôtures électriques ont évidemment une résistance interne très élevée .
Mais bon, je chipote aussi ...
Make beer great again (ndt : à bas la kro)
Avatar de l’utilisateur
Penn-Maen
Maître Brasseur
Maître Brasseur
Messages : 12678
Inscrit depuis : 14 ans 2 mois
Je suis tuteur : oui
Mon équipement : viewtopic.php?t=39535
Miss Vilaine ¯\_(ツ)_/¯
Brasseur : Amateur
Localisation : Morbihan centre
1 recettes partagées
A remercié : 777 fois
A été remercié : 1473 fois

Re: Cuve avec précision améliorée

Message par Penn-Maen »

Oui, la loi d'ohm, coté récepteur, pas coté source : je parlais du niveau cardiaque de l'utilisateur ;)

Pour me prendre régulièrement des bourres en 400V (celles en 230 ça ne compte pas, c'est pour les débutants :mrgreen:), certes ce n'est pas drôle (sauf pour les collègues), mais ça laisse beaucoup moins tremblotant que la seule fois de ma vie où j'ai fait joujou à l'insu de mon plein gré avec une alim en courant 100mA (un truc qui servait à allumer des LED un peu spécifiques, dans les premiers temps de ce type d'éclairage dans les magasins, et qui sort 100 mA pleine balle dès que quelque chose est connecté... y compris votre abruti de serviteur sur un escabeau).

cela dit, avec une install aux normes actuelles (donc avec un ID 30mA), celui qui se fait une "Claude François" soit il en fait exprès (et il y met beaucoup de bonne volonté et d'opiniatreté), soit il n'a vraiment pas de bol (et il fait parti du petit pourcentage de la population sensible cardiaque à partir de 10 mA). Mais je doute que Peujton se connecte directement au pied de colonne* ou au poteau Enedis ;)

PM, électro pas sensible

*Si tu en es là, referme ce capot tout de suite, je t'envoie les plombs (les machins jaunes ou gris que tu viens d'arracher pour brancher tes pinces :naughty: ). Ta résistance interne n'est pas à la hauteur de celle du transfo EDF...
Regarde, écoute, questionne, apprend, transmet, recommence sans cesse
Disclaimer : je dis certainement plus de conneries que la moyenne, alors vérifiez !

SE PRESENTER ...et... Guide pour débutants
Avatar de l’utilisateur
Arwen
Ch'ti nouveau
Messages : 148
Inscrit depuis : 2 ans
Mon équipement : Bricolage maison en biab à partir de 2 futs de 30l, chauffage électrique commandé par un arduino, pompe, échangeur à plaques, fermenteur Brico Dépot, frigo régulé par stc1000.
Brasseur : Amateur
Localisation : Brest
2 recettes partagées
A remercié : 2 fois
A été remercié : 22 fois

Re: Cuve avec précision améliorée

Message par Arwen »

Pour ceux qui voudraient se lancer dans l'amélioration de la régulation en température d'un stérilisateur, j'ai un peu modularisé le programme de Peujton pour permettre de l'adapter en fonction des éléments à sa disposition (il suffira de modifier p. ex. la fonction correspondante, lecture de la température, méthode d'entrée des commandes, type d'affichage ...). J'ai gardé en revanche la méthode de règlage de la puissance, valeurs à retoucher en fonction de sa cuve, ou à remplacer par une fonction PID.
N'ayant pas le matériel pour tester, j'ai uniquement vérifié qu'il se compile correctement. Pour le débogage, rajouter des Serial.print) aux endroits critiques ...

Code : Tout sélectionner

#include <TimerOne.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define relais 3
#define potentiometre A0

OneWire oneWire(4); // à changer en fonction de la broche du 18B20
DallasTemperature DS18B20(&oneWire);
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

int temperatureConsigne = 0, puissanceConsigne = 0, puissanceVraie = 0;
float temperatureVraie;

/**************************************************************/
void gereChauffe() {
  if(temperatureVraie > temperatureConsigne){  // vrai si dépasse de 1/10°
    digitalWrite(relais, LOW);
  }else{
    puissanceVraie += 1;
    if(puissanceVraie == 100){
      puissanceVraie = 0;
    }
 // varie de 0 à 99, gère les cas puissanceConsigne = 0 et = 100
    if(puissanceVraie < puissanceConsigne){
      digitalWrite(relais, HIGH);
    }else{
      digitalWrite(relais, LOW);
    }
  }
}
/**************************************************************/
void litTemperature(){
  DS18B20.requestTemperatures();
  temperatureVraie =  DS18B20.getTempCByIndex(0); // on peut avoir plusieurs sondes, la suivante p.ex. temperatureLue1 =  DS18B20.getTempCByIndex(1);
}
/**************************************************************/
void litConsigne(){
  temperatureConsigne = analogRead(potentiometre)/10;      // compris théoriquement entre 0 et 102
  if (temperatureConsigne > 100) temperatureConsigne = 100;
}
/**************************************************************/
void calculePuissance(){
  int ecartTemperature = temperatureConsigne - temperatureVraie;
  
  if(ecartTemperature > 15){
    puissanceConsigne = 100;
    return;
  }
  if(ecartTemperature > 10){
    puissanceConsigne = 80;
    return;
  }
  if(ecartTemperature > 5){
    puissanceConsigne = 66;
    return;
  }
  if(ecartTemperature > 2){
    puissanceConsigne = 33;
    return;
  }
  
// l'écart de température est < 2°
  if(temperatureConsigne < 65){
    puissanceConsigne = 7;
    return;
  }
    if(temperatureConsigne < 80){
    puissanceConsigne = 17;
    return;
  }
  
// la consigne est au dessus de 80°
  puissanceConsigne = 33;
}
/**************************************************************/
void afficheEtat(){        // uniquement les deux températures
  lcd.setCursor(0, 0);
  lcd.print("T° cible : ");
  if(temperatureConsigne < 100){ //
    lcd.print(' ');              //
  }                              // pour alignement de l'affichage
  if(temperatureConsigne < 10){  //
    lcd.print(' ');              //
  }
  lcd.print(temperatureConsigne);
  
  lcd.setCursor(0, 1);
  lcd.print("T° vraie : ");
  if(temperatureVraie < 100){ //
    lcd.print(' ');           //
  }                           // pour alignement de l'affichage
  if(temperatureVraie < 10){  //
    lcd.print(' ');           //
  }
  lcd.print(temperatureVraie, 1); // affiche au dixième de degré
}
/**************************************************************/
void setup() {
  pinMode(potentiometre, INPUT);
  pinMode(relais, OUTPUT);
  Serial.begin(9600); // utile uniquement si on veut rajouter des Serial.write pour le débogage
  Timer1.initialize(300);
  Timer1.attachInterrupt(gereChauffe);
// la fonction gereChauufe sera appelée ttes les 300mS => cyle de chauffe de 30S
  DS18B20.begin();
  lcd.begin(16, 2);
}
/**************************************************************/
void loop() {
  litTemperature();
  litConsigne();
  calculePuissance();
  afficheEtat();
  delay(1000); // Rafraichissement une fois par seconde.
}
A vos fers à souder.

@Penn-Maen
en hors sujet pour finir,
De mon côté je demande à EDF de couper le courant dans mon quartier à chaque fois que je m'approche d'un prise . :jesors2:
Make beer great again (ndt : à bas la kro)