Probleme bouton on/off et lancement programme

Bonjour, je débute en arduino et j'ai réalisé déjà quelques montages basics mais la je bloque sur l'utilisation de mon bouton, je vous mets en upload mon schéma via tinkercad.

En gros, l'idée pour le moment et que lorsque j'appuie sur le bouton, le buzzer sonne avec une modulation de 4000 à 4500 et les led clignotent à 500 ms. Puis pour arrêter ce programme, il suffit de rappuyer sur le bouton.
Les parties buzzer et led fonctionnent parfaitement sur la board sans le bouton, mais dès que je rajoute ce dernier, j'allume avec le bouton, le programme se lance mais impossible de l'arrêter. J'ai utilisé une instruction boolean pour réaliser le codage mais je coince quelques parts et impossible d'identifier où.
J'ai tester le boolean avec juste une led, un tuto trouvé sur ce site, il fonctionne au top, mais impossible de le faire fonctionner avec mon buzzer et mon code précédent...

Est-ce que quelqu'un pourrait m'aider à comprendre où je coince?

merci à vous !

mon code:

boolean buttonWasUp = true;
boolean ledEnabled = false;

int led=12;

void setup()
{
  pinMode(led, OUTPUT); // variable de sortie
  pinMode(4, OUTPUT); // variable du buzzer
  pinMode(2, INPUT_PULLUP);
 
}

void loop() {

   boolean buttonIsUp = digitalRead(2);
   if (buttonWasUp && !buttonIsUp) {
      delay(10);
    buttonIsUp = digitalRead(2);
      if (!buttonIsUp) {
         ledEnabled = !ledEnabled;
         digitalWrite(led, HIGH);
         tone(4,4500); //variable activation buzzer
         delay(500); 
         digitalWrite(led, LOW);
         tone(4,4000); //variable activation buzzer
         delay(500); 
      }
   }
   buttonWasUp = buttonIsUp;
  }

buttonWasUp = buttonIsUp; permet de mémoriser le nouvel état. Le programme fait environ:

Si j'ai un changement
          Si j'ai appuyé
                    je sonne et j'allume
          Je mémorise le nouvel état.

Malheureusement le " Je mémorise le nouvel état" ne se trouve pas dans la boucle "Si j'ai un changement". Ce qui est fait est:

Si j'ai un changement
          Si j'ai appuyé
                    je sonne et j'allume
Je mémorise le nouvel état.

Du coup, pour enter dans la boucle, il faut appuyer pendant le retour de loop (entre la fin de loop et le début ce qui est vraiment aléatoire. Il suffit de remonterbuttonWasUp = buttonIsUp; d'une ligne (à vérifier, je n'ai pas fait le test).

En passant par un simulateur qui va plus lentement, on a plus de chance de tomber dans le court instant du retour.

Et pour arrêter le buzzer, il faut placer un noTone() quelque part.
Ou indiquer une durée dans tone().

Merci pour vos réponses, je vais tester la monter de la ligne.

Pour fdufnews, justement le but est que tout le programme se stop quand on re-appui sur le bouton.

Rebonjour messieurs, je viens de tester en remontant la ligne, rien n'y fait.
Le soucis reste identique, mais demain je vais essayer sur la board, pour voir si c'est pas le simulateur qui déconne.
Je vous tiens au courant, mais si vous avez une autre idée pour faire fonctionner mon bouton je prends :wink:

