Arduino Forum

International => Français => Topic started by: fantome92 on Apr 11, 2019, 11:09 am

Title: Help vitesse moyenne avec un capteur à effet hall
Post by: fantome92 on Apr 11, 2019, 11:09 am
Bonjour, pour mon lycée je dois faire un projet ou je dois acquérir la vitesse instantanée d'un kart et sa vitesse moyenne, j'ai déjà réussi a avoir ma vitesse instantanée mais je suis bloquer pour avoir la vitesse moyenne
voici mon montage du capteur : (https://image.noelshack.com/minis/2019/15/4/1554973396-20190411-105910.png) (https://www.noelshack.com/2019-15-4-1554973396-20190411-105910.jpg)

voici mon code arduino :
Code: [Select]
unsigned int capteur = 2; // Capteur effet hall
unsigned long chrono; // Valeur courante du chrono
unsigned long chrono_depart = 0; // Valeur de depart du chrono
unsigned long chrono_2; // Valeur courante du chrono 2
unsigned long chrono_depart_2 = 0; // Valeur de depart de chrono 2
unsigned long periode; // La periode calcule pour un tour de roue
unsigned int duree_inactivite = 5000; // Duree d'inactivite de la vitesse si le kart n'avance pas pendant 5 seconde
float vitesse_moyenne = 0; // Variable de la vitesse moyenne
float vitesse = 0; // Variable de vitesse
float periR = 1.7; // Périmetre de la roue en m d*pi/100
bool flagMesure = false; // Concerne la mesure de la vitesse



void compteurInc()
{
  chrono = micros();
  periode = chrono - chrono_depart;
  chrono_depart = chrono;
  flagMesure = true; // On a une mesure de periode valide
}
void setup()
{
  Serial.begin(9600); // Initialisation du moniteur

  chrono_depart_2 = millis();

  // La fonction compteurInc est appelée sur chaque front descendant (FALLING) du "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); // On calcule la vitesse en fonction de la période et de la distance que parcourt la roue en 1 tour (périmètre).
    Serial.print(vitesse,1);
    Serial.println(" km/h");
    chrono_depart_2 = millis(); // On remet à zéro le chronomètre de départ 2 (compteur d'inactivité) 
  }


 
 

 
 
}


donc voilà j'ai ma vitesse instantanée qui s'affiche mais je suis perdu pour afficher la vitesse moyenne en meme temps dans le moniteur.
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: dbrion06 on Apr 11, 2019, 11:14 am
Si vous avez 5 notes, comment calculez vous leur moyenne?
si vous avez Nsamples notes, comment calculez vous leur moyenne?
Si vous avez Nsamples vitesses instantanées?
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: fantome92 on Apr 11, 2019, 12:01 pm
Si j'ai 5 note , on additionne les 5 note et on divise par le nombre total donc 5, je sais comment calculer mais en le codant avec arduino j'ai largement beaucoup de mal je ne comprend pas beaucoup...
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: dbrion06 on Apr 11, 2019, 12:30 pm
Bon, je vois trois façons de calculer une moyenne:
a) au fil de l'eau:
 je remplis une valeur notée cumul par cumul+=vitesseInstantanée  ; j'incrémente iSamples (initialisé à zero)
 tous les Nsamples (le test est donc if (iSamples  == Nsamples ) )
je divise cumul par iSamples  ; je remets iSamples  à zero
   --> vous calculez de temps en temps une vitesse moyenne
b) par moyenne glissante
vous vous donnez un tableau de vitesses, de taille Nsamples; à chaque vitesse instantanée disponible
vous inserez tab[iSample] = vitesseInstantanée  ;
vous incrementez iSamples, et vous le repliez pour qu'il puisse toujours servir d'indice de tableau
     iSamples = (1 +  iSamples) % Nsamples;
vous calculez la moyenne des Nsamples elements de ce tableau (comme pour une moyenne de notes)
Au départ, les valeurs sont forcement bizarres... mais vous avez un rafraîchissement très rapide.

