Aller au contenu


Photo
- - - - -

robot autonome


88 réponses à ce sujet

#41 Francky

Francky

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 967 messages
  • Gender:Male

Posté 24 juin 2012 - 08:24

en plus si la somme des force est égale à 0 et que le systeme est en MRU, il n'y a pas de force motrice logiquement ><

Bah en fait ça te permet de calculer la valeur de la force pour laquelle ton système est à l'arrêt x') Après il faudrait prendre une force motrice supérieure à celle que t'aurais calculée. Enfin c'est un peu space comme démarche.

Par contre, le truc qui me semble bizarre, c'est qu'en MRU (Mouvement de rotation uniforme ?) on ne calcule que des vitesses (accélérations et positions), non ? "^^
Perso, ce genre de calculs je les faisais avec le PFS.

#42 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 24 juin 2012 - 11:08

Bah en fait ça te permet de calculer la valeur de la force pour laquelle ton système est à l'arrêt x') Après il faudrait prendre une force motrice supérieure à celle que t'aurais calculée. Enfin c'est un peu space comme démarche.

Par contre, le truc qui me semble bizarre, c'est qu'en MRU (Mouvement de rotation uniforme ?) on ne calcule que des vitesses (accélérations et positions), non ? "^^
Perso, ce genre de calculs je les faisais avec le PFS.


MRU = mouvement rectiligne uniforme...

ça m'a fait réfléchir à quelque chose: en pente nulle, le poids est compensé par la composant verticale de la réaction du support, donc le couple ne sert plus qu'à vaincre les frottements pour entretenir la vitesse? du coup le calcul du couple nécessaire sur terrain plat revient à un calcul de frottements? Image IPB
Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#43 thermo_nono

thermo_nono

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 825 messages

Posté 24 juin 2012 - 04:13

et moi ça me fait penser que sur un terrain plat si : | P | = | F |/sin(°pente)
avec pente=0 (donc sin(pente)=0) ..
on se retrouve avec une division par zero..
et demandons maintenant à un AVR-atmega32 ce qu'il pense des divisions par zero..

#44 Francky

Francky

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 967 messages
  • Gender:Male

Posté 25 juin 2012 - 11:12

MRU = mouvement rectiligne uniforme...

J'ai pas appris le même sigle xD Il n'empêche que ça concerne toujours les vitesses et les accélérations...

ça m'a fait réfléchir à quelque chose: en pente nulle, le poids est compensé par la composant verticale de la réaction du support, donc le couple ne sert plus qu'à vaincre les frottements pour entretenir la vitesse? du coup le calcul du couple nécessaire sur terrain plat revient à un calcul de frottements?

Franchement ce que tu dis me paraît douteux. A mon avis le problème doit se résoudre en dynamique (chose que je ne sais pas faire, on voit ça en prépa je crois).
Mais bon, à ce moment là ce ne serait pas le couple mais la force motrice, non ?

et moi ça me fait penser que sur un terrain plat si : | P | = | F |/sin(°pente)
avec pente=0 (donc sin(pente)=0) ..
on se retrouve avec une division par zero..
et demandons maintenant à un AVR-atmega32 ce qu'il pense des divisions par zero..

Dans ce cas là ça ne s'appliquerait pas (en plus je suis pas sûr que la formule de base soit correcte) parce que tu n'aurais plus un triangle.

#45 FJProd

FJProd

    Membre

  • Membres
  • 14 messages

Posté 25 juin 2012 - 05:28

Bon visiblement mon explication est très flou. J'ai donc ressorti le dessin qui m'a permis d'arriver au résultat. DessinPoidsMax.png . Cela permet juste d'approximer la valeur du poids.

On pourrait améliorer la fiabilité en comptant les frottements et en résolvant en dynamique (comme le dit @Francky). Ce que je ne sais pas faire. Donc si vous avez des méthodes, je suis prenneur.

Deplus cette techinique place le robot dans un monde parfait (loins de la réalité ), où il suffit de soufller sur le robot pour le faire avancer. Voilà pourquoi @thermo_nono, mes résultats peuvent donner des choses absurbes (comme la division par zero !).

