Go Down

Topic: [ ] Problème de priorité des conditions (Read 12580 times) previous topic - next topic

electricircus

Hello,

Ouch! je ne comprends plus!
les capteurs ne répondent plus, pourtant ils fonctionnent avec d'autres codes...

affichage 0 cm sur le moniteur série
et je ne vois pas ce que j'oublie dans le code

Code: [Select]
#include "URMSerial.h"   
#include "Servo.h" 
URMSerial urm;   
Servo myservo; //objet servo controle un servo

int distance1;
int distance2;
int E1 = 5;     //M1 Speed Control  //Standard PWM DC control
int E2 = 6;     //M2 Speed Control
int M1 = 4;    //M1 Direction Control
int M2 = 7;    //M1 Direction Control
int IRpin = 19;   // déclaration du pin pour le capteur


// déclaration des constantes utiles

const int R=1;
const int V=1;

// --- Déclaration des constantes des broches E/S numériques ---

const int ledVert=14; // Constante pour la broche 14
const int ledRouge=15; // Constante pour la broche 15

void setup()

{   
Serial.begin(9600); // initialisation de la connexion Arduino / PC 
urm.begin(9,10,9600); // initialisation du capteur sur les pattes 9 et 10 à la vitesse 9600 
myservo.attach(11);
int i;
for(i=4;i<=7;i++)
pinMode(i, OUTPUT);

pinMode(IRpin,INPUT);

// ------- Broches en sorties numériques ------- 
pinMode (ledVert,OUTPUT); // Broche ledVert configurée en sortie
pinMode (ledRouge,OUTPUT); // Broche ledRouge configurée en sortie

void loop()   

{
myservo.write(45);
  delay(500);//délai de stabilisation du servo
 
urm.requestMeasurementOrTimeout(1, distance1);// mise à jour de la distance       
{
  float volts = analogRead(IRpin)*0.0048828125;   // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 27*pow(volts, -1.10);          // calculé à partir du graph, 27=distance théorique / (1/Volts)S
}
  Serial.print("Distance 1: "); // affichage de la distance
  Serial.println(distance1); 
  Serial.print("Distance 2: "); // affichage de la distance
  Serial.println(distance2);
  delay(500);
 
myservo.write(90);
  delay(500);//délai de stabilisation du servo
 
urm.requestMeasurementOrTimeout(1, distance1);// mise à jour de la distance       
  {
  float volts = analogRead(IRpin)*0.0048828125;   // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 27*pow(volts, -1.10);          // calculé à partir du graph, 27=distance théorique / (1/Volts)S
  }
  Serial.print("Distance 1: "); // affichage de la distance
  Serial.println(distance1); 
  Serial.print("Distance 2: "); // affichage de la distance
  Serial.println(distance2);
  delay(500);
 
myservo.write(135);
  delay(500);//délai de stabilisation du servo
 
urm.requestMeasurementOrTimeout(1, distance1);// mise à jour de la distance       
  {
  float volts = analogRead(IRpin)*0.0048828125;   // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 27*pow(volts, -1.10);          // calculé à partir du graph, 27=distance théorique / (1/Volts)S
  }
Serial.print("Distance 1: "); // affichage de la distance
  Serial.println(distance1); 
  Serial.print("Distance 2: "); // affichage de la distance
  Serial.println(distance2);
  delay(500);
 
myservo.write(90);
  delay(500);//délai de stabilisation du servo
 
urm.requestMeasurementOrTimeout(1, distance1);// mise à jour de la distance       
{
  float volts = analogRead(IRpin)*0.0048828125;   // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 27*pow(volts, -1.10);          // calculé à partir du graph, 27=distance théorique / (1/Volts)S
}
Serial.print("Distance 1: "); // affichage de la distance
  Serial.println(distance1); 
  Serial.print("Distance 2: "); // affichage de la distance
  Serial.println(distance2);
  delay(500);
 
myservo.write(45);
  delay(500);//délai de stabilisation du servo
 
urm.requestMeasurementOrTimeout(1, distance1);// mise à jour de la distance       
  {
  float volts = analogRead(IRpin)*0.0048828125;   // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 27*pow(volts, -1.10);          // calculé à partir du graph, 27=distance théorique / (1/Volts)S
  }
  Serial.print("Distance 1: "); // affichage de la distance
  Serial.println(distance1); 
  Serial.print("Distance 2: "); // affichage de la distance
  Serial.println(distance2);
  delay(500);
 
if (distance1 >= 30 || distance2 >= 30) //si distance supérieure à 30 cm
{
digitalWrite(ledVert,HIGH); // allume la led verte 
digitalWrite(ledRouge,LOW); // éteind la led rouge 

analogWrite (E1,52);     
digitalWrite(M1,HIGH);   
analogWrite (E2,45);   
digitalWrite(M2,HIGH);
delay(3000);
analogWrite (E1,0);     
digitalWrite(M1,HIGH);   
analogWrite (E2,0);   
digitalWrite(M2,HIGH);
delay(2000);
}
else if (distance1 < 30 || distance2 < 30) //si distance inférieure à 30 cm
{
digitalWrite(ledRouge,HIGH); // allume la led rouge 
digitalWrite(ledVert,LOW); // éteind la led verte

analogWrite (E1,52);     
digitalWrite(M1,LOW);   
analogWrite (E2,45);   
digitalWrite(M2,LOW);
delay(1000);
analogWrite (E1,45);
digitalWrite(M1,LOW);   
analogWrite (E2,45);     
digitalWrite(M2,HIGH);
delay(50);
}
}



Please, help me!
(Mal de tronche incroyable ! :~ )

@+
Hervé

osaka

Ouch effectivement.  :smiley-mr-green:

Hormis un fameux problème d'algo et code répétitif ...

Code: [Select]

  float volts = analogRead(IRpin)*0.0048828125;   // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 27*pow(volts, -1.10);          // calculé à partir du graph, 27=distance théorique / (1/Volts)S


Je n'ai pas ce genre de capteur mais ...
Je suppose que ton calcul est pour avoir une valeur plus précise ?
Quote
Les variables float ont seulement 6 à 7 chiffres de précision. Ceci concerne le nombre total de chiffres, pas seulement le nombre à droite de la virgule.

AnalogRead retourne un entier il risque d'y avoir une conversion de ton 0.0048828 en 0, peut être "(float)analogRead(IRpin)" ? (pas certain pour ceci, mais il me semble avoir rencontré un cas similaire  :smiley-zipper:)
Attention également au poids et calcul sur flottant en mémoire et temps c'est énorme.  :~

electricircus

bonsoir Osaka,

pour l'algo répétitif; je sais mais je n'arrive pas à faire un code qui compile sur le modèle du tuto "blinkwithoutdelay"

Pour :
float volts = analogRead(IRpin)*0.0048828125;   // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 27*pow(volts, -1.10);          // calculé à partir du graph, 27=distance théorique / (1/Volts)S

je me suis inspiré de çà; http://luckylarry.co.uk/arduino-projects/arduino-processing-make-a-radar-screen-part-3-visualising-the-data-from-sharp-infrared-range-finder/

çà me lit bien une distance en cm, deux chiffres après la virgule sur un autre code (sans servo, sans capteur URM, sans contrôle moteur)

et l'ensemble de mon code fonctionnait "bien" avant que je rajoute ces lignes de calculs pour le capteur analogique...

est-ce que je n'oublie pas de déclarer quelque part des "const" ou des "int" ?

j'ai essayé tellement de choses que je me suis paumé dans mon raisonnement

fdufnews

Je n'ai pas poussé très loin la recherche mais déjà je pense que tu as une mauvaise compréhension de l'utilisation de la librairie.
le prototype de la méthode requestMeasurementOrTimeout indique que value est un pointeur sur un entier.

Code: [Select]
int URMSerial::requestMeasurementOrTimeout(int mType, int& value)

donc tes appels devraient avoir la forme suivante:
Code: [Select]
urm.requestMeasurementOrTimeout(1, &distance1);// mise à jour de la distance   

D'ailleurs tu dois avoir des erreurs lors de la compilation

electricircus

bonsoir fdufnews,

Ce foutu capteur US (URM37) ne fonctionne  qu'avec la version 018, ou 022 de l'ide et j'ai repris quasiment tel quelle le librairie de Miles Burton... au grand jamais j'aurais changé quelque chose que je connaissais pas il y a encore 1 mois (je l'ai installé pendant un stage d'initiation Arduino chez PingBase)

Maintenant je ne remets pas en doute ce que tu me dis! çà expliquerai peut-être sa foutu lenteur de détection...

et oui, des erreurs de compile, j'en ai...mais c'est le plus souvent de la syntaxe, rien de critique, si je me réfère au FAQ

Autrement, pour me remonter le moral, j'ai passé commande :
Platine de commande de moteur DC Monster Moto Shield, Module afficheur graphique couleur pour Arduino, Platine "Arduino Mega ADK", Module boussole "CMPS03"

Comme qui dirait que je je n'ai pas fini de venir vous les briser, mais je suis toujours sur ce projet
http://arduino.cc/forum/index.php/topic,74889.msg564376.html#msg564376


fdufnews

Quote
Ce foutu capteur US (URM37) ne fonctionne  qu'avec la version 018, ou 022 de l'ide et j'ai repris quasiment tel quelle le librairie de Miles Burton

Non non nous nous sommes mal compris, la librairie n'est pas en cause. C'est la manière d'appeler les méthodes qui n'est pas correcte.
il faut regarder dans le(s) fichier(s) .h de la librairies ou dans la doc mais je n'en ai pas vu (j'ai pas non plus cherché longtemps). Dans le fichier .h  il y a la déclaration des fonctions et donc la façon de les utiliser.
Pour la fonction en question l' argument value est déclaré int * donc cela signifie que l'on doit passer un pointeur vers la variable et non la variable elle même. Le fait de passer un pointeur sur la variable permet à la fonction de modifier la valeur dans la variable.

Quote
des erreurs de compile, j'en ai...mais c'est le plus souvent de la syntaxe, rien de critique,

dans le cas dont je parle tu dois avoir une erreur qui te dit:
erreur: invalid conversion from 'int' to 'int*'

electricircus

Ok, je crois comprendre la subtilité

je n'ai pas eu çà mais j'ai eu:
error: redeclaration of "requestMeasurementOrTimeout(int mType, int& value)"

c'est ressemblant, non?

@+

electricircus

Bonsoir,

j'ai relu encore une fois le pdf Arduino du site du Zero,

et j'ai reconnecté mon capteur US sur les bons pins (mode: grosse boulette)...çà c'est réglé ! lecture de la distance OK
l'erreur de redéclaration, j'ai trouvé aussi...
en gros, je comprends vite, mais faut m'expliquer longtemps!  :~

par contre la formule pour le capteur IR me rend sceptique; le capteur lit bien une valeur (fausse) qui augmente suivant la position du servo, et reste "bloqué" dessus

je cherche donc une autre formule... la courbe de tension n'est pas linéaire sinon j'aurai fait un "map"

amicalement

@+

fdufnews

Avec un tableur et la fonction de régression, j'obtiens:
distance =25,2476 * volt ^-1,303757072
Sur les courtes distances il y a une légère erreur

electricircus

Merci fdufnews

tu as trouvé çà sous Excell ?
"formule de régression"...c'est pas de mon niveau, çà!

en language C++, çà donne la formule que tu as écris?
A quoi correspond l'accent circonflexe?

Si c'est juste une légère erreur, je peux peut-être laissé la mienne?

La plupart des codes que je lis ,avec un capteur IR, font juste une lecture analogique de la sortie capteur, mais un article sur "Pobot", explique l'erreur sans donner la soluce...


Amicalement
@+ 


fdufnews

Quote
tu as trouvé çà sous Excell ?
"formule de régression"...c'est pas de mon niveau, çà!

Pas Excell, OpenOffice Calc. Mais sous Excell tu as la même chose.

- Tu fais un tableau avec la liste des valeurs, dans notre cas distance et tension (mais ce serait mieux avec distance et valeur retournée par l'ADC de l'arduino en faisant une phase calibration car dans la datasheet du capteur ils annoncent quand même des dispersions importantes)
- Tu fais tracer le graphique, type de courbe xy
- Dans les options de la courbe il y a "tracer une courbe de tendance". Là on choisi le type de polynome à utiliser suivant la forme de la courbe et on demande l'affichage de l'équation.

Quote
A quoi correspond l'accent circonflexe?

L'accent circonflexe c'est une élévation à la puissance.
distance =25,2476 * volt ^-1,303757072 en C cela donne:
Code: [Select]
distance =25,2476 * pow(volt,-1.303757072);
Si tu regardes, cette formule à la même forme que celle que tu utilisais mais les arguments changent légèrement

electricircus

#26
Mar 10, 2012, 11:20 am Last Edit: Mar 10, 2012, 11:45 am by electricircus Reason: 1
Ok Doc!  ;)

C'est reparti!
je vais bosser aussi sur l'organigramme de mon code; j'ai dans l'idée que çà va déjà améliorer pas mal de choses
@+



electricircus

Bonjour,

je pense maintenant avoir un code un peu plus propre :

Code: [Select]
#include "URMSerial.h"   
#include "Servo.h" 

URMSerial urm;   
Servo myservo; //objet servo controle un servo
int distance1;
int distance2;

int E1 = 5; // déclaration broche E1 Contrôle vitesse moteur
int E2 = 6; // déclaration broche E2 Contrôle vitesse moteur2
int M1 = 4; // déclaration broche M1 contrôle direction Moteur1
int M2 = 7; // déclaration broche M2 contrôle direction Moteur2
int IRpin = 19; // déclaration broche pour le capteur IR
int ledVert=14; // déclaration broche pour la led verte
int ledRouge=15; // déclaration broche pour la led rouge


void setup()
{   
  Serial.begin(9600); // initialisation de la connexion Arduino / PC 
  urm.begin(9,10,9600); // initialisation du capteur sur les pattes 9(tx) et 10(rx) à la vitesse 9600 
  myservo.attach(11); //Broche servomoteur
int i;
  for(i=4;i<=7;i++)
    pinMode(i, OUTPUT); //Broches moteur configurées en sortie
    pinMode(IRpin,OUTPUT); //Broche capteur IR configurée en sortie
    pinMode (ledVert,OUTPUT); // Broche ledVert configurée en sortie
    pinMode (ledRouge,OUTPUT); // Broche ledRouge configurée en sortie


void loop()   
{
  urm.requestMeasurementOrTimeout(1, distance1); // mise à jour de la distance capteur US     
  float volts = analogRead(IRpin)*0.0048828125; // valeur du capteur multiplié par (5/1024) - si capteur en 5V
  float distance2 = 46*pow(volts, -1.10); // mise à jour de la distance capteur IR     
 
  if (distance1 >= 30 || distance2 >= 30) //si distance supérieure à 30 cm
{
  digitalWrite(ledVert,HIGH); // allumage led verte 
  digitalWrite(ledRouge,LOW); // extinction led rouge 
  analogWrite (E1,51); // vitesse moteur 1     
  digitalWrite(M1,HIGH); // marche avant moteur 1   
  analogWrite (E2,45); // vitesse moteur 2
  digitalWrite(M2,HIGH); // marche avant moteur 2
  Serial.print("Distance 1: "); // affichage de la distance capteur US
  Serial.println(distance1); 
  Serial.print("Distance 2: "); // affichage de la distance capteur IR
  Serial.println(distance2);
}
  else if (distance1 < 30 || distance2 < 30) //si distance inférieure à 30 cm
{
  digitalWrite(ledRouge,HIGH); // allumage led rouge 
  digitalWrite(ledVert,LOW); // extinction led verte
  analogWrite (E1,45); // vitesse moteur 1
  digitalWrite(M1,LOW); // marche arrière moteur 1 
  analogWrite (E2,45); // vitesse moteur 2   
  digitalWrite(M2,HIGH); // marche avant moteur 2
  delay(250); // pendant 250ms
}
}



J'ai un petit bot réactif, détectant les obstacles à 10cm environ, car que je commence par détecter, avant d'exécuter 2 conditions.
Le problème : quand je veux programmer des positionnements du servomoteur (45° 90° 135° 180°) pour une lecture à chaque angle, avec un delai de stabilisation du servo, je me retrouve avec une boucle contenant des répétions et je perds la réactivité à cause de l'accumulation des délais...
Comment structurer le code?
je ne vois pas  du tout comment utiliser la fonction "millis" dans mon code
Faut-il lire les valeurs envoyées par les capteurs à chaque angle et les stockées dans un "swictch" "case" avec une action attribuée à chaque case?

je suis perdu sur la structure que doit prendre le programme

Pouvez-vous de me donner une piste?

encore merci

@+




osaka

#28
Mar 12, 2012, 04:25 pm Last Edit: Mar 12, 2012, 07:14 pm by osaka Reason: 1
Il faudrait que tu procèdes plus par petite étapes, là le tout (servo, capteur,distance, etc) c'est pas l'idéal et tu mélange tout.
En premier essaie de t'occupé la partie servo ensuite la lecture et en fin les cas de distance, mais pas les trois en même temps.
Exemple pour le servo:
Code: [Select]

#include "Servo.h"  

Servo myservo; //objet servo controle un servo

byte sens = 0;
byte pos = 0;

void setup()
{
 myservo.attach(11);  
}

void loop() //voir loop comme une boucle infinie ex: while(1);
{          
 if(sens) // si sens positif 0-> 180°
 {
   pos+=45; //on incrémente de 45°
   if(pos == 180) //si fin du premier sens de balayage
   {
     sens = 0; // on active le retour de balayage
   }
 }
 else // sens negatif (retour balaye) 180°->0°
 {
   pos-=45; // on decrement de 45°
   if(pos == 0) // revenu a 0, fin du balayage complet
   {
     sens = 1; //on repart pour un nouveau balayage
   }
 }
 
 myservo.write(pos); //on positionne le servo
 delay(15);
}


c'est quand même plus facile à comprendre qu'un pavé (paté  :smiley-mr-green:) de code.
;)

