Retarder l'execution de la boucle loop() par un nombre d'appui sur poussoir

Bonjour à tous,

Pour l'un de mes projets je vais être amené à retarder l’exécution de tout ou partie de ma boucle loop() de plusieurs minutes.

Le but est d'alimenter l'arduino, d'appuyer X fois sur un bouton poussoir dans une durée fixée (ou de valider à l'aide d'un second bouton ou d'un appui long) et d'appliquer un délai à l'exécution de la boucle équivalent à N minutes * X appuis sur le bouton.

Pour l’exécution du programme "utile" je pense utiliser un while avec une fonction de comparaison simple qui dit que tant qu'une variable n'est pas à 1 , on n'éxecute pas le contenu du while.
La variable en question serait alors placée à 1 dès que le délai souhaité serait atteint.

Là où je sèche vraiment, c'est sur la partie gestion du (des) bouton(s) qui permettent de déterminer le délai souhaité.

Il est important que ce délai puisse atteindre plusieurs dizaines de minutes donc je pense pour cela utiliser la fonction "millis()" qui indique une valeur de débordement autour de 49-50 jours....

Si parmi vous, certains ont des exemples de sketch pour le fonctionnement d'une gestion d'un bouton avec comptage PUIS lancement de la suite de la boucle loop() je suis preneur.

Merci :slight_smile:

Pour ton problème, tu dois simplement compter le nombre d'appuis sur le bouton puis faire un (ou plusieurs) delay : mais ceci doit être fait dans le setup, avant de lancer la loop.

Pour compter les appuis, le plus simple est d'utiliser une bibliothèque de gestion des boutons poussoirs, comme bounce2, mais il y en a d'autres...

Pour simplifier votre gestion des boutons, éventuellement utilisez la librairie de @bricoleau. il a des exemples

lesept:
Pour ton problème, tu dois simplement compter le nombre d'appuis sur le bouton puis faire un (ou plusieurs) delay : mais ceci doit être fait dans le setup, avant de lancer la loop.

Pour compter les appuis, le plus simple est d'utiliser une bibliothèque de gestion des boutons poussoirs, comme bounce2, mais il y en a d'autres...

Merci de cette réponse rapide.

L'idée de gérer un compteur dans le setup() avant de passer à la boucle loop() me plaît beaucoup, mais c'est justement ce que je ne sais pas faire.

Comment procéder pour rester dans le setup() pendant une durée donnée (me laissant le temps d'appuyer X fois sur le poussoir), ou tant que l'on n'a pas validé l'opération, avant de passer à la boucle loop() ?

Merci.

un

while (cestPasEncoreLeMoment) {
....
}

A la fin du setup, mettre:

uint32_t debut=millis();
while (millis() - debut < dureeDonneeEnMs) {
// gèrer les appuis sur les boutons
if (valid) return; // gère la validation
}

(non testé)

Merci à tous les deux !

Je ne pensais pas qu'on pouvait utiliser while dans le setup, c'est finalement simple....

Je reviendrai vers vous selon mes avancements.

Bonne journée :slight_smile:

le programme généré par l'IDE - en simplifiant "un peu" - fait ceci:

int main(void)
{
  init();
  setup();
  for (;;) {loop();}
  return 0;
}

donc setup() et loop() ne sont que deux fonctions standard qui n'ont rien de particulier, vous pouvez coder dedans ce que vous voulez

Tu veux simplement faire une boucle de lecture du bouton tant que une durée n'est pas écoulée ou qu'un nombre maximum d'appuis sur le bouton n'est pas compté

Pour mesurer une durée, tu crées une variable

unsigned long chrono = 0;

tu l'initialises pour lancer le chrono

chrono = millis();

et tu compares avec la durée choisi pour voir si elle est dépassée :

while (millis() - chrono < duree) ...

Pense à définir duree comme un unsigned long aussi : par exemple

#define duree 60000ul

Damned, grillé !

Merci pour les ajouts.

Je pense que j'ai des bonnes bases/approches pour commencer le projet :slight_smile:

Avec votre aide et un tuto sur la gestion des interruptions, j'ai déjà un bout de code qui fonctionne en simulation :

int boutonPin  = 2 ;
int compteur = 0 ;
#define duree 5000ul
#define pas 1000ul

//  Pour qu'on puisse changer la valeur d'une variable depuis une fonction de
// gestion d'interruption, il faut que la variable soit déclaré "volatile"
volatile boolean changed = false;

void doContact() {
  changed = true;
  compteur++;
}



void setup()
{
	// Broche en entrée avec résistance de pull-up
	pinMode(boutonPin, INPUT_PULLUP);
  
	//fonction ISR, detection de flanc déscendant (5v vers 0v)
	attachInterrupt(0, doContact, FALLING);
  
	
	Serial.begin(9600);
	pinMode(13, OUTPUT);
	uint32_t debut=millis();
  
	while (millis() - debut < duree) {
		digitalWrite(13, HIGH);
      	if ( changed ) {
    		changed = false;
    		Serial.print("bouton touché ");
    		Serial.print(compteur);
    		Serial.println(" fois");
    	}

	}
  	digitalWrite(13, LOW);
  	unsigned long wait=compteur*pas;
    Serial.print("Fin du setup, attente de ");
  	Serial.println(wait);
    Serial.println("milisecondes");
  	delay(wait);
  	Serial.println("Poursuite vers loop");
  	
}

void loop()
{
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  Serial.print("compteur=");
  Serial.println(compteur);
  delay(1000);
}

Avez-vous un avis sur la gestion du délai à préférer entre :

  • Gestion du "delay" comme fait actuellement en fin du setup()
    ou
  • Mise en place d'une boucle while en début de loop, similaire à celle du setup(), qui vérifie si le chrono actuel a atteint la durée "wait" souhaitée, avant de laisser le reste du loop() s'exécuter

La deuxième solution nécessitera l'évaluation de la condition du while à chaque itération de la boucle, mais je ne sais pas si c'est réellement gênant/consommateur de ressources)

Un conseil ?

Merci

Il faut déclarer 'compteur' en volatile aussi.
je pense qu'il vaut mieux en rester à une gestion dans le setup, il est fait pour ça. Ta loop sera plus propre...

lesept:
Il faut déclarer 'compteur' en volatile aussi.
je pense qu'il vaut mieux en rester à une gestion dans le setup, il est fait pour ça. Ta loop sera plus propre...

Peux-tu m'éclairer sur la nécessite de déclarer le compteur en volatile ?

Quel est le risque à ne pas le faire ?

zebu14:
Peux-tu m'éclairer sur la nécessite de déclarer le compteur en volatile ?
Quel est le risque à ne pas le faire ?

vous ne voulez pas lire une copie cachée dans un registre qui ne changerait pas...

idéalement il faudrait le dupliquer dans la loop() dans une section critique car un int tient sur 2 octets, un des deux peut changer pendant que vous jouez avec à cause de l'interruption..