Go Down

Topic: Fonction Micros() (Read 275 times) previous topic - next topic

pandorfr

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,

J-M-L

#1
Mar 24, 2020, 07:11 pm Last Edit: Mar 24, 2020, 07:12 pm by J-M-L
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...
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

pandorfr

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 ?

68tjs

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.

J-M-L

, 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

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

olivier_pecheux

Quote
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:

Quote
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:

Code: [Select]
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.

kamill

#6
Mar 25, 2020, 10:20 am Last Edit: Mar 25, 2020, 10:21 am by kamill
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
Code: [Select]
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()

J-M-L

#7
Mar 25, 2020, 11:13 am Last Edit: Mar 25, 2020, 11:13 am by J-M-L
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.
Code: [Select]
if (millis() - topChrono >= delaiAttente) { ... }
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

olivier_pecheux

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.

J-M-L

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.
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

pandorfr

Bonjour,

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

olivier_pecheux

Quote
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.

J-M-L

#12
Mar 26, 2020, 07:55 pm Last Edit: Mar 26, 2020, 07:56 pm by J-M-L
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é.

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Go Up