Dans la réalisation d'un projet personnel, je voudrais réaliser un compteur de vitesse pour vélo via mon arduino uno avec un écran lcd et un capteur à effet de hall
Tout d'abord, je voulais vous montrer ce que j'ai fais:
#include <Adafruit_GFX.h>
#define PULSE_PIN 2
#define PULSE_TIMEOUT 1000000
#include <SPI.h>
#include <Adafruit_PCD8544.h>
#include <avr/sleep.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
unsigned long trm;
const float pi = 3.14;
void setup()
{
pinMode(PULSE_PIN, INPUT);
display.begin();
display.setContrast(50);
digitalWrite(PULSE_PIN, HIGH);
}
void loop()
{
trm = pulseIn(PULSE_PIN, LOW, PULSE_TIMEOUT);
trm = (60 / (trm / 1000000.0)) * 1.2874; // trm=km/h et 1.2874 périmeter de ma roue
display.clearDisplay();// efface le lcd
display.println(trm, DEC);
display.display();// affiche la lettre
delay(500);
}
Mon soucis arrive là, mon écran Lcd m'affiche des valeurs énorme comme 20540 et ma valeur n'est pas fixe elle varie très souvent!
Je pense que mon équation est bonne et j'ai pensé à mon capteur à effet hall qui est le suivant: Capteur à effet hall
Si vous aviez une idée de la ou je m**** je suis preneur, je débute
Sinon si j'arrive à réaliser cela pour mon vélo, je voudrais l'implanter dans un longskate que je partagerais avec plaisir
A mon avis l'utilisation de PulseIn pour mesurer le temps entre 2 passages à HIGH du pin sur lequel est branché ton capteur n'est pas la bonne solution.
Avec ton code, PulseIn déclanche le début de la mesure lorsque le pin 2 est à LOW mais par forcement au moment du passage à LOW du pin et arrête la mesure au moment du passage à HIGH du pin 2. Tu peux/as donc probablement un démarrage de la mesure du temps en cours de cycle. La durée mesurée est donc bien inférieure à la réalité et donc ta vitesse beaucoup plus importante.
ex :
| |____| |
| |
| fin de la mesure
début de la mesure
Tu devrais plutot utiliser les interruptions pour mesurer le temps entre 2 valeurs HIGH du pin 2.
Bigben99, impossible de trouver de bon renseignements sur les interrupteurs avec mon projet! Je galère vachement avec les interrupteurs et ça complique énormement le code non ?
J'ai essayé de m'inspirer de ce code suivant mais je suis cuis, j'y arrive pas :s
//calculations
//tire radius ~ 13.5 inches
//circumference = pi*2*r =~85 inches
//max speed of 35mph =~ 616inches/second
//max rps =~7.25
#define reed 2//pin connected to read switch
//storage variables
int reedVal;
long timer;// time between one full rotation (in ms)
float mph;
float radius = 13.5;// tire radius (in inches)
float circumference;
int maxReedCounter = 100;//min time (in ms) of one rotation (for debouncing)
int reedCounter;
void setup(){
reedCounter = maxReedCounter;
circumference = 2*3.14*radius;
pinMode(reed, INPUT);
// TIMER SETUP- the timer interrupt allows precise timed measurements of the reed switch
//for more info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
cli();//stop interrupts
//set timer1 interrupt at 1kHz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;
// set timer count for 1khz increments
OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
//END TIMER SETUP
Serial.begin(9600);
}
ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
reedVal = digitalRead(reed);//get val of A0
if (reedVal){//if reed switch is closed
if (reedCounter == 0){//min time between pulses has passed
mph = (56.8*float(circumference))/float(timer);//calculate miles per hour
timer = 0;//reset timer
reedCounter = maxReedCounter;//reset reedCounter
}
else{
if (reedCounter > 0){//don't let reedCounter go negative
reedCounter -= 1;//decrement reedCounter
}
}
}
else{//if reed switch is open
if (reedCounter > 0){//don't let reedCounter go negative
reedCounter -= 1;//decrement reedCounter
}
}
if (timer > 2000){
mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
}
else{
timer += 1;//increment timer
}
}
void displayMPH(){
Serial.println(mph);
}
void loop(){
//print mph once a second
displayMPH();
delay(1000);
}
Si vous pouviez me faire un petit boost, petit aide, ce serait super cool, merci beaucoup!
pulsuIn ne mesure pas la période complète du signal mais la période à l'état haut ou la période à l'état bas ce qui n'est pas adapté au besoin.
Il faudrait générer une interruption au passage de l'aimant devant le capteur et mémoriser la valeur de micro() au moment de l'interruption pour calculer le temps écoulé depuis l'interruption précédente.
J'edit ce message car j'ai peut être trouvé une solution mais ce n'est pas encore ça. En effet, comme vous me l'avez conseillé j'utilise maintenant des interruptions et voici le code:
//Mesure du nombre de tours avec capteur à effet Hall + aimant.
//Ce programme mesure le temps passé pour effectuer 1 tours ( 1 fronts montants du capteur) et l’envoi au PC. Premiere valeur faussée?
//Capteur sur pin 2 et pull up interne sur pin 2 activé.
//Capteur à effet Hall US5881LUA 22/09/2012
volatile byte cpttours; // compage tours
unsigned int tp_ms ; // Temps en ms
unsigned long tempsprec; // Time précédent
//unsigned long rpm;
void setup() //Setup
{
Serial.begin(9600); // Init liaison serie
attachInterrupt(0,Int0, RISING); // Init interruption 0
digitalWrite(2, HIGH); // Pull up sur broche 2
cpttours = 0; // Raz cpttours
tp_ms = 0; // Raz tp_ms
tempsprec = 0; // Raz tempsprec
}
void loop() // Boucle
{
if (cpttours >= 1) // Si cpttours >= 2
{
tp_ms = (millis() - tempsprec); // Temps écoulé
tempsprec = millis(); // Copie millis() dans tempsprec
cpttours = 0;
//tp_ms = (1/tp_ms)*60;
//Serial.write(2); // Start of text
Serial.println(tp_ms, DEC); // Envoi temps en ms
//Serial.write(3); // End of text
}
}
void Int0 () // Interruption
{
cpttours++; // Increment cpttours
}
Cela m'affiche le temps en ms (dans les 300ms pour faire un tour avec un aimant accroché sur un tournevis lui même accroché sur une visseuse électrique.
Sauf que quand je rentre la formule tp_ms = (1/tp_ms)*60; pour m'afficher les tr/min mais ca me met tous le temps 0!
Bigben, est-ce que je susi dans la bonne voie au moins ?
Merci à vous en tout cas!!
Pour les interruptions, il faut regarder du coté de la fonction attachInterrupt(interrupt, ISR, mode).
// en branchant le capteur sur le pin 2
volatile long lastTime;
volatile long period = 0;
void setup() {
attachInterrupt(0, highTime, RISING);
}
void loop() {
if(period > 0) {
// calcul de la vitesse par rapport à la valeur de la variable period
}
}
void highTime() {
long time;
time = millis();
period = lastTime - time
lastTime = time
}
A chaque passage de LOW à HIGH (RISING), l'interruption sur le pin 2 sera activée et la méthode highTime sera exécutée. La méthode effectue une prise de temps et le calcul du temps écoulé depuis la dernière prise de temps. Tu n'as plus qu'à utiliser la variable period (en ms) pour calculer ta vitesse.
Je commence un peu à comprendre ce qu'il se passe avec les interruptions, c'est juste une histoire d'enregistrer le temps entre deux RISING c'est ça!
Du coup je suis repartis de ton code (merci) et tu as tout fais en fait?
//Mesure du nombre de tours avec capteur à effet Hall + aimant.
//Ce programme mesure le temps passé pour effectuer 1 tours ( 1 fronts montants du capteur) et l’envoi au PC. Premiere valeur faussée?
//Capteur sur pin 2 et pull up interne sur pin 2 activé.
unsigned int tp_ms ;
volatile long lastTime;
volatile long period = 0;
void setup()
{
Serial.begin(9600);
attachInterrupt(0,highTime, RISING); // Init interruption 0
digitalWrite(2, HIGH); // Pull up sur broche 2
tp_ms = 0;
}
void loop()
{
if (period > 0)
{
tp_ms = (1/period)*60;
Serial.println(tp_ms, DEC);
}
}
void highTime ()
{
long time;
time = millis();
period = lastTime - time;
lastTime = time ;
}
Bon cela ne m'affiche rien mais normalement c'est ça ?
hum... je ne comprends pas le calcul que tu fais pour alimenter tp_ms. A quoi correspond cette variable ? Si cela correspond au temps en milliseconde d'une période, tu as déjà cette information dans période.
Quoi qu'il en soit, tes variables sont déclarées en int et tu commences ton calcul par 1 / period donc un réel inférieur à 1 donc c'est normal que tu ne vois pas grand chose. En toute logique tu ne devrais avoir que des 0.
Le calcul c'est pour avoir la fréquence donc 1/périod et si je multiplie ça par 60 je l'ai en tour/ minutes.
Oui oui j'ai corrigé la déclaration de tp_ms en regardant dans mes cours en double mais ça ne m'affiche rien à par si je change les déclarations de volatile long...
Pfiou, ca marche pas d'un coté, ça marche pas de l'autre muarf, je suis un boulet, désolé et merci de ton aide en tout cas!
pourquoi calcules-tu une fréquence ? Je croyais que tu voulais une vitesse ? Or tu as un temps (period) et une distance (le périmétre de ta roue) donc tu n'as rien d'autre à faire que le rapport de ta distance au temps pour avoir ta vitesse, non ?
Sinon, essaies d'y aller par étape, vérifie que tu as bien une valeur dans time à chaque fois que tu passes l'aimant devant ton capteur. Puis vérifie la différence et la valeur de périod.
Bonjour à tous les arduineurs en ligne sur ce post que je me permets de déterrer après quelques mois de repos.
j'ai effectué le montage et injecté le code, mais j'obtiens des données erronées. Pire, lorsque je retire le capteur du breadboard, j'ai toujours les même valeurs et lorsque je "stimule" le capteur avec un aimant, sa led s'allume, mais l'affichage ne varie pas...
A votre avis, d'où peut venir le problème ?
merci à vous d'avance