Néanmoins cette méthode a une qualité, je sais la faire (et encore...). Tout ce qui est de la dynamique, ou du calcule des frottements dépassent mes connaissances.
Donc mes connaissances :tatice_03: et moi-même vous remercient à l'avance pour votre future aide .

#46 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 27 juin 2012 - 04:20

Petite interruption dans les calculs de forces (de toute façon on a commandé les moteurs donc on verra bien ;))
J'ai commencé à réfléchir à l'asservissement des moteurs et j'ai fait un code pour l'asservissement PID en angle d'un moteur, je voulais savoir si il vous semblait bon: on a pas encore reçu de quoi le tester...

Voici le code:
#include <SimpleTimer.h>

const int ki = 0;
const int kd = 0;
const int kp=0;
const int pin_codeur_A = 2;
const int pin_codeur_B = 3;
const int pin_moteur = 5;
const int res_codeur = 4; //4° par tour
const int freq = 50; //frequence de l'asservissement

volatile int compteur = 0;
int consigne_angle = 0;
int erreur = 0;
int somme_erreurs = 0;
int var_erreur = 0;
int erreur_prec = 0;
int mesure_angle = 0;
int periode = 0;

SimpleTimer timer; 

void setup() {
  pinMode(pin_codeur_B, INPUT);
  pinMode(pin_codeur_A, INPUT);
  pinMode(pin_moteur, OUTPUT);
  
  digitalWrite(pin_codeur_A, HIGH); //pull up
  digitalWrite(pin_codeur_B, HIGH); //pull up
  
  periode=1000/freq; //calcul de la periode en ms (T=1/F s)
  
  attachInterrupt(0, comptage, RISING); //interruption sur front montant
  timer.setInterval(periode, asservissement); //calcul du PID toutes les n ms
  
  Serial.begin(9600); //débuggage

}

void loop() {
  timer.run;
  delay(10);
}

void comptage() {
  if (pin_codeur_B == HIGH){ //si au front montant de A, B est à l'etat haut...
    compteur++; //on incrémente le compteur
  } 
  else if (pin_codeur_B == LOW){
    compteur--;
  }
}


int mesure() {
  mesure_angle = res_codeur * compteur; //nombre de tick * résolution du tick = angle
  mesure_angle = mesure_angle % 360; //remet le compteur à 0 à chaque tour
  return mesure_angle;
}

int asservissement() {
    mesure_angle = mesure(); //mesure de l'angle
    erreur = consigne_angle-mesure_angle; //calcul de l'erreur
    
    int P;
    int I;
    int D;
    
    somme_erreurs += erreur; //calcul de la somme des erreurs
    var_erreur = erreur - erreur_prec; //dérivée de l'erreur
    erreur_prec = erreur;
    
    P = kp * erreur; //calcul de l'asservissement P
    I = ki * somme_erreurs; //calcul de l'asservissement P
    D = kd * var_erreur; //calcul de l'asservissement P
    
    consigne_angle = P + I + D; //calcul de la consgne par asservissement PID
    return consigne_angle;
}


Je me suis aidé de ces deux super(s?) sites:
http://clubelek.insa-lyon.fr/joomla/fr/base_de_connaissances/informatique/asservissement_et_pilotage_de_robot_autonome_introduc_5.php et http://www.ferdinandpiette.com/blog/2012/04/asservissement-en-vitesse-dun-moteur-avec-arduino/

Par contre je ne coprends pas trop ce que me rencoit "commande": ça devrait être une valeur comprise entre 0 et 255... Je dois la mapper pour ça ou pas?
J'ai hâte qu'on reçoive les moteurs pour pouvoir tester un peu tout ça :/
Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#47 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 27 juin 2012 - 05:18

Hello !
Le code est globalement bien structuré

je voulais savoir si il vous semblait bon: on a pas encore reçu de quoi le tester...


