Bonjour à tous, je travailles sur un projet d'anémomètre (dans le cadre d'un TIPE), et pour que celui-ci fonctionne correctement, je dois pouvoir obtenir des intervalles de temps inférieurs à 4 microsecondes (limite actuelle imposée par arduino) j'ai réussi à trouver des bibliothèques me permettant d'aller en dessous de cette limite, mais rien de très concluant. Je m'adresse donc à vous pour savoir s'il existe une carte (arduino de préférence) qui permet d'obtenir des intervalles de temps très court (plus petite que 4 microsecondes). Merci d'avance
Bonjour,
Tu es sur que tu dois mesurer des intervalles inférieurs à 4µs?
En général les impulsions d'un anémomètre se mesurent plutôt en ms.
effectivement, les temps mesurés sont plus important, mais il nous faut une meilleure précision qui nécessite un temps inférieur à 4 microsecondes
Peut être faudrait il alors changer de plateforme ?
Tu as besoin d'une précisionjustesse de moins de 0.001%
Même si je ne vois pas comment t'aider, pour mon information personnelle, j'aurais aimé que tu nous en dise plus sur la justesse de ton nanomètre, ainsi qu'un exemple de la justesse et précision que tu souhaites atteindre?
Pour avoir une précision acceptable, il faudrait obtenir une précision d'environ 0.5 m/s. Cependant, les écarts sont plus de l'ordre de 4 m/s résultant d'intervalles de temps d'environ 10 microsecondes. J'aimerai donc savoir s'il est possible de coder quelque chose qui nous ferait descendre en dessous des 4 microsecondes. De plus, les fluctuations de temps d'exécution du code sont gênantes, j'aimerais bien savoir s'il est possible de se libérer de cette contrainte, c'est-à-dire d'avoir un code s'exécutant en un temps t identique a chaque exécution.
Je ne suis pas sure que tu comprennes bien ce que je t'ai indiqué ?
la précision c'est ce que tu affiches, donc la tu indique que tu voudrais des valeurs de 0.5 en 0.5, par exemple 3, 3.5, 4.0.
C'est vraiment cela que tu veux ?
Quand est-il de la justesse, c'est à dire que si c'est ±0.5 lorsque tu affiche la valeur 5, cela veut dire que la valeur est en faite compris entre 4.5 et 5.5.
C'est peut être cela que tu veux ?
Comme tu ne donnes aucune information sur ton matériel, si on se tient à ce que tu rapporte, il faudrait que tu divises ton temps au moins par 10, si ce n'est plus.
De même tu ne donnes aucun code au quel ce référer.
Exactement le même code, mettra le même temps. si tu as des temps différents, c'est que tu passes par des blocs différents.
Lorsque l'on lit ce genre de chose, souvent cela fait pensé au interruption, mais je ne peux pas garantir que ce soit la solution.
Personnellement j'ai quand même l'impression que la solution à tous tes problèmes a été indiqué par @kamill au post #2
Car les mesures que tu indiques me sembles donner 10000tour/s, soit 600000RPM, ca me parait un chouia élevé?
sur le lien suivant, il indique 1 tour par seconde pour 2.4km/h
Je crois qu'il manque un élément de contexte : tu attends quoi d'un tel anémomètre et pour en faire quoi ?
Si le flux d'air dans lequel il est utilisé est turbulent (le vent en extérieur par exemple) ton anémomètre mesurera... ce qu'il veut bien mesurer.
C'est quoi comme technique ? Anémomètre à godets, à hélice ou à fil chaud ?
Comment comptes-tu l'étalonner ?
Oui autant pour moi c'est bel et bien une justesse de 0.5 m/s qu'il faudrait. Par exemple, si l'on se trouve dans une pièce à température ambiante isolée du vent il faudrait que la valeur que l'on lit soit comprise entre 0 et 0.5 m/s.
C'est un anémomètre à ultrasons, une information importante que j'ai en effet oublié de communiquer
lequel ?
un produit comme le Renkeer Ultrasonic Anemometer a une sortie RS485 et mesure de 0 à 40m/s avec une résolution de 0.01 m/s et une précision de ±0.5+2%FS soit environ ±1.3 m/s.
En avez vous un plus précis ?
Je crois qu'il y a méprise nous n'utilisons pas un anémomètre à ultrasons déjà fait, notre TIPE consiste à FAIRE un anémomètre à ultrasons. C'est pour ça que nous essayons de le rendre le plus précis/juste possible dans l'espoir, avec les moyens dont nous disposons, d'effleurer la qualité de ceux présents sur le marché
Donnez nous alors plus de détails sur le montage quels sont les transducteurs ultrasoniques utilisés etc
je suppose que les 4µs dont vous parlez sont la résolution de la fonction micros()
expliquez donc aussi quel code vous utilisez
Comme @J-M-L tel que je vois les choses, comme on ne sait pas le comment du pourquoi.
Si tu es sûre d'avoir besoin d'une résolution inférieur à la microseconde, peut être que le plus simple et de partir sur un µC qui fait ça facilement ?
Je ne me suis jamais penché sur la question, mais je crois qu'il y a ici, des experts des µC qui savent configurer le µC pour descendre en dessous de cette résolutions pour le timer utilisé par micros ou millis(je crois que c'est le même).
Si il ne participe pas à la conversation, je pense que c'est qu'il y a quelque chose qui les choques avec ton besoin
Oui on peut utiliser les timers directement
Le prédiviseur utilisé par défaut sur Timer0 pour la fonction micros()
sur l'Arduino UNO est de 64. Cela signifie que le "tick" se produit toutes les 4 µs
cf le code:
Si on prend Timer1 qui est sur 16 bit et qu'on ne met pas de pré-diviseur, on peut compter à la fréquence de base de l'arduino, soit 16 MHz ➜ cela signifie qu'il peut compter jusqu'à 65 535 en 65 535 cycles d'horloge avant de déborder et chaque pas est 1/16000000 = 62.5 nano seconde
Après quand on s'approche de la fréquence d'horloge, chaque instruction compte (un branchement, une sauvegarde mémoire, un calcul, des test etc que vous faite dans le code vont aussi consommer des cycles. si vous voulez maitrise précisément ce qu'il se passe et pouvoir compter ces cycles "perdus" il faudra sans doute regarder l'assembleur généré ou coder en assembleur.
un exemple :
imaginons que lors du top départ un front montant soit généré sur la pin 2 et lors de la réception un front montant soit généré sur le port 3 d'un arduino type UNO,
Avec ce type de code on reset le timer1 lors de l'interruption sur la pin2 et on note le compte obtenu lors de l'interruption sur la pin 3 (si on dépasse les 65536 ticks, l'interruption affectée au timer1 va aussi augmenter une variable (nbDebordements). J'ai pris un byte ce qui nous permet de mesurer 255 débordements, soit 255*65536 cycles d'horloge - soit un peu plus d'une seconde - ce qui devrait être largement suffisant pour le besoin).
Lors de la réception on lève un drapeau que la loop() va regarder pour imprimer la durée
on déclenche le chrono un peu en retard (le temps d'arriver dans l'ISR soit environ 0.5µs) mais on le lit aussi en décalé donc ces temps se compensent.
const byte brocheDebut = 2;
const byte brocheFin = 3;
volatile uint16_t valeurTimer1 = 0;
volatile uint8_t nbDebordements = 0;
volatile bool finDetectee = false;
void debut() {
TCNT1 = 0; // Mettre le compteur Timer1 à zéro
nbDebordements = 0; // Réinitialiser le nombre de débordements
}
void fin() {
valeurTimer1 = TCNT1; // Lire la valeur du compteur Timer1
finDetectee = true; // Activer le drapeau pour dire qu'on a la mesure
}
ISR(TIMER1_OVF_vect) {
nbDebordements++; // compter le nombre de débordements (le compteur a atteint 65536 et est revenu à 0)
}
void setup() {
noInterrupts();
TCCR1A = 0; // Configurer Timer1 en mode normal, avec aucun prédiviseur
TCCR1B = (1 << CS10); // Activer l'horloge de Timer1 avec aucun prédiviseur
TIMSK1 |= (1 << TOIE1); // Activer l'interruption de débordement de Timer1
attachInterrupt(digitalPinToInterrupt(brocheDebut), debut, RISING); // la pin est en INPUT par défaut
attachInterrupt(digitalPinToInterrupt(brocheFin), fin, RISING); // la pin est en INPUT par défaut
interrupts();
Serial.begin(115200);
Serial.println(F("PRET"));
}
void loop() {
if (finDetectee) {
// section critique
noInterrupts();
uint32_t copieNbDebordements = nbDebordements;
uint32_t copieValeurTimer1 = valeurTimer1;
finDetectee = false; // Réinitialiser le drapeau
interrupts();
uint32_t totalTicks = (copieNbDebordements * 65536UL) + copieValeurTimer1;
uint32_t duree_ns = (totalTicks * 1000000000ULL) / F_CPU;
Serial.print("total Ticks : "); Serial.println(totalTicks);
Serial.print("Durée ns : "); Serial.println(duree_ns);
Serial.flush(); // on attend la fin de l'impression
}
}
comme on fait une impression il ne faut pas qu'une début arrive pendant qu'on imprime (plusieurs interruptions ce n'est pas terrible)
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.