Erreur de boucle dans un switch/case

Bonjour,

J'ai un petit souci dans une partie de mon programme. J'attends de l'utilisateur qu'il saisisse des valeurs, valeurs que je vérifie après la saisie.
Quand les valeurs saisies sont correctes, pas de problème, le programme fait ce que j'attends.
Par contre, dès que je teste une valeur erronée, le programme ne fait pas ce que j’attends et boucle toujours sur la même partie (celle correspondant au cas choix =0), y compris quand je saisis par la suite une valeur corrigée qui respecte les critères.
Merci pour votre aide

void reglages()
{
  while (topDepart == 0)
  {
    envoi = Serial.readString();

    affiche_texte_lcd(0, 0, "Suivre indications ");
    affiche_texte_lcd(0, 1, "sur moniteur serie ");
    affiche_texte_lcd(0, 2, "pour parametrage de");
    affiche_texte_lcd(0, 3, "l'acquisition      ");

    affiche_gamme();
    parametrage(0); //on parametre la gamme

    affiche_echantillonnage();
    parametrage(1); //on parametre la periode d'échantillonnage

    affiche_duree();
    parametrage(2); //on parametre la durée totale


    Serial.println(F("Saisir S pour démarrer l'acquisition : "));
    parametrage(3); //on lance l'acquisition
  }
  lcd.clear();
}

void parametrage(byte phase)
{
  while (Serial.available() == 0 );
  {
    unsigned int choix = Serial.parseInt();
    switch (phase)
    {
      case 0: //on est dans la phase de choix de la gamme
        while ((choix != 1) && (choix != 2) && (choix != 3)) //on teste la saisie
        {
          Serial.println(F("Erreur : il faut saisir 1, 2 ou 3\n"));
          affiche_gamme();
          parametrage(0);
        }
        Serial.print(F("Vous avez choisi la gamme "));
        if (choix == 1)
          Serial.println(F("0-2 mS/cm\n"));
        else if (choix == 2)
          Serial.println(F("2-20 mS/cm\n"));
        else
          Serial.println(F("automatique\n"));

        delay(1000); //délai de temporisation
        break;

      case 1: //on est dans la phase de saisie de l'échantillonnage
        if (choix == 0)
          parametrage(0);
        else if (choix <= 0)
        {
          Serial.println("Erreur de saisie : la période d'échantillonnage doit être un entier supérieur  à 0");
          affiche_echantillonnage();
          parametrage(1);
        }
        Serial.print(F("Période d'échantillonnage saisie : "));
        Serial.print(choix);
        Serial.println(F(" s\n"));
        timeRes = choix * 1000;
        delay(1000); //délai de temporisation
        break;

      case 2:
        if (choix == 0)
          parametrage(1);
        else if (choix <= timeRes / 1000)
        {
          Serial.println("Erreur de saisie : la durée d'acquisition doit être un entier supérieur ou égal à la période d'échantillonnage");
          affiche_duree();
          parametrage(2);
        }
        Serial.print(F("Durée d'acquisition saisie : "));
        Serial.print(choix);
        Serial.println(F(" s\n"));
        dureeAcquisition = choix * 1000;
        delay(1000); //délai de temporisation
        break;

      case 3 :
        topDepart = 1;
        tempsPrec = 0;
        tempsZero = millis();

        break;

    }
  }
}

Bonjour,

Vérifies que tu n'envoies pas retour chariot et/ou line feed après le nombre

Il est préférable d'envoyer cr lf, mais dans ce cas il faut vider le buffer après réception du nombre.

Dans le moniteur série, j'ai bien sélectionné "pas de fin de ligne"
je ne comprends pas la dernière partie "Il est préférable d'envoyer cr lf, mais dans ce cas il faut vider le buffer après réception du nombre."

Il est préférable d'envoyer un terminateur car autrement la parseint attend le timeout

Affiches la valeur de choix après réception.

En sélectionnant d'abord 0 (donc erreur) puis 1 (normalement correct), en affichant la valeur prise par choix (=parseInt), j'obtiens :

Quelle gamme de mesure du conductimètre :
calibre 0-2 mS/cm --> tapez 1
calibre 2-20 mS/cm --> tapez 2
calibre automatique --> tapez 3

0
Erreur : il faut saisir 1, 2 ou 3

Quelle gamme de mesure du conductimètre :
calibre 0-2 mS/cm --> tapez 1
calibre 2-20 mS/cm --> tapez 2
calibre automatique --> tapez 3

1
Vous avez choisi la gamme 0-2 mS/cm

Erreur : il faut saisir 1, 2 ou 3

Quelle gamme de mesure du conductimètre :
calibre 0-2 mS/cm --> tapez 1
calibre 2-20 mS/cm --> tapez 2
calibre automatique --> tapez 3