Quelques petites remarques tout de même :
  • A aucun moment tu ne commande ton moteur... Oo il ne risque pas de se réguler ^^
  • L'interruption "asservissement" ne doit rien retourner car de toute manière la valeur de retour ne sera pas rattrapé par rien... A la place du return, il faut justement commander le moteur.
  • Dans la loop, la méthode run de ton timer est justement une méthode (et non une variable) => timer.run()
  • Je ne comprend pas ton interruption comptage ! Pourquoi décrémenter la variable de contage sur front descendant ?? De plus, comme tu ne déclenche ton interruption que sur front montant, ta variable ne risque pas de se décrémenter ...
  • Attention avec ta fonction "mesure" ! Là, tu vas certes asservir en angle, mais uniquement toutes les 50ms ! ça veut dire qu'avec ton code (comme tu fais un modulo), ton moteur peut potentiellement faire 1 tour, 2 tours, ... ou n tours exactement. L'angle sera toujours de 0° toutes les 50ms et ton système sera considéré comme asservi (bien que la roue tourne ...) (tu vois ce que je veux dire ?)
  • Pour le débug, il vaut mieux mettre un baudrate très élevé afin de vite transférer les données ! Imagine que tu veuilles débugger dans la fonction asservissement qui s'exécute toute les 50ms et que tes Serial.print prennent plus que 50ms ... ça bugguera ! (c'est un problème que j'ai eu !)

Par contre je ne coprends pas trop ce que me rencoit "commande": ça devrait être une valeur comprise entre 0 et 255... Je dois la mapper pour ça ou pas?


commande ? Je ne vois cette variable nulle part dans le code

++
Black Templar

Mon site internet : http://ferdinandpiette.com/


#48 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 27 juin 2012 - 05:46

  • A aucun moment tu ne commande ton moteur... Oo il ne risque pas de se réguler ^^

Oui, je n'ai pas encore géré le moteur dans ce code pour simplifier un peu ;)

  • L'interruption "asservissement" ne doit rien retourner car de toute manière la valeur de retour ne sera pas rattrapé par rien... A la place du return, il faut justement commander le moteur.
  • Dans la loop, la méthode run de ton timer est justement une méthode (et non une variable) => timer.run()

Je pensais commander le moteur dans le loop(), c'est pour ça que je renvoyais la commande; mais je vais faire comme tu me dis

  • Je ne comprend pas ton interruption comptage ! Pourquoi décrémenter la variable de contage sur front descendant ?? De plus, comme tu ne déclenche ton interruption que sur front montant, ta variable ne risque pas de se décrémenter ...

en fait j'ai un signal en quadrature, et je veux incrémenter ou décrémenter ma variable "compteur" selon le sens de rotation. vu que mon interruption se déclenche sur front montant, je regarde à chaque front montant de A l'état de B. vu que j'ai un signal de ce type:
codeur.png

ça me permet de savoir dans quel sens tourne l'encodeur (enfin en théorie, je me trompe peut-être)

  • Attention avec ta fonction "mesure" ! Là, tu vas certes asservir en angle, mais uniquement toutes les 50ms ! ça veut dire qu'avec ton code (comme tu fais un modulo), ton moteur peut potentiellement faire 1 tour, 2 tours, ... ou n tours exactement. L'angle sera toujours de 0° toutes les 50ms et ton système sera considéré comme asservi (bien que la roue tourne ...) (tu vois ce que je veux dire ?)

non j'ai pas trop compris désolé... tu veux dire que si le moteur tourne a vitesse constante de façon à ce que l'angle toutes les 50ms soit de x°, le système croira qu'il respecte la consigne alors que ça tourne? Il faut que je fasse un modulo qui incrémente une variable à chaque tour alors?

commande ? Je ne vois cette variable nulle part dans le code

Désolé, commande=consigne_angle, la valeur renvoyée par le PID

en tout cas merci pour ta réponse


Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#49 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 27 juin 2012 - 06:35

Je pensais commander le moteur dans le loop(), c'est pour ça que je renvoyais la commande; mais je vais faire comme tu me dis

