[résolu]Problème pour faire clignoter LED avec millis pendant 10 secondes

Bonjour tout le monde.
Je suis nouveau sur le forum et débutant dans le code.

Je travaille actuellement sur un projet qui permettra entre autre de déclencher un son quand on appuie sur un bouton et qui fera en même temps clignoter un LED pendant toute la durée de diffusion du son (qui dure 10 secondes).

Mon premier objectif est de réussir à faire clignoter la LED pendant une durée définie de 10 secondes après avoir appuyé puis relâché le bouton poussoir. En résumé voici ce que je souhaite faire:

1-j'appuis sur le bouton et je le relâche immédiatement
2-cela déclenche le clignotement de la LED pendant 10 secondes
3-au bout de 10 secondes, la LED devient éteinte
4-si j'appuie de nouveau sur le bouton, la séquence de clignotement recommence etc...

J'y arrive avec la fonction delay en jouant avec un compteur. Mais cela n'est pas très "pro" car le compteur n'est pas en mesure de temps mais en nombre de fois d'exécution de boucle. En tâtonnant j'arrive à avoir à peu près 10 secondes en faisant boucler 5 fois.

//CODE Bouton+LED Blink pendant 5 secondes avec DELAY

int led = 4;  //led branchée en pin 4
int bouton = A3;  //bouton branché en pin A3

void setup() {
  
  pinMode(led, OUTPUT); //broche de la LED configurée en sortie
     pinMode(bouton, INPUT_PULLUP); //broche du bouton configurée en entrée avec activation résistance pullup

}

void loop() {
    if (digitalRead(bouton) == LOW) { //si le bouton est appuyé,
      for (int count = 0; count < 5; count++) { // répète 5 fois le clignotement de la LED
        digitalWrite(led, HIGH); //allume la LED
        delay(1000); //pause de 1 seconde
        digitalWrite(led, LOW); //éteint la LED
        delay(1000); //pause de 1 seconde
      }

    }

}

Mais je souhaite utiliser la fonction millis() en remplacement de la fonction delay() pour éviter de bloquer le code et c'est là que ça se complique.
J'ai l'impression de tout mélanger et je ne sais pas comment gérer les conditions entre elles, à quel moment lire l'état du bouton, comment assembler tout ça...

J'ai fait un essai dans le code ci après mais rien ne marche malheureusement... et je ne omprends pas pourquoi... :confused:

Auriez-vous des pistes à me proposer? Faut-il utiliser millis(), existe t'il un moyen plus simple? La boucle FOR est elle adaptée?
Merci d'avance pour votre aide.

//CODE non fonctionnel Bouton+LED Blink pendant 5 secondes avec MILLIS

int led = 4;  //led branchée en pin 4
int bouton = A3;  //bouton branché en pin A3

int etat_bouton;  //lecture de l'état des boutons 
int etat_led; //stockage de l'état de la led
long temps; // stockage de la mesure du temps

void setup() {
  
  pinMode(led, OUTPUT); //broche de la LED configurée en sortie
     pinMode(bouton, INPUT_PULLUP); //broche du bouton configurée en entrée avec activation résistance pullup
      etat_led = LOW;//état de la LED au départ
}

void loop() {
    if (digitalRead(bouton) == LOW) { //si le bouton est appuyé,
     temps = millis(); //initialisation du temps
       for (int count = 0; count < 5; count++) { // répète 5 fois le clignotement de la LED
        if((millis() - temps) > 1000)
       {
            etat_led = !etat_led; // on inverse l'état de la LED
             digitalWrite(led, etat_led); // on allume ou éteint
              temps = millis(); // on stocke la nouvelle heure

      }

    }

}
}

Avec une boucle for le code sera tout aussi bloquant qu'avec delay().

Il faut mémoriser l'état du bouton dans une variable (globale ou statique) s'il passe à LOW, par exemple donner la valeur true à une variable var.
Ajouter également un compteur de clignotement (global ou statique) .
Éliminer la boucle for.

Si bouton == LOW :
var = true
Si var == true :
faire le traitement avec millis() comme ci-dessus en ajoutant :
incrémenter le compteur à chaque extinction
si compteur == 5 :
var = false
compteur = 0

Tiens, sans avoir testé et vite fait:

void loop() {
	static unsigned long _start_ms = 0;
	static unsigned long _blink_ms = 0;
	static bool _running = false;
	static bool _led_on = true;
	if (digitalRead(bouton) == LOW) { //si le bouton est appuyé,
		running = true; // on memorise qu'on est en "running"
		_start_ms = millis(); // init time
		_blink_ms = millis(); // init time
	}
	
	if (running) { // si on "runnning"
		if (_led_on) {
			digitalWrite(led, HIGH);
		} else {
			digitalWrite(led, LOW);
		}
		if (millis() - _blink_ms > 1000UL) { // pour le clignotement une fois par seconde
			_blink_ms = millis();
			_led_on = !_led_on; // on inverse l'état
		}
		if (_start_ms > 0 && millis() - _start_ms > 1000UL) { // si on running depuis + de 10 seconds
			_start_ms = 0;
			digitalWrite(led, LOW);
		}
	}
}

