Deux thermocouples K - LCD - incrémentation des alarmes - mise en veille du buzzer

Dans ce deuxième projet de débutant je souhaite, à partir d’une UNO, gérer deux modules thermocouples de Type MAX31855 K reliés à des capteurs de type K 1300°.

  • Le premier permettra de déclencher des alarmes (led + buzzer) pour les températures hautes et basses du four d’un poêle bouilleur. Les seuils haut et bas de ces alarmes pourront être incrémentés avec 4 boutons.
  • Le deuxième permettra de contrôler la températures des fumées en haut du conduit. Les alarmes (led et buzzer) me permettront de réagir rapidement si les fumées sont trop chaudes, voir en cas de feu de conduit.
  • Cerise sur le gâteau, un “bouton silence” me permettra de mettre en veille le buzzer tout en laissant clignoter la led de l’alarme en cours et parallèlement, d’allumer une led rouge durant ce “mode silence”.

Le seuil concernant le thermocouple du conduit sera réglable dans le programme.

La durée du “mode silence” sera réglable dans le programme.

Il y aura deux buzzer placés dans des pièces différentes, ils seront reliés à la carte par l’intermédiaire d’un transistor.

Je n’ai pas pu faire tourner mon programme sur wokwi car je n’y ai pas trouvé de thermocouple mais voici le dessin correspondant aux branchements.

J’ai écrit le programme à partir de l’exemple que l’on trouve dans l’IDE Arduino : Fichier / Exemples / AdafruitMax31855 / librairy / lcdthermocouple et de mon premier programme écrit avec l’aide des membres du forum sur Problème pour brancher 7 sondes DS18B20 sur le même bus - #106 by mjb

Il fonctionne très bien sur mon banc d’essai réel, avec du vrai matériel, et avec les branchements dessinés plus haut mais je suis certain qu’il peut être amélioré. Cela me ferait plaisir que vous m’apportiez votre avis et vos conseils.

/* 
  J'ai placé "animations" dans la loop car je ne parvenais pas à déclarer "cfour" et "cfeu" avant "animation" le téléversement m'était refusé.

*/

#include <OneWire.h>
//#include <SPI.h>                                // dans certaines configurations, les capteurs utilisent SPI pour communiquer, SPI travaille avec Adafruit MAX31855
#include "Adafruit_MAX31855.h"                  // j'inclue Adafruit_MAX31855 pour gérer les thermocouples
#include <LiquidCrystal_I2C.h>                  // J'inclue LiquidCrystal-I2C pour gérer le LCD
#include <Toggle.h>                             // j'inclue Toggle pour gérer le bouton silence

LiquidCrystal_I2C lcd(0x27, 20, 5);              // adresse du LCD i2c , nombre de colonnes, nombre de lignes de l'écran

#define MAXDO   2                             // sortie DO du Max 31855
#define MAXCS   3                             // sortie CS "  " " "
#define MAXCLK  4                             // sortie CLK " " " "
#define MAXCS2  5                             // sortie CS  2  " " "

const int  pinbtn1 = 6, pinbtn2 = 7, pinbtn3 = 8, pinbtn4 = 9, pinbuzzer = 10, pinledfourH = 11 , pinledfourB = 12, pinledfeu = 13, pinBoutonSilence = A0, pinLedSilence = A1 ;      // le bouton n°1 est relié en broche 6 , ...

Toggle boutonSilence(pinBoutonSilence);       //création d'une variable nommée bouton Silence, du type Toggle, qui est initialisée en utilisant le N° de la broche pinBoutonSilence (13)

bool etat1 ;                                       // déclare l'état du bouton 1 (bleu -)pour connaître l'état du bouton s'il est à 0 ou à 1 ... est-ce que j'établis le contact ou non... 0 contact non ; 1 contact oui.
bool etat2 ;                                       // déclare l'état du bouton 2 (bleu +) pour connaître l'état du bouton s'il est à 0 ou à 1 ... est-ce que j'établis le contact ou non... 0 contact non ; 1 contact oui.
bool etat3 ;                                       // déclare l'état du bouton 3 (rouge -) pour connaître l'état du bouton s'il est à 0 ou à 1 ... est-ce que j'établis le contact ou non... 0 contact non ; 1 contact oui.
bool etat4 ;                                       // déclare l'état du bouton 4 (rouge +) pour connaître l'état du bouton s'il est à 0 ou à 1 ... est-ce que j'établis le contact ou non... 0 contact non ; 1 contact oui.

int seuil_fourbas = 21;                                     // 21° seuil de la sonde four - Basse  (pour l'expérimentation) qui s'affiche lors de la réinitialisation, elle peut être incrémentée.
int seuil_fourhaut = 23;                                     // 23° seiol de la sonde four - Haute (pour l'expérimentation) qui s'affiche lors de la réinitialisation, elle peut être incrémentée.
int seuil_feu = 25;                                         // 25° seuil de la sonde placée en haut du conduit fumée pour détecter un incendie de cheminée (ne pourra pas s'incrémenter)