Même si tu fais le traitement dans la loop, ta fonction asservissement est une interruption. Donc tu ne pourras pas réceptionner la valeur de retour à l'aide d'un return (vu que tu n'appelles pas la fonction explicitement)


en fait j'ai un signal en quadrature, et je veux incrémenter ou décrémenter ma variable "compteur" selon le sens de rotation. vu que mon interruption se déclenche sur front montant, je regarde à chaque front montant de A l'état de B.

A oui, autant pour moi, je n'avais pas vu que tu avais une interruption sur la codeuse A et que tu regardais l'état de la codeuse B (pour moi, il n'y avait qu'une seule codeuse ^^)


non j'ai pas trop compris désolé... tu veux dire que si le moteur tourne a vitesse constante de façon à ce que l'angle toutes les 50ms soit de x°, le système croira qu'il respecte la consigne alors que ça tourne?

Exactement

Il faut que je fasse un modulo qui incrémente une variable à chaque tour alors?

Une division euclidienne ? Même pas la peine. Tu peux virer ta ligne modulo simplement. Tu auras juste un angle non borné à 0;2pi

Désolé, commande=consigne_angle, la valeur renvoyée par le PID

Dans ce cas, oui consigne_angle, c'est la consigne pwm entre 0 et 255 à appliqué à ton moteur. Pour plus de sécurité, tu peux borner ta variable pour ne pas qu'elle dépasse 255 ou 0 !

Mon site internet : http://ferdinandpiette.com/


#50 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 27 juin 2012 - 06:39

D'accord je comprends mieux!
Un dernier truc: si je ne met pas le modulo, je dois calculer l'angle en radians et non pas en degré, pour ne pas avoir d'angles de plus de 360° c'est bien ça?
Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#51 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 27 juin 2012 - 06:48

D'accord je comprends mieux!
Un dernier truc: si je ne met pas le modulo, je dois calculer l'angle en radians et non pas en degré, pour ne pas avoir d'angles de plus de 360° c'est bien ça?


Non, tu choisis dans quelle unité tu veux asservir ton robot : en degré ou en radian, aucune importance du moment que tu es cohérent.
Après, justement, tu peux avoir des angles plus grand que 360° (si on raisonne en degré ! ou plus grand que 2pi si on raisonne en radians) ! Si tu as une erreur de 500°, ça veut dire que ton moteur va beaucoup trop vite !!!!

Ensuite seconde petite chose : ton calcul de la mesure de l'angle est incorrecte car tu recalcules l'angle à chaque fois que tu calcules ton asservissement SANS prendre en compte les résultats précédents !
Ce qui veut dire que dans ton cas, si tu impose un angle de 45° par exemple, tu vas forcer le moteur à tourner de 45° A CHAQUE FOIS que tu l'asservis ! or, je présume que tu veux qu'il fasse un angle de 45° et qu'une fois fois qu'il est stabilisé, qu'il s'arrête, je me trompe ??

Mon site internet : http://ferdinandpiette.com/


#52 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 27 juin 2012 - 08:13

je n'ai pas trop compris l'histoire de l'angle remesuré à chaque fois: je suis obligé de le remesurer pour tenir l'erreur à jour non? je ne vois pas ce que tu veux dire... edit: j'ai compris je crois, en fait j'ai confondu consigne_angle et commande_moteur, j'aurai du les différencier

Autre chose: ma commande_moteur est soit positive soit négative en fonction du sens dans lequel le moteur doit tourner pour atteindre la consigne_angle non? je dois donc séparer le positif du négatif, en changeant le sens de rotation selon le signe de commande_moteur puis le rendre positif avant de le contraindre entre 0 et 255 c'est ça?
Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#53 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 27 juin 2012 - 10:35

Autre chose: ma commande_moteur est soit positive soit négative en fonction du sens dans lequel le moteur doit tourner pour atteindre la consigne_angle non? je dois donc séparer le positif du négatif, en changeant le sens de rotation selon le signe de commande_moteur puis le rendre positif avant de le contraindre entre 0 et 255 c'est ça?


Exactement

Mon site internet : http://ferdinandpiette.com/


#54 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 27 juin 2012 - 10:45

d'accord donc voilà le code corrigé, merci beaucoup pour ton aide.
je testerai ça une fois les moteurs arrivés.
#include <SimpleTimer.h>

const int ki = 0;
const int kd = 0;
const int kp=0;
const int pin_codeur_A = 2;
const int pin_codeur_B = 3;
const int pin_moteur = 5;
const int res_codeur = 4; //4° par tour
const int freq = 50; //frequence de l'asservissement

volatile int compteur = 0;
int consigne_angle = 0;
int commande_moteur = 0;
int erreur = 0;
int somme_erreurs = 0;
int var_erreur = 0;
int erreur_prec = 0;
int mesure_angle = 0;
int periode = 0;
int sens;

SimpleTimer timer; 

void setup() {
  pinMode(pin_codeur_B, INPUT);
  pinMode(pin_codeur_A, INPUT);
  pinMode(pin_moteur, OUTPUT);
  
  digitalWrite(pin_codeur_A, HIGH); //pull up
  digitalWrite(pin_codeur_B, HIGH); //pull up
  
  periode=1000/freq; //calcul de la periode en ms (T=1/F s)
  
  attachInterrupt(0, comptage, RISING); //interruption sur front montant
  timer.setInterval(periode, asservissement); //calcul du PID toutes les n ms
  
  Serial.begin(9600); //débuggage

}

void loop() {
  timer.run();
  delay(10);
}

void comptage() {
  if (pin_codeur_B == HIGH){ //si au front montant de A, B est à l'etat haut...
    compteur++; //on incrémente le compteur
  } 
  else if (pin_codeur_B == LOW){
    compteur--;
  }
}


int mesure() {
  mesure_angle = res_codeur * compteur; //nombre de tick * résolution du tick = angle
  return mesure_angle;
}

void asservissement() {
    mesure_angle = mesure(); //mesure de l'angle
    erreur = consigne_angle-mesure_angle; //calcul de l'erreur
    
    int P;
    int I;
    int D;
    
    somme_erreurs += erreur; //calcul de la somme des erreurs
    var_erreur = erreur - erreur_prec; //dérivée de l'erreur
    erreur_prec = erreur;
    
    P = kp * erreur; //calcul de l'asservissement P
    I = ki * somme_erreurs; //calcul de l'asservissement P
    D = kd * var_erreur; //calcul de l'asservissement P
    
    commande_moteur = P + I + D; //calcul de la consgne par asservissement PID
    
    if (consigne_angle < 0) {
      sens = 1/sens;
      consigne_angle = -consigne_angle;
      constrain(consigne_angle, 0, 255);
    } else {
      constrain(consigne_angle, 0, 255);
    }
    
    moteur(sens, consigne_angle);
}


(j'ai simplifié au maximum la commande moteur car ce n'est pas important pour l'instant)
Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#55 FJProd

FJProd

    Membre

  • Membres
  • 14 messages

Posté 03 juillet 2012 - 10:11

Bonjours, en attendant les moteurs, on s'occupe comme on peut... Et par chance j'ai reçus ma clé-pc (mk802), sur la quelle je fondais beaucoup d'espoir en robotique.

Tout d'abord, elle est initialement sur android, mais des groupes de personnes ont cré des linux(ubuntu, lubuntu, puppy linux, fedora,...) pour cette clé. J'ai donc installé lubuntu, ainsi que java, netbeans, et arduino IDE( 1.0), qui marchent très bien.

J'ai aussi développé une application java faisant appéle à la libraraie RXTX pour la connection programmePC/arduino.
L'application marche très bien sur un autre ordinateur(netbook) sous ubuntu.

Je pensais avoir fais le plus dur... :dance2:

Quand soudain c'est le drame : ma mk802 (alias clé-PC) ne reconnait pas la carte arduino ! Impossible de dialoger par l'appli java maison. Impossible d'uploader un programme depuis l'IDE. Depuis j'ai retourné internet pour trouver une solution en vain...

J'ai vérifié grace à Synaptic les paquets comportants "USB" entre la mk802 (lubuntu) et le netbook(ubuntu), ils sont pareils. Le driver FTDI est installer avec la version 0.19-4.

Pour plus d'information j'ai tapé "lsusb" dans le terminal voici ça réponse :

Bus 001 Device 001 : ID ld6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001 : ID ld6b:0002 Linux Foundation 1.1 root hub
Bus 003 Device 001 : ID ld6b:0003 Linux Foundation 1.1 root hub
Bus 004 Device 001 : ID ld6b:0004 Linux Foundation 1.1 root hub <--- je ne sais pas ce que sait
Bus 005 Device 001 : ID ld6b:0005 Linux Foundation 1.1 root hub
Bus 004 DEvice 002: ID 0bda:8176 Realtek Semiconductor Corp 802.11n WLAN <---je pense être le wifi
Bus 001 Device 003: ID 046d:c52b Logitech, Inc <------ mon clavier/souris
Bus 003 Device 002: ID 2341:0001 <--------- l'arduino ??????


Je vous remercie déjà pour l'aide que vous avez précédemment apportée. De plus ce problème repose sur un matériel peut connu (mk802 est loins d'être présent dans chaque foyer :tatice_03: ) et hacké... Donc une réponse directe serait merveilleuse, mais peut proprabable, voila pourquoi je prends TOUTES LES PISTES.

#56 FJProd

FJProd

    Membre

  • Membres
  • 14 messages

Posté 04 juillet 2012 - 09:00

Bon ce problème est déjà moins flou et complexe :P

Le driver FTDI utilisé doit être le mauvais. Celui mis par défault doit être conçu pour les processeurs 32 ou 64 bits, mais certainement pas pour les processeurs ARM !.

Sur le site FTDI, ils montrent une version pour ARM pour un seul des deux drivers proposés.

Lequel des drivers FTDI ai-je besoin pour connecter une arduino ?
Est-ce que le driver "suitable for Rpi" a des chance de fonctionner sur mon mk802, ou chaque ARM est complètement différent ?

Je vous remercie à l'avance pour vos réponses.

#57 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 26 août 2012 - 11:37

Bonjour!

ça fait hyper longtemps qu'on a pas posté et j'en suis désolé, nous avons principalement écrit sur notre blog...
Voici une petite màj de l'avancement du projet:

Le problème de la mk802 a été résolu en installant une version plus récente de Lubuntu ; nous pouvons donc maintenant faire dialoguer ce mini-pc avec une Arduino.

J'ai fait le programme Arduino qui s'occupe de récupérer les informations des capteurs et la vitesse de chaque roue pour l'envoyer à la mk802:
#include <SimpleTimer.h> // librairie pour la gestion des timers

SimpleTimer timer; //création d'un nouveau timer

volatile int compteurD = 0; //compteur du nombre de ticks roue gauche
volatile int compteurG = 0; //compteur du nombre de ticks rue droite
const int pin_codeur_D = 2;
const int pin_codeur_G = 3;
const int res_codeur = 180; //180 impulsions par tour
const int nb_capteurs = 3;
const int pin_capteur_us_trigger[] = {10, 11, 12};
const int pin_capteur_us_echo[] = {5,6,7};
const int r = 0.09; //rayon=90mm
const float pi = 3.14159265;

int distance[] ={0,0,0} ; //tableau de distance des capteurs
int NumCapteur =0;
int VitesseGauche = 0;
int VitesseDroite = 0;
long temps1, temps2, duree;

void setup() {
  attachInterrupt(0, comptageD, CHANGE); //interruption sur front montant
  attachInterrupt(1, comptageG, CHANGE); //interruption sur front montant
  timer.setInterval(50, envoi); //calcul + envoi trame toutes les n ms
  
  pinMode(pin_codeur_D, INPUT);
  pinMode(pin_codeur_G, INPUT);
  digitalWrite(pin_codeur_D, HIGH); //pull up
  digitalWrite(pin_codeur_G, HIGH); //pull up
}

void loop() { // boucle principale
  timer.run(); // on lance le timer
} // fin loop()

void comptageD() {
  compteurD++;
}

void comptageG() {
  compteurG++;
}

void envoi() {
  temps1 = millis();
  // calcul distance
  digitalWrite(pin_capteur_us_trigger[NumCapteur], HIGH);
  delay(10);
  digitalWrite(pin_capteur_us_trigger[NumCapteur], LOW);
  distance[NumCapteur] = pulseIn(pin_capteur_us_echo[NumCapteur], HIGH)/58;
  
  //On mesure la durée lors du déplacement
  temps2 = millis();
  duree = (temps2-temps1+50)/1000; // (durée en s)
  
  //calcul Vitesse Gauche
  VitesseGauche = (compteurG/res_codeur)*2*pi*r/duree;
  VitesseDroite = (compteurD/res_codeur)*2*pi*r/duree;
  
  //envoi de la trame
  Serial.print(VitesseGauche);
  Serial.print("-");
  Serial.print(VitesseDroite);
  Serial.print("-");
  Serial.print(NumCapteur);  Serial.print("-");
  Serial.println(distance[NumCapteur]);  Serial.print("-");
  
  //raz ticks
  compteurG=0;
  compteurD=0;
  
  //incrémentation NumCapteur
  NumCapteur = (NumCapteur+1) % nb_capteurs;
}


Comme vous pouvez le constater, la Arduino envoie une trame de cette forme: vG-vD-#capteur-distance.
Cette trame est interprétée par un programme Java sur la mk802 qui s'en sert pour dessiner une carte de la pièce (pour le programme de cartographie, voir ici)

Nous avons un problème pour les calculs d'odomètrie: nous avons trouvé 3 méthodes sur internet et nous n'en comprenons aucune:

méthode 1: http://fr.wikipedia.org/wiki/Odom%C3%A9trie
problème: je ne comprends pas le calcul de R ni de dTeta...


méthode 2: http://clubelek.insa-lyon.fr/joomla/fr/base_de_connaissances/informatique/calcul_d_odometrie_approximation_tra.php
problèmes: je ne comprend que le calcul de dDelta et quand ils disent dx, c'est pendant quel intervalle de temps? n'importe lequel du moment qu'il est assez faible et qu'il reste fixe?

méthode 3: http://clubelek.insa-lyon.fr/joomla/fr/base_de_connaissances/informatique/asservissement_et_pilotage_de_robot_auto_2.php
Là c'est la pire, je comprends ni les calculs, ni le problème précédent de l'intervalle de temps, ni ce qu'ils veulent dire par "entraxe en ticks"...

en attendant on utilise la méthode Wikipédia, voici le pseudo code que j'ai fait:

Pseudo code odométrie :

Const int e=15 ;

Int vG=0 ;

Int vD=0 ;

Int v=0 ;

Int d=0 ;

Int R=0 ;

Int Ѳ=0 ;

Int dѲ=0 ;

Int xO=0 ;

Int yO=0 ;

Int X=0;

Int Y=0;

 

vG=serial.read

vD=serial.read

if (vG==vD){

v=(vG+vD)/2

R=(e/2)(vD+vG)/(vD-vG)

d=v*65

dѲ=d/R

xO=x-R*sin(Ѳ)

yO=y+R*cos(Ѳ)

 

Ѳ+=d Ѳ

X=xO+R*sin (Ѳ)

Y=yO-R*cos(Ѳ)

}

Else {

V = vG




}


Si quelqu'un peut nous expliquer les calculs et nous dire si les codes sont bons ce serait sympa :)

Merci d'avance!

p-s: ci-jointes 2 petites photos pour vous mettre en appétit
IMG_20120825_192529.jpg

IMG_20120825_192602.jpg

Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#58 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 27 août 2012 - 06:27

Bon apparemment le code Java de la méthode wikipedia ne fonctionne pas, je laisse francois vous poster le code et vous décrire les symptomes...
Notre blog, à FJprod et moi: http://2froblog.wordpress.com/

#59 Hexa Emails

Hexa Emails

    Membre passionné

  • Membres
  • PipPipPip
  • 439 messages
  • Gender:Male

Posté 27 août 2012 - 07:15

Heu, je trouve ça logique que ça en fonctionne pas entre ces 2 codes...
la partie arduino envoie par exemple
8-7-0-0
8-7-0-0
6-7-0-0

et la partie java s'attend à recevoir

87
87
67

et faites attention à discerner Serial.print et Serial.write... il y a un gros piège à ce niveau.

pour le code arduino les interruptions ne se font pas sur front montant mais sur changement non? (c'est juste un détail)

Le "SimpleTimer" ne sert à rien... à part rendre le truc plus compliqué et moins fiable.

Et dernière remarque: si vous pouviez enlever le capteur US de votre fonction "envoi", ce serait plus propre:
on ne sais jamais combien de temps une mesure au capteur US va "prendre le focus" (à moins que vous ayez fait des essais?)

Je surveille ça de près parce que ça ressemble à ce que l'on a fait l'an dernier pour la coupe, alors si on peut vous éviter de retomber dans les mêmes pieges...

[hs]bon je vais voir ce que donne la pièce en cours sur ma reprap :P [/hs]

#60 swolf

swolf

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 626 messages
  • Gender:Male

Posté 27 août 2012 - 08:11

Heu, je trouve ça logique que ça en fonctionne pas entre ces 2 codes...
la partie arduino envoie par exemple

8-7-0-0
8-7-0-0
6-7-0-0

et la partie java s'attend à recevoir

87
87
67

et faites attention à discerner Serial.print et Serial.write... il y a un gros piège à ce niveau.

pour le code arduino les interruptions ne se font pas sur front montant mais sur changement non? (c'est juste un détail)

Le "SimpleTimer" ne sert à rien... à part rendre le truc plus compliqué et moins fiable.

Et dernière remarque: si vous pouviez enlever le capteur US de votre fonction "envoi", ce serait plus propre:
on ne sais jamais combien de temps une mesure au capteur US va "prendre le focus" (à moins que vous ayez fait des essais?)

Je surveille ça de près parce que ça ressemble à ce que l'on a fait l'an dernier pour la coupe, alors si on peut vous éviter de retomber dans les mêmes pieges...

[hs]bon je vais voir ce que donne la pièce en cours sur ma reprap :P [/hs]


Quand tu parles du code Java, tu parles du pseudo code? parce que en ce qui concerne la réception des vitesses, j'ai complètement résumé mais François (c'est lui qui s'occupe de la partie Java) a normalement bien décodé le signal comme il faut (en plus pour la simulation il utilise des potentiomètres pour faire varier vG et vD (c'est d'ailleurs peut-être de là que viendrait le pb...))

Pour Serial.print et Serial.write, tu veux dire qu'il faudra dans le code Java convertir les char en int, c'est ça?

Pour les interruptions, il me semble que j'ai bien mis en mode CHANGE... EDIT ah ouais, c'est sur les commentaires que je me suis trompé!

je ne comprends pas ce que tu veux dire par "le simpletimer ne sert à rien": comment pourrait-on faire sans?

Pour le capteur us, c'est pareil: je ne vois pas comment on pourrait faire autrement: il faut 50ms pour "l'évaporation" du son entre 2 mesures (d'où le timer réglé sur 50ms) et pour la durée de "prise de focus", on la chronomètre grâce à temps1=millis() et temps2=millis().

Merci pour ton aide, je suis rassuré que tu nous surveille parce que c'est un gros projet, surtout si tu en as fait un équivalent :)

[hs] la classe d'avoir une reprap! [/hs]
Notre blog, à FJprod et moi: http://2froblog.wordpress.com/



Répondre à ce sujet



  


0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users