regulation chaudiere probleme millis

bonjours, j’ai découvert Arduino depuis peu de temps et j’ai pas mal de difficulté a faire ce que je veux.
J’essaye de faire une régulation pour ma chaudière
Je souhaite allumer un relai 2 secondes (ça c bon) mais je voudrait qu’il s’éteigne 2 minutes et la j’ai tout essayé, je tourne en rond depuis quelque jours et je ni arrive pas.

voila mon code la parti qui me pose problème est dans le void vanne radiateur a la fin j’ai supprimé toutes mes tentatives pour les 2 minute éteint :

 #include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// sonde

int sonde_chaudiere = A7;
int sonde_interieur = A5;

// sonde depart radiateur

int sonde_dep_radiateur = A1;
float voltage_A1;
float valeur_sonde_dep_radiateur;

// sonde retour radiateur
 
int sonde_ret_radiateur = A2; 
float voltage_A2;
float valeur_sonde_ret_radiateur;

// sonde exterieur

int sonde_ext = A0;
float voltage_A0;
float valeur_sonde_ext;

// delta radiateur
float delta;

//calcule valeur temp depart radiateur

int a= 7; //temperature interieur souhaiter
int b= 23; //parrallele courbe chauffe
float c=1.5; // pente courbe de chauffe
float valeur_temp_dep;

// electrovanne radiateur

const int ouverture = 9; // relai elctrovanne ouverture pin 9
const int fermeture = 8; // relai elctrovanne fermeture pin 8
const int reposV = 7; // led bleu electrovanne au repos pin 7
float valeur_d_ecart = 1.5;
boolean etat_ouverture;
boolean etat_fermeture;

//bruleur

const int bruleur= 26; // relai bruleur
int etat_bruleur;
int valeur_demarage= 40;
int valeur_coupure= 60;

//bouton,menu

unsigned int selecteurPage=0;
const int bp_menu =24;
int etat_bp_menu;
int memoire_menu = HIGH;


// bouton moins temperature interieur demander
// bouton plus temperature interieur demander

const int bp_moins_T_Int= 13;
const int bp_plus_T_Int= 10; 
int etatbps_T_Int;
int memoire_plus = HIGH;
int memoire_moins = HIGH;

//millis

long temps;
long temporisation;
unsigned long delai_attente;

// tableau sonde temperature ext

const int nb_valeur= 10; //nbre valeur ds tableau
int tableau[nb_valeur]; // declaration tableau de 10 valeur
int lecture_tableau =0; 
float total =0;
float moyenne_sonde_ext =0;

// tableau sonde depart radiateur

const int nb_valeur_sdr=10;
int tableau_sdr[nb_valeur_sdr];
int lecture_tableau_sdr=0;
float total_sdr=0;
float moyenne_sonde_dep_radiateur=0;


void setup() {
  
  lcd.begin(16,2);
  lcd.clear ();
  delay(100);
  lcd.setCursor(0,0);
  lcd.print("regul chaudiere");
  delay(1000);
  lcd.setCursor(0,1);
  lcd.print(" by Palex");
  delay(1000);
  lcd.clear ();
  delay(100);
  
  Serial.begin(9600);
  
  pinMode(bruleur,OUTPUT);

  pinMode(ouverture,OUTPUT); //LED rouge simule relai ouverture vanne:
  pinMode(fermeture,OUTPUT); //LED verte  simule relai ouverture vanne:
  pinMode(reposV,OUTPUT); //led bleu indique vanne repos:
  reposV,LOW;

  pinMode(bp_menu,INPUT);
  
  pinMode(bp_plus_T_Int,INPUT);
  pinMode(bp_moins_T_Int,INPUT);
  
  etat_ouverture=0;
  digitalWrite(ouverture,etat_ouverture);
  etat_fermeture=0; // bobine relai alimenter contact ouvert electrovanne pas alimenter
  digitalWrite(fermeture,etat_fermeture);
  
  temporisation=millis();
  temps=millis();
  delai_attente=millis();

  for (int lecture=0; lecture < nb_valeur;
  lecture++)
  tableau[lecture]= 0;

  for (int lecture_sdr=0; lecture_sdr < nb_valeur_sdr; lecture_sdr++)
  tableau_sdr[lecture_sdr]=0;

}


