Programmer une action dans le futur avec millis()

Bonjour,
J'ai le problème suivant.

Préambule :

  • Je connais les avantages de la fonction millis() par rapport à la fonction delay(). Je ne peux pas utiliser delay() car j'ai des données arrivant sur le port série à surveiller et traiter.
  • Pour ne pas être tributaire du bug qui peut arriver au 50ieme jour, au rebouclage du compteur millis(), j'ai compris l'idée de procéder avec une différence, pour ne pas être affecté par le problème lors du rebouclage du compteur.
  • Je n'utilise pas la fonction millis() directement, mais plutot une fonction dérivée du type millis() + une_constante_proche_du_rebouclage, afin de provoquer le rebouclage dès le début de l'exécution de mon programme, afin de pouvoir débugger ce qui se passe.

Mon problème :
Je veux, suite par exemple à l'appui sur un bouton, provoquer une action qui devra avoir lieu dans le futur, 100 secondes après l'appui. Et je veux que cette action ne soit pas affectée par le problème du rebouclage de millis().

C'est là que j'ai un peu de mal.
J'ai testé des solutions qui :
-déclenche l'action intempestivement lors du rebouclage.
-ne déclenche pas l'action au bout de 100 secondes s'il y a eu un rebouclage dans l'interval.

J'ai un peu de mal avec ça.
Quelqu'un peut il me mettre sur la bonne voie.

D'avance merci

Bonjour,

Je ne comprends pas trop ton problème. Tu as donné toi même la solution en utilisant une différence

void loop() {
 static unsigned long debut;

 if (..) // test appui bouton
   debut=millis();         // mémorise le temps de l'appui

 if (millis()-debut>100000UL)
 {
   // faire l'action qui va bien
 }
}

Merci de ta réponse.

Problème 1 :
Sans aucun appui sur le bouton, la condition millis()-debut>100000UL va devenir vraie.
Donc cela va déclencher l'action sans appui sur le bouton.

Problème 2 :
Si on appuie sur le bouton juste avant le bouclage, millis()-debut>100000UL va devenir vraie dès l'instant où le compteur va boucler.

C'est sur ce type de problèmes que je bute.

Problème 1: C'était juste une trame. C'est bien sur à toi de compléter le programme et de gérer un flag.

Problème 2: Non, ça ne va pas devenir vrai. C'est justement pour ça qu'on fait la différence.

Pour tester ce qu'il va se passer au roll over de millis(), point n'est besoin d'attendre 50 jours, sinon ça fait des phases de test un peu longues :smiling_imp:

Il suffit de remplacer partout dans le code les appels à millis() par des appels à ma_millis(), avec

uint32_t ma_millis()
{
  return millis() - 60000UL; //roll over 60 secondes après démarrage
}

Variante :

#include "simpleBouton.h"
#include "simpleMinuteur.h"

const uint8_t pin_bouton = 5;

simpleMinuteur minuteur;
simpleBouton bouton(pin_bouton);

bool action_engagee = false;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  bouton.actualiser();
  if (bouton.vientDEtreEnfonce())
  {
    action_engagee = true;
    minuteur.demarrer(10000);
  }

  if (action_engagee && minuteur.estTermine())
  {
    Serial.println("Action !");
    action_engagee = false;
  }
}

bonjour,

une autre solution consisterait à comparer debut à millis(),
si debut > millis() alors, c’est que ça a bouclé,
le temps écoulé est alors de
4 294 967 295 - debut + millis()

ça reste valable tant qu’on ne fait pas plusieurs fois le tour du compteur.

Bonjour,

C'est vrai pourquoi faire simple quand on peut faire compliqué.

if (millis()-debut>100000UL)

ne pose aucun problème en cas de rebouclement.

à la lecture de vos posts, je crois que j'ai été un peu léger dans mes tests, dans mon interprétation des problèmes que j'ai rencontrés, et dans le temps que j'ai passé à essayer de mettre ça au point.

Ca à l'air finalement d'être plutôt basic, je vais mettre ça en œuvre !

Merci à tous !

oui, ce n'est pas immédiat à la première lecture, mais comme la différence de deux nombres non signés est non signée donc toujours positive, ça permet de gérer correctement le débordement.