Fonction Micros()

Bonjour,

Je viens vers vous pour une précision sur la fonction Micros() d'arduino.

timer0_overflow_count compte le nombre de débordement, qui permettras de retourner la valeur micros

Cependant, cette fonction permet de compter au dessus de 71 minutes si je comprend bien. On pourrait afficher une valeur en microseconde supérieur à 71 minutes ?

Merci,

la valeur de micros est retournée dans un entier signé sur 4 octets. la plus grande valeur représentable est 4294967295 microsecondes (232 - 1).

ça fait un chouia moins que 4295 secondes soit 71 minutes et 35 secondes à peu près. Pour représenter plus grand, il faudrait plus d'octets...

vu la précision de l'horloge, compter plus d'une heure à la microseconde près ça sert à rien, ce sera faux de toutes façons...

Merci de votre réponse rapide,

Merci pour la précision sur la plus grande valeur représentable, néanmoins, je ne comprend plus maintenant à quoi la fonction timer0_overflow_count pourrais servir dans le calcule de la valeur retourner ?

Attention à cause de la configuration choisie par Arduiro pour les microntroleur d'architecture avr (Uno, Mega, Léonardo) le pas de mesure de la fonction micro() est de 4 microsecondes.

Pour les autres microcontroleurs il faut regarder, avec les micro 32 bits le pas est peut-être de 1µs.

pandorfr:
, je ne comprend plus maintenant à quoi la fonction timer0_overflow_count pourrais servir dans le calcule de la valeur retournée ?

N’oubliez pas que Le timer0 est sur 8 bits.

Si vous voulez fabriquer un nombre sur 32 bits il va valoir compter un certain nombre de débordements...c’est ce à quoi sert cette variable qui est décalée de 8 bits puis l’octet de poids faible provient directement du timer et enfin c’est divisé par le bon ratio de cycles d’horloge par microsecondes en fonction du scaler qui est de 64

Cf le code source

compter plus d'une heure à la microseconde près ça sert à rien, ce sera faux de toutes façons...

Je traduis en utilisant millis() au lieu de micros(), ce que j'utilise:

compter plus de 50 jours à la milliseconde près ça sert à rien, ce sera faux de toutes façons...

J'ai aussi ce problème.Il ne s'agit pas forcément de compter pendant 50 jours pour avoir la précision, mais parfois de compter une différence de temps. J'utilise plusieurs métronomes. L'un deux peut être décrit par:

  • tempsFinMétronome est une variable contenant l'heure en millisecondes de fin de la période
  • PERIODE est une constante qui donne la durée (entre 1ms et beaucoup)
  • pour réarmer mon métronome, j'utilise tempsFinMétronome = millis() + PERIODE
  • j'agis quand tempsFinMétronome <= millis()

ce qui donne:

 1: tempsFinMétronomeN°1 = millis() +  PERIODE
 2: tempsFinMétronomeN°2 = millis() +  PERIODE
       ....
 3: début de boucle infinie
 4:     si tempsFinMétronomeN°1 <= millis()
 5:         tempsFinMétronomeN°1 = millis() +  PERIODE
 6:         action déclenchée par le métronome N°1
 7:     si tempsFinMétronomeN°1 <= millis()
 8:         tempsFinMétronomeN°1 = millis() +  PERIODE
 9:         action déclenchée par le métronome N°1
      ....
10:    si problème de corona virus ou autre, sortir de la boucle infernale
11: fin de la boucle infinie

Je ne cherche pas à avoir un compte exact sur une longue période, mais il faut bien que je compte les millisecondes sur mes 50 jours. Même plus, parce qu'il y a un petit bug au bout de 50 jours!

si j'arme mon temporisateur pour 1000ms au bout de 4294967195 ms de fonctionnement, (caleur maxi du compteur 4294967295)

  • tempsFinChronométrage va valoir
    tempsFinChronométrage = millis() + PERIODE = 4294967195 +1000 = 900 (débordement)
    Si ma boucle me prends 2ms, au bout de ces 2ms, comme tempsFinMétronomeN°1 <= millis() (900<4294967197), je déclence encore mon action. Je réarme mon métronome avec millis() + PERIODE soit 902 et je vais déclencher mon action sans arrêt jusqu'à ce que millis() déborde à son tour.

Dans mon application, j'ai le choix de compter le temps à la milliseconde près pendant mes 50 jours et avoir une possibilité de bug au 50ème jour, ou de compter à la milliseconde près pendant 255 fois plus sachant que dans 35 ans mon montage aura cessé de fonctionné ou qu'une panne de secteur aura tout remis à zéro.