void loop () {

 
  calcul_mesure();
  gestion_bruleur();
  vanne_radiateur ();
  bouton();
  
  
    switch(selecteurPage){
    case 0:
    affichage_parametre();
    break;
    case 1:
    affichage_reglage();
    break;
    case 2:
    affichage_info_chaudiere();
    break;
    case 3:
    affichage_sonde_circuit_radiateur();
    break;
    default:
    affichage_parametre();
    break;
  }
  
}
  
 void calcul_mesure (){
  
//calcule de la valeur temp ext toutes les seconde
     
   if((millis() - temps) > 1000) {
  int valcapt = analogRead(sonde_ext);
  voltage_A0 =  valcapt*5.0/1024.0;
  valeur_sonde_ext = (voltage_A0 - 0.5)*100;  
  Serial.print ("temps ext");
  Serial.println (valeur_sonde_ext);
 
  
// tableau moyenne de temperature exterieur

    total = total - tableau[lecture_tableau];
    tableau[lecture_tableau]= valeur_sonde_ext;
    total = total + tableau[lecture_tableau];
    lecture_tableau = lecture_tableau +1;
    if (lecture_tableau >= nb_valeur)
    lecture_tableau = 0;
    moyenne_sonde_ext = total/nb_valeur;
    Serial.print ("moyenne temps ext");
    Serial.println (moyenne_sonde_ext);

// calcul valeur sonde depar radiateur 

  int valcapt1 = analogRead(sonde_dep_radiateur);
  voltage_A1 =  valcapt1*5.0/1024.0;
  valeur_sonde_dep_radiateur = (voltage_A1 - 0.5)*100;


// tableau moyenne sonde depart radiateur

    total_sdr = total_sdr - tableau_sdr[lecture_tableau_sdr];
    tableau_sdr[lecture_tableau_sdr]= valeur_sonde_dep_radiateur;
    total_sdr = total_sdr + tableau_sdr[lecture_tableau_sdr];
    lecture_tableau_sdr = lecture_tableau_sdr +1;
    if (lecture_tableau_sdr >= nb_valeur_sdr)
    lecture_tableau_sdr = 0;
    moyenne_sonde_dep_radiateur = total_sdr/nb_valeur_sdr;


// calcul valeur sonde retour radiateur 

  int valcapt2 = analogRead(sonde_ret_radiateur);
  voltage_A2 =  valcapt2*5.0/1024.0;
  valeur_sonde_ret_radiateur = (voltage_A2 - 0.5)*100;  
   
    temps= millis();
  }                 
  
// calcul de la valeur de depart radiateur voulu

valeur_temp_dep = c*(a-moyenne_sonde_ext)+b;

//calcul delta radiateur

delta = valeur_sonde_dep_radiateur - moyenne_sonde_dep_radiateur;

 }


void gestion_bruleur(){
  
  etat_bruleur=digitalRead(bruleur);

  if(sonde_chaudiere>= valeur_coupure){
    digitalWrite(bruleur,LOW);
  }  
  else if((valeur_coupure-20)<sonde_chaudiere){
  digitalWrite(bruleur,HIGH);  
  }
  else{
  digitalWrite(bruleur,LOW);
  }

}
 
