Problème de mesure de temps

Bonjour, je suis en train actuellement de réaliser une station météo mais je rencontre un petit problème avec la mesure de temps séparant deux impulsions de mon anémomètre qui peut être éviter mais ne comprenant pas d'ou il vient je pose la question ici :slight_smile:

J'utilise la fonction micro et l'interruption de la pin D2 en front montant

De manière aléatoire le temps minimum mesuré à une valeur totalement incohérente sachant que j'ai réalisé un debounce du vecteur d'interruption de la pin D2 à l'aide du timer 2 qui me génère lui même une interruption ou bout d' 1ms afin de réactiver l'interruption du port D2 et 1 ms en us ça fait 1000 mais j'arrive à avoir des valeur inférieur à la centaine!

voila le code

test_interrupt_timer_counter_micro.ino (2.03 KB)

unsigned long last_mesure = 0;
unsigned long old_mesure =0;

unsigned long time_mesure =0;
unsigned long time_min =0xFFFFFFFF;
unsigned long time_average =0;
unsigned long time_old = 0;

float frequency_mesure =0;
float frequency_max = 0;
float time_mesure_float = 0;

// the setup routine runs once when you press reset:
void setup() {
 Serial.begin(9600); // initialize serial communication at 9600 bits per second
 
 attachInterrupt(digitalPinToInterrupt(2), mesure_micros, RISING); //ext interrupt n°0(pin2)enable and attach to "mesure_micros"

 cli(); // Disable global interrupt
 TCCR2A = 0b00000010;
 TCCR2B = 0b00000111; // Clock / 1024 soit 64 micro-s et WGM22 = 0
 TIMSK2 = 0b00000000; // local interrupt disable by OCIE2A
 OCR2A = 16;  // set compar interrupt to 16x64us = 1ms
 sei(); // Enable global interrupt
}

void mesure_micros() {
 detachInterrupt(digitalPinToInterrupt(2)); //disable ext intrrupt n°0 pin2
 TIMSK2 = 0b00000010; // enable timer 2 interrupt for debounce interrupt pin2
 last_mesure = micros(); 
 time_mesure = last_mesure - old_mesure;
 if (time_mesure < time_min) {
   time_min = time_mesure;
 }
 if (time_old > 0){
 time_average = (time_mesure + time_old) /2;
 }
 old_mesure = last_mesure;
 time_old = time_mesure;
}

ISR(TIMER2_COMPA_vect) {
 TIMSK2 = 0b00000000; // local interrupt disable by OCIE2A
 attachInterrupt(digitalPinToInterrupt(2), mesure_micros, RISING); //ext interrupt n°0(pin2)enable and attach to "mesure_micros"
}


// the loop routine runs over and over again forever:
void loop() {
 if (time_mesure > 0)
 {
   //time_mesure_float = time_mesure;
   //frequency_mesure = 1000000/time_mesure_float;
   //time_mesure_float = time_min;
   //frequency_max = 1000000/time_mesure_float;
 }
 else
 {
   frequency_mesure = 0;
 }
 Serial.print (time_mesure);
 Serial.print ("/"); 
 Serial.println(time_min);
 
 time_old = 0; 
 time_min = 0xFFFFFFFF;
 
 delay(3000);        // delay in between reads for stability
}

Faut utiliser des volatile pour vos variables

Votre double interruption avec le timer c’est vraiment l’arme lourde... pour éviter le rebond testez juste dans l’ISR si millis() ou micros() est suffisamment plus tard que la dernière interruption ou mettez un Condo

Les maths sur unsigned long devraient être effectués avec une copie des variables de l’ISR obtenue en bloquant les interruptions le temps de la copie

=====
lisez comment utiliser le forum (les posts épinglés en haut du forum comme « Bien éditer son post pour les nuls » , « Faire un Nouveau Sujet ou le corriger avec les Balises... » et « Règles du forum francophone »), et faites un post « propre »

corrigez votre post ci dessus et rajoutez les code tags autour du code:
[code]`` [color=blue]// votre code ici[/color] ``[/code].

ça doit ressembler à cela:// votre code ici
(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l’IDE avant de copier le code pour qu’il soit indenté correctement)

C'est bien le cas où pour éviter l'effet des rebonds la solution 100% matérielle est préférable.
Un simple condensateur de 100nF céramique connecté en parallèle sur le contact et c'est fini.
L'anti rebond est totalement indépendant de la programmation, plus de prise de tête.

Le condensateur est déjà installé mais ce n est jamais assez fiable il faut toujours limité la mesure de n'importe quelle grandeur d ailleurs au niveaux logiciel.

Je vais essayer la manip de ne pas faire d interruption lors de mon calcul

Je vais aussi essayer de concaténer la fonction micro en 16 bits ne manipuler que des int

Pourquoi cela est vraiment important de mettre volatil arduino n est pas dérivé du c/cpp?

Merci d'avoir corrigé ton message :wink:

Pour un anti-rebond efficace, il vaut mieux un circuit RC :


Tiré de : boutons-sans-rebond-bascules-de-schmitt

A toi de dimensionner la constante de temps en fonction de tes rebonds.

Pourquoi cela est vraiment important de mettre volatil arduino n est pas dérivé du c/cpp?

Non, Arduino est du C / C++. :grin:
volatil te garantit que dans une boucle par exemple, le code recharge la valeur de la variable à chaque fois qu'elle est utilisée, au lieu de la stocker dans un registre. comme elle est modifiée par une interruption, elle peut changer de valeur au sein d'une boucle.
Dans ton cas, cela ne devrait pas être utile, mais c'est une bonne habitude à prendre.