Adafruit_MAX31855 thermocouple1(MAXCLK, MAXCS, MAXDO);      // création d'une variable nommée thermocouple1, du type Adafruit_MAX31855 , qui est initialisée en utilisant les N° des broches qui concernent le thermocouple 1
Adafruit_MAX31855 thermocouple2 (MAXCLK, MAXCS2, MAXDO);    // création d'une variable nommée thermocouple2, du type Adafruit_MAX31855 , qui est initialisée en utilisant les N° des broches qui concernent le thermocouple 2

enum : uint8_t {AUCUNE_ALARME = 0, ALARME_FOUR_H = 1, ALARME_FOUR_B = 2, ALARME_FEU = 4};
uint8_t alarmesEnCours = AUCUNE_ALARME;

//*******************************************************************************************************************************************

//void animations() {


// *******************************************************************************************************************************


void setup() {

  lcd.init();                     // active le LCD
  lcd.backlight();               // active le rétroéclairage

  pinMode (pinbtn1, INPUT_PULLUP) ;                                               // active l'entrée du signal envoyé par le bouton poussoir 1 (bleu-) avec un mode pullup qui ajoute une résistance sur le circuit afin de le stabiliser.
  pinMode (pinbtn2, INPUT_PULLUP) ;                                               // active l'entrée du signal envoyé par le bouton poussoir 2 (bleu+) avec un mode pullup qui ajoute une résistance sur le circuit afin de le stabiliser.
  pinMode (pinbtn3, INPUT_PULLUP) ;                                               // active l'entrée du signal envoyé par le bouton poussoir 1 (rouge-) avec un mode pullup qui ajoute une résistance sur le circuit afin de le stabiliser.
  pinMode (pinbtn4, INPUT_PULLUP) ;                                               // active l'entrée du signal envoyé par le bouton poussoir 1 (rouge+) avec un mode pullup qui ajoute une résistance sur le circuit afin de le stabiliser.
  pinMode (pinbuzzer, OUTPUT) ;      digitalWrite(pinbuzzer, LOW);                // active la sortie 13 du buzzer
  pinMode (pinledfourH, OUTPUT) ;     digitalWrite(pinledfourH, LOW);             // active la sortie 11 de la led alarme four Haut
  pinMode (pinledfourB, OUTPUT) ;     digitalWrite(pinledfourB, LOW);              // active la sortie 11 de la led alarme four Bas
  pinMode (pinledfeu, OUTPUT) ;     digitalWrite(pinledfeu, LOW);                  // active la sortie 12 de la led alarme feu
  pinMode (pinLedSilence, OUTPUT) ;     digitalWrite(pinLedSilence, LOW);          // active la sortie A1 de la led silence          
  boutonSilence.begin(pinBoutonSilence);

  Serial.begin(115200);
  Serial.println("PRET");
  delay(1000);                  // pour stabiliser la lecture

}