Pour l'instant j'envisage effectivement de compter les ms sur 35 ans.

Si je dois refaire un compteur, si je limite les périodes à 100ms mini, je peux compter les dixièmes de secondes pendant 13 ans.

Bonjour,

Il n'y a pas de problème au débordement au bout de 50 jours. Il y a possibilité de mesurer une durée jusqu'à 50 jours.
si tu fais

unsigned long debut;
// ...
unsigned long duree=millis()-debut;

le résultat sera correct même s'il y a eu débordement de millis() du fait qu'on travaille sur des non signés

Même raisonnement pour micros()

il faut toujours procéder par soustraction du top départ avec millis() ou micros() et tant que le délai réel effectif à mesurer ne dépasse pas ce qui est représentable par un uint32_t alors vous serez dans les clous débordement ou pas.if (millis() - topChrono >= delaiAttente) { ... }

Génial, ça passe...

Si j'ai pris le problème dans l'autre sens, c'est parce que cela me permettait de faire une fois pour toutes l'addition, cela ne diminue pas le code, ne change pas la taille des variables...

Mais le test qui est le plus souvent négatif prenait moins de temps.

Merci.

olivier_pecheux:
Si j'ai pris le problème dans l'autre sens, c'est parce que cela me permettait de faire une fois pour toutes l'addition, cela ne diminue pas le code, ne change pas la taille des variables...

oui mais imaginez que vous approchez du moment fatidique du rollover, en faisant une addition vous basculez et retournez vers 0... et le test ne fonctionnera pas comme voulu.

Bonjour,

Merci J-M-L pour ton temps et tes indications.

oui mais imaginez que vous approchez du moment fatidique du rollover, en faisant une addition vous basculez et retournez vers 0... et le test ne fonctionnera pas comme voulu.

Je n'avais pas eu le bug, en plus il n'est pas systématique. Mais j'ai vu le problème. Maintenant j'utilise la soustraction.

J'ai cherché un moment avant de comprendre pourquoi a>b+c ne fonctionne pas mais que a-c>b fonctionne. J'en suis arrivé au fait que quand je faisais a>b+c , cela calcule des instants qui foirent à cause du roll over, mais si je fais a-c>b je compare des intervalles qui sont forcément positif.

C'était pas si évident. Je crois avoir compris. Merci. Cela fait un bug rayé de la liste.

olivier_pecheux:
J'ai cherché un moment avant de comprendre pourquoi a>b+c ne fonctionne pas mais que a-c>b fonctionne. J'en suis arrivé au fait que quand je faisais a>b+c , cela calcule des instants qui foirent à cause du roll over, mais si je fais a-c>b je compare des intervalles qui sont forcément positif.

c'est exactement cela

imaginez que le rollover pour faire simple est à 100 et que vous voulez tester une durée de 10.

si c=91 dans le cas de l'addition vous testez a > (91+10) soit avec le rollover (a > 0) qui sera toujours vrai est donc vous exécutez instantanément le if même si vous n'avez pas attendu les 10ms.

dans le cas de la soustraction, même si a fait un rollover et retourne à 0 puis passe à 1 pour quand vous allez faire le test, (1-91) en entier non signé fera bien 10 et vous déclencherez au bon moment.

--> la magie se passe dans le fait que le calcul se fait en non signé.

Bonsoir

Je reviens pour plus de précision sur le timer0_overflow_count de la fonction micros sous l'architecture Atmel AVR.

"Si vous voulez fabriquer un nombre sur 32 bits il va valoir compter un certain nombre de débordements...c'est ce à quoi sert cette variable qui est décalée de 8 bits puis l'octet de poids faible provient directement du timer et enfin c'est divisé par le bon ratio de cycles d'horloge par microsecondes en fonction du scaler qui est de 64"

Je voulais savoir, on peux connaître le temps même après le débordement, je veux dire, que même s'il s'écoule 71 minutes et que le timer revient à 0, on seras capable de dire qu'il c'est effectué par exemple 90minutes etc... On ne seras pas bloqué définitivement à 71 minutes ? Si oui , c'est le timer0_overflow_count qui permet de faire ca ?

Merci,

Cordialement,

sur 32 bits vous ne pouvez pas compter plus loin que ces ~71 minutes

Si vous lisez micros() de temps en temps et capturez le fait que ça a basculé, vous pouvez incrémenter un autre compteur de 32 bits mais ce n'est pas fait automatiquement.

Mais bon, utiliser micros() pour mesurer des durées qui se compteraient en heures c'est ridicule... utiliser millis() et si vous voulez comptez des jours ou des mois, passez sur une RTC.