Problème de débutant: gestion de boutons

Bonjour à tous,

Je butte sur un petit soucis tout con dans un de mes montages.

J'utilise deux boutons pour incrémenter ou décrémenter une valeur. Mon soucis se situe au niveau de la gestion de la modification de la valeur.
La valeur se modifie en continue quand je pousse le bouton, hors j'ai besoin qu'elle ne bouge que d'une unité par appuie.

J'utilise deux boutons avec des ponts diviseurs sur une entrée analogique. Je n'ai pas de soucis du coté de l'acquisition, l'anti-rebond fonctionne bien.

Voici la partie du code qui concerne mon soucis:

   int tmpButtonState = LOW;
   buttonValue = analogRead(buttonPin);
   if(buttonValue>BUTTON2LOW && buttonValue<BUTTON2HIGH){
     tmpButtonState = BUTTON2;
   }else if(buttonValue>BUTTON1LOW && buttonValue<BUTTON1HIGH){
     tmpButtonState = BUTTON1;

   if (tmpButtonState != lastButtonState) {
     lastDebounceTime = millis();
   } 


   if ((millis() - lastDebounceTime) > debounceDelay) {
     buttonState = tmpButtonState;
   }
   lastButtonState = tmpButtonState;

switch(buttonState){
     case BUTTON1:
     if(LedLevel !=0){
         LedLevel--;
       }
     break;
     case BUTTON2:
       if (LedLevel < 6){
         LedLevel++;
       }
     break;
   }

Mon but est de faire varier LedLevel d'une unité dans un sens ou dans l'autre à chaque appuie sur un des deux boutons, dans un interval de 0 à 6.

C'est pour m’entraîner à gérer des boutons pour plus tard manipuler des menus.

La valeur se modifie en continue quand je pousse le bouton

Parce que tu parcours la boucle de ton programme plusieurs fois tant que le bouton est maintenu.
Il faut tester le relâcher du bouton juste après le switch/case comme ça tu ne boucleras que si le bouton est revenu au repos.

Oui, j'ai bien compris que le problème vient de la.

Mais je ne sais pas comment gérer cet aspect dans mon code.

Tu peux fair eun delay() + while :

delay(20); // permet au signal de se stabiliser sans compromettre la réactivité
while(digitalRead(Bouton,HIGH); //tant que le bouton est appuyé, le programme reste la
delay(20); // permet au signal de se stabiliser sans compromettre la réactivité

Pas con, mais ca bloque tout le programme.

Dans mon cas actuel c'est du test c'est pas génant, mais si je dois faire un menu sur une plateforme qui gère des E/S ca risque de poser soucis.

Il y a forcement un moyen de gérer les boutons tout en laissant le programme boucler.

Salut,

Il y a forcement un moyen de gérer les boutons tout en laissant le programme boucler.

En utilisant les interruptions XD

La librairie qu'il te faut est ici: Arduino Playground - HomePage
Ca élimine les rebonds ("debounce") et ça permet de détecter les fronts pour n'avoir qu'un seul déclenchement.

Edit: elle ne fonctionnera pas avec une entrée analogique je pense.
Il faut donc que tu mémorises l'état précédent de chaque bouton, et que tu ne déclenches tes actions que quand l'état précédent est 0 et que l'état courant est 1 (une détection de front montant, en somme).

A la fin de loop() tu n'oublies par de mettre à jour tes variables stockant l'état précédent des boutons avec l'état courant, pour être prêt pour l'itération suivante.

Dans mon cas actuel c'est du test c'est pas génant, mais si je dois faire un menu sur une plateforme qui gère des E/S ca risque de poser soucis.

Si tu ne veux pas bloquer, tu lèves un drapeau lorsqu'une touche est reconnue.

A chaque lecture de l'état des boutons tu regardes si une touche est appuyée ou non.
si elle est appuyée et que le drapeau est baissé tu exécutes ton code normalement
si elle est appuyée et que le drapeau est levé tu passes
si elle relâchée tu effaces le drapeau
Quelque part cela revient à ajouter un second "else" dans le" if" qui suit l'analogRead au début de ton code.

patg_:
La librairie qu'il te faut est ici: Arduino Playground - HomePage
Ca élimine les rebonds ("debounce") et ça permet de détecter les fronts pour n'avoir qu'un seul déclenchement.

Edit: elle ne fonctionnera pas avec une entrée analogique je pense.
Il faut donc que tu mémorises l'état précédent de chaque bouton, et que tu ne déclenches tes actions que quand l'état précédent est 0 et que l'état courant est 1 (une détection de front montant, en somme).

A la fin de loop() tu n'oublies par de mettre à jour tes variables stockant l'état précédent des boutons avec l'état courant, pour être prêt pour l'itération suivante.

Parfait, c'etait la bonne solution. Merci :smiley:

C'est vraiment tout con, j'aurais du y penser !

Coucou revoilà l'analogicien de service :grin:

Tu as tout à fait le droit de compliquer ton programme en ajoutant des lignes de codes qui permettent de patienter en attendant que les rebonds s'arrêtent.

Mais tu as aussi parfaitement le droit d'éliminer les effets des rebonds à l'endroit même où ils sont créés.
Il suffit simplement de placer un condensateur en parrallele sur le contact, une valeur de 100 nF convient dans quasiment tout les cas.
Et hop plus de pollution dans le code. :grin:

68tjs:
Coucou revoilà l'analogicien de service :grin:

Tu as tout à fait le droit de compliquer ton programme en ajoutant des lignes de codes qui permettent de patienter en attendant que les rebonds s'arrêtent.

Mais tu as aussi parfaitement le droit d'éliminer les effets des rebonds à l'endroit même où ils sont créés.
Il suffit simplement de placer un condensateur en parrallele sur le contact, une valeur de 100 nF convient dans quasiment tout les cas.
Et hop plus de pollution dans le code. :grin:

C'est ce que je ferais surement dans le proto final surtout que je bosse en analogique pour l'entrée des boutons (pour n'avoir qu'une entrée pour tous les boutons), mais pour le moment sur la breadboard c'est plus facile en soft qu'en hard :wink: