Bonjour,
je suis sur un projet assez simple, mon but est de calculer la vitesse de deux roues de vélo qui tournent l'une sur l'autre( étude du glissement). J'aimerais tracer les courbes de vitesses à l'aide du traceur série pour pouvoir observer le glissement lors d'un freinage.
Voici le principe de mon capteur de vitesse: de part et d'autre de chaque roue j'ai placé une photodiode et une lampe torche, un carton troué de quatre trous est placé sur les rayons de la roue. La photodiode capte les flashs de lumière et mon programme permettrait de calculer le temps entre chaque flashs. Connaissant le temps entre chaque flashs et la distance entre les trous je peux alors remonter à la vitesse.
Je découvre Arduino et après de nombreuses recherches autour du sujet j'avoue m'être un peu emmêlé les pinceaux. J'espérais que vous pourriez m'aider à débroussailler mon programme et me donner quelques conseils quant à la précision de mes mesures. Merci d'avance pour votre aide.
float pDiode1=A0;
float pDiode2=A1;
float value1;
float value2;
float dt1;
float dt2;
unsigned long ot1=0;
unsigned long ot2=0;
float vitesse1; //vitesse de la roue de voiture
float vitesse2; //vitesse de la voiture par rapport à la route
float distance1; //distance entre deux trous du carton
float distance2;
void setup() {
Serial.begin(9600);
pinMode(pDiode1,INPUT);
pinMode(pDiode2,INPUT);
// put your setup code here, to run once:
}
void loop() {
value1=analogRead(pDiode1); //lie la valeur de la diode1
value2=analogRead(pDiode2); //lie la valeur de la diode2
dt1=100;
dt2=100;
if((value1>10) && dt1>80) //début du capteur de vitesse pour la roue de la voiture, si la valeur que lit le capteur est superieur à une certaine tension alors le programme la relève
{
unsigned long dt1=millis()-ot1; //calcul le temps entre deux trous
ot1=millis();
if (dt1>30)
{
distance1=PI/2;
vitesse1=(distance1*1000)/dt1; //vitesse en metre/sec
Serial.print(vitesse1);
}
Serial.println();
}
if((value2>15) && dt2>80) //début du capteur de vitesse pour la vitesse de la voiture par rapport à la route
{
unsigned long dt2=millis()-ot2; //calcul le temps entre deux trous
ot2=millis();
if (dt2>30)
{
distance2=PI/2;
vitesse2=(distance2*1000)/dt2; //vitesse en metre/sec
Serial.print(vitesse2);
}
}
}
L'idéal pour ce genre de mesures, est d'utiliser les interruptions et, pour ce faire, utiliser les entrées 2 et 3 de ton Arduino.
Mets tes photodiodes sur ces 2 entrées et, avec un digitalRead(pDiode1); et un digitalRead(pDiode2); contrôles bien que tu aies 1 et 0, illuminée et pas illuminée.
Après, de par les interruptions, tu as en "direct" et en permanence le temps entre 2 trous pour les 2 roues.
Bonjour jpbbricole et merci beaucoup de ta réponse,
le digitalRead affiche bien des 1 pour illuminé et des 0 sinon. J'ai donc essayé dans un premier temps de relever le temps entre deux flashs pour une seule photodiode, j'ai deux problèmes; le chronomètre, je ne suis pas convaincu par mes boucles notamment où placer le "ot1=millis()" et deuxième problème, lorsque la photodiode détecte un flash, elle ne renvoie pas qu'un seul 1 mais plusieurs à la suite( dû au renouvellement de la boucle je pense), comment faire pour que le chronomètre de se déclenche qu'au "premier 1"?
Je te fais suivre le code que j'ai écrit;
int pDiode1=3;
int value1;
float ot1=0;
float dt1;
void setup() {
Serial.begin(9600);
pinMode(pDiode1,INPUT);
// put your setup code here, to run once:
}
void loop() {
value1=digitalRead(pDiode1);
if (value1==1);
{
unsigned long dt1=millis()-ot1;
ot1=millis();
Serial.println(dt1);
}
// put your main code here, to run repeatedly:
}
Ca peut provenir du temps de transition du 0 au 1 qui ne se fait pas franchement, un peu comme les rebonds d'un bouton.
Mesurer comme tu le fais, n'est, à mon avis, pas la meilleur façon de procéder. Le mieux est d'utiliser les interruptions. L'avantage est que la mesure se fait "sans que tu t'en occupes", et le résultat est directement disponible.
Je te fais un exemple.
Le code en question ne testait que l'état pas les fronts, le problème c'est plutôt que loop() avait le temps de faire plusieurs itérations.
Quelques conseils pour rendre la mesure plus simple
placer les photodiodes dans un petit tube pour réduire leur champs de vision.
tu utilises une torche pour éclairer, donc tu travailles dans le visible. Il faut par conséquent limiter les lumières parasites, faire les mesures dans une pièce sombre de préférence. Le plus simple aurait été de choisir une source de lumière et une photodiode travaillant dans l'infrarouge.
faire des trous assez petits dans le masque placé sur la roue.
si ce sont vraiment des photodiodes (on appelle photodiode tout et n'importe quoi qui capte la lumière), elles ont l'inconvénient de ne délivrer qu'un courant assez faible. Il faut ajouter un étage derrière pour donner du gain et mettre en forme le signal pour qu'il soit exploitable par l'Arduino.
Merci pour ton programme jpbbricole qui fonctionne parfaitement. J'ai juste modifié le nombre dans le Serial.begin; 115200 ne m'affichait que des "?", j'ai donc essayé avec 9600 et cela fonctionnait (j'avoue ne pas bien percevoir la différence entre les deux...) .
Le temps de contrôle pour l'anti-rebond est adapté.
J'en déduis qu'à l'aide de ce programme je peux remonter à la vitesse de mes roues connaissant le nombre de pics durant 1 seconde (2 pics=PI/2). Par contre je pense qu'au début de chaque mesure je vais mettre mes photodiodes en face d'un trou pour pouvoir connaître la distance exact parcouru par mes roues (le premier pic indiquera donc que ma roue a tourné de PI/2).
Je te fais suivre la ligne de code que j'ai modifié pour que le moniteur m'affiche la vitesse des roues:
Peut-être y-a-t-il plus simple ou plus compact... dans tous les cas, j'ai des ordres de grandeurs de l'orde de 90 m/s ce qui est impossible donc j'ai du faire une erreur de conversion d'unité...
Sauf si je me trompe, 35km/h c'est 9,7m/s Avec une roue se 0,62m de diamètre soit de 1,94 m de circonférence, cela fait 5 tours par secondes soit 20 impulsions par secondes.
On peur compter les impulsions pendant une seconde maison obtient une valeur bonne avec 5% de tolérance pour 35km/h. Si des fois on mesure en dessous de 2km/h, On aura moins de 1 impulsion par seconde et le résultat sera parfois de 1 impulsion dans la seconde, parfois de 0.En dessous de 2km/h on aura une mesure qui donnera parfois 2km/h, parfois 0km/h
Pour mesurer une période ou une fréquence, on peut mesurer le plus avantageux et faire un calcul. Si on veut un affichage toutes les secondes, et si on veut 1% d'erreur max, il faut compter au moins 100 impulsions.
Dans le cas présent, il faut mesurer la période du signal (temps entre deux impulsions) et prendre l'inverse (avec un float) pour avoir le nombre d'impulsions par seconde. Avec une impulsion toutes les 50ms, on a une précision de 4% à 35km/h (millis est précis à 2ms environ). En utilisant micro on augmente gratuitement la précision.
A éviter en une seul fois: Serial.println(String(pDiode1Compteur) + "\t" + String(pDiode2Compteur));
qui doit fragmenter la mémoire et bloquer le fonctionnement. Utiliser plutôt 3 print.
Attention aussi à Serial.println(pDiode1Compteur);
Car la valeur de pDiode1Compteur est changée pendant une interruption et la lecture sans protection peut donner une erreur de lecture.
Pourquoi int?
− on attend des valeurs négatives? si non prendre plutôt unsigned int
− on attend plus de 127 impulsions (va-t-on dépasser les 200 km/h)? si non autant prendre un byte ou un uint8_t qui en outre est non signé
D'ccord si il y a des pins négatives et si la carte a plus de 256 broches. Mais si c'est pour utiliser derrière pinMode(pDiode1,INPUT); qui attend un uint8_t, autant prendre une bonne habitude de mettre const uint8_t pDiode1 = 2;
Je suis conscient que le compilateur corrige cette erreur et que le code généré est le même, mais ce n'est pas une bonne raison de le faire.
Il y a aussi les conventions du C qui préconisent de mettre les constantes en majuscules. C'est toujours mieux de bine écrire. Surtout si on fait relire le code par quelqu'un d'autre.
62cm c'est par exemple 620/1000 mais pas 6200/1000. Ta vitesse est de 9m/s
Si on veu des vitesses correctes, il vaut mieux n'avoir qu'une impulsion par tour, comme tous les compteurs de vitesses, plutôt que 4. Si on en veut 4, il faut alors être sûr qu'ils soit parfaitement positionnés pour ne pas introduire d'erreur supplémentaire. Avec une seule impulsion par tour, il n'y a plus d'erreru dû au positionnement. Et cela n'a pas d'intérêt de mettre 4 impulsions par tour.
Il aurait mieux valu faire le contraire conserver 115200 dans le programme et changer la vitesse dans la console série.
Le problème d'utiliser 9600 bauds c'est que s'il y a beaucoup de texte à transférer on peut saturer le buffer d'emission et dans ce cas on ralenti le programme
Edit : pas vu que fdufnews avait déjà répondu sur ce point.
La communication série n'utilise qu'un seul fil : celui des données
Comme il n'y a pas de fil horloge il faut que l'émetteur et le récepteur soit réglé sur le même débit.
En conséquence, si tu émets à 115200 il faut aussi le spécifier au moniteur de l'IDE arduino.
Tu ne vois pas la différence, mais tu en verras le jour où la loop() devra être rapide et qu'elle sera ralentie parce que tu auras un long message émis à seulement 9600.
Sauf que tu ne te le rappelleras pas et que tu ne comprendras pas.
Merci pour tes conseils et explications. Il y a juste une chose sur laquelle je doute un peu c'est le fait de n'avoir qu'une impulsion par tour; certes il y aura plus d'erreur lié au positionnement des trous mais la vitesse des roues peut très bien varier entre deux impulsions ( ce que je ne verrais pas s'il n'y a qu'un seul trou).