Go Down

Topic: Problème tachymètre sur carte UNO (Read 782 times) previous topic - next topic

Condecta

bonjours à tous,

Je suis en ce moment sur un projet de tachymètre avec capteur Hall sur carte UNO, qui d'ailleurs fonctionne bien, mais avec un petit soucis d'affichage de la valeur lors de l'arrêt du moteur .

Mon capteur Hall fonctionne de la manière suivante, lors du passage de l'aimant la broche de sortie de celui-ci passe au niveau bas et sans l'aimant reste au niveau haut.

Le code ci-dessus est trouvé sur le net car je n'ais pas encore assez de connaissance! mais petit à petit l'oiseau fait son nid, je l'ais juste modifié pour l'écran LCD.

L'avantage de ce code qui fonctionne avec la mesure par interruption attachInterrupt(), c'est pour moi le seul qui permet de travailler en parallèle avec le reste du programme en cours .

Mon problème est le suivant, lors de l'arrêt du moteur mon afficheur LCD m'affiche la dernière la valeur gardée en mémoire donc une valeur fausse à la place de 0 Trs/min,  le comptage ne se reset pas, par contre en mouvement tout fonctionne bien et la valeur en RPM est correct.

Voilà le code, j'espère que quelqu'un puisse m'aider à modifier ce code ou me donner une explication.

Merci ...

Code: [Select]
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd (0x27, 2,1,0,4,5,6,7,3,POSITIVE);

#define NOT_AN_INTERRUPT -1

/* constantes pour la broche de mesure */
const byte PIN_SIGNAL = 2;

/* Variables pour la mesure */
volatile unsigned long periode = 0;

/** Fonction d'interruption pour la mesure entre deux fronts */
void tick() {
  static unsigned long previousMicros = 0;
  unsigned long currentMicros = micros();
 
  /* Calcul le temps écoulé depuis le précédent front */
  periode = currentMicros - previousMicros;
 
  /* Met à jour la variable pour la prochaine interruption */
  previousMicros = currentMicros;
}

/** Fonction setup() */
void setup() {
 
  lcd.begin(16,2);
  lcd.clear();
  /* Initialise le port série */
  Serial.begin(115200);
 
  /* Met la broche en entrée */ 
  pinMode(PIN_SIGNAL, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_SIGNAL), tick, FALLING);
 
  /* Permet une première màj de "periode" */
 
}

/** Fonction loop() */
void loop() {
 
  lcd.setCursor(0,0);
  lcd.print(1000000 / periode * 15);
  lcd.print("Trs/min      ");
  /* Affiche le résultat de la mesure en RPM */
  Serial.println(1000000 / periode * 15);
 
}

 


infobarquee

bonjour,
tu peux utiliser la variable periode pour ca dans ton loop.
si elle est supérieure à X seconde ===> periode = 0
AUCUNE AIDE PAR MP

Condecta

Merci pour le conseil, avec plusieurs tentatives et essais divers, je suis arrivé au résultat que j'attendais!
En utilisant la fonction millis(), j'ai d'abord tenté de suivre ton conseil en intégrant dans loop que si la période > que temps le calcul se reset et m'affiche 0, mais cela ne fonctionne pas parce que le comptage du temps entre 1er et 2ème front ne s'effectue qu'avec un certain nombre de tour au démarrage, donc lors de l'arrêt complet du rotor ma condition n'est pas valable, enfin je crois ou je n'ais pas compris ta suggestion entre période et temps X.

Tandis qu'avec la fonction millis(), le compteur  de celle-ci et remis à 0 dans void tick(), pendant la phase de calcul des fronts. Dès que le moteur se retrouve à l'arrêt, le compteur démarre pour ensuite définir que  ==>période = 0;  sinon afficher "0 Trs/min" sur le LCD.

Voilà mon résultat...

Le code ci-dessous modifié;


Code: [Select]
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd (0x27, 2,1,0,4,5,6,7,3,POSITIVE);
int long temps ;
#define NOT_AN_INTERRUPT -1

/* constantes pour la broche de mesure */
const byte PIN_SIGNAL = 2;

/* Variables pour la mesure */
volatile unsigned long periode = 0;

/** Fonction d'interruption pour la mesure entre deux fronts */
void tick() {
  static unsigned long previousMicros = 0;
  unsigned long currentMicros = micros();
 
  /* Calcul le temps écoulé depuis le précédent front */
  periode = currentMicros - previousMicros;
  temps=millis()-0;
  /* Met à jour la variable pour la prochaine interruption */
  previousMicros = currentMicros;
}