c) par un filtre
moyenne = 0.75* moyenne + 0.25 * vitesseInstantanée  ;
(en 2 tours -revoyez votre cours sur les suites géomètriques-, l'erreur sur la valeur initiale est divisée par 2; elle est divisée par 1000 en 20 tours). Le choix de 1/4 3/4 comme coefficients est que la division par une puissance de deux est très rapide sur tout contrôleur.

Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: fantome92 on Apr 12, 2019, 08:14 am
Merci pour ces informations, mais je suis bloqué pour mon code arduino, parce que vraiment je ne vois pas du tout comment faire cela en utilisant un code.
Si vous pourriez m'aidez je vous en serai très reconnaissant.
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: lesept on Apr 12, 2019, 08:18 am
Cherche "arduino average library" sur Google, tu trouveras des choses toutes faites
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: fantome92 on Apr 12, 2019, 08:55 am
J'ai essayé de chercher, je n'ai pas trouvé je sais que je dois prendre plusieurs vitesse instantanée et ensuite diviser sur un intervalle de temps mais je ne sais le programmer...
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: higgins91 on Apr 12, 2019, 01:58 pm
la solution a de dbrion06 est donc à privilégier.

Code: [Select]


la tu déclare les variables:
une pour la moyenne: moy
une pour le nombre de mesure: nbmesure


unsigned int capteur = 2; // Capteur effet hall
unsigned long chrono; // Valeur courante du chrono
unsigned long chrono_depart = 0; // Valeur de depart du chrono
unsigned long chrono_2; // Valeur courante du chrono 2
unsigned long chrono_depart_2 = 0; // Valeur de depart de chrono 2
unsigned long periode; // La periode calcule pour un tour de roue
unsigned int duree_inactivite = 5000; // Duree d'inactivite de la vitesse si le kart n'avance pas pendant 5 seconde
float vitesse_moyenne = 0; // Variable de la vitesse moyenne
float vitesse = 0; // Variable de vitesse
float periR = 1.7; // Périmetre de la roue en m d*pi/100
bool flagMesure = false; // Concerne la mesure de la vitesse



void compteurInc()
{
  chrono = micros();
  periode = chrono - chrono_depart;
  chrono_depart = chrono;
  flagMesure = true; // On a une mesure de periode valide
}
void setup()
{
  Serial.begin(9600); // Initialisation du moniteur

  chrono_depart_2 = millis();

  // La fonction compteurInc est appelée sur chaque front descendant (FALLING) du "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");

A cet endroit tu fais l'addition de ta vitesse avec ta variable de moyenne:
moy=moy+vitesse
nbmesure=nbmesure+1

et à la suite tu fais une condition si le nombre est > à x mesures
if nbmesure>x
   moy=moy/nbmesure
    Serial.println("moy");
    moy=0
    nbmesure=0
fin if



    Serial.println(" km/h");
    delay(500);
  }
  else if (flagMesure)
  {
    noInterrupts();
    unsigned long t = periode;
    flagMesure = false;
    interrupts();
    vitesse=periR/1000/(t/1e6/3600); // On calcule la vitesse en fonction de la période et de la distance que parcourt la roue en 1 tour (périmètre).
    Serial.print(vitesse,1);
    Serial.println(" km/h");
    chrono_depart_2 = millis(); // On remet à zéro le chronomètre de départ 2 (compteur d'inactivité)
  }

 
}



reste plus qu'a coder "au propre"  :D
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: fantome92 on Apr 13, 2019, 04:15 pm
Bonjour merci d'avoir répondu donc j'ai fais comme vous m'avez dis je ne sais pas si c'est ok
Code: [Select]


