Arrêt dans Void loop ()

Bonjour/Bonsoir !

Dans un projet Arduino, un buzzer doit sonner plusieurs fois mais dois, à chaque fois, être arrêté par un bouton poussoir :

tone(Beeper, 880);
  
if (press(Bouton1))
{
  noTone(Beeper);
}

press() est une fonction de type booléen qui renvoie TRUE lorsque le bouton est appuyé. Elle a été testée séparément.
[/tt]
Lorsque l’instruction tone(Beeper, 880) est placée dans le Setup, comme ici, tout marche à merveille :

void setup()
{
  autresInstructions;
  tone(Beeper, 880);
} 

void loop()
{
    if (press(Bouton1))
     {
        noTone(Beeper);
     }
}

Seulement, pour que le buzzer puisse sonner plusieurs fois (ce n’est pas la seule action du projet, bien sûr, je dois donc le faire sonner dans void loop), cela ne marche pas… :

void loop()
{
     tone(Beeper, 880);
  
if (press(Bouton1))
{
  noTone(Beeper);
}
  delay(100000);
}

Pensant que la boucle va trop vite pour que l’arrêt soit perceptible par l’humain, j’ai rajouté un delay(100000) qui devrait normalement faire une pause avant de rentrer à nouveau dans la boucle. Une idée ?

Voici aussi, à titre informatif, une partie de mon vrai code pour comprendre l’enjeu :

