Interface avec l'utilisateur via boutons poussoir

Bonjour,

Tout d'abord, je vous présente tous mes voeux pour cette nouvelle année.

Je viens demander de l'aide car je tourne en rond sur des boucles. Mon appareil est constitué d'un capteur (sonde de pH), de 2 boutons (branchés en pull-up interne) branchés sur une carte UNO.
J'étalonne le capteur avec 2 points de mesure (pH=7 et pH=4). A la fin de la procédure, je fais afficher la valeur du pH mesuré et demande à l'utilisateur s'il est content de son étalonnage ou non : s'il est content, le programme se poursuit sinon on réitère la procédure d'étalonnage.

Le choix de l'utilisateur se fait via les 2 boutons (ils fonctionnent correctement car la fonction etalonnage qui les utilise fonctionne parfaitement)

Actuellement, j'ai programmé ceci :

while (EtalonnageValide == 0)
  {
    while (testEtalonnage == 0)
    {
      etalonnage(7);
    }
    testEtalonnage = 0;
    while (testEtalonnage == 0)
    {
      etalonnage(4);
    }
    etatBoutonEnter = digitalRead(pinBoutonEnter);  
    etatBoutonExit = digitalRead(pinBoutonExit); 
    while (etatBoutonEnter != LOW || etatBoutonExit != LOW ) 
    {
      mesure_simple();
      affiche_texte_lcd(0, 0, "Etalonnage bon ?");
      affiche_texte_lcd(0, 1, "oui --> EXIT");
      affiche_texte_lcd(0, 2, "non --> ENTER");
      etatBoutonEnter = digitalRead(pinBoutonEnter); 
      etatBoutonExit = digitalRead(pinBoutonExit);
      if (etatBoutonExit == LOW) 
      {
        EtalonnageValide = 0;
        testEtalonnage = 0;
      }
      //delay(5000);

      if (etatBoutonExit == LOW) 
      {
        EtalonnageValide = 1;
      }
    }
  }

Avec ce code, j'arrive bien à l'écran qui me demande si l'étalonnage est bon mais le programme reste figé dessus, l'appui sur les boutons ne fait plus rien.

J'imagine que mon problème vient des boucles qui sont inadaptées ou pas correctement placées mais j'ai beau avoir fait plusieurs essais, je n'arrive pas à obtenir ce que je souhaite.

Quelqu'un pourrait-il m'aider ?

Merci d'avance

ça semble normal pour une boucle :slight_smile:

que fait la fonction etalonnage(), elle modifie la variable testEtalonnage je suppose ? comment ?

➜ postez tout le code.

Bonjour,

Le code de la fonction etalonnage qui effectivement modifie le valeur de testEtalonnage à l'issue de la procédure :

void etalonnage(byte valtampon) //fonction qui lance la procédure d'étalonnage du capteur
{
  //Affichage sur LCD par fonction
  affiche_texte_lcd(5, 0, "ETALONNAGE");
  delay(1000);
  affiche_texte_lcd(0, 1, "Plonger sonde dans");
  affiche_texte_lcd(0, 2, "sol. tampon pH= ");
  if (valtampon == 7)
    affiche_texte_lcd(15, 2, "7");
  else
    affiche_texte_lcd(15, 2, "4");
  affiche_texte_lcd(0, 3, "Appuyer ENTER si OK");


  //temperature = readTemperature();  // mesure de la température via la fonction readTemperature dédiée

  // on teste si le bouton ENTER est pressé
  etatBoutonEnter = digitalRead(pinBoutonEnter);  //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
  if (etatBoutonEnter == LOW )  //si le bouton était précédemment non appuyé alors lastBoutonEnter=1=HIGH
  {
    testBoutonEnter = 1;
    voltage = analogRead(PH_PIN) / 1024.0 * 5000; // read the voltage
    phValue = ph.readPH(voltage, temperature); // convert voltage to pH with temperature compensation
    ph.calibration(voltage, temperature, Enter); // on envoie la commande ENTEREC au module pour commencer la calibration
    lcd.backlight();
    lcd.clear();
    affiche_texte_lcd(0, 0, "ETALONNAGE");

    int i = 6;
    while (i >= 0)
    {
      lcd.setCursor(0, 2);
      lcd.print(F("Attendre "));
      lcd.setCursor(9, 2);
      lcd.print(i);
      lcd.setCursor(10, 2);
      lcd.print(F(" sec      "));
      delay(1000);
      i = i - 1;
    }
    lcd.clear();
    affiche_texte_lcd(5, 0, "ETALONNAGE");
    affiche_texte_lcd(0, 2, "CAL pour valider    ");

    if (lastBoutonCal == HIGH)   // on  teste si Cal n'est pas appuyé après que le bouton Enter ait été appuyé
      while (testBoutonEnter == 1)
      { // on teste si le bouton CAL est pressé --> si oui, on valide l'étalonnage
        etatBoutonCal = digitalRead(pinBoutonCal);  //on lit l'état du bouton Cal
        if (etatBoutonCal == 0) //si le bouton Cal est pressé alors etatBoutonCal=LOW=0 car pin en mode pull up interne
        {
          //lcd.backlight();
          lcd.clear();
          ph.calibration(voltage, temperature, Cal); // calibration process by Serail CMD
          //lcd.backlight();
          affiche_texte_lcd(0, 0, "->Etalonnage reussi ");
          affiche_texte_lcd(0, 1, "EXIT pour sauvegarde");
          affiche_texte_lcd(0, 2, "et pour quitter     ");
          testBoutonCal = 1;
        }
        if (lastBoutonExit == HIGH)   // Appui sur Exit après appui sur Enter
          while (testBoutonCal == 1)
          {
            etatBoutonExit = digitalRead(pinBoutonExit);
            if (etatBoutonExit == 0)
            {
              //lcd.backlight();
              lcd.clear();
              ph.calibration(voltage, temperature, Exit); // calibration process by Serail CMD
              //lcd.backlight();
              affiche_texte_lcd(0, 0, "->Etalonnage termine");
              delay(1000);
              lcd.clear();
              testBoutonEnter = 0;
              testBoutonCal = 0;
              testEtalonnage = 1;
              break;
            }
          }
      }
  }
  else
  {
    etatBoutonCal = digitalRead(pinBoutonCal);
    etatBoutonExit = digitalRead(pinBoutonExit);
    if (etatBoutonExit > lastBoutonExit && etatBoutonCal == 0)
    {
      ph.calibration(voltage, temperature, Exit); // calibration process by Serail CMD
      //lcd.backlight();
      lcd.clear();
      affiche_texte_lcd(0, 0, "->Etalonnage arrete");
      delay(2000);
      lcd.clear();
    }
  }
  lastBoutonEnter = etatBoutonEnter;
  lastBoutonCal  = etatBoutonCal;
  lastBoutonExit = etatBoutonExit;
}