void bouton(){

  //bouton reglage temperature interieur
  
  etatbps_T_Int= digitalRead(bp_plus_T_Int);
  if((etatbps_T_Int != memoire_plus) && ( etatbps_T_Int==LOW)) {
    a++; 
  }
  memoire_plus=etatbps_T_Int;
  
  etatbps_T_Int= digitalRead(bp_moins_T_Int);
  if((etatbps_T_Int != memoire_moins) && ( etatbps_T_Int==LOW)) {
    a--;
  }
  memoire_moins=etatbps_T_Int;
  
  if(a>30){
    a=30;
  }
  if(a<7){
    a=7;
  }
  
//bouton menu

 etat_bp_menu=digitalRead(bp_menu);
   if((etat_bp_menu!= memoire_menu) && (etat_bp_menu==LOW)){
  selecteurPage--;
 }
 memoire_menu = etat_bp_menu;

  
   if(selecteurPage>3){
   selecteurPage=3;
  }
   if(selecteurPage<0){
    selecteurPage=0;
  }
}
 
 
 
 // affichage ldc
 
 void affichage_parametre (){
 
  
  lcd.setCursor(0,0);
  lcd.print( "Te:");
  lcd.print(moyenne_sonde_ext);
  lcd.println("c  ");
  
  lcd.setCursor(10,0);
  lcd.print( "TI:");
  lcd.print(a  );
  lcd.println(" c");
   
  lcd.setCursor(0,1);
  lcd.print( "VTD:");
  lcd.print(valeur_temp_dep,0);
  lcd.print("c ");
  lcd.setCursor(8,1);
  lcd.print( " VSD:");
  lcd.print(moyenne_sonde_dep_radiateur,0);
  lcd.print("c");
 }

 void affichage_reglage(){

  lcd.setCursor(0,0);
  lcd.print("pente      :");
  lcd.println(c);
  
  lcd.setCursor(0,1);
  lcd.print("parrallele   :");
  lcd.println(b);
  
  
}

void affichage_info_chaudiere(){

  lcd.setCursor(0,0);
  lcd.print("etat bruleur : ");
  lcd.print(etat_bruleur);

  lcd.setCursor(0,1);
  lcd.print("temp chaudiere");
  lcd.print(sonde_chaudiere);
  lcd.print("c");
  
}

void affichage_sonde_circuit_radiateur(){
  
  lcd.setCursor(0,0); 
  lcd.print( "S dep R :");
  lcd.print(moyenne_sonde_dep_radiateur,0);
  lcd.setCursor(11,0);
  lcd.print( "delta");
  lcd.setCursor(11,1);
  lcd.print(" :");
  lcd.print(delta);
  lcd.setCursor(0,1); 
  lcd.print( "S ret R :");
  lcd.print(valeur_sonde_ret_radiateur,0);

   
}

void vanne_radiateur (){

// ouverture de la vanne

 if (valeur_temp_dep >(moyenne_sonde_dep_radiateur + valeur_d_ecart)){
  digitalWrite(reposV,LOW); 
  if( millis() - temporisation>2000){          
  etat_ouverture=!etat_ouverture;              
  digitalWrite(ouverture,etat_ouverture);
  temporisation=millis();
  }
 }

//fermeture de la vanne
  else if(valeur_temp_dep <(moyenne_sonde_dep_radiateur - valeur_d_ecart)){
  digitalWrite(reposV,LOW);
  if( millis() - temporisation>2000){           
  etat_fermeture=!etat_fermeture;
  digitalWrite(fermeture,etat_fermeture);
  temporisation=millis();
  }
 }
 
 // vanne au repos
  else {
  digitalWrite(reposV,HIGH);
  digitalWrite(fermeture,LOW); 
  digitalWrite(ouverture,LOW);
  }
}



[code]

on peut rien faire avec cela, il nous faut tout le code avec la loop et le setup pour comprendre comment vous appelez votre truc

l'idéal pour ce genre de pb c'est une machine a état.

les états c'est ON ou OFF et définir ce qui crée des transitions d'un état à l'autre.

qu'est-ce qui fait passer à ON? une fois ON qu'est qui le fait revenir à OFF?

j' ai éditer mon message le code et en entier. je suis pas sur de comprendre ce que tu me dit j’utilise une boolean donc je crois que c'est bon

la fonction loop() est fournie dans le code du premier message J-M-L, regarde bien. L'indentation est douteuse mais c'est bien là...

Sinon, palex81, au vu du volume du code c'est où que tu gères le timing ou le relais qui t'intéresse ? c'est celui du brûleur, des vannes, autre chose... ? Un peu plus de précisions ne seraient pas de refus... ;)

