Je travaille actuellement sur un projet de mesure de vitesse d'un objet se déplaçant dans un tube avec un Arduino UNO.
Pour réaliser cette mesure, je dispose de 2 barrières lumineuses (raccordées aux entrées numériques de l'Arduino), se référer au schéma en annexe .
J'ai réalisé mon premier code Arduino, en me basant sur la fonction micros() afin de mesurer le temps entre les 2 impulsions des barrières lumineuses (je dois être le plus précis possible, donc j'évite la fonction millis).
Connaissant la distance entre ces 2, je pourrai calculer la vitesse de l'objet.
Par contre, lorsque j'affiche la valeur du temps entre les 2 impulsions (delais dans mon programme, j'obtiens toujours la même valeur (16us ou 12us) malgré que je passe mon doigt à des vitesses très différentes).
J'en déduis qu'il y a un problème avec la fonction micros, avez-vous une idée d'où cela peut-il venir ?
Merci d'avance pour votre aide !
Mon code :
/*------------------------------------------------Declaration des variables-----------------------------------------------------------*/
int dureeON = 1000; // 1ms
unsigned long time1 = 0;
unsigned long time2 = 0;
const int Broche_Barriere_Lumineuse_1 = 9;
const int Broche_Barriere_Lumineuse_2 = 8;
const int Broche_trigger = 13;
/*------------------------------------------------Fonction appelee au demarrage de l'Arduino------------------------------------------*/
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(Broche_Barriere_Lumineuse_1, INPUT);
pinMode(Broche_Barriere_Lumineuse_2, INPUT);
pinMode(Broche_trigger, OUTPUT);
}
/*------------------------------------------------Boucle de fonctionnement de l'Arduino-----------------------------------------------*/
void loop() {
// put your main code here, to run repeatedly:
// Lit l'état du bouton
byte Etat_Barriere_Lumineuse_1 = digitalRead(Broche_Barriere_Lumineuse_1);
byte Etat_Barriere_Lumineuse_2 = digitalRead(Broche_Barriere_Lumineuse_2);
if (Etat_Barriere_Lumineuse_1 == HIGH)
{
time1 = micros();
}
else
{
if (Etat_Barriere_Lumineuse_2 == HIGH && (time1>0))
{
time2 = micros();
long delais = time2-time1;
delay(delais);
OutputON();
Serial.print("dt=");
Serial.print(delais);
Serial.println("us");
time1=0;
time2=0;
}
}
}
/*------------------------------------------------Déclaration fonction activation trigger-----------------------------------------------*/
void OutputON()
{
digitalWrite(Broche_trigger,HIGH);
delay(dureeON);
digitalWrite(Broche_trigger,LOW);
}
Tout d'abord il n'y a aucun problème avec la fonction micros()
Pour mesurer la vitesse comme tu veux le faire il faut mesurer le temps entre les deux fronts des signaux et non entre deux étant.
Donc il faut que tu mesures le temps entre le passage de 0 à 1 de la première barrière et le temps de passage de 0 à 1 de la deuxième barrière.
Rider1991:
... J'ai réalisé mon premier code Arduino, en me basant sur la fonction micros() afin de mesurer le temps entre les 2 impulsions des barrières lumineuses (je dois être le plus précis possible, donc j'évite la fonction millis). ...
Attention : ne pas confondre précision et résolution. Les fonctions millis() et micros() présentent la même précision puisque basées sur la même horloge. Par contre, la fonction micros() à une résolution mille fois supérieure à la fonction millis().
Maintenant, il est évident que si l'intervalle de temps que vous voulez mesurer fait intervenir des fractions de millisecondes, il faut utiliser la fonction micros(), qui vous permettra de mieux quantifier votre valeur.
Le timer qui sert à la mesure du temps est le timer 0.
Ce timer est configuré par Arduino en fonction de divers paramètres réagissant sur l'homogénéité de l'environnement.
La fonction arduino : init(), qui n’apparaît pas dans le fichier ino mais qui y est incluse par l'IDE avant la compilation et se lance en début de programme, règle le diviseur d'horloge_timer 0 à 64 --> 16MHZ/64 = 250 kHz soit une période de 4µs --> tu as l'explication de ce que tu constate.
Tu peux modifier les réglages des timers pour avoir un pas de mesure plus petit.
Attention si le timer 0 est modifié les fonctions delay(), millis(), micro(), PWM sur D5 et D6 auront un comportement différent.
Le mieux est d'utiliser un autre timer comme le timer 2 --> on lit la valeur de son compteur --> registre TCNT2
Remarque : la fréquence de la PWM sur les sorties D3 et D11 sera modifiée.
Avec un diviseur d'horloge de 1, le pas de mesure du timer est d'un cycle horloge soit 62,5 ns (avec un quartz de 16 MHz).
Il suffit après de lire le registre du compteur du timer (TCNTx).
Les diviseurs disponibles sur le timer 2 sont :1, 8, 64.
Avec un diviseur = 8 tu aurais un pas de mesure de 0,5µs et 62,5ns avec un diviseur par 1
Les fonctions arduino sont réductrices et n'exploitent pas la totalité des possibilités du microcontrôleur.
Pour aller plus loin la meilleure solution est la lecture de la datasheet du micro, celle qui est écrite par Atmel et a télécharger uniquement à partir du site d'Atmel si tu ne veux pas avoir une ancienne version.
Voici comment je fais :
uint8_t lecture ; // le timer 2 est un timer 8 bits, pour lire son compteur je déclare une variable sur 1 octet
TCCR2B = 0b00000001; // écriture dans le registre TTCR2B pour fixer le diviseur de l'horloge du timer par 1
TCNT2 = 0; // je force le compteur du timer à prendre la valeur 0 --> pour faire plus simple
{action qui est à mesurer}
lecture = TCNT2 ;
{ ton traitement de lecture}