Dans ce morceau de code

Pour moi, testBoutonEnter n'est jamais mis à jour dans le code du while donc boucle infinie.
Erreur de ma part, je n'avais pas vu l'affectation un peu plus bas.

La procédure d'étalonnage fonctionne pourtant correctement.

cette condition est vrai tant que les 2 boutons ne sont pas appuyés ensembles.
Toi, tu veux sortir si l'un des 2 est appuyé, il faut faire

while (etatBoutonEnter == HIGH && etatBoutonExit == HIGH )

Cette condition reste vrai tant qu'aucun des boutons n'a été appuyé

A noter, la lecture de l'état des boutons avant d'entrer dans le while peut empêcher d'entrer dans la boucle, si l'un des boutons est déjà appuyé. Il faut supprimer ces lignes et ne conserver que la lecture à l'intérieur de la boucle.

Si je ne me trompe pas, on appui sur exit en quittant etalonnage().
Il faudrait alors faire un

while(digitalRead(pinBoutonExit) == LOW);

avant d'entrer dans la boucle de validation pour être certain que le bouton a été relâché.

Bonjour,

Si je change la boucle while (etatBoutonEnter != LOW || etatBoutonExit != LOW )

en while (etatBoutonEnter == HIGH && etatBoutonExit == HIGH )

soit je boucle infiniment sur l'étalonnage 4 (dès que je valide l'étalonnage 4, je reviens à l'étalonnage 4 sans rien toucher) si je supprime la lecture de l'état des boutons avant d'entrer dans la bouche while
soit j'arrive à l'écran qui demande si l'étalonnage est bon (à valider par l'utilisateur en pressant ENTER ou EXIT) mais où cela reste fixe, l'appui d'un bouton ne change rien

Oui parce que la touche exit est utilisée comme acceptation à la fin d'etalonnage() et dans la validation finale d'où l'ajout du test du relâchement du bouton pour ne pas sortir directement après etalonnage(). Par contre, il faut effectivement conserver la mise à jour de l'état des 2 boutons avant d'entrer dans le while.

Tu ne testes pas enter

      if (etatBoutonExit == LOW) 
      {
        EtalonnageValide = 0;
        testEtalonnage = 0;
      }
      //delay(5000);

      if (etatBoutonExit == LOW) 
      {
        EtalonnageValide = 1;
      }

Tu as des boucles imbriquées avec des variables qui définissent des états et qui sont réutilisées dans les différents blocs elles ne sont peut-être pas bien mise à jours. Peut-être utiliser des variables locales pour gérer ça.
Avec quelques Serial.print placés judicieusement dans ton code tu verrais mieux son déroulement.

Bonjour,

En fait, il n'y avait plus de problème suite à tes remarques ! C'est tout simplement que j'ai oublié de supprimer l'affichage de la demande à l'utilisateur qui paraissait bloquer le programme alors que les mesures étaient bien faites.

while (EtalonnageValide == 0)
  {
    while (testEtalonnage == 0)
    {
      etalonnage(7);
    }
    testEtalonnage = 0;
    while (testEtalonnage == 0)
    {
      etalonnage(4);
    }
    etatBoutonEnter = digitalRead(pinBoutonEnter);  //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
    etatBoutonExit = digitalRead(pinBoutonExit);  //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
    while (etatBoutonEnter == HIGH && etatBoutonExit == HIGH )
    {
      mesure_simple();
      affiche_texte_lcd(0, 0, "Etalonnage bon ?");
      affiche_texte_lcd(0, 1, "oui --> EXIT");
      affiche_texte_lcd(0, 2, "non --> ENTER");
      //delay(2000);
      etatBoutonEnter = digitalRead(pinBoutonEnter);  //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
      etatBoutonExit = digitalRead(pinBoutonExit);  //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
      if (etatBoutonEnter == LOW)  //si le bouton était précédemment non appuyé alors lastBoutonEnter=1=HIGH
      {
        EtalonnageValide = 0;
        testEtalonnage = 0;
        lcd.clear();

      }
      //delay(5000);

      if (etatBoutonExit == LOW)  //si le bouton était précédemment non appuyé alors lastBoutonEnter=1=HIGH
      {
        EtalonnageValide = 1;
        lcd.clear();
      }
    }
  }