float nbmesure = 0; // nombre de mesure
float moy = 0; //  moyenne variable
unsigned int capteur = 2; // Capteur effet hall
unsigned long chrono; // Valeur courante du chrono
unsigned long chrono_depart = 0; // Valeur de depart du chrono
unsigned long chrono_2; // Valeur courante du chrono 2
unsigned long chrono_depart_2 = 0; // Valeur de depart de chrono 2
unsigned long periode; // La periode calcule pour un tour de roue
unsigned int duree_inactivite = 5000; // Duree d'inactivite de la vitesse si le kart n'avance pas pendant 5 seconde
float vitesse_moyenne = 0; // Variable de la vitesse moyenne
float vitesse = 0; // Variable de vitesse
float periR = 1.7; // Périmetre de la roue en m d*pi/100
bool flagMesure = false; // Concerne la mesure de la vitesse



void compteurInc()
{
  chrono = micros();
  periode = chrono - chrono_depart;
  chrono_depart = chrono;
  flagMesure = true; // On a une mesure de periode valide
}
void setup()
{
  Serial.begin(9600); // Initialisation du moniteur

  chrono_depart_2 = millis();

  // La fonction compteurInc est appelée sur chaque front descendant (FALLING) du "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");
    moy=moy+vitesse;
    nbmesure=nbmesure+1;

if (nbmesure>0);
   moy=moy/nbmesure;
    Serial.println("moy");
    moy=0;
    nbmesure = 0;



    Serial.println("km/h");
    delay(500);
  }
  else if (flagMesure)
  {
    noInterrupts();
    unsigned long t = periode;
    flagMesure = false;
    interrupts();
    vitesse=periR/1000/(t/1e6/3600); // On calcule la vitesse en fonction de la période et de la distance que parcourt la roue en 1 tour (périmètre).
    Serial.print(vitesse,1);
    Serial.println(" km/h");
    chrono_depart_2 = millis(); // On remet à zéro le chronomètre de départ 2 (compteur d'inactivité)
  }

 
}
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: dbrion06 on Apr 13, 2019, 04:27 pm
A priori, votre solution n'est pas trop incorrecte; cependant, il est plus que vraisemblable que votre moyenne soit le cas dégénéré où on fait le calcul de la moyenne ... sur une (1+0; 0+1; 1*1) donnée et elle doit donc se confondre avec la vitesse instantanée (au prix de lignes de code en plus...)
Code: [Select]

if (nbmesure == nSamples);
   moy = moy/ (float)nSamples ;
    Serial.println("moy");
    moy = 0.0;
    nbmesure = 0;



    Serial.println("km/h");
    delay(500); // A quoi sert ce delai?
  }
(non testé)
Pour ce faire, il vous faut déclarer nSamples
cons uint8_t nSamples = 5; // vous faites une moyenne sur 5 valeurs; adaptez si besoin