Evidemment à adapter selon tes besoins.

Merci à vous deux pour vos réponses rapides!
Alors pour l'instant ça ne marche malheureusement toujours pas.

@hbachetti : je te remercie pour tes explications. J'ai bien supprimé la boucle FOR. J'ai essayé de suivre la trame que tu me donnes mais je ne suis pas certain d'arriver à assembler le code correctement. Ca donne quelque chose comme ça et ça ne fonctionne malheureusement pas, rien ne se passe quand j'appuis sur le bouton... mais je dois mal m'y prendre... Peux tu m'éclairer davantage stp?

int led = 4;  //led branchée en pin 4
int bouton = A3;  //bouton branché en pin A3

int etat_bouton;  //lecture de l'état des boutons 
int etat_led; //stockage de l'état de la led
long temps; // stockage de la mesure du temps

static bool valeur_bouton = true; //mémorisation de l'état bouton s'il passe à lOW
int compteur = 0;

void setup() {
  
  pinMode(led, OUTPUT); //broche de la LED configurée en sortie
     pinMode(bouton, INPUT_PULLUP); //broche du bouton configurée en entrée avec activation résistance pullup
      etat_led = LOW;//état de la LED au départ
}

void loop() {
    if (digitalRead(bouton) == LOW) { //si le bouton est appuyé,
      valeur_bouton = true; //on stocke la valeur de l'état du bouton

      if (valeur_bouton == true){
        
      
     temps = millis(); //initialisation du temps
      
        if((millis() - temps) > 1000)
       {
            etat_led = !etat_led; // on inverse l'état de la LED
             digitalWrite(led, etat_led); // on allume ou éteint
              temps = millis(); // on stocke la nouvelle heure
              compteur++; //on incrémente le compteur de +1
              

      }
       if(compteur == 5){
        valeur_bouton = false;
        compteur = 0;
       }

    }

}
}

@Ninnin: Un gros merci aussi pour tes lignes de code. J'ai assemblé tout ça avec le mien mais ça ne marche malheureusement pas complètement : la LED clignote bien une fois le bouton allumé mais elle clignote à l'infini et non pas pendant 10 secondes. J'ai conscience qu'il me manque des notions. Peux-tu me dire ce que j'ai fais de travers?

int led = 4;  //led branchée en pin 4
int bouton = A3;  //bouton branché en pin A3
  static unsigned long _start_ms = 0;
  static unsigned long _blink_ms = 0;
  static bool _running = false;
  static bool _led_on = true;

void setup() {

 pinMode(led, OUTPUT); //broche de la LED configurée en sortie
     pinMode(bouton, INPUT_PULLUP); //broche du bouton configurée en entrée avec activation résistance pullup
}



void loop() {

  if (digitalRead(bouton) == LOW) { //si le bouton est appuyé,
    _running = true; // on memorise qu'on est en "running"
    _start_ms = millis(); // init time
    _blink_ms = millis(); // init time
  }
  
  if (_running) { // si on "runnning"
    if (_led_on) {
      digitalWrite(led, HIGH);
    } else {
      digitalWrite(led, LOW);
    }
    if (millis() - _blink_ms > 1000UL) { // pour le clignotement une fois par seconde
      _blink_ms = millis();
      _led_on = !_led_on; // on inverse l'état
    }
    if (_start_ms > 0 && millis() - _start_ms > 1000UL) { // si on running depuis + de 10 seconds
      _start_ms = 0;
      digitalWrite(led, LOW);
    }
  }
}

Bonjour,

Essaies comme ceci:

const byte led = 4;  //led branchée en pin 4
const byte bouton = A3;  //bouton branché en pin A3

const unsigned long blinkDuration = 10000;
const unsigned long blinkPeriod = 500;

void setup() {
  pinMode(led, OUTPUT); //broche de la LED configurée en sortie
  pinMode(bouton, INPUT_PULLUP); //broche du bouton configurée en entrée avec activation résistance pullup
}

void loop() {
  static unsigned long startms = 0;
  static unsigned long blinkms = 0;

  if (digitalRead(bouton) == LOW) { //si le bouton est appuyé,
    startms = millis(); // init time
  }

  if (startms && millis() - startms <= blinkDuration)
  {
    if (millis() - blinkms >= blinkPeriod)
    {
      digitalWrite(led, !digitalRead(led)); // inverse état led
      blinkms = millis();
    }
  }
  else
  {
    startms = 0;
    digitalWrite(led, LOW);
  }
}

@kamill: Eh bien ça marche parfaitement comme attendu!!! Un énorme merci pour ta réponse rapide et pour ton code très clair! Je comprends mieux la structure désormais.

Merci à tous pour votre contribution!

J'étais bien loin de savoir répondre seul à ma problématique... Je vais donc éplucher vos conseils pour compléter mon apprentissage et poursuivre ce projet en espérant aussi prochainement être capable de filer un coup de main sur le forum ;)

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