/** Fonction setup() */
void setup() {
 
  temps = millis();
  lcd.begin(16,2);
  lcd.clear();
  /* Initialise le port série */
  Serial.begin(115200);
 
  /* Met la broche en entrée */ 
  pinMode(PIN_SIGNAL, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_SIGNAL), tick, FALLING);
 
  /* Permet une première màj de "periode" */
  delay(500);
}

/** Fonction loop() */
void loop() {

 if((millis()-temps)>2000){
  periode = 0;
 
  lcd.setCursor(0,0);
  lcd.print("0 Trs/min       ");}
 
  else{
  lcd.setCursor(0,0);
  lcd.print(1000000 / periode * 30);
  lcd.print(" Trs/min         ");
  /* Affiche le résultat de la mesure en RPM */
  Serial.println(1000000 / periode * 30);
  delay(1000);
 
 
}}

 


infobarquee

Code: [Select]
temps=millis()-0;
ca ne rime à rien cette formule
autant écrire
temps = 20000 -0 ===> fera toujours 20000

tu peux simplifier en mettant temps en micros()
dans ton loop
pas besoin de else etc... qui va ralentir ton code

Code: [Select]
if ((micros() - periode) > 200000) periode = 0; // valeur au pif
AUCUNE AIDE PAR MP

Condecta

Ok donc avec le code suivant?


Code: [Select]
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd (0x27, 2,1,0,4,5,6,7,3,POSITIVE);
int long temps ;
#define NOT_AN_INTERRUPT -1

/* constantes pour la broche de mesure */
const byte PIN_SIGNAL = 2;

/* Variables pour la mesure */
volatile unsigned long periode = 0;

/** Fonction d'interruption pour la mesure entre deux fronts */
void tick() {
  static unsigned long previousMicros = 0;
  unsigned long currentMicros = micros();
 
  /* Calcul le temps écoulé depuis le précédent front */
  periode = currentMicros - previousMicros;
 
  /* Met à jour la variable pour la prochaine interruption */
  previousMicros = currentMicros;
}

/** Fonction setup() */
void setup() {
 
  temps = millis();
  lcd.begin(16,2);
  lcd.clear();
  /* Initialise le port série */
  Serial.begin(115200);
 
  /* Met la broche en entrée */ 
  pinMode(PIN_SIGNAL, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_SIGNAL), tick, FALLING);
 
  /* Permet une première màj de "periode" */
  delay(500);
}

/** Fonction loop() */
void loop() {

 if ((micros() - periode) > 2000000){ //micros = 2 secondes
  periode = 0;
 }
 
  lcd.setCursor(0,0);
  lcd.print(1000000 / periode * 30);
  lcd.print(" Trs/min         ");
  /* Affiche le résultat de la mesure en RPM */
  Serial.println(1000000 / periode * 30);
  delay(1000);
 
 
}

 


infobarquee

par exemple, mais vire le   delay(1000)
delay = blocage du code
AUCUNE AIDE PAR MP

Condecta

je viens de tester sans ou avec delay, négatif, plus de comptage et moteur à l'arrêt valeur affichée ("4294697266 Trs/min").

infobarquee

#7
Apr 25, 2017, 03:54 pm Last Edit: Apr 25, 2017, 04:14 pm by infobarquee
mets le code modifié
et rajoute dans le loop
mets le résultat aussi

Code: [Select]
Serial.println(periode);


EDIT
erreur de ma part
previousMicros et non periode, puisque periode est un résultat

Code: [Select]
if ((micros() -previousMicros) > 2000000) periode = 0;
AUCUNE AIDE PAR MP

Condecta

Code: [Select]
Voilà le code modifié, mais cela ne fonctionne pas, enfin le comptage s'effectue seulement 2 seconde au démarrage, par contre j'étais obligé de mettre previousMicros en int en haut de programme parce qu'au téléversement il m'affichait "previousMicros was not declared in this scope".
Le moniteur série affiche 0 à l'arrêt en en mouvement la valeur de la periode...