De même, nbmesures n'a pas à être déclaré en float: un integer (int, uint8_t ou ...) fait très bien l'affaire (et lui rajouter 1 est plus rapide et consomme moins de cycles que rajouter 1.0 à un float; la conversion n'a lieu que pour la  division)

Cette solution (au besoin, améliorée pour qu'elle compile: je n'ai pas testé) vous permettrait d'échapper au cas trivial (qui n'est pas faux, mais mange d"es ressources inutilement) que vous avez programmé (moyenne == instantané)
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: fantome92 on Apr 15, 2019, 08:26 pm
Bonjour, merci d'avoir répondu, du coup je n'ai pas trop compris je dois m'y prendre comment ? je laisse le code que j'ai fais ou je dois rajouter des lignes de codes notamment ce que vous venez de me montrer ?
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: dbrion06 on Apr 15, 2019, 08:36 pm
Vous remplacez le bloc
if (nbmesures>0) {
....
}
par le bloc que je vous ai passé.


Nora: ce serait plus beau si vous remplaciez aussi :   Serial.println("moy"); par :   Serial.println(moy);
(je n'ai pas testé ce bloc: je suppose que vous pouvez comprendre 5 lignes de code .... sinon, ce serait absurde de les demander....
 et je susi sûr  que vous avez de meilleurs moyens que moi -disponibilité d'un arduino et de son IDE - de tester)


Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: fantome92 on Apr 15, 2019, 09:21 pm
Merci d'avoir répondu du coup cela me donne ça :
Code: [Select]
uint8_t nSamples = 5; // vous faites une moyenne sur 5 valeur adaptez si besoin
int nbmesure = 1; // nombre de mesure
float moy = 0; //  moyenne variable
unsigned int capteur = 2; // Capteur effet hall
unsigned long chrono; // Valeur courante du chrono
unsigned long chrono_depart = 0; // Valeur de depart du chrono
unsigned long chrono_2; // Valeur courante du chrono 2
unsigned long chrono_depart_2 = 0; // Valeur de depart de chrono 2
unsigned long periode; // La periode calcule pour un tour de roue
unsigned int duree_inactivite = 5000; // Duree d'inactivite de la vitesse si le kart n'avance pas pendant 5 seconde
float vitesse_moyenne = 0; // Variable de la vitesse moyenne
float vitesse = 0; // Variable de vitesse
float periR = 1.7; // Périmetre de la roue en m d*pi/100
bool flagMesure = false; // Concerne la mesure de la vitesse



void compteurInc()
{
  chrono = micros();
  periode = chrono - chrono_depart;
  chrono_depart = chrono;
  flagMesure = true; // On a une mesure de periode valide
}
void setup()
{
  Serial.begin(9600); // Initialisation du moniteur

  chrono_depart_2 = millis();

  // La fonction compteurInc est appelée sur chaque front descendant (FALLING) du "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");
    moy=moy+vitesse;
    nbmesure=nbmesure+1;

if (nbmesure == nSamples);
   moy = moy/(float)nSamples ;
    Serial.println(moy);
    moy = 0.0;
    nbmesure = 0;



    Serial.println("km/h");
    delay(500); // A quoi sert ce delai?
 
  }
  else if (flagMesure)
  {
    noInterrupts();
    unsigned long t = periode;
    flagMesure = false;
    interrupts();
    vitesse=periR/1000/(t/1e6/3600); // On calcule la vitesse en fonction de la période et de la distance que parcourt la roue en 1 tour (périmètre).
    Serial.print(vitesse,1);
    Serial.println(" km/h");
    chrono_depart_2 = millis(); // On remet à zéro le chronomètre de départ 2 (compteur d'inactivité)
  }

 
}


Et le delay je le supprime ou pas si vous pensez qu'il ne sert à rien ? mon code est mieux comme cela ? et que signifie "uint8_t" s'il vous plaît ?
Title: Re: Help vitesse moyenne avec un capteur à effet hall
Post by: dbrion06 on Apr 16, 2019, 09:07 am
uintXX_t est une façon de spécifier sans ambiguité le nombre d'octets que l'on veut utiliser (uint8_t pour un octet, uint16_t pour deux octets, uint32_t pour 4 octets). Il offre l'avantage d'être portable : un code testé sur un vieux PC (où les entiers sont des (u)int32_t) peut fonctionner , avec des chances raisonnables, sur un arduino(où les entiers sont des (u)int16_t).

Votre code est vraisemblablement moins mauvais comme ça: C'est à VOUS de voir

a) s'il se compile (c'est trivial: il suffit d'appuyer sur un bouton si vous disposez d'un IDE arduino)

b) s'il donne des valeurs vraies ou réalistes (je ne peux pas organiser votre façon de tester)

Si JE pense que le delay ne sert à rien, c'est MON opinion( hors sujet de ce fil et VOUS êtes libre d'être en désaccord.
Je ne peux que vous signaler que delay mange un nombre fou de cycles,
à ne RIEN faire d'utile,
 et qu'il existe des façons plus habiles d'interdire un bloc de programme de s'executer pendant xxx millisecondes, sans perte de ressources: un bel exemple est dans
fichiers->exemples->digital->blinkWithoutDelay IIRC.