void loop()
{

  for (int i=0; i<10; i++)
  {
    tone(Beeper, 880);
    int t = millis();
    
    while ([i]buzzerOn[/i])
    {
      if (press(Bouton1)&&!press(Bouton2))
      {
        VainqueurManche = 1;
        noTone(Beeper);
        buzzerOn = false;                
      }
      if (press(Bouton2)&&!press(Bouton1))
      {
        VainqueurManche = 2;
        noTone(Beeper);
        buzzerOn = false;                        
      }
      if (press(Bouton1)&&press(Bouton2))
      {
        VainqueurManche = 12;
        noTone(Beeper);
        buzzerOn = false;                
      }
    }

buzzerOn est une variable booléenne qui permet de savoir si le buzzer est en train d’émettre un son. Merci à Kamill qui m’a aidé sur ce forum !

Je précise que je ne suis qu’un débutant avec Arduino…

Merci d’avance et bonne soirée :slight_smile:

ce post va partir à la benne si vous ne l'édité pas avec des balises

J4l13n:
ce post va partir à la benne si vous ne l'édité pas avec des balises

Je ne sais pas si j'ai bien compris ce qu'il fallait faire, j'ai modifié mon message. Merci !

corrigez votre post ci dessus et rajoutez les code tags autour du code:
[code]`` [color=blue]// votre code ici[/color] ``[/code].

ça doit ressembler à cela:// votre code ici
(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l’IDE avant de copier le code pour qu’il soit indenté correctement)

lisez comment utiliser le forum (les posts épinglés en haut du forum comme “Bien éditer son post pour les nuls” , “Faire un Nouveau Sujet ou le corriger avec les Balises…” et “Règles du forum francophone”), et faites un post “propre”

Merci beaucoup et excusez-moi pour le désagrément. Dois-je recréer un nouveau sujet ou rester sur celui-là ?

Jules09:
press() est une fonction de type booléen qui renvoie TRUE lorsque le bouton est appuyé. Elle a été testée séparément.

Ca ne prouve rien, tu ne dis pas comment tu l'as testée, et ça ne montre pas que la conception de cette fonction pour cette application est correcte. On ne sait pas ce que fait la fonction tant que le bouton n'est pas appuyé.
Tu devrais poster son code.

Par ailleurs, quelques Serial.print() par-ci- par-là t'aideraient à comprendre ce qui se passe.

Oui, postez tout le code

Et on n’arrête généralement pas la loop avec un long délai parce que une fois dedans vous ne testez plus ce qu’il se passe sur votre bouton, on s’arrange jute pour que la loop tourne « à vide »

void loop()
{
  if (boucleToujoursActive) {
    // la boucle à des choses á faire
  } else {
    // on ne fait rien (éventuellement tester quand même une action qui redéclenche la loop sinon vous êtes coincé là jusqu’au reset du module)
  }
}

Bonjour et merci pour vos réponses.

Voici le code de la fonction press() :

 bool press(int Bouton) //Renvoie vrai si le bouton passé en paramètre est pressé. OK.
{
  bool BoutonPressed = digitalRead(Bouton);
  if (BoutonPressed == 1)
  {
    return(0);
  } else 

  {
    return(1);
  }
}

Mes boutons ont été déclarés ainsi :

  pinMode(Bouton1, INPUT_PULLUP);
  pinMode(Bouton2, INPUT_PULLUP);

Bonjour,
Comment traites-tu les rebonds mécaniques des boutons poussoirs ?

Je ne les utilise pas en tant qu'interrupteur, la fonction press() renvoie true si le bouton est "maintenu appuyé" et false dès qu'il est relâché.

Jules09:
Je ne les utilise pas en tant qu'interrupteur, la fonction press() renvoie true si le bouton est "maintenu appuyé" et false dès qu'il est relâché.

vous avez lu ce qu'est un rebond ?

Sinon évitez les mélanges sémantiques de type, certes ça marche avec 1 et 0 derrière, mais c'est moche. mais ne prenez pas cette habitude.

  • digitalRead retourne HIGH ou LOW, sémantiquement une tension
  • un booléen c'est true ou false, sémantiquement une valeur de vérité
  • un int c'est des entiers, sémantiquement un nombre pour faire des calculs entiers

votre fonction (telle que, sans gestion du rebond) s'écrirait alors simplement

bool press(int Bouton) //Renvoie vrai si le bouton passé en paramètre est pressé. OK.
{
  return(digitalRead(Bouton) == HIGH); // ou LOW si INPUT_PULLUP
}

J-M-L:
vous avez lu ce qu'est un rebond ?

J'avais mal compris, désolé. Je programme et teste avec Tinkercad, je ne sais pas s'il faut rajouter un condensateur, ce n'est qu'une simulation. Mais je pense que mon problème est plutôt informatique plutôt qu'électronique... je ne suis pas expert, corrigez-moi si je raconte des bêtises :smiley:

je ne sais pas si les boutons tinkerCad rebondissent - mais voilà un exemple où quelqu'un a mis un condo pour être tranquille

dans la vraie vie quand vous appuyez ou relâchez un bouton à contact mécanique, pendant quelques millisecondes (jusqu'à une quinzaine de ms en pratique avec les boutons que l'on trouve couramment) vous avez une oscillation entre HIGH et LOW. votre arduino va avoir le temps de boucler des centaines voire des milliers de fois en quinze millisecondes et donc va voir tous ces HIGH et LOW.

si vos boutons sont en INPUT_PULLUP ils doivent être câblés d'un côté vers la pin et de l'autre vers GND et ils seront LOW quand ils seront appuyés, pas HIGH

J-M-L:
vous avez lu ce qu’est un rebond ?

Sinon évitez les mélanges sémantiques de type, certes ça marche avec 1 et 0 derrière, mais c’est moche. mais ne prenez pas cette habitude.

  • digitalRead retourne HIGH ou LOW, sémantiquement une tension
  • un booléen c’est true ou false, sémantiquement une valeur de vérité
  • un int c’est des entiers, sémantiquement un nombre pour faire des calculs entiers

votre fonction (telle que, sans gestion du rebond) s’écrirait alors simplement

bool press(int Bouton) //Renvoie vrai si le bouton passé en paramètre est pressé. OK.

{
 return(digitalRead(Bouton) == HIGH); // ou LOW si INPUT_PULLUP
}

Je ne sais pas pourquoi lorsque je remplace ma fonction par la vôtre, Arduino cesse d’émettre un son.

Voici mon code original (avec ma fonction), et où tout fonctionne :

#include <LiquidCrystal.h>
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


int Beeper = 1;
int Led = 6;
int Bouton1 = 10;
int Bouton2 = 9;



bool press(int Bouton) //Renvoie vrai si le bouton passé en paramètre est pressé. OK.
{
  bool BoutonPressed = digitalRead(Bouton);
  if (BoutonPressed == 1)
  {
    return(0);
  } else 

  {
    return(1);
  }
}


void setup()
{
  //Serial.begin(9600);
  pinMode(Beeper, OUTPUT);
  pinMode(Bouton1, INPUT_PULLUP);
  pinMode(Bouton2, INPUT_PULLUP);
  pinMode(Led, OUTPUT);
  tone(Beeper, 440);
}



void loop()
{

  if (press(Bouton1))
  {
    noTone(Beeper);
  }
}

et voici celui où votre fonction remplace la mienne, mais où même le buzzer ne fonctionne plus :

#include <LiquidCrystal.h>
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


int Beeper = 1;
int Led = 6;
int Bouton1 = 10;
int Bouton2 = 9;



bool press(int Bouton) //Renvoie vrai si le bouton passé en paramètre est pressé. OK.
{
  return(digitalRead(Bouton) == HIGH);
}

void setup()
{
  //Serial.begin(9600);
  pinMode(Beeper, OUTPUT);
  pinMode(Bouton1, INPUT_PULLUP);
  pinMode(Bouton2, INPUT_PULLUP);
  pinMode(Led, OUTPUT);
  tone(Beeper, 440);
}



void loop()
{

  if (press(Bouton1))
  {
    noTone(Beeper);
  }
}

Bonjour,

Dans le commentaire il est indiqué

// ou LOW si INPUT_PULLUP

Il faut remplacer HIGH par LOW puisque tu utilises INPUT_PULLUP

Jules09:
Je ne sais pas pourquoi lorsque je remplace ma fonction par la vôtre, Arduino cesse d'émettre un son.

oui vous êtes en PULLUP donc LOW quand on est appuyé; écrivez la fonction comme

bool press(int Bouton) //Renvoie vrai si le bouton passé en paramètre est pressé. OK.
{
  return(digitalRead(Bouton) == LOW); // ou HIGH si pas INPUT_PULLUP
}

kamill:
Bonjour,

Dans le commentaire il est indiqué

// ou LOW si INPUT_PULLUP

Il faut remplacer HIGH par LOW puisque tu utilises INPUT_PULLUP

Oups. Petite étourderie. Merci à toi ! Merci J-M-L, effectivement avec votre fonction c'est plus intuitif.

Concernant mon problème initial (lancer et arrêter le son plusieurs fois) vous avez une idée pour comment faire ?

qu’est-ce qui lance le buzzer ?

De base c'était la fonction tone() dans le void loop pour pouvoir le refaire plusieurs fois. J'ai remarqué cependant que ça ne marche que s'il est lancé dans le Setup.

ben si vous l'arrêtez il faut bien que quelqu'un le relance...

Si vous voulez que ça beep en permanence sauf si vous appuyez sur le bouton, il suffit d'interrompre le buzzer quand le bouton est appuyé et réactiver le buzzer quand vous relâchez

void loop()
{
  if (press(Bouton1))
    noTone(Beeper);
  else
    tone(Beeper, 880);
}

au passage notez que la fonction press() serait mieux nommée comme isPressed()