[code#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd (0x27, 2,1,0,4,5,6,7,3,POSITIVE);
#define NOT_AN_INTERRUPT -1

/* constantes pour la broche de mesure */
const byte PIN_SIGNAL = 2;
int previousMicros;
/* Variables pour la mesure */
volatile unsigned long periode = 0;

/** Fonction d'interruption pour la mesure entre deux fronts */
void tick() {
  static unsigned long previousMicros = 0;
  unsigned long currentMicros = micros();
 
  /* Calcul le temps écoulé depuis le précédent front */
  periode = currentMicros - previousMicros;
 
  /* Met à jour la variable pour la prochaine interruption */
  previousMicros = currentMicros;
}

/** Fonction setup() */
void setup() {
 
 
  lcd.begin(16,2);
  lcd.clear();
  /* Initialise le port série */
  Serial.begin(115200);
 
  /* Met la broche en entrée */ 
  pinMode(PIN_SIGNAL, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_SIGNAL), tick, FALLING);
 
  /* Permet une première màj de "periode" */
  delay(500);
}

/** Fonction loop() */
void loop() {
 
 if((micros()- previousMicros)>2000000){
  periode = 0;}
 
 
  lcd.setCursor(0,0);
  lcd.print(1000000 / periode * 30);
  lcd.print(" Trs/min         ");
  /* Affiche le résultat de la mesure en RPM */
 
  Serial.println(periode);
 
 
 
}

 

]

infobarquee

y a rien qui te gène dans ton code?

Code: [Select]
int previousMicros;
....
  static unsigned long previousMicros = 0;
.......
  previousMicros = currentMicros;
AUCUNE AIDE PAR MP

infobarquee

#10
Apr 25, 2017, 08:50 pm Last Edit: Apr 25, 2017, 08:51 pm by infobarquee
teste ca

Code: [Select]
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd (0x27, 2,1,0,4,5,6,7,3,POSITIVE);
#define NOT_AN_INTERRUPT -1

/* constantes pour la broche de mesure */
const byte PIN_SIGNAL = 2;
unsigned long previousMicros;
 unsigned long currentMicros;
/* Variables pour la mesure */
volatile unsigned long periode = 0;

/** Fonction d'interruption pour la mesure entre deux fronts */
void tick() {

  currentMicros = micros();
 
  /* Calcul le temps écoulé depuis le précédent front */
  periode = currentMicros - previousMicros;
 
  /* Met à jour la variable pour la prochaine interruption */
  previousMicros = currentMicros;
}

/** Fonction setup() */
void setup() {
 
 
  lcd.begin(16,2);
  lcd.clear();
  /* Initialise le port série */
  Serial.begin(115200);
 
  /* Met la broche en entrée */
  pinMode(PIN_SIGNAL, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_SIGNAL), tick, FALLING);
 
  /* Permet une première màj de "periode" */
  delay(500);
}

/** Fonction loop() */
void loop() {
 
 if((micros()- previousMicros)>2000000)  periode = 0;
 
 
  lcd.setCursor(0,0);
  lcd.print(1000000 / periode * 30);
  lcd.print(" Trs/min         ");
  /* Affiche le résultat de la mesure en RPM */
 
  Serial.println(periode);
 
 
 
}

 

]
AUCUNE AIDE PAR MP

Condecta

Ah là je m'incline! c'est bon sa fonctionne bien et ton code et plus simple que le mien, l'expérience sans doute, merci beaucoup pour ton aide et  ta patience et à bientôt pour un nouveau projet...

infobarquee

de rien, simplement un peu de réflexion.
édite ton 1er post et mets RESOLU
AUCUNE AIDE PAR MP

Condecta

bonjours à tous,

Je suis en ce moment sur un projet de tachymètre avec capteur Hall sur carte UNO, qui d'ailleurs fonctionne bien, mais avec un petit soucis d'affichage de la valeur lors de l'arrêt du moteur .

Mon capteur Hall fonctionne de la manière suivante, lors du passage de l'aimant la broche de sortie de celui-ci passe au niveau bas et sans l'aimant reste au niveau haut.

Le code ci-dessus est trouvé sur le net car je n'ais pas encore assez de connaissance! mais petit à petit l'oiseau fait son nid, je l'ais juste modifié pour l'écran LCD.

L'avantage de ce code qui fonctionne avec la mesure par interruption attachInterrupt(), c'est pour moi le seul qui permet de travailler en parallèle avec le reste du programme en cours .

Mon problème est le suivant, lors de l'arrêt du moteur mon afficheur LCD m'affiche la dernière la valeur gardée en mémoire donc une valeur fausse à la place de 0 Trs/min,  le comptage ne se reset pas, par contre en mouvement tout fonctionne bien et la valeur en RPM est correct.

Voilà le code, j'espère que quelqu'un puisse m'aider à modifier ce code ou me donner une explication.

Merci ...

Go Up