void loop() {

  // relevé des températures

  double cfour = thermocouple1.readCelsius();        // Lecture en degrés Celcius du capteur 1
  double cfeu = thermocouple2.readCelsius();        // Lecture en degrés Celcius du capteur 2

  //***************************************************************************************************************************

  // relevé de l'état des boutons et incrémentation

  etat1 = digitalRead(pinbtn1) ;                   // lire l'état de mon bouton 1 bleu-
  if (etat1 == 0) {                               // si j'appuies sur le bouton bleu-, je baisse de 1°C
    seuil_fourbas--;                                      //  deg-- est équivalent à deg = deg -1 ;
  }
  etat2 = digitalRead(pinbtn2) ;                   // lire l'état de mon bouton 2 bleu+
  if (etat2 == 0) {                              // si j'appuies sur le bouton bleu+, je monte de 1°C
    seuil_fourbas++;                                      //  deg-- est équivalent à deg = deg -1 ;
  }
  etat3 = digitalRead(pinbtn3) ;                   // lire l'état de mon bouton 3 rouge -
  if (etat3 == 0) {                             // si j'appuies sur le bouton rouge - , je baisse de 1°C
  
    seuil_fourhaut--;                                      //  deg-- est équivalent à deg = deg -1 ;
  }
  etat4 = digitalRead(pinbtn4) ;                   // lire l'état de mon bouton 4 rouge +
  if (etat4 == 0) {                               // si j'appuies sur le bouton 4 rouge +, je monte de 1°C
    seuil_fourhaut++;
  }

  //**************************************************************************************************************************///////////////////////////////////////////

//void animations() {

  static bool modeSilence = false;                                // Variable persistante conservant l’état du mode silence entre deux appels de la fonction.
  static uint32_t debutModeSilence = 0;                           // Instant, en millisecondes depuis le démarrage, auquel le mode silence a été activé.
  static const uint32_t dureeModeSilence = 10000ul;               // définition d'une constante pour la durée maximale du mode silence en millisecondes.

  boutonSilence.poll();
  if (boutonSilence.onPress()) {                                  // si le bouton est appuyé on rentre dans ce if
    modeSilence = not modeSilence;                                // Inversion explicite de l’état du mode silence à chaque appui.
   digitalWrite(pinLedSilence, modeSilence ? HIGH : LOW);        // La LED reflète directement l’état logique du mode silence. on interroge  l'état du mode silence, s'il est "true"  la pinledSilence devient HIGH sinon on retourne LOW ???
  
  /*static uint32_t chrono = 0;                                                    // Référence temporelle persistante utilisée pour cadencer le clignotement….(le compteur est relevé)
    if (millis() - chrono >= 100) {                                                // Inversion de l’état de la LED toutes les 100 ms, ce qui fixe la fréquence de clignotement.
      digitalWrite(pinLedSilence, digitalRead(pinLedSilence) == HIGH ? LOW : HIGH);    // la led HP clignote… l'écriture de cette fonction s'appelle l'opérateur ternaire elle Inverse l'état en sortie pinLedHP… si pinLedHP est HIGH alors retourne LOW sinon retourne HIGH …on pourrait l'écrire digitalWrite(pinLedHP, !(digitalRead(pinLedHP)));
      chrono = millis();   
    }*/
    
 if (modeSilence) debutModeSilence = millis();                 // Mémorisation de l’instant d’activation pour mesurer la durée écoulée.
  }

  if (modeSilence && millis() - debutModeSilence >= dureeModeSilence) {   // si  la durée maximale du mode silence est dépassée.(si le compteur continue moins le compte relevé au début du MS est supérieur ou égal à 10 secondes  (dureeModeSilence) )
    modeSilence = false;                                                  // le mode silence devient faux (est désactivé… le buzzer sonne.
    digitalWrite(pinLedSilence, LOW);                                     // et la led silence s'éteint
  }

  //**************************************************************

  if (cfour >= seuil_fourhaut)  {                                                    // si la dernière température du capteur four est supérieure à son seuil haut
    static uint32_t chrono = 0;                                                    // Référence temporelle persistante utilisée pour cadencer le clignotement….(le compteur est relevé)
    if (millis() - chrono >= 100) {                                                // Inversion de l’état de la LED toutes les 100 ms, ce qui fixe la fréquence de clignotement.
      digitalWrite(pinledfourH, digitalRead(pinledfourH) == HIGH ? LOW : HIGH);    // la led HP clignote… l'écriture de cette fonction s'appelle l'opérateur ternaire elle Inverse l'état en sortie pinLedHP… si pinLedHP est HIGH alors retourne LOW sinon retourne HIGH …on pourrait l'écrire digitalWrite(pinLedHP, !(digitalRead(pinLedHP)));
      chrono = millis();                                                           // on se souvient du moment de la dernière inversion
    }
    alarmesEnCours |= ALARME_FOUR_H;                                              // Activation du bit correspondant à l’alarme HP sans modifier les autres bits. |= est un OU bit à bit
  } else {                                                                        // sinon
    digitalWrite(pinledfourH, LOW);                                               // la led HP n'est pas alimentée
    alarmesEnCours &= ~ALARME_FOUR_H;                                             // Effacement du bit ALARME_HP par masquage binaire, les autres alarmes restent inchangées.

  }

  //**************************************************************

  if (cfour <= seuil_fourbas) {                                                    // si la dernière température du capteur four est inférieure à son seuil bas
    static uint32_t chrono = 0;
    if (millis() - chrono >= 100) {
      digitalWrite(pinledfourB, digitalRead(pinledfourB) == HIGH ? LOW : HIGH);
      chrono = millis();
    }
    alarmesEnCours |= ALARME_FOUR_B;
  } else {
    digitalWrite(pinledfourB, LOW);
    alarmesEnCours &= ~ ALARME_FOUR_B;
  }

  //**************************************************************

  if (cfeu >= seuil_feu) {                                                           // si la dernière température du capteur feu est supérieure à son seuil
    static uint32_t chrono = 0;
    if (millis() - chrono >= 100) {
      digitalWrite(pinledfeu, digitalRead(pinledfeu) == HIGH ? LOW : HIGH);
      chrono = millis();
    }
    alarmesEnCours |= ALARME_FEU;
  } else {
    digitalWrite(pinledfeu, LOW);
    alarmesEnCours &= ~ALARME_FEU;
  }

  //********************************************************************

  if (not modeSilence && alarmesEnCours != AUCUNE_ALARME) {

    // une alarme au moins est en cours et on n'est pas en mode silence
    static uint32_t chrono = 0;
    if (millis() - chrono >= 300) {
      digitalWrite( pinbuzzer, digitalRead(pinbuzzer) == HIGH ? LOW : HIGH);
      chrono = millis();
    }
  }
  else
  {
    digitalWrite(pinbuzzer, LOW);
  }

  //*****************************************************************************************************************************///////////////////////////////////////////////////

  //Configuration du LCD
  /*
    lcd.setCursor(0, 0);                        // sur la première colone de la première ligne
    lcd.print("T");                              // on imprime les caractères "T"
    lcd.print((char)223);                       // symbole °
    lcd.print("ambiante");                        // on imprime les caractères "ambiante"
    lcd.print(thermocouple1.readInternal());   // on imprime la température ambiante donnée par le capteur 1
    /*
    lcd.setCursor(0, 1);                        // sur la première colone de la deuxième lign
    lcd.print("Int. Temp 2 = ");                  // on imprime les caractères "Int. Temp 2 = "
    lcd.print(thermocouple2.readInternal());   // on imprime la température ambiante donnée par le capteur MAX
  */
  lcd.setCursor(4, 0);                          // sur la première colone de la quatrième ligne
  lcd.print("Seuil bas  = ");
  lcd.print (seuil_fourbas);                    // le LCD imprime la valeur du seuil bas que l'on peut incrémenter
  lcd.print((char)223);

  lcd.setCursor(0, 1);                          // sur la première colone de la deuxième ligne
  lcd.print("T");
  lcd.print((char)223);
  lcd.print("FOUR ");
  lcd.print(cfour);                             // on imprime la température captée par le thermocouple du four                       // on imprime la température captée par le thermocouple du conduit de cheminée

  lcd.setCursor(4, 2);                        // sur la première colone de la cinquième ligne
  lcd.print("Seuil haut = ");
  lcd.print (seuil_fourhaut);                   // le LCD imprime la valeur du seuil haut que l'on peut incrémenter
  lcd.print((char)223);

  lcd.setCursor(0, 3);                          // sur la première colone de la troisième ligne
  lcd.print("T");
  lcd.print((char)223);
  lcd.print("CONDUIT ");
  lcd.print(cfeu);

  Serial.print ("alarmesEnCours") ; Serial.println(alarmesEnCours) ;
  Serial.print ("T° FOUR") ; Serial.println(cfour) ;
  Serial.print ("T° CONDUIT") ; Serial.println(cfeu) ;


  delay(10);                                     // 10ms pour que l'incrémentation ne soit pas trop rapide
  //animations();
}

