Arduino Forum

International => Français => Topic started by: Belo on Aug 15, 2019, 11:26 am

Title: compteur de vitesse
Post by: Belo on Aug 15, 2019, 11:26 am
Bonjour, je voudrais réaliser un compteur de vitesse pour vélo avec un capteur à effet hall et un écran oled.

- Mon afficheur OLED est de 0.96'' 128*64 en I2C ( adresse I2C trouvé avec scanner = 0x3C ) SSD1306.

- Mon capteur à effet hall est un UGN3503 qui envoie du 2.5v quand aucun champs magnétique augmente      quand un champs magnétique "nord" se rapproche ( quand il passe environ 3v ) et diminue quand un  champs magnétique "sud" se rapproche.        Mon capteur est donc analogique pas comme les "autres"( la   majorité ).

Je n'ai aucun problème au niveau cablâge ( ecran 5v et gnd + sda sur sda et sci sur sci ) (effet hall supply sur 5v gnd sur gnd et output sur A0 ) par contre au niveau programmation je n'arrive pas du tout; j'ai déjà regardé les différents articles de capteur à effet hall tachymetre mais je ne comprends rien à ceux-ci.


J'ai déjà un code qui devrais m'afficher sur serial le temps entre deux interruptions mais qui m'affiche millis :

Code: [Select]

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

void loop(){
  unsigned long temps = millis();
  unsigned long tempstrouve;
  unsigned long dernierPassage;

  if(analogRead(A0) <= 410  || analogRead(A0) >=615 ){  //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    tempstrouve = temps - dernierPassage;
 dernierPassage = temps;
    Serial.println(tempstrouve);
  }
}



Je ne sais même pas si c'est la bonne méthode pour calculer la vitesse et j'ai surtout un problème pour arriver à calculer la vitesse à partir d'un périmètre de roue et d'un temps entre deux interruptions!.. :smiley-confuse:
Title: Re: compteur de vitesse
Post by: lesept on Aug 15, 2019, 12:02 pm
Tu devrais stocker la valeur lue dans une variable int et faire ton test sur cette variable.
Pour la vitesse, il suffit de diviser la distance par le temps, donc le périmètre par l'intervalle de temps mesuré
Il faut bien sûr faire une division en float sinon ça ne sera pas précis
Title: Re: compteur de vitesse
Post by: Belo on Aug 15, 2019, 03:32 pm
Maintenant j'arrive à lire sur serial le tempstrouve correctement donc c'est ok pour ça mais j'ai réécri le programme pour avoir la vitesse :

Code: [Select]

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

void loop(){
  unsigned long temps = millis();
  int tempstrouve;
  unsigned long dernierPassage;
  int perimetre = 2;  //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon
  int vitesse;

  if(analogRead(A0) <= 410  || analogRead(A0) >=615 ){  //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    tempstrouve = temps - dernierPassage;
    dernierPassage = temps;
    vitesse = (perimetre / (tempstrouve / 1000))*3.6; //donne la vitesse en km/h grace à v = d/t
    Serial.println(vitesse);
    delay(50);  //delay juste pour les tests et que ce soit lisible
   
  }
}





Mais ça ne fonctionne pas, le serial m'envoie n'importe quoi toujours en descendant la valeur ( valeur plus faible que précédente ) alors que j'augmente la cadence de passage de l'aimant.


il me la descend jusqu'à 0 puis juqu'à des nombres négatifs !!!
Title: Re: compteur de vitesse
Post by: kamill on Aug 15, 2019, 03:41 pm
Bonjour,

La variable dernierPassage doit être conservée entre chaque appel de loop(). Il faut la déclarer static
Code: [Select]
static unsigned long dernierPassage;

Il faut aussi que la valeur de A0 sorte de l'intervalle avant de faire la mesure suivante.
Title: Re: compteur de vitesse
Post by: Belo on Aug 15, 2019, 05:20 pm
Maintenant ça m'affiche tout le temps -3 sauf parfois 0 ou 3 ou 7

le code :

Code: [Select]
void setup(){
  Serial.begin(9600);
}

void loop(){
  unsigned long temps = millis();
  int tempstrouve;
  static unsigned long dernierPassage;
  int perimetre = 2;  //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon
  int vitesse;


  if(analogRead(A0) <= 410  || analogRead(A0) >=615 ){  //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    tempstrouve = temps - dernierPassage;
    dernierPassage = temps;
    vitesse = (perimetre / (tempstrouve / 1000))*3.6; //donne la vitesse en km/h grace à v = d/t
    Serial.println(vitesse);
    delay(50);  //delay juste pour les tests et que ce soit lisible
    
  }
}



Et aussi je ne sais pas comment faire
Il faut aussi que la valeur de A0 sorte de l'intervalle avant de faire la mesure suivante.
Title: Re: compteur de vitesse
Post by: lesept on Aug 15, 2019, 05:55 pm
Et il faut définir vitesse en float
float vitesse;
Title: Re: compteur de vitesse
Post by: PBZOOM on Aug 15, 2019, 06:22 pm
au risque de dire une co....

si  Mr kamil dit :
"..Il faut aussi que la valeur de A0 sorte de l'intervalle avant de faire la mesure suivante."
 c'est peut étre que :
manque  changement d' état...

au moment déclenchant le calcul résultat de comptage :

