Go Down

Topic: Vitesse et capteur Hall (Read 1 time) previous topic - next topic

landid

J'ai suivi un peu de loin la discussion sur le calcul de la vitesse par rapport au temps. Par contre n'ayant pas d'expérience dans les capteurs a effet hall j'ai navigué un peu sur le web pour comprendre.

 J'ai trouvé un code sur ce post qui me semble bien plus simple et qu'il serait sûrement intéressant de tester et/ou d'adapter. Le calcul de la vitesse est réalisée dans le programme d'interruption et il utilise une astuce intéressante avec millis() sans doute reproductible avec micros(). Il reprend pas mal l'aspect de celui précédent de Kamill

Voilà si cela peux rendre service:
Code: [Select]
//
// Débutant: Tachymètre à sonde effet Hall
// http://forum.arduino.cc/index.php?topic=78333.0
//
volatile unsigned long time = 0; // time en ms depuis le démarrage de l'arduino
volatile unsigned long rpm = 0; // vitesse en tr/min

void setup() { // Fonction éxécuté au démarage de l'arduino
 Serial.begin(9600); // Configuration du port série en 9600bauds
 pinMode(2, INPUT); // Broche D2 en entrée
 attachInterrupt(0, int_cb, FALLING); // Configuration de l'interruption INT0(D2) pour pointer sur la fonction int_cb en cas de front descendant
}

void loop() { // Fonction éxécuté en boucle jusqu'a l'arret de l'arduino
 Serial.println(rpm); // Affiche la vitesse de rotation
 delay(1000); // Attend une seconde
}

void int_cb() { // Fonction appelé lors d'un front descendant (HIGH -> LOW) sur la broche D2 (INT0)
 rpm = (millis() - time) / 60000; // Calcul de la vitesse par rapport au temps précédant
 time = millis(); // Astuce: millis() est "freezé" lors du interruption, sa valeur ne s'incrémentera pas, inutile de crée une variable pour stocker le nouveau temps
}
Si le seul outil que vous avez est un marteau, vous verrez tout problème comme un clou.
      Abraham Maslow

kamill

Bonjour landid,

C'est un programme très (trop ?) simplifié que tu as trouvé.
Il fonctionne sans doute pour des vitesses faibles (mais peut être que ça suffit à notre ami Walex68)

Il y a quand même plusieurs inconvénients
- calcul en ms
- calcul en entier -> la résolution peut être insuffisante à haute vitesse
- pas de synchronisation entre le programme loop et le programme d'interruption. La valeur à peut avoir été rafraichie 10 fois entre chaque affichage.
- pas de protection si la valeur rpm est modifiée pendant qu'on l'affiche
- il faut essayer d'avoir des interruptions les plus courtes possibles or les multiplications/divisions prennent pas mal de temps.

Walex68

Merci pour vos réponses, le programme de kamill me semble une bonne base, je l'est testé et il fonctionne...
Je vais l'adapter à mes besoins, notamment la remise à zéro de la valeur vitesse passé 2 ou 3 sec d'inactivité pour ne pas afficher une valeur positive alors que le véhicule est à l'arrêt et pour pouvoir calculer les distances parcouru...

Je verrais ça demain, je vous tiens au jus, merci encore pour votre aide !

kamill

Effectivement comme tu l'as vu, il faut ajouter le cas de l'arrêt ou vitesse très faible.

Walex68

Des news ! Je n'ai pas eu le temps de m'en occuper hier mais je poste le code "fini" de la partie calcul de la vitesse avec mise à zéro de l'affichage au bout d'un temps donné (3 sec). Il ne reste plus qu'à faire les calculs de distances etc.. ;)

Merci pour votre aide ! Je pense que ce code va en aider beaucoup, souvent quand la solution est trouvé le code final et fonctionnel n'est pas posté :/ !

Code: [Select]
unsigned int capteur = 2; // Pin capteur à effet Hall
unsigned long chrono; // Valeur courante du chrono
unsigned long chrono_depart = 0; // Valeur de départ du chrono
unsigned long chrono_2; // Valeur courante du chrono_2
unsigned long chrono_depart_2 = 0; // Valeur de départ du chrono_2
unsigned long periode; // Periode calculé pour 1 tour de roue
unsigned int duree_inactivite = 3000; // Durée d'inactivité de la vitesse (si le véhicule n'avance plus pendant 3 sec)
float vitesse = 0; // Varriable de vitesse
float periR = 1.884; // Périmètre de la roue (en mètre) -> diamètre*3.14/100 (ex: diamètre = 60cm *3.14 /100 = 1,884m)
bool flagMesure = false; // "Concerne la mesure de vitesse"

void compteurInc()
{
  chrono = micros();
  periode = chrono - chrono_depart;
  chrono_depart = chrono;
  flagMesure = true;    // On a une mesure de période valide
}

void setup()
{
  Serial.begin(9600);

  chrono_depart_2 = millis();

  //La fonction compteurInc sera appelée sur chaque front descendant (FALLING) de "capteur" (pin 2 = interuption 0)
  attachInterrupt(0, compteurInc, FALLING);
  digitalWrite(capteur, HIGH);
 
}

void loop()
{
  chrono_2 = millis();

  if (flagMesure == false && (chrono_2 - chrono_depart_2 > duree_inactivite)){
    vitesse = 0;
    Serial.print(vitesse,0);
    Serial.println(" km/h");
    delay(500);
  }
  else if (flagMesure)
  {
    noInterrupts();
    unsigned long t = periode;
    flagMesure = false;
    interrupts();
    vitesse=periR/1000/(t/1e6/3600); //Calcul de la vitesse en fonction de la période et de la distance que parcour la roue en 1 tour (périmètre). Autre méthode : (3600000.0/t)*periR
    Serial.print(vitesse,1);
    Serial.println(" km/h");
    chrono_depart_2 = millis(); // Mise à zéro du chrono de départ 2 (compteur d'inactivité)
  }
 
}

Go Up