Partage
  • Partager sur Facebook
  • Partager sur Twitter

Affichage rapide et non prise en compte du choix

Sujet résolu
    6 novembre 2018 à 17:29:30

    Bonjour,

    Le titre n'est pas très parlant, mais j'essais de faire un menu avec un LCD 16,2 et une matrice de bouton (pour faire un genre de coffre fort).

    Lors de mon premier test j'ai bien le menu qui s'affiche mais dès que je fais un choix l'affichage passe au second menu mais ne me laisse pas le temps de choisir et boucle directement, si je mets un delay plus long il ne prend pas en compte mon choix.

    Voici le code 

    #include <Keypad.h>
    #include <Wire.h> 
    #include <LiquidCrystal_I2C.h>
    #include <Password.h>
    
    //i2c pins
    LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    const byte ROWS = 4; // Four rows
    const byte COLS = 4; // Three columns
    // Define the Keymap
    char keys[ROWS][COLS] = {
      {'A','3','2','1'},
      {'B','6','5','4'},
      {'C','9','8','7'},
      {'D','#','0','*'}
    };
    
    // Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
    byte rowPins[ROWS] = { 9,8,7,6 };
    // Connect keypad COL0, COL1 and COL2 to these Arduino pins.
    byte colPins[COLS] = { 13,12,11,10 }; 
    
    // Create the Keypad
    Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
    char Tab[8];
    int i=0;
    //int Temps = 80;
    int Minute = 0;
    int Seconde = 0; 
    int choix = 0;
    int Temps = 0;
    int Code [3];
    
    
    
    
    void setup()
    {
      Serial.begin(9600);
      lcd.begin(16,2);
      lcd.backlight();
    }
    
    
    
    void loop()
    {
      char key = kpd.getKey();
      lcd.setCursor(0,0);
      lcd.print("1/ Temps 2/ Code");
      lcd.setCursor(3,1);
      lcd.print("3/ DEPART");
      switch (kpd.getState())
      {
        case PRESSED :
          switch (key)
          {
            case '1' :  
             lcd.clear();
             lcd.setCursor(0,0);
             lcd.print("Choix Temps");
             delay(1000);
             lcd.setCursor(0,0);
             lcd.print("1/20 2/30 3/40");
             lcd.setCursor(0,1);
             lcd.print("4/50 5/60");
             switch (kpd.getState())
             {
               case PRESSED :
               switch (key)
               {
                 case '1' :
                 Temps=1200;
                 lcd.clear();
                 lcd.setCursor(0,0);
                 lcd.print(Temps);
                 break;
                 case '2' :
                 Temps=1800;
                 break;
               }
               default  :  break;
             }
               delay(1000);
               lcd.clear();
               break;
             default  :  break;
          }
        default : break;
      }
    }

    Ici dans un premier temps je doit choisir la variable Temps avec plusieurs choix. Mais une fois que 'on choisi l'option Temps cela boucle et revient au menu principal (1/ Temps 2/ Code 3/ DEPART)

    Si quelqu'un a une idée je suis preneur ;-)

    à bientôt et merci

    • Partager sur Facebook
    • Partager sur Twitter
      6 novembre 2018 à 21:46:14

      Bonsoir,

      à la ligne 70, la valeur de la touche est celle lue à la ligne 48

      Il faudrait peut-être relire la touche entre les lignes 69 et 70, non ? 

      • Partager sur Facebook
      • Partager sur Twitter
        7 novembre 2018 à 12:00:20

        Bonjour,

        J'ai mis ce code 

        char key2 = kpd.getKey();

        entre les lignes 48 et 49 et j'ai changé à la ligne 70 key par key2 cela ne fonctionne pas.

        j'ai tenté aussi de mettre 

        char key = kpd.getKey();

        entre les lignes 69 et 70 mais j'ai  une erreur qui apparaît...

        Coffre.ino: In function 'void loop()':
        Coffre:70: error: jump to case label
        Coffre:69: error: crosses initialization of 'char key'
        Coffre:86: error: jump to case label
        Coffre:69: error: crosses initialization of 'char key'
        • Partager sur Facebook
        • Partager sur Twitter
          7 novembre 2018 à 20:26:53

          Bonsoir,

          c'est normal, il ne faut pas redéclarer la variable key.

          En ligne 48, la variable key est déclarée par : char key
          et est affectée par key = xxxx ;

          Pour réutiliser la variable il ne faut pas remettre char devant.

          Par ailleurs si cela ne marche c'est peut-être que la valeur lue ne correspond pas à ce que l'on veut, il serait pertinent d'utiliser l'affichage sur la console pour visualiser la valeur de la variable key 

          -
          Edité par clgbzh 7 novembre 2018 à 20:29:11

          • Partager sur Facebook
          • Partager sur Twitter
            8 novembre 2018 à 11:14:39

            Bonjour,

            J'ai rajouté entre les lignes 52 et 53 le code suivant :

            Serial.print(key);


            entre les lignes 59 et 60 le code suivant :

            Serial.print("Case1");

            et entre les lignes 69 et 70 le code suivant :

            key = kpd.getKey();
            Serial.print(key);

            j'ai pour retour respectif :

            1
            Case1
            2 // si j'appuis sur la touche 2

            mais je n'ai le troisième donc je rentre pas dans le deuxième switch :euh:



            • Partager sur Facebook
            • Partager sur Twitter
              8 novembre 2018 à 15:32:18

              La fonction getKey() n'est pas bloquante, c'est à dire qu'elle n'attend pas le prochain appui sur la touche. Ton code, avant le 2e switch, doit l'appeler en boucle jusqu'à ce que l'utilisateur ait appuyé sur quelque chose ou éventuellement qu'un temps d'attente ait expiré. 

              L'autre façon de faire, pour n'avoir qu'un seul appel à getKey() au début de la fonction loop(), est d'écrire un automate à états finis qui sera plus simple à faire évoluer par la suite.

              • Partager sur Facebook
              • Partager sur Twitter
                8 novembre 2018 à 15:59:36

                alexisdm a écrit:

                La fonction getKey() n'est pas bloquante, c'est à dire qu'elle n'attend pas le prochain appui sur la touche. Ton code, avant le 2e switch, doit l'appeler en boucle jusqu'à ce que l'utilisateur ait appuyé sur quelque chose ou éventuellement qu'un temps d'attente ait expiré. 

                J'ai rajouté un getKey() avant le deuxième switch mais j'ai toujours le même problème.

                Par contre là tu m'as perdu totalement... Tu pourrais m'éclairer un peu s'il te plait ?

                alexisdm a écrit:

                L'autre façon de faire, pour n'avoir qu'un seul appel à getKey() au début de la fonction loop(), est d'écrire un automate à états finis qui sera plus simple à faire évoluer par la suite.



                -
                Edité par --Gwen-- 8 novembre 2018 à 16:00:36

                • Partager sur Facebook
                • Partager sur Twitter
                  15 novembre 2018 à 14:30:53

                  --Gwen-- a écrit:

                  J'ai rajouté un getKey() avant le deuxième switch mais j'ai toujours le même problème.

                  Un seul ne suffit pas. Tu peux faire une boucle, ou remplacer getKey() par waitForKey() qui va appeler getKey() en boucle jusqu'à ce que la fonction renvoie autre chose que NO_KEY (et donc waitForKey() est bloquante sans possibilité de faire faire autre chose à l'arduino sans utiliser les routines d'interruption).

                  De plus, getKey() (donc waitForKey() aussi) teste déjà getState(), donc ce n'est pas la peine d'ajouter ce test dans ton code.

                  Si on garde à peu près la structure de ton code, ça devrait faire quelque chose comme ça:

                  bool mauvaise_touche;
                  
                  void loop()
                  {
                    char key = kpd.getKey();
                    // ... Affichage Menu principal ...    
                    switch (key)
                    {
                      case '1' : 
                      // ... Affichage Menu Temps ...
                      do {
                        key = kbd.getKey();
                        mauvaise_touche = false;    
                        switch (key)
                        {
                        case '1' :
                          // ...    
                          break;
                        case '2' :
                          // ...    
                          break;
                        default  : 
                          // si on arrive ici, la touche appuyée ne correspond
                          // pas aux choix du menu ou aucune touche n'a été appuyée (NO_KEY)
                          mauvaise_touche = true;
                          break;
                        }
                      } while (mauvaise_touche);
                      // ... Affichage du choix ...
                      delay(1000);    
                    }
                  }

                  Il faudrait essayer de ne réafficher le menu principal que quand il y a une raison de le faire, sinon ça peut provoquer un clignotement visible de l'écran, il n'y a rien dans ton code et dans ce que j'ai mis pour empêcher ça.

                  Pour la machine à état, ça consiste à avoir quelques variables qui vont stocker l'état de ton système, comme le menu dans lequel tu te trouves, le temps de démarrage de certaines action et de réagir aux événements pour changer cet état. Par exemple (non testé) :

                  enum Etat {
                    E_Initial,
                    E_MenuPrincipal,
                    E_MenuTemps,
                    E_MenuCode
                  } etat_actuel, etat_precedent, etat_suivant;
                  
                  void setup()
                  {
                    ...
                    etat_actuel = etat_suivant = etat_precedent = E_Initial;
                  }
                  
                  void loop()
                  {
                    key = kbd.getKey();
                    
                    switch(etat_actuel) {
                    case E_Initial:
                      etat_suivant = E_MenuPrincipal;
                      break;
                      
                    case E_MenuPrincipal:
                      if(etat_actuel != etat_precedent) {
                        // on vient d'entrer dans l'etat, donc on affiche le menu
                        afficherMenuPrincipal();
                      }
                      
                      switch(key) {
                      case '1':
                        etat_suivant = E_MenuTemps;
                        break;
                        
                      case '2':
                        etat_suivant = E_MenuCode;
                        break;
                      }
                      
                      break;
                      
                    case E_MenuTemps:
                    
                      // Entree dans le menu Temps
                      if(etat_actuel != etat_precedent) {
                        afficheMenuTemps();
                      }
                      
                      etat_suivant = E_MenuPrincipal;
                      
                      switch(key) {
                      case '1':
                        temps = 1200;
                        break;
                        
                      case '2':
                        temps = 1800;
                        break;
                        
                      default:
                        etat_suivant = E_MenuTemps;
                        break;
                      }
                      
                      // Sortie du menu Temps
                      if(etat_suivant != etat_actuel) {
                        afficheTempsChoisi();
                      }
                      
                      break;
                    }
                    
                    etat_precedent = etat_actuel;
                    etat_actuel = etat_suivant;
                  }
                  

                  On peut factoriser un peu le code dans des classes, si les répétitions s'accumulent (tests de l'entrée et de la sortie d'état), éventuellement faire des sous-états pour remplacer les delay après les affichages par l'utilisation de millis()...

                  • Partager sur Facebook
                  • Partager sur Twitter
                    23 novembre 2018 à 9:18:41

                    Heeeeuuuu merci pour toutes ces informations 0_0 je vais essayé de digérer tout ca et je reviens vers toi ^^
                    • Partager sur Facebook
                    • Partager sur Twitter
                      28 novembre 2018 à 10:21:28

                      Bonjour,

                      Petit retour sur mes tests de ce code :

                      enum Etat {
                        E_Initial,
                        E_MenuPrincipal,
                        E_MenuTemps,
                        E_MenuCode
                      } etat_actuel, etat_precedent, etat_suivant;
                       
                      void setup()
                      {
                        ...
                        etat_actuel = etat_suivant = etat_precedent = E_Initial;
                      }
                       
                      void loop()
                      {
                        key = kbd.getKey();
                         
                        switch(etat_actuel) {
                        case E_Initial:
                          etat_suivant = E_MenuPrincipal;
                          break;
                           
                        case E_MenuPrincipal:
                          if(etat_actuel != etat_precedent) {
                            // on vient d'entrer dans l'etat, donc on affiche le menu
                            afficherMenuPrincipal();
                          }
                           
                          switch(key) {
                          case '1':
                            etat_suivant = E_MenuTemps;
                            break;
                             
                          case '2':
                            etat_suivant = E_MenuCode;
                            break;
                          }
                           
                          break;
                           
                        case E_MenuTemps:
                         
                          // Entree dans le menu Temps
                          if(etat_actuel != etat_precedent) {
                            afficheMenuTemps();
                          }
                           
                          etat_suivant = E_MenuPrincipal;
                           
                          switch(key) {
                          case '1':
                            temps = 1200;
                            break;
                             
                          case '2':
                            temps = 1800;
                            break;
                             
                          default:
                            etat_suivant = E_MenuTemps;
                            break;
                          }
                           
                          // Sortie du menu Temps
                          if(etat_suivant != etat_actuel) {
                            afficheTempsChoisi();
                          }
                           
                          break;
                        }
                         
                        etat_precedent = etat_actuel;
                        etat_actuel = etat_suivant;
                      }

                      Il fonctionne super bien, j'ai bien le temps de faire mes choix et me balader dans les menus.

                      Merci beaucoup à vous pour cette aide.

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Affichage rapide et non prise en compte du choix

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown