Remise à zéro de la fonction millis()

Bonjour messieurs,

J'avais une question concernant la fonction millis().

En effet, pour un projet de sciences de l'ingénieur en Terminale S, je programme actuellement un arduino qui fera office d'anémomètre, avec une girouette (avec un potentiomètre, je ferais donc une mesure analogique), et un ILS (l'arduino comptera les impulsions de l'ILS pour calculer la vitesse du vent).

Concernant la mesure de vitesse, autrement dit le comptage des impulsions, j'utilise la fonction millis, et pour mesurer les impulsions sur 10 secondes (par exemple) j'affecte la valeur de millis à une variable, puis j'utilise une fonction while qui compte tant que la différence entre millis() et ma variable est inférieure à 10 000.

Jusque là, je maitrise, cependant, concernant la remise à zéro de la fonction millis(), j'ai vu sur le site francophone arduino qu'une fois la capacité de la variable (unsigned long) dépassée, la variable revient à zéro, ce qui a lieu au bout d'environ 50 jours.
Le problème, c'est qu'en suivant ce raisonnement, si la fonction millis()revient à zéro en plein milieu de ma mesure (en admettant que j'ai fait tourner le programme pendant 50 jours), ma fonction while fera donc la mesure pendant 50 jours du coup, en attendant que la valeur de millis() revienne à la valeur de la variable à laquelle elle est comparée.

J'aimerais savoir si par hasard il était possible de remettre à zéro la fonction millis() en cours de programme (alors qu'au début elle se lance avec le programme), afin de proposer une solution qui soit automatisée sur le long terme, sans avoir besoin de redémarrer le programme tous les 49 jours pour ne pas avoir de problèmes.

Je joins le code de mon programme, mais il n'est pas très commenté, voilà pourquoi j'ai expliqué précédemment sa fonction.

Je vous remercie de votre patience, et vous souhaite une bonne journée.

const int entree_impulsion = 2;  //on initialise le pin de mesure des impulsions
int etat_ILS = 0;  //on mesurera l'état du contacteur
int last_etat_ILS = 0;  //pour garder en mémoire l'ancien état du contacteur
unsigned int compteur = 0;
float vitesse_vent = 0;
unsigned long chrono = 0;


void setup()
{
  pinMode(entree_impulsion, INPUT); //on met le pin entree impulsion en lecture
  
  Serial.begin(9600); //initialiser la communication serie
}

void loop()
{
  
  compteur = 0; //on réinitialise le compteur
  chrono = millis(); //on affecte millis() à notre variable chrono
  Serial.println(compteur); //affichage d'un 0 pour signaler le début de la mesure sur le moniteur série
 
  while (millis() - chrono < 10000) //mesurer 10 secondes
  {
    etat_ILS = digitalRead(entree_impulsion); //lecture de l'état de l'ILS
  
    if (etat_ILS != last_etat_ILS) //en cas de changement de l'état de l'ILS
    {
      compteur++; // on incrémente le compteur
      last_etat_ILS = etat_ILS;
    }
  }
      
  vitesse_vent = compteur / 20; //calcul du nombre de tour par seconde de l'hélice
  vitesse_vent = vitesse_vent * 3.87; //coefficient pour calculer la vitesse en km/h
    
  Serial.println(vitesse_vent); //affichage de la vitesse
  
  delay(5000); //pause entre les mesures
  
}

D'abord, tu édites ton message et tu mets ton code entre les balise code (le bouton #)...

Ensuite, tu rajoute une condition if() qui contrôle que millis() est plus petit que Chrono... si c'est le cas, mets Chrono à "0" ce qui te permet de sortir de ton while.

Il n'est pas souhaitable de remettre à zero la fonction millis().
D'autres librairies pourrais s'en servir et cela les perturberait.
Il vaut mieux apprendre à s'en servir correctement.

Le compteur utilisé par millis() est un unsigned long (entier non signé 32 bits).
Il suffit de mémoriser les valeurs de temps dans une variable du même type.
Ainsi les différences seront aussi effectuées sur 32 bits.