Merci pour le filtre passe du 1er ordre mais déjà fait;)

Je persiste un anti rebond matériel ne suffit pas!

blue_note:
Merci pour le filtre passe du 1er ordre mais déjà fait;)
Je persiste un anti rebond matériel ne suffit pas!

hum c'est très surprenant ou alors mal dimensionné...

Si ce n'est avec des topologie plus complexe mais autant ce servir du uc.

Sauf si le code d'anti-rebond est buggé. Un circuit RC est sans bug.
Ou alors l'anémomètre est moisi.

C est bien pour ça que je tente de le débugger :slight_smile:

Je persiste un anti rebond matériel ne suffit pas!

C'est bien la première fois que je vois ça !
C'est que tu ne sais pas l'utiliser.

L'anti rebond logiciel ne consiste qu'à cacher la poussière sous le tapis --> il bloque le programme jusqu'à ce qu'il n'y ait plus de rebond détectés. Tu n'es pas à l'abri d'une non détection de rebond et plus le contact est pourri plus le programme est bloqué longtemps.
Alors qu'avec l'anti rebond matériel il suffit de calibrer le couple R C en fonction du contact et l'information toujours disponible immédiatement.

Mais bon puisque tu es sur de toi continue à t'embêter avec l'anti rebond logiciel.

Mais bon puisque tu es sur de toi continue à t'embêter avec l'anti rebond logiciel.

Surtout avec un anti-rebond logiciel dans une interruption !

Il faut déjà tester ta gestion de timer seule pour voir si elle marche vraiment.

J'ai déjà fait ça pour une librairie de boutons. J'ai aussi utilisé le timer2 comme anti-rebond.
J'utilisais cette librairie : Arduino Playground - MsTimer2

68tjs:
C'est bien la première fois que je vois ça !
C'est que tu ne sais pas l'utiliser.

L'anti rebond logiciel ne consiste qu'à cacher la poussière sous le tapis --> il bloque le programme jusqu'à ce qu'il n'y ait plus de rebond détectés. Tu n'es pas à l'abri d'une non détection de rebond et plus le contact est pourri plus le programme est bloqué longtemps.
Alors qu'avec l'anti rebond matériel il suffit de calibrer le couple R C en fonction du contact et l'information toujours disponible immédiatement.

Mais bon puisque tu es sur de toi continue à t'embêter avec l'anti rebond logiciel.

Il ne bloqué pas le programme puisque le timer permet justement de désactiver l interruption pendant 1ms

@68tjs

effectivement le debounce du pauvre :grinning: delay(15); bloque le programme. Mais correctement fait (c'est à dire avec une machine à état qui ignore les rebonds pendant un certains temps) alors ça mange du temps CPU mais ça ne bloque pas le programme

toujours la vieille discussion des softeux versus les hardeux :slight_smile: mais je n’ai pas vu une solution hard proprement dimensionnée ne pas amortir les rebonds

Il ne bloqué pas le programme puisque le timer permet justement de désactiver l interruption pendant 1ms

Comment peut-il fonctionner en faisant autrement que d'attendre que les rebonds cessent ?
Si ce n'est pas un blocage strict comme la fonction delay() c'est quand même un blocage car pour utiliser l'information du bouton il faut attendre que la lame cesse de rebondir.

Le principe matériel fonctionne sur deux constantes de temps :
A l'appui sur le bouton : Constante de temps de décharge du condensateur proche de 0s -> résistance de décharge > 1ohm
Au rebond : Constante de temps à la charge suffisamment grande (Résistance de charge >= 10 k) pour que le signal sur l'entrée numérique ne puisse pas dépasser le niveau du seuil de commutation.
Conclusion : la lame peut rebondir sans problème l'information est disponible dès l'appui.

Je pense que tu n'as pas bien digéré tes lectures où que tu as consulté des sites d'auto-proclamés experts qui "causent bien" mais qui en savent moins que toi.

@J-M-L
Que notre poseur de question veuille faire un anti-rebond logiciel ne me dérange pas, c'est son droit.
Ce qui me dérange c'est qu'il le fasse dans une interruption et qu'il s'étonne d'avoir des problèmes, c'est donner des bâtons pour se faire battre, et surtout ce qui me dérange c'est les affirmations fausses.

Bonjour 68tjs,

Je ne voudrai pas relancer la guerre filtrage hard/filtrage soft (tiens suis-je en train de le faire ? ;D), mais dans le cas d'un filtrage soft l'info est disponible dès l'appui.
if (digitalRead(button)==HIGH)
{
// Traitement immédiat ici sans aucune attente
delay(20);
}

Si on ne veut pas attendre qq ms, on peut utiliser millis().

Bonjour blue_note,

Je vois trois problèmes dans ton filtrage des interruptions.

1-Même si tu dévalides l'interruption, lorsque l'interruption apparaît elle est latchée. Il faudrait donc acquitter l'interruption avant de la réautoriser.
2-Il peut y avoir des rebonds à l'ouverture des contacts, il faut donc interdire les interruptions aussi en cas d'ouverture, donc faire une routine d'interruption sur CHANGE.
3-La méthode que tu utilises me parait assez compliquée (quoique fonctionnelle), il suffit d'utiliser micros() lors de l'interruption et faire un retour immédiat si le temps depuis l'interruption précédente est inférieur à 1000µs.

Merci de ta réponse kamill, je pensais qu il n y avais pas besoin de baisser le flag d interruption que la librairie d arduino le gerai?