if(analogRead(A0) <= 410  || analogRead(A0) >=615 ){

il faut prendre en compte que la loop précédente été avec un analog read hors intervalle..

un peut comme une variable anti-rebond....

if(analogRead(A0) <= 410  || analogRead(A0) >=615 ||...ici... ){

 ...par exemple..
Title: Re: compteur de vitesse
Post by: Belo on Aug 15, 2019, 06:46 pm
Maintenant ça m'affiche 3.60



Je suis vraiment désolé mais je ne comprends toujours pas le truc d'intervalle, que dois-je changer à mon code ??

Peut-être qu'il faut que je mette une sorte de delay ou un truc du genre :

if(analogRead(A0) <= 410  || analogRead(A0) >=615  & DernierPassage > 50){

???
Title: Re: compteur de vitesse
Post by: supercc on Aug 15, 2019, 07:14 pm
J'essaye autrement ;-)

la fonction loop tourne à une cadence de plusieurs centaines de fois par seconde (cela dépend du code quel contient).

Le capteur sera dont vu "actif" (...<= ... || ... >= ...) dans une suite importante d'appels consécutif de la fonction loop. Du coup le calcul de vitesse = ... ne fonctionne pas puisque les variables  temps et dernierPassage ne représente pas 2 passages consécutifs du capteur mais 2 tours de boucles consécutifs...

Il faut donc que tu n'effectues le calcul si tu viens d'un état inactif à un état actif. Tu peux par exemple gérer une variable dernierEtat reflétant l'état détecté dans le tour précédent, que tu consulteras au moment de prendre la décision de faire le calcul.

Un peu la même technique que dernierPassage ;-)



Title: Re: compteur de vitesse
Post by: kamill on Aug 15, 2019, 07:28 pm
Il faut que tu prennes en compte uniquement le franchissement du seuil et non si tu as déjà franchi le seuil.
Tu dois utiliser un flag pour ça.
Code: [Select]
void loop() {
  int perimetre = 2;  //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon
  static unsigned long dernierPassage;
  static bool flagMesure = false;
  int tempstrouve;
  int vitesse;

  if (analogRead(A0) <= 410  || analogRead(A0) >= 615) { //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if (flagMesure)
    {
      unsigned long temps = millis();
      tempstrouve = temps - dernierPassage;
      dernierPassage = temps;
      vitesse = (perimetre / (tempstrouve / 1000)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;     // pour attente cycle suivant
      Serial.println(vitesse);
      //    delay(50);  //delay juste pour les tests et que ce soit lisible
    }
  }
  else
  {
    flagMesure = true;  // prêt pour une nouvelle mesure
  }
}
Title: Re: compteur de vitesse
Post by: PBZOOM on Aug 15, 2019, 09:07 pm
@ Belo.

euuuuuuuuuuu......

if(analogRead(A0) <= 410  || analogRead(A0) >=615 ||...ici... ){
le rajout  ||...ici...
c' est pas bon /trop condensé.. ...scusa me....

C 'est effectivement efectivement plus compréhensible
les soluce Kamil et mieux explique par supercc...
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 09:54 am
Maintenant j'ai compris le principe, j'ai essayé le code de kamill avec en plus float vitesse mais ça ne marche pas ( sur le serial ), ça me donne ça ( capture d'écran en bas en lien ). Ce n'est que des multiples de 3.6 (0*3.6, 1*3.6, 2*3.6 ) et justement j'utilise 3.6 dans mes calculs , y-a-t'il un rapport ??
 
Et aussi cette partie la m'intrigue :

 if (flagMesure)               Il ne faut pas mettre un truc du genre "if (flagMesure == true)"


Title: Re: compteur de vitesse
Post by: supercc on Aug 16, 2019, 09:59 am
En C :
  * var vaut le contenu de la variable (normal ;-))
  * en C, seule les valeurs 0 et false sont considérées comme "faux" et tout le reste est vrai (plus original !) : true 1, -1, 34.8 sont vrais

donc if(var) ne sera vrai que si var est !=0 ou !=false. Mais si tu veux tu peux écrire if(var!=0) ou if(var == true).

Tu dois avoir un problème dans la formule !

EDIT : précisions + correction
Title: Re: compteur de vitesse
Post by: kamill on Aug 16, 2019, 10:00 am
Affiches le tempsTrouve, peut être que la résolution n'est pas suffisante.

"if (flagMesure)" et "if (flagMesure == true)" sont identiques. Ce sont tous deux des booleens.
C'est inutile de comparer flagMesure à true ou false puisqu'il vaut déjà true ou false
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 10:24 am
J'affiche le tempstrouve et c'est bon, ça m'affiche le tempstrouve.


Peut-être devrais-je faire plusieurs calculs au lieu d'un gros ? 
( au lieu de ça :   vitesse = (perimetre /(tempstrouve / 1000)) * 3.6;



Et remplacer par ça :

vitesse = perimetre / tempstrouve;
vitesse = vitesse * 3600;


J'ai essayé comme au dessusmais ça m'affiche que 0.00 dés que je passe l'aimant
Title: Re: compteur de vitesse
Post by: kamill on Aug 16, 2019, 10:31 am
Et ça donne combien pour tempsTrouve?
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 10:39 am
Quand j'affiche tempstrouve ba ça me donne le temps en ms entre chaque passage de l'écran
Title: Re: compteur de vitesse
Post by: lesept on Aug 16, 2019, 10:44 am
Peut-être devrais-je faire plusieurs calculs au lieu d'un gros ? 
( au lieu de ça :   vitesse = (perimetre /(tempstrouve / 1000)) * 3.6;

Et remplacer par ça :

vitesse = perimetre / tempstrouve;
vitesse = vitesse * 3600;

J'ai essayé comme au dessusmais ça m'affiche que 0.00 dés que je passe l'aimant
Ton problème est de faire une division en flottant. Mais si tes nombres sont des int et que tu ne précises pas que tu veux un flottant, ta division sera entière.
Pour ça plusieurs solutions, la plus simple est de dire explicitement que tu veux du flottant

Code: [Select]
vitesse = perimetre * 1.0 / tempstrouve;
vitesse = vitesse * 3600.0;


Sinon tu peux faire un cast, une promotion, qui va changer temporairement un int en float, le temps de l'opération

Code: [Select]
vitesse = (float) perimetre / tempstrouve;
vitesse = vitesse * 3600;
Title: Re: compteur de vitesse
Post by: kamill on Aug 16, 2019, 11:11 am
Peut-être devrais-je faire plusieurs calculs au lieu d'un gros ? 
( au lieu de ça :   vitesse = (perimetre /(tempstrouve / 1000)) * 3.6;
...
Il faut faire le calcul en flottant
Code: [Select]
vitesse = (perimetre /(tempstrouve / 1000.0)) * 3.6
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 02:24 pm
D'accord, maintenant ça y est, j'ai la vitesse en km/h.
Et finalement j'ai changé le vitesse en int car je ne souhaite pas de nombres à virgule.

J'ai réalisé un second programme qui m'affiche cette vitese mais sur un écran oled cette fois-ci, je travaille pour mesurer la distance et l'afficher et travaille avec l'EEPROM ( j'essaye ) pour afficher dans un second menu la distance totale et d'autres trucs ( vitesse max ...).

J'aurais sans doute besoin d'aide pour l'EEPROM car je n'ai jamais utilisé celle-ci mais ayant lu des tutos, je pense que ça devrait le faire....
Title: Re: compteur de vitesse
Post by: lesept on Aug 16, 2019, 02:49 pm
Tu risques de perdre en précision, reste en flottant pour le calcul et affiche avec zéro chiffre après la virgule

Code: [Select]
Serial.print (vitesse, 0);
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 04:09 pm
OK c'est fait. J'ai fait un code qui affiche la vitesse et la distance sur l'écran oled ( sans les unitées de km et km/h )mais mon écriture prend trop de temps donc je ne peux pas mesurer plus de 11km/h.  Comment-y remédier ? :smiley-sad:


Mais si par exemple j'enlève l'écriture de la distance, je peux mesurer jusqu'à 21 km/h
Title: Re: compteur de vitesse
Post by: lesept on Aug 16, 2019, 05:00 pm
Poste ton code...
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 05:05 pm
J'avais oublié !!! désolé
Code: [Select]

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );



void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
 
}

void loop() {

unsigned long temps = millis();
int perimetre = 2;  //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon                       !!!!! EN METRE !!!!!
static unsigned long dernierPassage;
static bool flagMesure = false;
int tempstrouve;
float vitesse;
float distance;

  if (analogRead(A0) <= 410  || analogRead(A0) >= 615) { //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if (flagMesure)
    { tempstrouve = temps - dernierPassage;
      dernierPassage = temps;
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;     // pour attente cycle suivant
      distance = distance + (perimetre / 1000.0);

      display.clearDisplay();   //efface l'écran pour le réactualiser
    }
  }
  else
  {
    flagMesure = true;  // prêt pour une nouvelle mesure
  }

display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(40, 2);  //essai donc placement on s'en fout
display.print(distance, 1);
display.display();

display.setTextSize(4);
display.setTextColor(WHITE);
display.setCursor(0, 2);  //essai donc placement on s'en fout
display.print(vitesse,0);
display.display();



}



Title: Re: compteur de vitesse
Post by: lesept on Aug 16, 2019, 05:11 pm
Il faut exécuter les commandes d'affichage uniquement lorsque tu fais le calcul de la vitesse, pas à chaque tour de la loop. C'est ça qui te ralentit

Il est possible que ton clear display finisse par faire clignoter l'affichage... Mais on verra plus tard
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 06:22 pm
Maintenant que j'ai mis tout ça dans le if et avec les calculs, je peux monter à 21km/h max.

Title: Re: compteur de vitesse
Post by: lesept on Aug 16, 2019, 07:18 pm
Je peux t'aider à optimiser ton code, mais j'aurais besoin de savoir ce que donnent les valeurs du analogRead. Peux-tu faire tourner ta roue et afficher ces valeurs ?
Title: Re: compteur de vitesse
Post by: Belo on Aug 16, 2019, 08:11 pm
Déjà, pour que ce soit plus clair, mon capteur n'est pas monté, je passe juste un aimant "à la main" comme ça en essayant d'être régulier et de faire varier la vitesse.  Tout est monté sur breadboard avec un arduino uno.

Mon analogRead me donne environ 515 sans aimant, cela oscille un peu mais c'est normal, c'est comme ça sur la fiche technique. En fait quand le champs magnétique est à peu près nul, il donne 2.5v en sortie.

Quand je passe un aimant pôle sud à environ 1-2 cm, ça descend en dessous de 2v environ ( d'où le 410 ( 1024/5 = 204.8  et 204.8*2 = environ 410)).
Quand je passe un aimant pôle nord à environ 1-2 cm,  ça monte eau dessus de 3v environ ( d'où le 615 ( 1024/5 = 204.8  et 204.8*3 = environ 815)).

Attention, tant que je laisse l'aimant devant le capteur, sa tension reste de <2v ou >3v.

C'est un capteur analogique du coup, pas comme la majorité des autres capteurs à effet hall ou comme les capteurs reed (switch magnétique, équivalent capteur ILS si j'ai bien compris... :smiley-confuse: ).
Title: Re: compteur de vitesse
Post by: lesept on Aug 16, 2019, 08:29 pm
21km/h ça fait près de 6 m/s donc 3 tours de roue par seconde. C'est très peu, à mon avis tu dois monter bien plus haut. Comment evalues tu cette valeur ?
Title: Re: compteur de vitesse
Post by: lesept on Aug 16, 2019, 11:20 pm
Alors voila un code, que je pense un peu plus optimisé

Code: [Select]
/*
   Compteur de vitesse
   Lesept 08/2019
*/
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );

// Définir ici les seuils min et max du analogRead
#define valMin 410
#define valMax 615
// Définir ici les coordonnées pour l'effacement du texte
// x : abscisse min, y : ordonnée min, w : largeur, h : hauteur du rectangle
// Voiri :https://learn.adafruit.com/adafruit-gfx-graphics-library/graphics-primitives
#define xDist 40
#define yDist 20
#define wDist 40
#define hDist 20
#define xVit  00
#define yVit  20
#define wVit  40
#define hVit  20

const int valMoy = (valMin + valMax) / 2;
const int seuil = (valMax - valMin) / 2;
const int perimetre = 2;  //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon                       !!!!! EN METRE !!!!!
bool flagMesure = false;
unsigned long tempstrouve = 0;
unsigned long dernierPassage = 0;
float vitesse = 0;
float distance = 0;

void Affiche (float distance, float vitesse) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.fillRect (xDist,yDist,wDist,hDist,BLACK);
  display.setCursor(40, 2);  //essai donc placement on s'en fout
  display.print(distance, 1);

  display.setTextSize(4);
  display.setTextColor(WHITE);
  display.setCursor(0, 2);  //essai donc placement on s'en fout
  display.fillRect (xVit,yVit,wVit,hVit,BLACK);
  display.print(vitesse, 0);
 
  display.display();
}

void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
  Affiche (distance, vitesse);
}

void loop() {
  int diff = abs(analogRead(A0) - valMoy);
  if (diff >= seuil) { //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if (flagMesure) {
      tempstrouve = millis() - dernierPassage;
      dernierPassage = millis();
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;     // pour attente cycle suivant
      distance = distance + (perimetre / 1000.0);
      Affiche (distance, vitesse);
    }
  }
  else
  {
    flagMesure = true;  // prêt pour une nouvelle mesure
  }
}


Au lieu d'effacer l'écran entier à chaque fois, je trace un rectangle aux endroits ou tu affiches la distance et la vitesse. Ces endroits sont définis par
Code: [Select]
#define xDist 40
#define yDist 20
#define wDist 40
#define hDist 20
#define xVit  00
#define yVit  20
#define wVit  40
#define hVit  20

Mais il faut que tu trouves les bonnes valeurs sur ton écran.

Pour le capteur, j'ai modifié le test afin de ne plus avoir de OU. Le principe c'est de calculer la distance de la valeur mesurée à la moyenne. Par exemple, si un passage correspond à une valeur mesurée inférieure à 400 ou supérieure à 600 (c'est plus facile à voir avec des nombres entiers), on peut faire
Code: [Select]
if (valeur <=400 || valeur >= 600)
mais on peut aussi se dire que la distance de la valeur à 500 doit être supérieure à 100, ce qui donne
Code: [Select]
diff = abs(valeur - 500);
if (diff >= 100)

500 est la valeur moyenne de 400 et 600, et 100 et la moitié de la distance entre 400 et 600.

Si vraiment c'est encore trop lent (mais il faudrait le tester sur une vraie roue,en vraie grandeur) on peut  afficher les valeurs moins souvent, par exemple toutes les secondes. On pourra voir ça plus tard...
Title: Re: compteur de vitesse
Post by: supercc on Aug 16, 2019, 11:29 pm
Chouette une petite routine d'interruption en vue ;-)
Title: Re: compteur de vitesse
Post by: savoriano on Aug 17, 2019, 12:22 am
Au lieu de colorer un rectangle on peu mémoriser la vitesse et la réécrire dans la couleur du fond. Mémoriser la vitesse peut aussi servir pour savoir si la vitesse est diffèrente à la nouvelle vitesse calculée et donc de la écrire ou pas.

P.s. on est sur que le font utilisé nécessite de effacer avant de réécrire ?
Title: Re: compteur de vitesse
Post by: Belo on Aug 18, 2019, 11:45 am
Merci beaucoup lesept, ton code marche à merveille, j'arrive à monter vers 40 km/h mais seulement à cause de mes bras que je ne peux pas bouger à la vitesse de la lumière !!!( je suis drôle )
Je vais donc bientôt mettre en place le capteur et tout sur le vélo et puis fixer la valeur du vrai périmètre.


J'ai changé les coordonnées du rectangle vitesse et distance et c'est bon.

Il n'y a juste un truc que je ne comprends pas ( et pas uniquement sur ce code ), pourquoi utiliser vous ( les "pros" ) #define ..... au lieu d'une variable "normale" ( int par exemple )?  



Mais aussi, un truc me casse la tête; j'aimerais stocker la distance totale depuis la première activation et utilisation du code grâce à l'EEPROM mais je ne sais pas comment faire. Déjà, la mémoire EEPROM à une durée de vie limitée à environ 100 000 cycles d'écritures par emplacement ( selon le site officiel arduino ) donc je ne veux pas réécrire la distance totale toutes les deux secondes.( je pensais la réécrire tous les km )???
Mon second problème est comment calculer cette distance totale car si on ajoute à cette distance
totale la distance, il faudrait remettre à zéro cette distance etc, etc...

J'ai donc créé une variable distancebis qu'on remet à 0 quand on l'écrit dans l'EEPROM, cette variable est du coup la même que distance.  Comme dit dans le code, ce programme ne gère pas l'affichage des variables.


Code: [Select]



/*  Ce programme est totalement open-source, je remercie la communauté du forum arduino qui m'a aidé à construire ce code.

Ce programme permet de calculer la vitesse en km/h d'un vélo ou autre à partie d'un capteur à effet hall numérique
 *  Il permet donc de calculer la vitesse instantanée, la distance du trajet, la vitesse max, la vitesse max totale ainsi que la distance totale.
 *  
 *  On stocke la vitesse max totale et la distance totale dans la mémoire EEPROM et on calcule la vitesse ( donc la distance, etc.. ) en mesurant le temps entre
 *  chaque interruptions ( donc passage de l'aimant devant le capteur == un tour de roue ) et en appliquant la formule v = d/t.
 *  
 *  Avant d'utiliser ce programme, il faut calculer le périmètre de la roue et le rentrer dans " int perimetre = (ici la valeur du périmètre en m)" Dans la ligne suivi de points d'exclamations.
 *  ((( Pour rappel le périmètre est égal à      pi x 2 x rayon       ou        pi x diamètre.   )))
 *  
 *  Ce programme ne permet pas l'affichage sur écran ou port série ou autres de ces valeurs. Il utilise un capteur à effet hall analogique UGN3503 qui envoie du 2.5v quand aucun champs magnétique,
 *  augmente quand un champs magnétique "nord" se rapproche ( quand il passe environ 3v ) et diminue quand un  champs magnétique "sud" se rapproche.
 */
#include <EEPROM.h>

void setup(){

  
}

void loop() {

  //les variables pour les calculs des variables finales
  float perimetre = 2;                      //!!!!!!!!!!!!!!!!!EN METRES!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  static unsigned long dernierPassage;
  static bool flagMesure = false;
  int tempstrouve;                          //le temps trouvé entre deux passage de l'aimant ( le temps trouvé pour un tour de roue )
  float distancebis;                        //la variable distancebis pour calculer la varible distance totale

  //les variables finales pour l'affichage : vitesse, distance, vitesse max, vitesse max totale et distance totale
  float vitesse;                            //la variable vitesse
  float distance;                           //la variable distance
  byte vitessemax;                          //la variable vitesse maximum                        //byte car moitié moins d'octet et suffisant ( à moins d'aller à plus de 255 km/h )
  byte vitessemaxtotale = EEPROM.read(0);   //la variable vitesse max totale pour l'EEPROM       //byte car moitié moins d'octet ( à moins d'aller à plus de 255 km/h )
  int distancetotale = EEPROM.get(1, distancetotale);      //la variable distance totale pour l'EEPROM




  

  
  if(analogRead(A0) <= 410  || analogRead(A0) >= 615) {     //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if(flagMesure)
    {
      unsigned long temps = millis();
      tempstrouve = temps - dernierPassage;
      dernierPassage = temps;
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;                                   // pour attente cycle suivant
      distance = distance + perimetre;
      distancebis = distancebis + perimetre;
    }
  }
  else
  {
    flagMesure = true;                    // prêt pour une nouvelle mesure
  }

 if(vitesse > vitessemax){                //calcule la vitesse max du trajet
  vitessemax = vitesse;
 }
 if(vitessemax > vitessemaxtotale){       //calcule la vitesse max totale
  vitessemaxtotale = vitessemax;
  EEPROM.update( 0, vitessemaxtotale);    //on écrit la variable vitesse max totale dans l'EEPROM
 }
 if(distancebis >= 1.0){
  distancetotale = distancetotale + distancebis;     //on calcule la variable distance totale
  distancebis = 0;                                   //on remet la variable distancebis à 0 pour le calcul suivant ( dans 1 km )
  EEPROM.put( 1, distancetotale);                 //on écrit la variable distance totale dans l'EEPROM
 }
}


Mais j'ai un doute pour EEPROM.get et EEPROM.put, j'ai mis ça car je veux écrire pas un octet mais deux ( distance totale est un int donc 2 octets ), car je compte parcourir plus de 255km avec mon vélo au total ( je ne fais pas le tour de France non plus... :)  )
Je pense qu'il y a une erreur ( ou plusieurs ) dans le code, surtout pour l'utilisation de l'EEPROM que je n'ai jamais utilisé auparavant. Si vous voyez des erreurs, n'hésitez surtout pas à me le dire.
Title: Re: compteur de vitesse
Post by: Belo on Aug 18, 2019, 07:40 pm
J'aimerais mettre ce programme en même temps sauf que il y a tellement de mesures et tout que je ne peux pas mesurer plus de 3 km/h, comment faire ???

Code: [Select]

/*                                                    programme pour afficher et mesurer une tension max de 30VDC pour batteries
 *schema de montage pont diviseur de tension         VIN 30vdc        R1 = 10kOhm     R2 = 2KOhm    Vout = 5V quand Vin 30v
 *
 * pour plus de précision mesurer avec précision les résistances r1 et r2 et calculer   Vout    sur digikey___calcul_pont_diviseur_de_tension faire 204,6 / ( VIN / Vout )
 *
 *
 * les valeurs de capacité selon tensions sont trouvées sur internet et à peu près vrai ( la capacité ne dépent pas que de la tension )  
 */

 
 
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );



void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
  
  
  
}

void loop(){


   //partie bitmap affiché continuellement
  display.display();
  display.drawRect( 101,  0,  27,  11,  WHITE);  //changer les x et y ( la position)              ligne 1
  display.drawRect( 96,  3,  5,  5,  WHITE);  //si ligne 1 changé de position, faire 2 premieres valeurs -3 et les recopier
  display.display();


  
 float tension = analogRead(A0);  //définie la broche mesurant la tension
  tension = ( tension / 34.1 );   //calcule la tension réelle

  int restant;
  if ( tension >= 25.46 ) {
    restant = 100;
  }

  else if ( tension >= 25.24 ) {
    restant = 90;
  }

  else if ( tension >= 25 ) {
    restant = 80;
  }

  else if ( tension >= 24.74 ) {
    restant = 70;
  }

  else if ( tension >= 24.48 ) {
    restant = 60;
  }

  else if ( tension >= 24.20 ) {
    restant = 50;
  }

  else if ( tension >= 23.92 ) {
    restant = 40;
  }

  else if ( tension >= 23.63 ) {
    restant = 30;
  }

  else if ( tension >= 23.32 ) {
    restant = 20;
  }

  else if ( tension >= 23.02 ) {
    restant = 10;
  }
  
  delay(750);
  display.fillRect( 102,  1,  25,  9,  BLACK);
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(103, 2);
  display.print(restant);
  display.print("%");
  display.display();


}



Title: Re: compteur de vitesse
Post by: kamill on Aug 18, 2019, 08:37 pm
Tu supprimes le delay(750)
Tu mémorises la dernière valeur de restant et tu ne réaffiche que si la valeur a changé.
Title: Re: compteur de vitesse
Post by: savoriano on Aug 18, 2019, 09:13 pm
Même chose pour la batterie.
Comme j'ai dit plus haut, peut être que il ne faut par effacer avant de récrire.
Title: Re: compteur de vitesse
Post by: Belo on Aug 19, 2019, 09:58 am
Si, j'ai testé et il faut effacer avant d'écrire à chaque fois sinon on écrit sur l'écriture et donc ça fait un truc chelou illisible.

Et c'est vrai que je n'avais pas pensé à supprimer le delay car c'était un programme seul à la base !.

Title: Re: compteur de vitesse
Post by: savoriano on Aug 19, 2019, 10:11 am
Quote
j'ai testé et il faut effacer avant d'écrire
Ok,
Plus réduire le blinking tu peux
Mémoriser la dernière valeur de vitesse et récrire seulement si nouvelle vitesse != ancienne vitesse.
Pour effacer plus rapidement tu peux écrire l'ancienne vitesse avec la couleur de fond: je pense que sera plus rapide.
Pour la batterie tu peux rafraîchir la valeur toute le minutes. Je pense que peut suffire.
Title: Re: compteur de vitesse
Post by: kamill on Aug 19, 2019, 10:15 am
Si, j'ai testé et il faut effacer avant d'écrire à chaque fois sinon on écrit sur l'écriture et donc ça fait un truc chelou illisible.
Tu peux aussi écrire avec le fond en précisant la couleur du fond dans setColor()
Code: [Select]
 display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(103, 2);
  display.print(restant);
  display.print("%");
  if (restant<100)
  display.print(" ");
  display.display();
Title: Re: compteur de vitesse
Post by: lesept on Aug 19, 2019, 10:26 am
En général on traite le cas des valeurs inférieures à 10 et à 100 en écrivant un espace à gauche, et pas à droite, pour éviter que le chiffre bouge bizarrement au passage de 9 à 10 par exemple.
Le plus simple serait d'utiliser un tableau de char pour écrire le texte formaté dedans puis d'afficher ce tableau sur l'écran.
Title: Re: compteur de vitesse
Post by: kamill on Aug 19, 2019, 10:45 am
Oui, c'est mieux.
J'avais respecté le cadrage initial.
Title: Re: compteur de vitesse
Post by: savoriano on Aug 19, 2019, 12:29 pm
Quote
Tu peux aussi écrire avec le fond en précisant la couleur du fond dans setColor()
Je n'avais pas vu ça!
Donc il faut refaire le test s'il faut effacer avant d'écrire en définissant la couleur du fond. 
Title: Re: compteur de vitesse
Post by: Belo on Aug 19, 2019, 03:13 pm
J'ai donc effacé toute la partie carrée à remplacer et j'ai continué mon programme qui permet d'afficher toutes les variables.  J'ai fait en m'inspirant de ce que vous aviez dit et alélioré et à partie de deux programmes que je vais nommer 1 et 2


programme1
Code: [Select]

#define valMin 410                          // Définir ici les seuils min
#define valMax 615                          // et max de l'analogRead.

const int valMoy = (valMin + valMax) / 2;
const int seuil = (valMax - valMin) / 2;
const int perimetre = 2;                    //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon                       !!!!! EN METRE !!!!!
bool flagMesure = false;
unsigned long tempstrouve = 0;
unsigned long dernierPassage = 0;
float vitesse = 0;
float distance = 0;

void Affiche (float distance, float vitesse) {
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(53, 2);
  display.print(distance, 1);

  display.setTextSize(4);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(vitesse, 0);
 
  display.display();
}

void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
  Affiche (distance, vitesse);
}


void loop() {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(74, 2);
  display.print("km");

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(52, 18);
  display.print("km/h");
  
  int diff = abs(analogRead(A0) - valMoy);
  if (diff >= seuil) { //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if (flagMesure) {
      tempstrouve = millis() - dernierPassage;
      dernierPassage = millis();
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;     // pour attente cycle suivant
      distance = distance + (perimetre / 1000.0);
      Affiche (distance, vitesse);
    }
  }
  else
  {
    flagMesure = true;  // prêt pour une nouvelle mesure
  }
}




programme 2
Code: [Select]



/*  Ce programme permet de calculer la vitesse en km/h d'un vélo ou autre à partie d'un capteur à effet hall numérique
 *  Il permet donc de calculer la vitesse instantanée, la distance du trajet, la vitesse max, la vitesse max totale ainsi que la distance totale.
 *  
 *  On stocke la vitesse max totale et la distance totale dans la mémoire EEPROM et on calcule la vitesse ( donc la distance, etc.. ) en mesurant le temps entre
 *  chaque interruptions ( donc passage de l'aimant devant le capteur == un tour de roue ) et en appliquant la formule v = d/t.
 *  
 *  Avant d'utiliser ce programme, il faut calculer le périmètre de la roue et le rentrer dans " int perimetre = (ici la valeur du périmètre en m)" Dans la ligne suivi de points d'exclamations.
 *  ((( Pour rappel le périmètre est égal à      pi x 2 x rayon       ou        pi x diamètre.   )))
 *  
 *  Ce programme ne permet pas l'affichage sur écran ou port série ou autres de ces valeurs. Il utilise un capteur à effet hall analogique UGN3503 qui envoie du 2.5v quand aucun champs magnétique,
 *  augmente quand un champs magnétique "nord" se rapproche ( quand il passe environ 3v ) et diminue quand un  champs magnétique "sud" se rapproche.
 */
#include <EEPROM.h>

void setup(){

  
}

void loop() {

  //les variables pour les calculs des variables finales
  float perimetre = 2;                      //!!!!!!!!!!!!!!!!!EN METRES!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  static unsigned long dernierPassage;
  static bool flagMesure = false;
  int tempstrouve;                          //le temps trouvé entre deux passage de l'aimant ( le temps trouvé pour un tour de roue )
  float distancebis;                        //la variable distancebis pour calculer la varible distance totale

  //les variables finales pour l'affichage : vitesse, distance, vitesse max, vitesse max totale et distance totale
  float vitesse;                            //la variable vitesse
  float distance;                           //la variable distance
  byte vitessemax;                          //la variable vitesse maximum                        //byte car 1 seul octet et suffisant ( à moins d'aller à plus de 255 km/h )
  byte vitessemaxtotale = EEPROM.read(0);   //la variable vitesse max totale pour l'EEPROM       //byte car 1 seul octet ( à moins d'aller à plus de 255 km/h )
  int distancetotale = EEPROM.get(1, distancetotale);      //la variable distance totale pour l'EEPROM



  if(analogRead(A0) <= 410  || analogRead(A0) >= 615) {     //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if(flagMesure)
    {
      unsigned long temps = millis();
      tempstrouve = temps - dernierPassage;
      dernierPassage = temps;
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;                                   // pour attente cycle suivant
      distance = distance + perimetre;
      distancebis = distancebis + perimetre;
    }
  }
  else
  {
    flagMesure = true;                               // prêt pour une nouvelle mesure
  }

 if(vitesse > vitessemax){                           //calcule la vitesse max du trajet
  vitessemax = vitesse;
 }
 if(vitessemax > vitessemaxtotale){                  //calcule la vitesse max totale
  vitessemaxtotale = vitessemax;
  EEPROM.update( 0, vitessemaxtotale);               //on écrit la variable vitesse max totale dans l'EEPROM
 }
 if(distancebis >= 1.0){
  distancetotale = distancetotale + distancebis;     //on calcule la variable distance totale
  distancebis = 0;                                   //on remet la variable distancebis à 0 pour le calcul suivant ( dans 1 km )
  EEPROM.put( 1, distancetotale);                    //on écrit la variable distance totale dans l'EEPROM
 }
}








Title: Re: compteur de vitesse
Post by: Belo on Aug 19, 2019, 04:44 pm
( second message car limite de caractères )

ce qui donne un programme final comme ceci :

Code: [Select]

/*  Ce programme permet de calculer la vitesse en km/h d'un vélo ou autre à partie d'un capteur à effet hall numérique et d'afficher ces variables suivantes.
 *  Il permet donc de calculer la vitesse instantanée, la distance du trajet, la vitesse max, la vitesse max totale ainsi que la distance totale.
 *   
 *  On stocke la vitesse max totale et la distance totale dans la mémoire EEPROM et on calcule la vitesse ( donc la distance, etc.. ) en mesurant le temps entre
 *  chaque interruptions ( donc passage de l'aimant devant le capteur == un tour de roue ) et en appliquant la formule v = d/t.
 * 
 *  Avant d'utiliser ce programme, il faut calculer le périmètre de la roue et le rentrer dans " int perimetre = (ici la valeur du périmètre en m)" Dans la ligne suivi de points d'exclamations.
 *  ((( Pour rappel le périmètre est égal à      pi x 2 x rayon       ou        pi x diamètre.   )))
 * 
 *  Ce programme utilise un bouton poussoir pour changer de menu ( il n'y en a que deux )  le premier menu affiche la vitesse instantanée et la distance du trajet, le second menu affiche quant à lui
 *  l'affichage de la vitesse max du trajet, de la vitesse max totale et de la distance totale depuis la première activation et utilisation du programme et du système.
 * 
 *  Le système utilise :  - un capteur à effet hall analogique UGN3503 qui envoie du 2.5v quand aucun champs magnétique,
 *                          augmente quand un champs magnétique "nord" se rapproche ( quand il passe environ 3v ) et diminue quand un  champs magnétique "sud" se rapproche.
 *               
 *                        - un écran oled 0.96" 128*64 piloté en I2C par un driver intégré SSD1306.
 */

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );

#include <EEPROM.h>



#define valMin 410                          // Définir ici les seuils min
#define valMax 615                          // et max de l'analogRead.

const int valMoy = (valMin + valMax) / 2;
const int seuil = (valMax - valMin) / 2;
const float perimetre = 2;                    //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon                       !!!!! EN METRE !!!!!
bool flagMesure = false;
unsigned long tempstrouve = 0;
unsigned long dernierPassage = 0;
float distancebis;
int boutonpoussoir = digitalRead(0);
bool menu2 = false;

//les variables finales pour l'affichage : vitesse, distance, vitesse max, vitesse max totale et distance totale
float vitesse;                            //la variable vitesse
float distance;                           //la variable distance
byte vitessemax;                          //la variable vitesse maximum                        //byte car 1 seul octet et suffisant ( à moins d'aller à plus de 255 km/h )
byte vitessemaxtotale = EEPROM.read(0);   //la variable vitesse max totale pour l'EEPROM       //byte car 1 seul octet ( à moins d'aller à plus de 255 km/h )
unsigned int distancetotale = EEPROM.get(1, distancetotale);      //la variable distance totale pour l'EEPROM


void Affichemenu1 (float distance, float vitesse) {            //paragraphe fini
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(53, 2);
  display.print(distance, 1);

  display.setTextSize(4);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(vitesse, 0);
 
  display.display();
}