Pour mieux comprendre le cas particulié arduinesque de la fonction loop() voici la correspondance "while(1) = loop()" .
Essaie de visualisé les étapes (instruction) ou ligne à chaque passage de la boucle while (loop).
Code: [Select]

while(1) //voir loop comme une boucle infinie ex: while(1);
{          
 if(sens) // si sens positif 0-> 180°
 {
   pos+=45; //on incrémente de 45°
   if(pos == 180) //si fin du premier sens de balayage
   {
     sens = 0; // on active le retour de balayage
   }
 }
 else // sens negatif (retour balaye) 180°->0°
 {
   pos-=45; // on decrement de 45°
   if(pos == 0) // revenu a 0, fin du balayage complet
   {
     sens = 1; //on repart pour un nouveau balayage
   }
 }
 
 myservo.write(pos); //on positionne le servo
 delay(15);
}


Après pour le capteur (que tu auras tester séparément), il sera facile de savoir à quel moment tu dois faire la lecture donc ou placé son code, etc, etc ...

electricircus

Bonsoir Osaka,

pour les servos je comptais utiliser une boucle "for"...donc c'est raté!
j'ai très peu de doc avec exemples, sur l'utilisation  "pratique" d'une boucle "while" ; genre 10 lignes dans le bouquin de C. Tavernier et guère plus dans le tuto Arduino du Site du Zero

Alors si vous avez des exemples de codes entiers avec ces boucles ou des liens , j'apprécierais de pouvoir les étudier.

Merci à tous

@+

Go Up