je détail un peu plus : je compare la température départ du chauffage avec la valeur de température qu’il me faut en fonction du résultat j’actionne soit le relai pour ouvrir ma vanne soit celui pour fermer.

je l’action 2secondes et c’est la que je veux que le programme attende 2minute avant de ré actionner un relai pour laisser le temps a la sonde du tuyau de départ de changer de valeur.
j’ai fait des tableau et des moyenne pour avoir des température plus stable.

ok, merci, mais c'est dans quelle fonction de ton code que tu tentes de faire cette temporisation de 2 minutes ?

désoler Zorro_X je comprend pas trop le fonctionnement du forum je pouvais pas répondre.

c'est dans la fonction void vanne radiateur c'est pour agir sur les relai qui pilote la vanne

wow - le code est long :slight_smile: mais j’aime bien que vous ayez pris soin de structurer en fonctions (vous auriez pu mettre le switch (selecteurPage) { dans sa fonction et ça aurait fait une boucle super clean. :slight_smile:

je n’ai pas regardé les maths, mais plus la logique:

Je pense qu’un problème c’est que vous gérez vos “booléens” etat_ouverture dans un if

 if (valeur_temp_dep > (moyenne_sonde_dep_radiateur + valeur_d_ecart)) {
    digitalWrite(reposV, LOW);
    if ( millis() - temporisation > 2000) {
      etat_ouverture = !etat_ouverture;
      digitalWrite(ouverture, etat_ouverture);
      temporisation = millis();
    }
  }

donc si le if ne retourne plus vrai vous ne testerez plus l’attente des 2 secondes.

ne devriez vous pas commencer plutôt par un si etat_ouverture est HIGH et que j’ai déjà fermé reposV alors je sais que je suis dans la tempo de 2 secondes??


Quelques commentaires en vrac qu’il faudrait corriger (certains peu importants d’autres plus):

long temps;
long temporisation;

ça devrait être des unsigned long


boolean etat_ouverture;
boolean etat_fermeture;

si ce sont vraiment des booléens, traitez les comme tels; affectez true et false et ne les utilisez pas comme HIGH et LOW mais faites (etat_ouverture ? HIGH : LOW) pour être propre. Sinon déclarez les comme byte dans ce cas vous pouvez leur affecter HIGH et LOW pas etat_ouverture = 0; mais etat_ouverture = LOW; (pour la lisibilité)

dans ce cas etat_ouverture = !etat_ouverture; n’est pas très propre non plus intellectuellement parlant. (même si ça fonctionne).


dans calcul_mesure()

vous effectuez

 // calcul de la valeur de depart radiateur voulu
  valeur_temp_dep = c * (a - moyenne_sonde_ext) + b;
  //calcul delta radiateur
  delta = valeur_sonde_dep_radiateur - moyenne_sonde_dep_radiateur;

à chaque boucle, est-ce vraiment nécessaire alors que le reste du calcul se fait toutes les secondes?


dans le fonction gestion_bruleur

void gestion_bruleur() {
  etat_bruleur = digitalRead(bruleur);
  if (sonde_chaudiere >= valeur_coupure) {
    digitalWrite(bruleur, LOW);
  } else if ((valeur_coupure - 20) < sonde_chaudiere) {
    digitalWrite(bruleur, HIGH);
  } else {
    digitalWrite(bruleur, LOW);
  }
}

vous commencez par mettre à jour la variable etat_bruleur en lisant la valeur de la pin bruleur mais ensuite vous changez sans doute l’état de la pin… donc en sortie de cette fonction, la variable etat_bruleur n’est pas forcément correcte. est-ce bien souhaitable?

sinon les test que vous faites sont bizarres

si la sonde_chaudiere est plus grande que la valeur_coupure alors LOW mais dans le else vous dites
si la sonde_chaudiere est plus grande que la valeur_coupure moins 20 alors LOW aussi sinon HIGH

donc si c’est la bonne logique on n’a qu’à se préoccuper que du -20 j’écrirai cela comme cela:

void gestion_bruleur() {
  digitalWrite(bruleur, (sonde_chaudiere > valeur_coupure - 20) ? LOW : HIGH);
  etat_bruleur = digitalRead(bruleur); // ou avant le digitalWrite suivant ce que vous voulez avoir comme valeur
}

si vous ne connaissez pas la forme b = (a? x : y); ça veut dire si a est vrai alors b prends la valeur x, sinon b prends la valeur y. donc ici je mets dans le digitalWrite si la sonde_chaudiere est plus grande que la valeur_coupure moins 20 alors LOW sinon HIGH


Quand vous voulez mettre des zero partout dans la mémoire d’un tableau,

 for (int lecture = 0; lecture < nb_valeur;
       lecture++)
    tableau[lecture] = 0;

vous pouvez faire à la place

memset(tableau,0,sizeof(tableau));

idem pour tableau_sdr

memset(tableau_sdr,0,sizeof(tableau_sdr));

c’est plus simple.


 temporisation = millis();
  temps = millis();
  delai_attente = millis();

si vous voulez la même valeur dans les 3 vaut mieux appeler millis() une seule fois

 temporisation = millis();
  temps = temporisation;
  delai_attente = temporisation;

 reposV, LOW;

ça ne fait pas grand chose d’intéressant ça… (manque un digitalWrite?)

alors merci J M L mais comme vous pouvez voir je suis un débutant, c’est mon premier projet j’essaye de me débrouiller en suivant les cours.

j’ai pas compris toute vos remarque mais déjà la fonction bruleur est pas encore au point, je voulais que mon bruleur s’éteigne a 70° qu’ il reste éteint jusqu’à 40° et qu’il ce rallume mais je n’ai pas réussi.

pour les millis je souhaite bien 3 valeurs différentes :
temp=millis pour la mesure de température toute les seconde
temporisation= millis pour allumer 2S lle relai de la vanne
delai attente= millis pour ne rien faire2min après avoir actionner le relai 2s

et c’est cette temporisation que j’arrive pas a faire.

merci de votre aide je vais corriger tout ce que vous m’avez fait remarquer

si vous êtes un débutant bravo ! c'est déjà globalement du bon boulot. continuez sur cette voie!

pour les millis je souhaite bien 3 valeurs différentes :

oui j'ai bien compris, mais ça c'est après dans le programme... à l'initialisation vous appelez 3 fois de suite millis() ce n'est pas très optimal.

Je ne comprends pas bien ce que font tous vos relais. Vous avez une electrovanne et un bruleur, c'est cela? (pourquoi avez vous 2 relais sur l'electrovanne?)

Aussi je ne comprends pas ce que vous dites:

Je souhaite allumer un relai 2 secondes (ça c bon) mais je voudrait qu'il s'éteigne 2 minutes et la j'ai tout essayé, je tourne en rond depuis quelque jours et je ni arrive pas.

est-ce que ça veut dire que si le relai s'allume il doit d'abord être ON pour 2 secondes et ensuite OFF pour 2 minutes, quoi qu'il se passe - même si vous lui demandez de s'allumer?

il y a un relai pour l'ouverture de l’électrovanne et un pour la fermeture elle posede 3 fils: le neutre le marron pour ouverture le noir pour fermetur. j'ai aussi un relai pour alimenter le bruleur il y a deja un systeme avec des aquastat sur la chaudiere mais je voudrai aussi la piloter avec l'arduino.

pensez-vous qu'utiliser un module d'heure serrait mieux genre ds1307?

et oui c'est ce que je souhaite ON 2 seconde puis 2 minutes OFF pour que la sonde qui est sur le tuyau est bien de temps de prendre a compte la differnce pour avoir une temperature de depart stable

Voilà un bout de code à étudier - simplifié pour le principe.

toutes les secondes il calcule une température (ici un nombre aléatoire)
ensuite il gère le cycle d’une vanne qui d’abord s’allume 2 secondes, puis s’éteint pour 2 minutes.

J’utilise des variables statiques au sein de mes fonctions pour gérer le temps et l’état. Une variable statique c’est comme une variable globale au sens qu’elle conserve sa valeur entre 2 appels à la fonction, mais elle n’est visible que au sein de la fonction - ce qui permet de faire des choses plus propres.

J’utilise un enum (dans l’IDE pas besoin d’utiliser typedef). je m’en sers ici juste pour avoir des états lisibles en français. Mais vous pourriez déclarer une variable qui ne prend que des valeurs définies dans le typedef. (cf la doc pour enum)

voilà en espérant vous donner des idées !!!

const int electroVanne = 13; // relai elctrovanne ouverture pin 13 (la led pour tester)
enum {ETEINT, ALLUME, REPOS}; // on définit des mots clés pour la lisibilité

const unsigned long DUREE_ALLUME = 2000UL;    // 2 secondes
const unsigned long DUREE_REPOS  = 10000UL;  // 10 secondes pour tester (a remplacer par 120000)
// const unsigned long DUREE_REPOS  = 120000UL;  // 2 minutes. UL pour forcer unsigned long

int temperature;
const unsigned long PERIODE_TEMPERATURE = 1000UL;    // toutes les 1 seconde

// ----------------------------------------
// Gestion du relai:
// On demande au relai de s'allumer
// la premiere fois il s'allume MAIS ensuite
// au bout de 2 secondes il s'éteint
// et il reste ensuite au repos 2 minutes
// ----------------------------------------
void miseAJourRelai()
{
  static unsigned long tempsDuDernierChangement = 0;
  static byte EtatRelai = ETEINT;

  if (EtatRelai == ETEINT) {
    // premier appel on allume le relai
    digitalWrite(electroVanne, HIGH);
    EtatRelai = ALLUME;
    Serial.println("on allume");
    tempsDuDernierChangement = millis();
  } else if (EtatRelai == ALLUME) {
    // on attend les 2 secondes
    if (millis() - tempsDuDernierChangement >= DUREE_ALLUME) {
      // les 2 secondes sont écoulées, on éteint le relai
      digitalWrite(electroVanne, LOW);
      EtatRelai = REPOS;
      Serial.println("on passe en repos");
      tempsDuDernierChangement = millis();
    }
  } else if (EtatRelai == REPOS) {
    // on attend les 2 minutes
    if (millis() - tempsDuDernierChangement >= DUREE_REPOS) {
      Serial.println("fin du repos");
      EtatRelai = ETEINT;
    }
  }
}

// ----------------------------------------
//
// ----------------------------------------
void calcul_mesure()
{
  // ici on fait des trucs savants mais qu'une fois toutes les secondes
  static unsigned long tempsDeLaDerniereMesure = 0;

  if (millis() - tempsDeLaDerniereMesure > PERIODE_TEMPERATURE) {
    temperature = random(10, 100); // simulation
    Serial.print("Temperature = "); Serial.println(temperature);
    tempsDeLaDerniereMesure = millis();
  }
}

// ----------------------------------------
//
// ----------------------------------------
void setup() {
  Serial.begin(115200);
  pinMode(electroVanne, OUTPUT);
  temperature = 0;
}

// ----------------------------------------
//
// ----------------------------------------
void loop() {
  calcul_mesure();
  miseAJourRelai();
}

J'étais loin de trouver tout seul, je vous remercie je vais voir ça des demain matin et tester.

je vous tien au courant merci.

Ne vous laissez pas impressionner par les enum ou static.

Le statiques c'est comme une variable globale (en gros mais les autres fonctions ne peuvent pas la voir) et les enum c'est comme si vous disiez EtatRelai = 0 puis EtatRelai = 1 puis EtatRelai = 2 sauf qu'on a un nom qui fait plus joli :)

super je suis trop comptent ça marche parfaitement.

Je vous remercie pour m'avoir fait comprend un peu mieux l'utilisation du millis et de ma m'avoir donner cet solution. je regarderai la doc sur enum demain bonne soirée et merci encore.