Le 1 "correct'" est donc bien enregistré dans choix, avec la bonne phrase suivante (la gamme 0-2 mS/cm) mais il poursuit avec une Erreur, comme si je n'avais pas saisi 1

Tu cherches les problèmes en appelant parametrage() à l'intérieur de parametrage()

Il faut revoir l'organisation de paramétrage()

Je ne voyais pas trop comment faire d'autres : une autre piste (machine à états) m'a été proposée sur une autre discussion mais cela demande un peu de temps de compréhension et je n'ai pas trop le temps à consacrer à une "formation" malheureusement

(deleted)

Phase me permet de situer où j'en suis dans mon paramétrage

  • phase de saisie de la gamme : phase = 0
  • phase de saisie de l'échantillonnage ; phase = 1
  • phase de saisie de la durée d'acquisition : phase = 2
    --> en fonction de où j'en suis dans mon programme, j'appelle donc successivement parametrage(0) puis parametrage(1) puis parametrage(2)
  • pour l'échantillonnage, je me sers de la valeur 0 pour revenir au menu précédent --> je dois donc le tester au préalable
  • ma période est forcément >0 donc quand ce n'est pas le cas, j'informe de l'erreur

Mon programme ne fonctionne pas dès que je fais une saisie erronée (par exemple : valeur autre que 1, 2 ou 3dans le choix de la gamme, valeur 0 dans le choix de la période ...)

J'ai essayé une autre méthode (je n'ai mis que le début) :

void parametrage(byte phase)
{
  while (Serial.available() == 0 );
  {
    unsigned int choix = Serial.parseInt();
    switch (phase)
    {
      case 0: //on est dans la phase de choix de la gamme
        while (testGamme == 0)
        {

          if ((choix != 1) && (choix != 2) && (choix != 3)) //on teste la saisie
          {
            Serial.println(F("Erreur : il faut saisir 1, 2 ou 3\n"));
            affiche_gamme();
            choix = Serial.parseInt();
          }
          else
          {
            Serial.print(F("Vous avez choisi la gamme "));
            if (choix == 1)
              Serial.println(F("0-2 mS/cm\n"));
            else if (choix == 2)
              Serial.println(F("2-20 mS/cm\n"));
            else
              Serial.println(F("automatique\n"));
            testGamme = 1;
            delay(1000); //délai de temporisation
          }
        }
        break;

Quand je saisis la bonne valeur : ok pas de soucis.
par contre, quand je ne sélectionne pas une valeur correcte, il boucle en affichant le message d'erreur et le message qui figure dans la fonction affiche_gamme.
J'ai essayé une version modifiée en pensant qu'un caractère était envoyé

while ((testGamme == 0)&&(Serial.available()==0))

mais même problème

problème résolu : je ne testais pas le

Serial.available()

au bon endroit

Avec ceci, cela fonctionne :

void parametrage(byte phase)
{
  while (Serial.available() == 0 );
  {
    unsigned int choix = Serial.parseInt();
    switch (phase)
    {
      case 0: //on est dans la phase de choix de la gamme
        while (testGamme == 0)
        {

          if ((choix != 1) && (choix != 2) && (choix != 3)) //on teste la saisie
          {
            Serial.println(F("Erreur : il faut saisir 1, 2 ou 3\n"));
            affiche_gamme();
            while (Serial.available() == 0 );
            {
              choix = Serial.parseInt();
            }
          }
          else
          {
            Serial.print(F("Vous avez choisi la gamme "));
            if (choix == 1)
              Serial.println(F("0-2 mS/cm\n"));
            else if (choix == 2)
              Serial.println(F("2-20 mS/cm\n"));
            else
              Serial.println(F("automatique\n"));
            testGamme = 1;
            delay(1000); //délai de temporisation
          }
        }
        break;

(deleted)

pascaltech:
Si la variable phase n'est pas initialisée elle a la valeur 0 donc il n'y a que le cas 0 (case0) qui fonctionne.

Non.

La variable phase et un paramètre de la fonction

void parametrage(byte phase)

elle est donc forcément initialisée à l'appel de la fonction sinon ça ne compile pas.

D'autre part une variable non initialisée n'a pas toujours la valeur 0.

pascaltech:
J'ai peu d'expérience en C, alors pardonne-moi si je t'induis en erreur.

Parfois vaut mieux éviter d'affirmer sans savoir ou tout du moins sans vérifier....

@nlb

cela ressemble fortement à un double post. Est-ce la même chose qu'ici ?

J-M-L:
@nlb

cela ressemble fortement à un double post. Est-ce la même chose qu'ici ?

Mon programme de base oui mais comme l'autre discussion s'orientait plus dans la direction de la réponse "machine à états", j'ai recréé un second post.

je pensais pouvoir bricoler simplement en utilisant des variables booleennes pour chaque partie mais c'est un peu le serpent qui se mord la queue.
je crois que je vais devoir me plonger dans les machines à état, si j'arrive à me dégager du temps !