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.
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...
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() ?
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
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)
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 ?
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..