Si buttonWasUp est faux, la condition est fausse quelle que soit buttonIsUp. Une fois
buttonWasUp mis à faux, le programme coince.
Ce que tu voulais exprimer c'est "si le bouton est différent de la mémorisation" ce qui se traduit par
if (buttonWasUp == !buttonIsUp) {
ou
if (buttonWasUp != buttonIsUp) {

J'ai essayé les deux modifications et rien n'y fait, le programme tourne en boucle, cependant dès que je rappuis sur le bouton, le programme semble recommencer à zero, les leds reclignotent une fois et le buzzer sonne encore.

Si je mets en direct sans programmation le bouton, par exemple, l'appui du bouton physique actionnerait l'alimentation de l'arduino et par conséquent signerait le début du programme. Est-ce possible pour m'éviter la programmation de ce dernier?

Bien sûr. Mais redonnes le programme modifié, il y a forcément une erreur quelque part qui n'a pas été vue. Il n'y avait pas d'ambiguïté dans le cahier des charges, c'est faisable. Retrouver l'erreur en apprend plus que de l'ignorer.
Je rentre des moi aujourd'hui ou demain, je devrai pouvoir faire des essais.

Bonjour yohann31

Ton programme a 2 états bien bien séparés:
Bouton pressé et pas encore pressé (!buttonWasUp).
et
Bouton pressé et déjà pressé précédemment (buttonWasUp).

Cet état doit être mise à jour lors du test concerné, dans ton programme, il est mis à jour en permanence en fin de loop().

ta variable boolean buttonIsUp n'est pas utile, tu peux faire directement:
if (!buttonWasUp && !digitalRead(bouton))
De ce fait, au départ, boolean buttonWasUp = false;, ce qui est plus logique :wink:

de même que
delay(10);
les rebonds éventuels sont "couverts" par les divers delay() qui suivent.

Prends l'habitude de nommer toutes les broches utilisées, ça rend la lecture plus facile.

const int led=12;
const int bouton=2;
const int buzzer=4;

Pour débugger ton programme, utilises des Serial.println pour afficher son déroulement.

Voilà ton programme "restructuré"

boolean buttonWasUp = false;
boolean ledEnabled = false;

const int led=12;
const int bouton=2;
const int buzzer=4;

void setup()
{
	Serial.begin(115200);
	
	pinMode(led, OUTPUT); // variable de sortie
	pinMode(buzzer, OUTPUT); // variable du buzzer
	pinMode(bouton, INPUT_PULLUP);
	
}

void loop() 
{

	if (!buttonWasUp && !digitalRead(bouton))     // Si bouton pas encore été pressé et maintenant pressé
	{
		Serial.println("buttonWasUp && bouton presse  Buzzer ON");
		
		ledEnabled = !ledEnabled;
		digitalWrite(led, HIGH);
		tone(4,4500); //variable activation buzzer
		delay(500);
		digitalWrite(led, LOW);
		tone(4,4000); //variable activation buzzer
		delay(500);
		buttonWasUp = true;     // Enregistrement de l'état
	}

	if (buttonWasUp && !digitalRead(bouton))     // Si bouton ae été pressé et maintenant pressé
	{
		Serial.println("buttonWasUp && bouton represse  Buzzer OFF");

		noTone(buzzer);
		while(!digitalRead(bouton)) {}     // Tant que le bouton est pressé

		buttonWasUp = false;     // Enregistrement de l'état
	}
}

Cordialement
jpbbricole

Merci à toi!!

Le programme semble fonctionner correctement sur le simulateur je le teste demain sur la board ! merci aussi pour vos explications à tous! je comprends mes erreurs mais je vais encore avoir besoin de pratique pour vraiment bien les corriger à l'avenir :wink: encore merci à tous !

Bonjour à tous,

J'ai reproduit le schéma sur la board et appliqué le code, le démarrage se fait bien, mais je comprends pas pourquoi les leds et le buzzer ne fonctionne pas en continue.

En gros, voici comment le circuit se comporte :
-j'appuie sur le bouton, démarrage du programme,

  • les leds s'allument puis s'éteignent de suite.
  • le buzzer s'allument en même temps, tape dans les 4500 ton et retombe en 4000 et il y reste tant que je n'appuis pas sur le bouton.

J'aimerais que la boucle led+buzzer s'active en continu, que les leds clignotent à la vitesse demandée (avec le delay) et que le buzzer face de même, en variant de 4500 à 4000 ton. On dirait que la boucle du programme ne s'active qu'une fois, et qu'ensuite seul le buzzer reste actif.

De temps à autres, si je rappui sur le bouton pendant le loop, le circuit semble redémarrer de zero, et il faut que j'attends quelques secondes pour vraiment éteindre le programme avec le bouton.

J'ai essayé de modifier le code en "forçant la boucle" avec la fonction while mais il doit y avoir quelques choses de plus simple non?

Si jamais vous avez une idée :smiley:

Merci d'avance !

Si c'est le code juste au-dessus, c'est normal.
Lors de l'appui sur le bouton le programme fait

  • allumage des LEDs
  • tonalité 4500Hz
  • attente 500 ms
  • extinction des LEDs
  • tonalité 4000Hz
  • attente 500 ms
    et c'est tout. Après ça le son à 4000Hz continue

Sur un appui du bouton le programme coupe le son


Il faut dissocier l'appui et le fonctionnement des Leds et du buzzer.
Dans loop() il faut faire:

  • L'appui sur le bouton doit changer l'état d'une variable, appelons-la ACTION (à chaque appui on bascule de TRUE à FALSE et inversement)
  • Si ACTION == TRUE
    • on allume les LEDs
    • on émet un son à 4500Hz dans le buzzer
    • on attend 500ms
    • on éteint les LEDs
    • on émet un son à 4000Hz dans le buzzer
    • on attend 500ms
  • Si ACTION == FALSE
    • on éteint les LEDs
    • on coupe le buzzer

Merci pour ta réponse,

Je comprends l'idée, il faut séparer les différentes actions, mais est-ce le programme va se répéter à l'infini si ACTION == TRUE ?

loop() se répète à l'infini. Tant que la variable ACTION est vrai le programme exécute les actions décrites dans le test.
Le seul inconvénient de ce programme simple c'est qu'il faut tenir le bouton pendant une seconde pour qu'il soit pris en compte.
On peut faire un code plus réactif en ne gérant pas l'attente dans le if et en utilisant millis() mais c'est au prix d'un code un peu plus complexe.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.