Contrairement aux maths où les nombres sont infinis, en informatique les nombres sont limités par la résolution.
Ainsi un entier non signé de 8 bit permet de compter de 0 à 255 et donc 255+1 = 0

Raisonnons sur 8 bits pour simplifier :

uint8_t t1, t2, diff; // prenons des entiers 8 bits non signés en considérant pour simplifié que millis() retourne ce type
t1 = millis();   // retourne par exemple 202
fonction_truc_qui_bouffe_du_temps();
t2 = millis();   // retourne pas exemple 4 (par ce que le compteur a rebouclé)
diff = t2 - t1;
Serial.print( diff );

Commbien de temps s'est-il écoulé ?
4 - 202 = ..... = 58

Car -198 n'existe pas en uint8_t.

Pour comprendre il faut revenir à la représentation binaire :

    4 :   0000 0100
- 202:   1100 1010
=          0011 1010 = 58

Une autre façon de le voir c'est comme une piste de course circulaire :
Tu as de balises : 0, 1, 2, 3 .... 254, 255 et tu revient à 0
La distance entre 2 coureurs est toujours Posution2 - Position1 Modulo 256

C'est le modulo qui est important

Donc appliqué à millis() avec des unsigned long, ca marche tout seul, la différence de 2 dates te retournera toujours le temps écoulé entre les 2 dates même s'il y a eu un rebouclage du compteur.

A+

Désolé Jean-François, je pensais avoir mis mon code entre les balises, ce n'était pas le cas, je n'avais pas cliqué au bon endroit (veuillez m'excuser, c'est mon premier post).

Merci beaucoup à Barbudor pour tes explications, j'ai compris tout de suite :slight_smile:
Je vais donc pouvoir utiliser la fonction millis() sans avoir de problèmes :smiley:

Encore merci à vous deux, et passez une bonne soirée :slight_smile:

Pas de soucis, bonne continuation sur le forum :wink:

Merci Barbudor pour ces précisions.

[HS]
(Re)voir apparaitre Barbudor et JF sur le forum , qui plus est sur le même topic, ça... c'est "agréable" :grin:

Faut pas utiliser la fonction millis !
Un ILS c'est pas terrible en plus à cause des rebonds !
Tu mobilise l'essentiel du programme à compter des impulsions qui arrivent toutes les xx millisecondes.

Il est beaucoup plus simple de relier la sortie de l'anémomètre à une entrée d'interruption avec une routine d'interruption qui se contente d'incrémenter une variable.

Dans le programme principal, on teste la variable. C'est là qu'interviendront les millis .

La vitesse et la direction du vent fluctuent dans des proportions importantes .

Pour avoir des valeurs significatives, il faut faire des moyennes sur une période de temps assez importante.
Tout dépend de ce qu'on veut en faire mais moyenner sur une minute est assez raisonnable.

C'est là qu'il faudra aussi utiliser les millis .

Au bout de cinquante jours, il y aura une mesure fausse mais c'est pas gràve.

Artouste:
[HS]
(Re)voir apparaitre Barbudor et JF sur le forum , qui plus est sur le même topic, ça... c'est "agréable" :grin:

ça c'est gentil.... un peu débordé ces temps-ci :grin:

Jean-François:

Artouste:
[HS]
(Re)voir apparaitre Barbudor et JF sur le forum , qui plus est sur le même topic, ça... c'est "agréable" :grin:

ça c'est gentil.... un peu débordé ces temps-ci :grin:

Pareil :slight_smile:

barbudor:

Jean-François:

Artouste:
[HS]
(Re)voir apparaitre Barbudor et JF sur le forum , qui plus est sur le même topic, ça... c'est "agréable" :grin:

ça c'est gentil.... un peu débordé ces temps-ci :grin:

Pareil :slight_smile:

je sais bien que périodiquement pour tous d'abord et les uns et les autres ensuite :grin: les journées de 24h sont insuffisantes, mais il n’empêche qu'il ne faut pas bouder ce qui est agréable. 8)
Bon courage à vous tous

Je boude pas :grin:

Et je fais plusieurs incursions sur le forum tous les jours... XD