lis ne rebondissent pas vos boutons ?

et prenez la bonne habitude d'utiliser LOW et HIGH pas 0

  etat1 = digitalRead(pinbtn1) ;                   // lire l'état de mon bouton 1 bleu-
  if (etat1 == LOW) {                              // si j'appuies sur le bouton bleu-, je baisse de 1°C

c'est plus lisible

Bonsoir,

Trés bonne remarque

Les rebonds des contacts des boutons!

C’est assez rare que ces contacts ne rebondissent pas quand ils sont activés.

C’est à dire:

J’appuie sur le BP et je maintient l’appuie, pendant un temps court (pour l’humain) le contact se ferme, s'ouvre, se referme, ou rebondit.

Et pendant ce court pour l’humain, l’entrée du micro à la temps d’interpréter “fermé, ouvert, fermé, ouvert, etc…”.

Sur quel état le code va s’arrêter ?

Les rebonds, et leurs effets secondairs, c’est une notion à appréhender par les débutants.

Il s’arrête sur l’état imposé par l’utilisateur. En INPUT_PULLUP ce sera bien LOW lors de l’appui et HIGH lors du relâchement mais avec ce code

On risque d’avoir du mal à augmenter ou baisser juste de 1 si la loop tourne vite.

Si ça compte correctement c’est que le reste de la loop prend beaucoup de temps et les oscillations ont disparu la fois suivante où on repasse par là dans le code.

(Ou le bouton a un anti rebond intégré)

Ce qui est dommage c’est que @mjb n’a pas compris à quoi sert la classe Toggle lors de notre exemple précédent…

Encore un peu de boulot et ca va le faire !

1 Like

Bonjour,

Par mes remarques, j’essayais d’inciter l’utilisateur à réfléchir à ce genre d’effets secondaires générés par les rebonds (HIGH, LOW, HIGH, LOW, HIGH, …,LOW) en fonction du temps de boucle

Ah désolé - j’ai donné la réponse au lieu de laisser @mjb chercher

Pas de quoi être désolé :smirking_face:

Merci pour vos remarques,

J’avais lu quelques sujets au sujet des rebonds mais je ne m’y étais pas attardé et dans mon programme, j’ai résolu le problème en mettant un délai de 10ms. en fin de loop. si j’appuie de manière courte sur les boutons, j’incrémente facilement les unités et si je reste un peu trop longtemps appuyé, effectivement, j’en incrémente 2 ou 3 en même temps avec une possibilité de corriger avec le bouton voisin. Et si j’ai besoin d’aller de 20 à 100 cela ne me prend 7 secondes.

Je ne pense pas que mes boutons aient un dispositif anti-rebond cependant, ils sont neufs et réactifs. En vieillissant, des problèmes peuvent peut-être survenir.

En prenant conscience de vos remarques, j’ai lu cahiers-pratiques/gerer-rebonds-interrupteur et le tuto de pandaroux sur ce forum. Mais je n’ai rien trouvé sur l’utilisation de la bibliothèque Toggle.

J’y suis donc allé à tâtons pour écrire ce nouveau code en essayant d’utiliser Toggle.

#include <OneWire.h>
//#include <SPI.h>                                // dans certaines configurations, les capteurs utilisent SPI pour communiquer, SPI travaille avec Adafruit MAX31855
#include "Adafruit_MAX31855.h"                  // j'inclue Adafruit_MAX31855 pour gérer les thermocouples
#include <LiquidCrystal_I2C.h>                  // J'inclue LiquidCrystal-I2C pour gérer le LCD
#include <Toggle.h>                             // j'inclue Toggle pour gérer le bouton silence

LiquidCrystal_I2C lcd(0x27, 20, 5);              // adresse du LCD i2c , nombre de colonnes, nombre de lignes de l'écran

#define MAXDO   2                             // sortie DO du Max 31855
#define MAXCS   3                             // sortie CS "  " " "
#define MAXCLK  4                             // sortie CLK " " " "
#define MAXCS2  5                             // sortie CS  2  " " "

const int  pinbtn1 = 6, pinbtn2 = 7, pinbtn3 = 8, pinbtn4 = 9, pinbuzzer = 10, pinledfourH = 11 , pinledfourB = 12, pinledfeu = 13, pinBoutonSilence = A0, pinLedSilence = A1 ;      // le bouton n°1 est relié en broche 6 , ...

Toggle boutonSilence(pinBoutonSilence);       //création d'une variable nommée bouton Silence, du type Toggle, qui est initialisée en utilisant le N° de la broche pinBoutonSilence (13)
Toggle btn1(pinbtn1);
Toggle btn2(pinbtn2);
Toggle btn3(pinbtn3);
Toggle btn4(pinbtn4);

int seuil_fourbas = 21;                                     // 21° seuil de la sonde four - Basse  (pour l'expérimentation) qui s'affiche lors de la réinitialisation, elle peut être incrémentée.
int seuil_fourhaut = 23;                                     // 23° seiol de la sonde four - Haute (pour l'expérimentation) qui s'affiche lors de la réinitialisation, elle peut être incrémentée.
int seuil_feu = 25;                                         // 25° seuil de la sonde placée en haut du conduit fumée pour détecter un incendie de cheminée (ne pourra pas s'incrémenter)

Adafruit_MAX31855 thermocouple1(MAXCLK, MAXCS, MAXDO);      // création d'une variable nommée thermocouple1, du type Adafruit_MAX31855 , qui est initialisée en utilisant les N° des broches qui concernent le thermocouple 1
Adafruit_MAX31855 thermocouple2 (MAXCLK, MAXCS2, MAXDO);    // création d'une variable nommée thermocouple2, du type Adafruit_MAX31855 , qui est initialisée en utilisant les N° des broches qui concernent le thermocouple 2

enum : uint8_t {AUCUNE_ALARME = 0, ALARME_FOUR_H = 1, ALARME_FOUR_B = 2, ALARME_FEU = 4};
uint8_t alarmesEnCours = AUCUNE_ALARME;

void setup() {

  lcd.init();                     // active le LCD
  lcd.backlight();               // active le rétroéclairage

  pinMode (pinbuzzer, OUTPUT) ;      digitalWrite(pinbuzzer, LOW);                // active la sortie 13 du buzzer
  pinMode (pinledfourH, OUTPUT) ;     digitalWrite(pinledfourH, LOW);             // active la sortie 11 de la led alarme four Haut
  pinMode (pinledfourB, OUTPUT) ;     digitalWrite(pinledfourB, LOW);              // active la sortie 11 de la led alarme four Bas
  pinMode (pinledfeu, OUTPUT) ;     digitalWrite(pinledfeu, LOW);                  // active la sortie 12 de la led alarme feu
  pinMode (pinLedSilence, OUTPUT) ;     digitalWrite(pinLedSilence, LOW);          // active la sortie A1 de la led silence
  boutonSilence.begin(pinBoutonSilence);
  btn1.begin(pinbtn1);
  btn2.begin(pinbtn2);
  btn3.begin(pinbtn3);
  btn4.begin(pinbtn4);

  Serial.begin(115200);
  Serial.println("PRET");
  delay(1000);                  // pour stabiliser la lecture
}

void loop() {

  double cfour = thermocouple1.readCelsius();        // Lecture en degrés Celcius du capteur 1
  double cfeu = thermocouple2.readCelsius();        // Lecture en degrés Celcius du capteur 2

  btn1.poll();
  if (btn1.onPress()) {                                  // si le bouton est appuyé on rentre dans ce if
    seuil_fourbas--;                                      //  deg-- est équivalent à deg = deg -1 ;
  }
  btn2.poll();
  if (btn2.onPress()) {
    seuil_fourbas++;                                      
  }
  btn3.poll();
  if (btn3.onPress()) {
    seuil_fourhaut--;                                      
  }
  btn4.poll();
  if (btn4.onPress()) {
    seuil_fourhaut++;
  }

  

  //void animations() {

  static bool modeSilence = false;                                // Variable persistante conservant l’état du mode silence entre deux appels de la fonction.
  static uint32_t debutModeSilence = 0;                           // Instant, en millisecondes depuis le démarrage, auquel le mode silence a été activé.
  static const uint32_t dureeModeSilence = 10000ul;               // définition d'une constante pour la durée maximale du mode silence en millisecondes.

  boutonSilence.poll();
  if (boutonSilence.onPress()) {                                  // si le bouton est appuyé on rentre dans ce if
    modeSilence = not modeSilence;                                // Inversion explicite de l’état du mode silence à chaque appui.
    digitalWrite(pinLedSilence, modeSilence ? HIGH : LOW);        // La LED reflète directement l’état logique du mode silence. on interroge  l'état du mode silence, s'il est "true"  la pinledSilence devient HIGH sinon on retourne LOW ???

    /*static uint32_t chrono = 0;                                                    // Référence temporelle persistante utilisée pour cadencer le clignotement….(le compteur est relevé)
      if (millis() - chrono >= 100) {                                                // Inversion de l’état de la LED toutes les 100 ms, ce qui fixe la fréquence de clignotement.
        digitalWrite(pinLedSilence, digitalRead(pinLedSilence) == HIGH ? LOW : HIGH);    // la led HP clignote… l'écriture de cette fonction s'appelle l'opérateur ternaire elle Inverse l'état en sortie pinLedHP… si pinLedHP est HIGH alors retourne LOW sinon retourne HIGH …on pourrait l'écrire digitalWrite(pinLedHP, !(digitalRead(pinLedHP)));
        chrono = millis();
      }*/

    if (modeSilence) debutModeSilence = millis();                 // Mémorisation de l’instant d’activation pour mesurer la durée écoulée.
  }

  if (modeSilence && millis() - debutModeSilence >= dureeModeSilence) {   // si  la durée maximale du mode silence est dépassée.(si le compteur continue moins le compte relevé au début du MS est supérieur ou égal à 10 secondes  (dureeModeSilence) )
    modeSilence = false;                                                  // le mode silence devient faux (est désactivé… le buzzer sonne.
    digitalWrite(pinLedSilence, LOW);                                     // et la led silence s'éteint
  }

  //**************************************************************

  if (cfour >= seuil_fourhaut)  {                                                    // si la dernière température du capteur four est supérieure à son seuil haut
    static uint32_t chrono = 0;                                                    // Référence temporelle persistante utilisée pour cadencer le clignotement….(le compteur est relevé)
    if (millis() - chrono >= 100) {                                                // Inversion de l’état de la LED toutes les 100 ms, ce qui fixe la fréquence de clignotement.
      digitalWrite(pinledfourH, digitalRead(pinledfourH) == HIGH ? LOW : HIGH);    // la led HP clignote… l'écriture de cette fonction s'appelle l'opérateur ternaire elle Inverse l'état en sortie pinLedHP… si pinLedHP est HIGH alors retourne LOW sinon retourne HIGH …on pourrait l'écrire digitalWrite(pinLedHP, !(digitalRead(pinLedHP)));
      chrono = millis();                                                           // on se souvient du moment de la dernière inversion
    }
    alarmesEnCours |= ALARME_FOUR_H;                                              // Activation du bit correspondant à l’alarme HP sans modifier les autres bits. |= est un OU bit à bit
  } else {                                                                        // sinon
    digitalWrite(pinledfourH, LOW);                                               // la led HP n'est pas alimentée
    alarmesEnCours &= ~ALARME_FOUR_H;                                             // Effacement du bit ALARME_HP par masquage binaire, les autres alarmes restent inchangées.

  }

  //**************************************************************

  if (cfour <= seuil_fourbas) {                                                    // si la dernière température du capteur four est inférieure à son seuil bas
    static uint32_t chrono = 0;
    if (millis() - chrono >= 100) {
      digitalWrite(pinledfourB, digitalRead(pinledfourB) == HIGH ? LOW : HIGH);
      chrono = millis();
    }
    alarmesEnCours |= ALARME_FOUR_B;
  } else {
    digitalWrite(pinledfourB, LOW);
    alarmesEnCours &= ~ ALARME_FOUR_B;
  }

  //**************************************************************

  if (cfeu >= seuil_feu) {                                                           // si la dernière température du capteur feu est supérieure à son seuil
    static uint32_t chrono = 0;
    if (millis() - chrono >= 100) {
      digitalWrite(pinledfeu, digitalRead(pinledfeu) == HIGH ? LOW : HIGH);
      chrono = millis();
    }
    alarmesEnCours |= ALARME_FEU;
  } else {
    digitalWrite(pinledfeu, LOW);
    alarmesEnCours &= ~ALARME_FEU;
  }

  //********************************************************************

  if (not modeSilence && alarmesEnCours != AUCUNE_ALARME) {

    // une alarme au moins est en cours et on n'est pas en mode silence
    static uint32_t chrono = 0;
    if (millis() - chrono >= 300) {
      digitalWrite( pinbuzzer, digitalRead(pinbuzzer) == HIGH ? LOW : HIGH);
      chrono = millis();
    }
  }
  else
  {
    digitalWrite(pinbuzzer, LOW);
  }

 
  //Configuration du LCD
 
  lcd.setCursor(4, 0);                          // sur la première colone de la quatrième ligne
  lcd.print("Seuil bas  = ");
  lcd.print (seuil_fourbas);                    // le LCD imprime la valeur du seuil bas que l'on peut incrémenter
  lcd.print((char)223);

  lcd.setCursor(0, 1);                          // sur la première colone de la deuxième ligne
  lcd.print("T");
  lcd.print((char)223);
  lcd.print("FOUR ");
  lcd.print(cfour);                             // on imprime la température captée par le thermocouple du four                       // on imprime la température captée par le thermocouple du conduit de cheminée

  lcd.setCursor(4, 2);                        // sur la première colone de la cinquième ligne
  lcd.print("Seuil haut = ");
  lcd.print (seuil_fourhaut);                   // le LCD imprime la valeur du seuil haut que l'on peut incrémenter
  lcd.print((char)223);

  lcd.setCursor(0, 3);                          // sur la première colone de la troisième ligne
  lcd.print("T");
  lcd.print((char)223);
  lcd.print("CONDUIT ");
  lcd.print(cfeu);

  Serial.print ("alarmesEnCours") ; Serial.println(alarmesEnCours) ;
  Serial.print ("T° FOUR") ; Serial.println(cfour) ;
  Serial.print ("T° CONDUIT") ; Serial.println(cfeu) ;

}

Le code fonctionne, il faut appuyer environ une seconde sur un bouton pour incrémenter puis l’appui n’a plus d’effet donc, il n’y a pas de risque de rebond.

Cependant, l’appui long ne fonctionne pas.

Il y a certainement un moyen d’incrémenter rapidement sans rebond mais je n’ai pas trouvé.

oui c'est une autre bibliothèque. Vous pourriez essayer de prendre OneButton à la place de Toggle et écrire le code en fonction de cette bibliothèque, ce serait un bon exercice de mise en application du tuto de @pandaroux007

Pour le fonctionnement de Toggle les fonctions les plus utiles sont dans le .h

Vous demandez de maintenir l'état du bouton le plus souvent possible en appelant poll() et vous aurez une seul fois par appui onPress() qui est vrai - ensuite isPressed() et vrai jusqu'au relâchement ou vous aurez un seul onRelease() qui sera vrai oui après isReleased() qui est vrai.

Quant à onChange(), ça retourne 0 si pas de changement depuis la dernière fois et 1 si le bouton vient d'être appuyé et 2 si le bouton vient d'être relâché.

rien à faire, je ne trouve pas la formule, si j’écris par exemple

 btn1.poll();
  if (btn1.onPress()) 
    { 
      seuil_fourbas--;                                   
    }
    else 
      {
        seuil_fourbas ;
      }   
  

  if (btn1.isPressed()) 
    {
      seuil_fourbas--;
    }
    else {
      seuil_fourbas ;
    }
  

j’obtiens un déroulement sans pouvoir incrémenter pas à pas. à priori, j’ai besoin de bloquer la fonction onPress avant que la fonction isPressed devienne active mais je n’y parviens pas.

faut-il enclencher un chronomètre pour gérer la fonction isPressed ou y a-t-il un moyen plus simple?

Ça ne sert à rien cette instructions…

Be oui dès que vous pressez il y a decrementation (on press) et après isPressed est vrai donc ça décrémenter a fond…

Je n’ai pas compris comment coder cela.

La première question à vous poser c’est que voulez vous que ça fasse ?

Détaillez bien lors de l’appui et si appui continu ce que ça doit faire (et à quelle rapidité l’incrément doit se faire)

Bonjour,

Je voudrais avoir le même effet que dans mon programme actuel : incrémentation d’un pas avec un appui rapide et incrémentation continue de 10 pas toutes les secondes jusqu’à relâchement du bouton.

Si je parviens à écrire une formule d’anti-rebond avec les mêmes effets, ce serait mieux sinon, j’ai lu qu’il y avait des méthodes avec condensateur - résistance - diode éventuellement.

Je commence à comprendre quelques formules du langage Arduino, voir à les recopier et les agencer entre-elles tout cela grâce à votre aide, votre patience, votre pédagogie. Mais, je suis très loin d’avoir assez d’autonomie pour inventer de toute pièce des formulations.

Jusqu’ici, ce sont les réponses que vous m’avez données qui m’ont motivé pour faire des recherches et évoluer dans mon apprentissage. Ces réponses ont été précieuses.

J’ai cherché longtemps, sans trouver et je suis en situation d’échec sur ma capacité à fabriquer ce code anti-rebond.

La mise en échec par rétention d’information me semble beaucoup moins pédagogique que l’enseignement que vous m’avez apporté jusqu’ici.

Je comprends que votre générosité ait des limites aussi, je vous suis reconnaissant pour tout ce que vous m’avez enseigné au par avant.

essayez de regarder cet exemple

Bonjour,

Pour information, il n'y a pas de langage Arduino (dixit)

Les langages employés dans ce fil de discussion sont du Langage C et/ou du C++

A suivre...

Ça dépend si on parle de l’API setup() loop() digitqalRead() etc ce. Sont des éléments du langage pour arduino, mais oui sinon le langage de programmation c’est le C+c

Bonjour, j’ai pris le temps de réaliser différentes recherches sur Onebutton, de reprendre le tuto de pandaroux et de repartir de l’exemple donné par JLM sur wokwi.

J’ai réalisé un code pour incrémenter en positif et en négatif deux valeurs avec deux vitesses différentes, tel que je l’avais réalisé dans mon premier programme mais en y ajoutant une fonction antirebond et avec une lecture sur LCD.

c’est sur Wokwi et ci-dessous.

De quel manière peut-on améliorer ce programme :


#include <OneButton.h>                    // inclure la bibliothèque OneButton.h pour gérer les boutons
#include <LiquidCrystal_I2C.h>            // inclure la bibliothèque LiquidCrystal_I2C.h pour gérer le LCD

LiquidCrystal_I2C lcd(0x27, 20, 4);      // adresse du LCD i2c , nombre de colonnes, nombre de lignes de l'écran

int seuil_fourbas = 21;                                 // je décide de démarrer le comptage de l'incrémentation des température basses à 21°
int seuil_fourhaut = 23;                                // je décide de démarrer le comptage de l'incrémentation des température hautes à  23°

const byte pinbtn1 = 9, pinbtn2 = 8, pinbtn3 = 7, pinbtn4 = 6 ;  // je déclare les broches où sont reliés mes boutons

const unsigned long entreDeuxNotifications = 500;               // temps entre 2 notificationssur le moniteur série et rapidité de l'incrémentation sur le LCD.
const unsigned long dureeMinPourAppuiLong = 500;                // durée minimum pour que l'appui long soit pris en compte

OneButton bouton1(pinbtn1);                                     // création d'une variable nommée bouton1, du type OneButton, qui est initialisée en utilisant le N° de la broche pinbtn1  (9)
OneButton bouton2(pinbtn2);
OneButton bouton3(pinbtn3);
OneButton bouton4(pinbtn4);

unsigned long chronoAppui;                                      //   ??????? déclare que l'on va utiliser le compteur millis ??????????

void appui1() {                                                 // Fonction qui détermine ce qui se passe lors d'un appui simple
  seuil_fourbas --;
}
void appui2() {
  seuil_fourbas ++;
}
void appui3() {
  seuil_fourhaut --;
}
void appui4() {
  seuil_fourhaut ++;
}
void pendantAppuiLong1() {                                       // Fonction qui détermine ce qui se passe lors d'un appui long
  seuil_fourbas -= 10;
}
void pendantAppuiLong2() {
  seuil_fourbas += 10;
}
void pendantAppuiLong3() {
  seuil_fourhaut -= 10;
}
void pendantAppuiLong4() {
  seuil_fourhaut += 10;
}

void setup() {
  lcd.init();                                                        // initialisation du LCD
  lcd.backlight();                                                   // active le rétroéclairage

  //bouton1.setup(pinbtn1, INPUT_PULLUP, true);                        // à priori sans intérêt avec OneButton
  //bouton2.setup(pinbtn2, INPUT_PULLUP, true);
  //bouton3.setup(pinbtn3, INPUT_PULLUP, true);
  //bouton4.setup(pinbtn4, INPUT_PULLUP, true);

  bouton1.setDebounceMs(-25);                                          // temps d'attente de l'antirebond (temps qui s'écoule pour q'un changement d'état du bouton soit validé en front montant comme en front descendant.
  bouton2.setDebounceMs(-25);
  bouton3.setDebounceMs(-25);
  bouton4.setDebounceMs(-25);

  bouton1.setPressMs(dureeMinPourAppuiLong);                          // pour chaque bouton, on détermine la durée minimum pour que l'appui long soit pris en compte. Elle a été fixée en début de programme à 500ms.
  bouton2.setPressMs(dureeMinPourAppuiLong);
  bouton3.setPressMs(dureeMinPourAppuiLong);
  bouton4.setPressMs(dureeMinPourAppuiLong);

  bouton1.setLongPressIntervalMs(entreDeuxNotifications);            // pour chaque bouton, on détermine le temps entre 2 notificationssur le moniteur série et la rapidité de l'incrémentation sur le LCD. Elle a été fixée en début de programme à 500ms.
  bouton2.setLongPressIntervalMs(entreDeuxNotifications);
  bouton3.setLongPressIntervalMs(entreDeuxNotifications);
  bouton4.setLongPressIntervalMs(entreDeuxNotifications);


  bouton1.attachPress(&appui1);                                       // On précise que l'action du bouton 1 est déterminée dans la "void appui1"
  bouton2.attachPress(&appui2);
  bouton3.attachPress(&appui3);
  bouton4.attachPress(&appui4);
  bouton1.attachDuringLongPress(pendantAppuiLong1);
  bouton2.attachDuringLongPress(pendantAppuiLong2);
  bouton3.attachDuringLongPress(pendantAppuiLong3);
  bouton4.attachDuringLongPress(pendantAppuiLong4);
}

void loop() {
  bouton1.tick();                                               // On lit en permanence le bouton connecté à la broche 9 et le programme agit en conséquence.
  bouton2.tick();
  bouton3.tick();
  bouton4.tick();

  lcd.setCursor(0, 1);                        // mettre le curseur sur la première conlone, deuxième ligne
  lcd.print ("Seuil Bas = ");
  lcd.print (seuil_fourbas);                              // le LCD imprime la valeur à laquelle l'alarme Froide a été programmée.
  lcd.print((char)223);                       // symbole °
  lcd.print("C");

  lcd.setCursor(0, 2);                        // mettre le curseur sur la première conlone, deuxième ligne
  lcd.print ("Seuil Haut = ");
  lcd.print (seuil_fourhaut);                              // le LCD imprime la valeur à laquelle l'alarme Chaude a été programmée.
  lcd.print((char)223);
  lcd.print("C");
}

quizz (pour @mjb - pas pour les pros)

comment j'ai obtenu cet affichage erroné d'aprés vous ?

Effectivement, ce programme est loin d’être parfait.