void Affichemenu2 (byte vitessemax, byte vitessemaxtotale, unsigned int distancetotale){             //paragraphe à finir / non fini

  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print("vitesse max =    km/h ");

  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print("vitesse max totale =    km/h ");

  display.setTextSize(2);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print("distance totale =     km");

  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(vitessemax);

 
 
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(vitessemax);

  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(vitessemaxtotale);

  display.setTextSize(2);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(distancetotale, 0);
 
  display.display();
}

void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
 // Affichemenu1 (distance, vitesse);
}


void loop() {
 
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(74, 2);
  display.print("km");

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(52, 18);
  display.print("km/h");
 
  int diff = abs(analogRead(A0) - valMoy);
  if (diff >= seuil) { //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if (flagMesure) {
      tempstrouve = millis() - dernierPassage;
      dernierPassage = millis();
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;     // pour attente cycle suivant
      distance = distance + (perimetre / 1000.0);
      distancebis = distance + (perimetre / 1000.0);
      Affichemenu1 (distance, vitesse);
    }
  }
  else
  {
    flagMesure = true;  // prêt pour une nouvelle mesure
  }

  if(boutonpoussoir == 1 and menu2 == false){
    delay(100);                                    //anti-rebond
    display.clearDisplay();
    Affichemenu2;
    menu2 = true;
  }
  else if(boutonpoussoir == 1 and menu2 == true){
    delay(100);                                     //anti-rebond
    display.clearDisplay();
    Affichemenu2;
    menu2 = false;
  }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 if(vitesse > vitessemax){                           //calcule la vitesse max du trajet
  vitessemax = vitesse;
 }
 if(vitessemax > vitessemaxtotale){                  //calcule la vitesse max totale
  vitessemaxtotale = vitessemax;
  EEPROM.update( 0, vitessemaxtotale);               //on écrit la variable vitesse max totale dans l'EEPROM
 }
 if(distancebis >= 1.0){
  distancetotale = distancetotale + distancebis;     //on calcule la variable distance totale
  distancebis = 0;                                   //on remet la variable distancebis à 0 pour le calcul suivant ( dans 1 km )
  EEPROM.put( 1, distancetotale);                    //on écrit la variable distance totale dans l'EEPROM
 }
}





Il y a sans aucun doute un bon ptit millier d'erreurs et je m'excuse de la lisibilité atroce du programme ( le bordel quoi 8)
Je l'ai testé sans changer de mode mais j'ai l'impression que ça ralentit tout du coup !... :smiley-cry: En gros, j'ai l'impression de retourner à la case départ: l'affichage est plus lent et je peux mesurer 19 km/h max.
Je n'ai pas changé de mode car je n'ai simplement pas de bouton-poussoir mais je vais sans doute en trouver un sur un vieux circuit type autoradio ou n'importe quoi ( ça se trouve partout de toute façon !!! ).