Robotique2 1 : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
(Partie 2: Test)
(Assemblage du Robot)
 
(93 révisions intermédiaires par le même utilisateur non affichées)
Ligne 5 : Ligne 5 :
 
=Présentation du projet=
 
=Présentation du projet=
  
Le projet à pour objectif de réalisé un match entre 2 robots. Ceux-ci devront envoyé depuis leur terrain le plus de balle de tennis possible sans aller sur le terrain adverse. <br />
+
Le projet a pour objectif de réaliser un match entre 2 robots. Ceux-ci devront envoyer depuis leur terrain le plus de balles de tennis possible sans aller sur le terrain adverse. <br />
Le terrain mesure 8 mètres par 4 et est séparé en 2 parties par une ligne médiane donc chaque robot aura un terrain d'approximativement 16m² pour se déplacé.
+
Le terrain mesure 8 mètres par 4 et est séparé en 2 parties par une ligne médiane donc chaque robot aura un terrain d'approximativement 16m² pour se déplacer.
  
Une partie dure 90s,avant la fin du temps impartie le robot devra être immobile au niveau de la ligne médiane et avoir éclaté un ballon qu'il aura emporté avec lui au début du match <br />
+
Une partie dure 90s, avant la fin du temps imparti le robot devra être immobile au niveau de la ligne médiane et avoir éclaté un ballon qu'il aura emporté avec lui au début du match. <br />
 
Le vainqueur sera le robot avec le moins de balle sur son terrain. <br />
 
Le vainqueur sera le robot avec le moins de balle sur son terrain. <br />
  
Ligne 14 : Ligne 14 :
 
=={{Rouge|Objectif du Projet}}==
 
=={{Rouge|Objectif du Projet}}==
  
*Réalisé un Robot capable de se déplacer dans son terrain.
+
*Réaliser un Robot capable de se déplacer dans son terrain.
*Renvoyé des balles depuis son terrain jusqu'au terrain adverse.
+
*Renvoyer des balles depuis son terrain jusqu'au terrain adverse.
 
*Crever le ballon que l'on a emporté à l'arrêt devant la ligne médiane avant la fin du temps imparti.
 
*Crever le ballon que l'on a emporté à l'arrêt devant la ligne médiane avant la fin du temps imparti.
  
  
 
=={{Rouge|Règlement}}==
 
=={{Rouge|Règlement}}==
Voici ci-joint le règlement ainsi que les contraintes associé à la création du Projet.<br/>
+
Voici ci-joint le règlement ainsi que les contraintes associées à la création du Projet.<br/>
  
 
     *[[Media:Coupe_GEII_-_Règlement_-_2020.pdf| règlement de la coupe de robotique]]<br/>
 
     *[[Media:Coupe_GEII_-_Règlement_-_2020.pdf| règlement de la coupe de robotique]]<br/>
Ligne 30 : Ligne 30 :
 
*Le robot doit être dimensionné selon 30x30x40cm.<br />  
 
*Le robot doit être dimensionné selon 30x30x40cm.<br />  
  
*moteurs
+
*Moteurs
 
**Vitesse de rotation entre 600 à 800 tr/min max.
 
**Vitesse de rotation entre 600 à 800 tr/min max.
 
**Moteur MFA 970d (imposé par l'IUT)
 
**Moteur MFA 970d (imposé par l'IUT)
Ligne 36 : Ligne 36 :
 
*Châssis imposé par l'IUT
 
*Châssis imposé par l'IUT
  
*Le mécanisme lanceur de balle ne doit dépasser que pour envoyé la balle, il devra se replier après.
+
*Le mécanisme lanceur de balle dépassera seulement pour envoyer la balle, il devra se replier après.
  
 
*La batterie doit être en lithium Li-ion.<br />
 
*La batterie doit être en lithium Li-ion.<br />
Ligne 49 : Ligne 49 :
 
=={{Bleu|Découpage fonctionnel}}==
 
=={{Bleu|Découpage fonctionnel}}==
 
[[Fichier:Schéma fonctionnel robot geii.png|vignette]]<br/>
 
[[Fichier:Schéma fonctionnel robot geii.png|vignette]]<br/>
Afin de commencer le projet, nous avons du séparé les parties essentielles du projet pour ensuite répartir les tâches.
+
Afin de commencer le projet, nous avons dû séparer les parties essentielles du projet pour ensuite répartir les tâches.
  
 
*On a séparé le travail en différent groupe fonctionnel
 
*On a séparé le travail en différent groupe fonctionnel
**L'alimentation
+
**L' Alimentation
 
**Le Déplacement
 
**Le Déplacement
**Le système de renvoie des balles
+
**Le Système de renvoi des balles
**Les capteurs pour trouver les balles
+
**Les Capteurs pour trouver les balles
**Les capteurs pour se repérer dans l'espace
+
**Les Capteurs pour se repérer dans l'espace
**Un support ballon  
+
**Un Support ballon  
**Un système de crevaison de ballon
+
**Un Système de crevaison de ballon
  
Vous verrez ci-joint en vignette le schéma fonctionnel de notre robot.
+
Vous trouverez ci-joint en vignette le schéma fonctionnel de notre robot.
  
 
==Répartition des tâches==
 
==Répartition des tâches==
Nous nous sommes répartis les tâches de la façon suivante:
+
*Nous nous sommes répartis les tâches de la façon suivante:
  Jason Savouret a pour tâches de s'occuper du repérage dans l'espace grâce à des capteurs.
+
**Jason Savouret a pour tâches de s'occuper du repérage dans l'espace grâce à des capteurs.
 +
**Aurelien Noirault gère le système de renvoie des balles ainsi que le moyen de les  repérer et de les attraper, le montage du robot (pièces et composants), l'alimentation ainsi que la maintenance.
 +
**Aurelien Laurens a pour mission de crée le système pour supporter le ballon et du système de crevaison associé pour la fin de la partie, le montage du robot (pièces et composants), l'alimentation ainsi que la maintenance et le Site Web.
 +
**Cécile Forgeot s'oriente sur toute la partie mobilité du robot en gérant la partie déplacement ainsi que la maintenance du robot
  
  Aurelien Noirault gère le système de renvoie des balles ainsi que le moyen de les repérer et de les attraper.
+
==Repérage dans l'espace==
 +
===Partie 1: Objectif===
 +
[[Fichier:Boussolerobot.png|vignette|Boussole(MPU9250°]]
 +
*Le robot ne doit dépasser sous aucun prétexte la ligne médiane.
 +
*Le robot doit pouvoir se placer face au terrain adverse et connaître sa position vis à vis de celui-ci.
 +
 
 +
===Partie 2: Recherche===
 +
 
 +
[[Fichier:SEN10.png|vignette|Capteur SEN1010]]
 +
[[Fichier:CNY.png|vignette|Capteur CNY70]]
 +
*Afin de se repérer dans l'espace plusieurs choix ont été possible:
 +
**une boussole MPU9250 pour s’orienter vis à vis du camp adverse. Au démarrage le robot prendra en valeur initiale les coordonnées de la direction pour le camps adverses et ainsi il pourra connaître son orientation vis à vis du camp adverse.
 +
**un capteur de couleur SEN0101 afin de capter les couleurs du terrain. Son but serait de connaître la couleur sous le capteur afin de savoir s'il se situe au dessus d'une ligne blanche ou au dessus du sol (bleu foncé) du terrain. Avec ces information cela pourrait permettre au robot de se déplacer de manière autonome sur tout le terrain en analysant le terrain.
 +
*Dans le fonctionnement le capteur renvoie des valeurs pour connaître la composante de la couleur au dessus de laquelle il est. Grâce a une succession de tests on renvoie un état logique 1 ou 0.
 +
**0 permet de dire que l'on est sur le terrain (bleu).
 +
**1 permet de dire que l'on est sur une ligne blanche et donc possiblement la ligne médiane.
 +
Néanmoins la multitude de ligne blanche ne permet pas d'être très efficace et va davantage nuire au bon fonctionnement plutôt qu'être bénéfique. En effet, le robot pourrait confondre une ligne médiane et une autre ligne du terrain donc cette solution n'est pas optimale.
 +
 
 +
*Des capteurs infrarouge CNY70 pour savoir si il est sur le terrain ou sur la ligne médiane.
 +
 
 +
===Partie 3: Solution adoptée===
 +
*La boussole MPU9250 renvoie des valeurs qui permettent de calculer un angle en fonction de la position du robot. Au démarrage elle enregistre une valeur initiale d'angle qui sera donc la direction dans laquelle le camp adverse se situe car le robot sera placé face à celui-ci pour le début du match.
 +
**La boussole aura 2 buts:
 +
***S'il n'y a pas de balle devant le robot, la boussole enregistrera l'angle actuel puis le robot fera un tour sur lui-même sur la gauche jusqu'à retrouver sa position initiale en comparant son angle actuel à l'angle de début de tour et s'arrêtera de tourner s'il trouve une balle pour aller l'attraper.
 +
***Si le robot attrape une balle, la boussole comparera son angle avec celui du camps adverse, si le robot n'est pas dans la bonne direction il tournera sur la gauche jusqu'à se situé face au terrain adverse.
 +
*Nous adopterons aussi la solution d'utiliser 2 capteurs CNY70 placé à l'avant du robot dans les "mandibules"  et 1 capteur juste derrière le système de lancer de balle.  Les capteurs renverront chacun une valeur entre 0(clair) et 1023(foncée). En analysant en permanence les 3 capteurs et leurs valeurs, on établira une condition qui dira que si 2 capteurs renvoient un état logique 1 sachant que le robot pendant ce temps se déplace, cela reviendrait à dire que nous sommes sur la ligne médiane car les autres lignes sont assez fines donc on arrêtera le robot directement.
 +
 
 +
==Gestion des balles==
 +
===Partie 1: Objectif===
 +
*Le robot doit être capable de repérer la balle
 +
*L'attraper
 +
*La renvoyer
 +
 
 +
===Partie 2: Recherche===
 +
*Dans le but de repérer la balle, 2 choix ont été trouvé:
 +
**L'utilisation d'un capteur de distance VL53L1X qui permet de balayer le terrain pour trouver des reliefs(balles) tout comme le système de sonar d'un sous marin. Seulement le capteur n'est pas du tout assez précis et un angle légèrement différent rend l'utilisation bien moins fiable. De plus le capteur pouvait confondre un mur et les balles vu que il ne cherchait qu'un relief.
 +
**Une caméra pixy2 qui permettrait d'enregistrer des formes pour pouvoir les retrouver.
 +
 
 +
*En vue de l'attraper:
 +
**La réalisation d'une partie supplémentaire à l'avant du robot pour l'attraper et la bloquer.
 +
**Un servomoteur possédant une barre permettant de bloquer la balle.
 +
 
 +
*Dans l'intention de renvoyer la balle:
 +
**L'emploi de 2  moteurs avec 1 mini roue chacun dans le principe d'un lanceur de tennis mais le soucis rencontré est la place disponible. Donc des modifications, comme le fait d'utiliser 1 seul moteur avec une rampe ont été essayées. Cependant le soucis de place toujours présent et de puissance est remarqué, l'idée de remplacer la mini roue par une pale avec ou sans rampe fut testée mais toujours sans réelle réussite dû au manque de place et de puissance.
 +
**L'emploi d'un moteur brushless avec une partie pour frapper la balle
 +
 
 +
===Partie 3: Solution adoptée===
 +
*Pour repérer la balle, la caméra pixy2 est un bon système. En lui faisant enregistrer la forme et la couleur d'une balle elle est capable sur un maximum d'un mètre en face d'elle de repérer la dites balle et ses coordonnées. Ainsi le robot se dirigera vers elle peu à peu. Si le robot ne voit pas de balle face à lui il tournera sur lui même dans un premier temps pour observer autour de lui s'il y a une balle ou non.
 +
*La partie pour attraper la balle sera composée d'une extension réalisée en modélisation 3D en forme d'entonnoir et d'un servomoteur avec une barre. Quand le robot repérera la balle il avancera dans sa direction. Grâce aux extensions des mandibules la balle se logera à l'avant du robot et le servomoteur enfermera la balle, ce qui empêchera la balle de partir et d'autres balles de rentrer.
 +
*Pour renvoyer la balle un moteur brushless possédant une extension dans le style d'une barre permettra de frapper la balle quand le moteur tournera. On alimentera et contrôlera le moteur avec un Roxxy Bl-control 712 BEC qui a été relié au moteur Brushless.
 +
 
 +
==Crève ballon==
 +
[[Fichier:Support ballon.png|100px|vignette|Modélisation support-ballon]]
 +
===Partie 1: Objectif===
 +
*Crée un support pour placer le ballon
 +
*Trouver un moyen pour crever le ballon
 +
 
 +
===Partie 2: Recherche===
 +
[[Fichier:Arduino branchement.jpg|100px|vignette|Câblage arduino]]
 +
*Pour le support ballon il est nécessaire de trouver un moyen de fixer à minimum 30 cm du sol un ballon et une partie pour maintenir la pièce. La conception d'un modèle 3D fut donc nécessaire. Mais pour le maintenir une petite extension en haut de la colonne à tenté d'être faites mais quand le ballon bouge il y a des chances qu'il se détache et parte
 +
 
 +
*Pour crever le ballon plusieurs idées ont été testé:
 +
**Un servomoteur HS-311 avec une extension en plastique afin d'y placé un moteur à courant continue avec une partie pointu seulement le moteur manque de couple pour crever le ballon donc cette solution n'est pas utilisable.
 +
**Un servomoteur HS-311 et une extension en plastique avec un servomoteur GS-9018 mais par volonté d'optimisation de ressources, de fil et de consommation on a pas choisis cette solution.
 +
**Un servomoteur GS-9018 qui par mouvement à 180° pourrait crever le ballon.
 +
 
 +
===Partie 3: Solution adoptée===
 +
 
 +
[[Fichier:Partie creve ballon.jpg|100px|vignette|Système support et crève ballon]]
 +
*Une modélisation 3D d'une colonne a été réalisé à l'aide du logiciel Openscad, celle-ci possède 2 ouverture sur sa face afin de placer le servomoteur et l'autre permettant le câblage du servomoteur(schéma ci-contre de la modélisation). Un soucis a été rencontré en plus de maintenir le ballon durablement. Le ballon étant en plastique, il pouvait  être poussé par le crève ballon et non être percé. Pour remédier au soucis lié au ballon, une pince a été placé au sommet de la colonne pour l'attraper et le garder maintenue et une barre à été ajouté sur le coté de la colonne pour bloquer le ballon.
 +
 
 +
*Afin de percer le ballon, le servomoteur sera relié à un arduino (câblage ci-contre)et est équipé d'une extension réalisé en modélisation 3D afin de taper de coté le ballon en opposition à la barre qui sert à bloquer le ballon. Une pointe est placé au bout de cette extension, elle sera recouverte par un cache lors du transport pour ne représenté aucun danger et il sera enlevé une fois le robot sur le terrain.
 +
 
 +
==Déplacement==
 +
 
 +
===Partie 1: Objectif===
 +
 
 +
La partie moteur se doit d'être irréprochable. En fonction des données obtenues (capteurs, pixy, timer), les moteurs se mettent en marchent à une vitesse plus ou moins rapide.
 +
[[Fichier:Motor.png|vignette]]
 +
 
 +
 
 +
*Commander les moteurs grâce au MD13S
 +
[[Fichier:Cytron motor driver.jpg|vignette]]
 +
 
 +
===Partie 2: Recherche===
 +
 
 +
*Pour déplacer le robot, 2 moteurs MA 970D sont imposés. Pour chaque moteur on utilise un pilote de Moteur MD13S.
 +
*Le MD13S a besoin d'une PWM et d'un pin normal (DIR). Pour brancher les moteurs, il y a une borne GND.
 +
*Pour tester le fonctionnement des moteurs nous avons utilisé un potentiomètre pour simuler les capteurs de ligne et la boussole.
 +
*La vitesse des moteurs est au minimum de 0 et au maximum de 255.
 +
*Pour initialiser les moteurs sur Arduino, il faut enregistrer la librairie "Cytron Motor Driver" puis on utilisera la commande "setSpeed()" par la suite.
 +
*Problème rencontré: les 2 moteurs ne tournent pas à la même vitesse pour la même consigne.
 +
 
 +
===Partie 3: Solution adoptée===
 +
 
 +
*Pour permettre au robot de se déplacer, les bras des moteurs s'insèrent dans des roues.
 +
*Afin de remédier aux soucis de vitesse, nous avons remarqué que le problème était le manque de puissance. Avec une alimentation plus importante, le problème était réglé.
 +
*Pour le moteur de gauche, il est connecté au pins 3(PWM) et 4(DIR). Le moteur de droit quant à lui est connecté aux pins 6(PWM) et 7(DIR).
 +
*Voici un exemple de l'utilisation du MD13S :
 +
        moteurG.setSpeed(0);
 +
    moteurD.setSpeed(0);
 +
*En ce qui concerne la vitesse (0 à 255), nous avons privilégié des vitesses inférieures à 100. En effet, au dessus de cette valeur, le robot en devient incontrôlable.
 +
 
 +
==Programmation==
 +
Le robot fonctionne à l'aide d'un Arduino uno sur lequel on a connecté tous les composants. Chaque membre du groupe avait le code de sa partie puis nous les avons rassemblés de manière à que toutes les fonctions fonctionnent ensemble.
 +
Un chronomètre est initialisé grâce à la fonction millis ainsi qu'une boussole pour connaitre la position du terrain ennemie au début du match dans l'Arduino. Si le temps est inférieur à 85 s alors le robot sera en mode recherche de balle. Le robot tournera sur lui même en regardant avec la caméra pixy s'il voit une balle. Si le robot en trouve une, il ira la chercher puis la renvoyer dans le terrain adverse en se dirigeant grâce à la Boussole, face au terrain adverse.
 +
S'il n'en trouve pas alors il se déplacera puis effectuera la même démarche jusqu'à en trouver une.
 +
Si le temps est supérieur à 85s alors le robot montera à la ligne blanche et percera son ballon puis s'arrêtera de fonctionner.
 +
 
 +
{{boîte déroulante/début|titre=Programme}}
 +
<source lang=arduino>
 +
#include<Pixy2.h>
 +
#include<Servo.h>
 +
#include <Wire.h>
 +
#include <CytronMotorDriver.h>
 +
#include <math.h>
 +
#include <TimerOne.h>
 +
 
 +
#define ouvert 0
 +
#define fermer 50
 +
 
 +
//boussole
 +
#define MPU9250_ADDRESS        0x68
 +
#define MAG_ADDRESS            0x0C
 +
 
 +
#define GYRO_FULL_SCALE_250_DPS 0x00
 +
#define GYRO_FULL_SCALE_500_DPS 0x08
 +
#define GYRO_FULL_SCALE_1000_DPS  0x10
 +
#define GYRO_FULL_SCALE_2000_DPS  0x18
 +
 
 +
#define ACC_FULL_SCALE_2_G    0x00
 +
#define ACC_FULL_SCALE_4_G    0x08
 +
#define ACC_FULL_SCALE_8_G    0x10
 +
#define ACC_FULL_SCALE_16_G  0x18
 +
 
 +
float AngleZ = 0;
 +
int BonAngle = 1;
 +
float AngleInit;
 +
float AngleQuelconque = 0;
 +
 
 +
// Counter BOUSSOLE
 +
long int cpt = 0;
 +
 
 +
//////////////////////////////////BOUSSOLE
 +
// This function reads Nbytes bytes from I2C device at address Address.
 +
// Put read bytes starting at register Register in the Data array.
 +
void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
 +
{
 +
  // Set register address
 +
  Wire.beginTransmission(Address);
 +
  Wire.write(Register);
 +
  Wire.endTransmission();
 +
 
 +
  // Read Nbytes
 +
  Wire.requestFrom(Address, Nbytes);
 +
  uint8_t index = 0;
 +
  while (Wire.available())
 +
Data[index++] = Wire.read();
 +
}
 +
 
 +
// Write a byte (Data) in device (Address) at register (Register)
 +
void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
 +
{
 +
  // Set register address
 +
  Wire.beginTransmission(Address);
 +
  Wire.write(Register);
 +
  Wire.write(Data);
 +
  Wire.endTransmission();
 +
}
 +
// Initial time
 +
long int ti;
 +
volatile bool intFlag = false;
 +
////////////////////////////BOUSSOLE
 +
 
 +
//pixy
 +
Pixy2 pixy;
 +
double x;
 +
double y;
 +
 
 +
//Moteur
 +
CytronMD moteurG(PWM_DIR, 3, 4); // PWM = broche 3, DIR = broche 4 / moteur GAUCHE
 +
CytronMD moteurD(PWM_DIR, 6, 7); //PWM = broche 6, DIR = broche 7 / moteur DROIT
 +
 
 +
double var_inter;
 +
double consigneG;
 +
double consigneD;
 +
 
 +
// Manipulation Balle
 +
Servo esc;
 +
Servo blockBalle;
 +
 
 +
// Perce Ballon
 +
Servo perceBallon;
 +
 
 +
int pos;
 +
int i;
 +
 
 +
// Mesure temps
 +
int temps;
 +
const int t_max;
 +
 
 +
 
 +
// Prototype fonction
 +
void propulseBalle();
 +
void finPartie();
 +
void callback();
 +
 
 +
 
 +
 
 +
 
 +
void setup() {
 +
  pos = 0;
 +
  i = 0;
 +
 
 +
  pixy.init();
 +
 
 +
  // init servo
 +
  // perce ballon
 +
  perceBallon.attach(9);
 +
  perceBallon.write(pos);
 +
 
 +
  // block balle
 +
  blockBalle.attach(10);
 +
  blockBalle.write(ouvert);
 +
 
 +
  esc.attach(11);
 +
 
 +
  ////////////////////////// BOUSSOLE
 +
  // Arduino initializations
 +
  Wire.begin();
 +
  Serial.begin(9600);
 +
 
 +
  // Set accelerometers low pass filter at 5Hz
 +
  I2CwriteByte(MPU9250_ADDRESS, 29, 0x06);
 +
  // Set gyroscope low pass filter at 5Hz
 +
  I2CwriteByte(MPU9250_ADDRESS, 26, 0x06);
 +
 
 +
 
 +
  // Configure gyroscope range
 +
  I2CwriteByte(MPU9250_ADDRESS, 27, GYRO_FULL_SCALE_1000_DPS);
 +
  // Configure accelerometers range
 +
  I2CwriteByte(MPU9250_ADDRESS, 28, ACC_FULL_SCALE_4_G);
 +
  // Set by pass mode for the magnetometers
 +
  I2CwriteByte(MPU9250_ADDRESS, 0x37, 0x02);
 +
 
 +
  // Request continuous magnetometer measurements in 16 bits
 +
  I2CwriteByte(MAG_ADDRESS, 0x0A, 0x16);
 +
 
 +
  // pinMode(13, OUTPUT);
 +
  //pinMode(1, INPUT);
 +
  Timer1.initialize(10000);    // initialize timer1, and set a 1/2 second period
 +
  Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt
 +
 
 +
 
 +
  // Store initial time
 +
  ti = millis();
 +
}
 +
//////////////////////////////BOUSSOLE
 +
// Counter
 +
void callback()
 +
{
 +
  intFlag = true;
 +
  digitalWrite(13, digitalRead(13) ^ 1);
 +
}
  
  Aurelien Laurens a pour mission de crée le système pour supporter le ballon et du  système de crevaison associé pour la fin de la partie.
+
void loop() {
  
   Cécile Forgeot s'oriente sur toute la partie mobilité du robot en gérant la   partie déplacement.
+
   //////////////////////BOUSSOLE
 +
   while (!intFlag);
 +
  intFlag = false;
  
==Repérage dans l'espace==
+
  // Display time
===Partie 1: objectif===  
+
  Serial.print (millis() - ti, DEC);
*Le robot ne doit dépasser sous aucun prétexte la ligne médiane.
+
  Serial.print ("\t");
*Le robot doit pouvoir se placer face au terrain adverse et connaitre sa position vis à vis de celui-ci
+
 
 +
  delay(10);
 +
 
 +
  // _______________
 +
  // ::: Counter :::
 +
 
 +
  // Display data counter
 +
  //  Serial.print (cpt++,DEC);
 +
  //  Serial.print ("\t");
 +
 
 +
 
 +
  // ____________________________________
 +
  // :::  accelerometer and gyroscope :::
 +
 
 +
  // Read accelerometer and gyroscope
 +
  uint8_t Buf[14];
 +
  I2Cread(MPU9250_ADDRESS, 0x3B, 14, Buf);
 +
 
 +
  // Create 16 bits values from 8 bits data
 +
 
 +
  // Accelerometer
 +
  int16_t ax = -(Buf[0] << 8 | Buf[1]);
 +
  int16_t ay = -(Buf[2] << 8 | Buf[3]);
 +
  int16_t az = Buf[4] << 8 | Buf[5];
 +
 
 +
  // Gyroscope
 +
  int16_t gx = -(Buf[8] << 8 | Buf[9]);
 +
  int16_t gy = -(Buf[10] << 8 | Buf[11]);
 +
  int16_t gz = Buf[12] << 8 | Buf[13];
 +
 
 +
 
 +
 
 +
  // Display values
 +
 
 +
  // Accelerometer
 +
  /*Serial.print ("ax");
 +
Serial.print (ax,DEC);
 +
Serial.print ("\t");
 +
Serial.print ("ay");
 +
Serial.print (ay,DEC);
 +
Serial.print ("\t");
 +
Serial.print ("az");
 +
Serial.print (az,DEC);
 +
Serial.print ("\t");
 +
 
 +
// Gyroscope
 +
Serial.print ("gx");
 +
Serial.print (gx,DEC);
 +
Serial.print ("\t");
 +
Serial.print ("gy");
 +
Serial.print (gy,DEC);
 +
Serial.print ("\t");
 +
Serial.print ("gz");
 +
Serial.print (gz,DEC);
 +
Serial.print ("\t");*/
 +
 
 +
 
 +
  // _____________________
 +
  // :::  Magnetometer :::
 +
 
 +
 
 +
  // Read register Status 1 and wait for the DRDY: Data Ready
 +
 
 +
  uint8_t ST1;
 +
  do
 +
  {
 +
I2Cread(MAG_ADDRESS, 0x02, 1, &ST1);
 +
  }
 +
  while (!(ST1 & 0x01));
 +
 
 +
  // Read magnetometer data
 +
  uint8_t Mag[7];
 +
  I2Cread(MAG_ADDRESS, 0x03, 7, Mag);
 +
 
 +
 
 +
  // Create 16 bits values from 8 bits data
 +
 
 +
  // Magnetometer
 +
  int16_t mx = -(Mag[3] << 8 | Mag[2]);
 +
  int16_t my = -(Mag[1] << 8 | Mag[0]);
 +
  int16_t mz = -(Mag[5] << 8 | Mag[4]);
 +
 
 +
 
 +
  // Magnetometer
 +
  /*Serial.print ("mx+200");
 +
Serial.print (mx+200,DEC);
 +
Serial.print ("\t");
 +
Serial.print ("my-70");
 +
Serial.print (my-70,DEC);
 +
Serial.print ("\t");
 +
Serial.print ("mz-700");
 +
Serial.print (mz-700,DEC);
 +
Serial.print ("\t");*/
 +
 
 +
 
 +
 
 +
 
 +
  AngleZ = atan2(my, mx) * (180 / PI);
 +
  //3.14159265);
 +
  if (AngleZ < 0) {
 +
AngleZ = AngleZ + 360;
 +
  }
 +
 
 +
  delay(10);
 +
 
 +
  Serial.print ("Angle Z : ");
 +
  Serial.print (AngleZ);
 +
  Serial.print ("\t");
 +
 
 +
  delay(10);
 +
 
 +
  //ValeurBouton = digitalRead(1);
 +
  //Serial.print ("valeur bouton :");
 +
  // Serial.print (ValeurBouton);
 +
  // Serial.print ("\t");
 +
 
 +
  delay(10);
 +
 
 +
  //if (ValeurBouton == 1) {
 +
  //  BonAngle = 1;
 +
  // } else {
 +
  //  BonAngle = 0;
 +
  //}
 +
 
 +
  Serial.print("Bon angle : ");
 +
  Serial.print(BonAngle);
 +
  Serial.print("    ");
 +
  delay(10);
 +
 
 +
  if (BonAngle == 1) {
 +
AngleInit = AngleZ;
 +
BonAngle = 0;
 +
  }
 +
 
 +
  delay(10);
 +
 
 +
  if (AngleZ >= AngleInit - 15 && AngleZ <= AngleInit + 15) {
 +
//Code de lancé de balle
 +
Serial.print("on peut lancer la balle");
 +
  }
 +
 
 +
  // End of line
 +
  Serial.println("    ");
 +
  delay(10);
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
  // récupère données pixy
 +
  pixy.ccc.getBlocks();
 +
 
 +
  if (temps < t_max)
 +
  {
 +
if (pixy.ccc.numBlocks)
 +
{
 +
  x = pixy.ccc.blocks[0].m_x;
 +
  y = pixy.ccc.blocks[0].m_y;
 +
  if (y < 190)
 +
  {
 +
    consigneD = x / 316 * (-100) + 100;
 +
    var_inter = x / 316, 0;
 +
    consigneG = var_inter * 100;
 +
    moteurD.setSpeed(consigneD);
 +
    moteurG.setSpeed(consigneG);
 +
  }
 +
  else
 +
  {
 +
    moteurG.setSpeed(90);
 +
    moteurD.setSpeed(90);
 +
    delay(100);
 +
    moteurG.setSpeed(0);
 +
    moteurD.setSpeed(0);
 +
 
 +
    propulseBalle();
 +
  }
 +
}
 +
else
 +
{
 +
  //pas un tour complet
 +
  AngleQuelconque = AngleZ;
 +
  if (AngleQuelconque < 350) {
 +
    if (AngleZ < AngleQuelconque && AngleZ > AngleQuelconque + 10) {
 +
      moteurG.setSpeed (0);
 +
      moteurD.setSpeed(100);
 +
    } else {
 +
      moteurG.setSpeed(100);
 +
      moteurD.setSpeed(100);
 +
      delay(500);
 +
      moteurG.setSpeed(0);
 +
      moteurD.setSpeed(0);
 +
    }
 +
  } else { //au dessus de 350
 +
    if (AngleZ < AngleQuelconque && AngleZ > int(AngleQuelconque + 10) % 360) {
 +
      moteurG.setSpeed (0);
 +
      moteurD.setSpeed(100);
 +
    } else {
 +
      moteurG.setSpeed(100);
 +
      moteurD.setSpeed(100);
 +
      delay(500);
 +
      moteurG.setSpeed(0);
 +
      moteurD.setSpeed(0);
 +
    }
 +
  }
 +
}
 +
  }
 +
  else
 +
  {
 +
finPartie();
 +
  }
 +
  //pas en face
 +
  if (AngleInit >= 355) {
 +
while (AngleZ < AngleInit - 5 && AngleZ > int(AngleInit + 5) % 360) {
 +
  moteurG.setSpeed(0);
 +
  moteurD.setSpeed(100);
 +
}
 +
  }
 +
  else {
 +
if (AngleInit <= 5) {
 +
  while (AngleZ < int(AngleInit - 5) % 360 && AngleZ > AngleInit + 5) {
 +
    moteurG.setSpeed(0);
 +
    moteurD.setSpeed(100);
 +
  }
 +
} else {
 +
  if (AngleInit < 355 && AngleInit > 5) {
 +
    while (AngleZ < AngleInit - 5 && AngleZ > AngleInit + 5) {
 +
      moteurG.setSpeed(0);
 +
      moteurD.setSpeed(100);
 +
    }
 +
  }
 +
}
 +
  }
 +
 
 +
  if (AngleZ >= int(AngleInit - 5) % 360 && AngleZ <= int(AngleInit + 5) % 360) {
 +
moteurG.setSpeed(100);
 +
moteurD.setSpeed(100);
 +
delay(500);
 +
moteurG.setSpeed(0);
 +
moteurD.setSpeed(0);
 +
  } else {
 +
 
 +
//pas en retour position précedente
 +
 
 +
if (AngleQuelconque < 350) {
 +
  if (AngleZ < AngleQuelconque && AngleZ > AngleQuelconque + 10) {
 +
    moteurG.setSpeed (0);
 +
    moteurD.setSpeed(100);
 +
  }
 +
} else { //au dessus de 350
 +
  if (AngleZ < AngleQuelconque && AngleZ > int(AngleQuelconque + 10) % 360) {
 +
    moteurG.setSpeed (0);
 +
    moteurD.setSpeed(100);
 +
  }
 +
}
 +
  }
 +
}
 +
 
 +
 
 +
// Fonctions
 +
 
 +
void propulseBalle()
 +
{
 +
  // ferme servo
 +
  blockBalle.write(fermer);
 +
 
 +
  //pas tour complet
 +
  AngleQuelconque = AngleZ;
 +
  if (AngleQuelconque < 350) {
 +
if (AngleZ < AngleQuelconque && AngleZ > AngleQuelconque + 10) {
 +
  moteurG.setSpeed (0);
 +
  moteurD.setSpeed(100);
 +
}
 +
  } else { //au dessus de 350
 +
if (AngleZ < AngleQuelconque && AngleZ > int(AngleQuelconque + 10) % 360) {
 +
  moteurG.setSpeed (0);
 +
  moteurD.setSpeed(100);
 +
}
 +
  }
 +
  // OUVRE SERVO
 +
  blockBalle.write(ouvert);
 +
  esc.write(0);
 +
  delay(1000);
 +
  esc.write(180);
 +
  delay(1000);
 +
  esc.write(0);
 +
  // Tourne le moteur
 +
  esc.write(20);
 +
}
 +
 
 +
void finPartie()
 +
{
 +
  //partie servomoteur qui crève le ballon
 +
  while (i < 3) {
 +
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
 +
  // in steps of 1 degree
 +
  perceBallon.write(pos);      // tell servo to go to position in variable 'pos'
 +
  delay(5);                // waits 15ms for the servo to reach the position
 +
}
 +
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
 +
  perceBallon.write(pos);      // tell servo to go to position in variable 'pos'
 +
  delay(5);                // waits 15ms for the servo to reach the position
 +
}
 +
i++;
 +
 
 +
  }
 +
}
 +
</source>
 +
{{boîte déroulante/fin}}
 +
 
 +
==Assemblage du Robot==
 +
[[Fichier:Robot geii2.jpg|vignette]]
 +
*Le montage des différents systèmes et pièces du robot fut débuté tout d'abord par les grosses parties qui représentent la base du robot comme le bloc d'alimentation.
 +
**Le bloc d'alimentation ainsi que les différents réseaux d'alimentation
 +
**Bouton d'arrêt d'urgence
 +
**Moteur MA 970D
 +
 
 +
*Puis après avoir fixé ces pièces et câblé, nous avons assemblé et fixé les parties supplémentaires du robot qui sont:
 +
**Les supports des pilotes Moteurs MD13S auxquels nous les avons fixés.
 +
**Les différents capteurs comme les 3 CNY70 et la boussole MPU9250.
 +
**le système de renvoi de balle.
 +
**Le support du ballon et avec le système de perçage de ballon.
 +
Quand tous les derniers systèmes fut installé nous les avons reliés, câblés et alimentés.
 +
 
 +
==Travaux à finir==
 +
*Afin d'avoir un robot fonctionnel pour la compétition il reste encore quelque travaux à faire:
 +
**Test et mise au point du programme sur la partie recherche de balle.
 +
**Test et mise au point sur la partie "renvoie de balle".
 +
**Réglages divers.
 +
**Essaie du robot en situation de match pour observer le fonctionnement de chaque partie et si celle-ci ne présente pas de défaut ou dysfonctionnement sur le terrain.
  
===Partie 2: Test===
+
'''FORGEOT Cécile'''
*Afin de se repérer dans l'espace plusieurs choix ont été possible:
 
    *une boussole (MPU9250) pour s’orienter vis à vis du camp adverse. Au démarrage le robot prendra en valeur initiale les coordonnées de la direction pour le camps adverses et ainsi il pourra connaitre son orientation vis à vis du camp adverse.
 
  
    *un capteur de couleur SEN0101 afin de capter les couleurs du terrain le but serait de connaitre la couleur sous le capteur afin de savoir si il se situe au dessus d'une ligne blanche ou au dessus du sol bleu foncé du terrain. Le but serait de permettre au robot de se déplacé de manière autonome sur tout le terrain en sachant les analysants le terrain
+
'''LAURENS Aurélien'''
  
    *Des capteurs infrarouge CNY70 pour savoir si il est sur le terrain ou sur la ligne médiane.
+
'''NOIRAULT Aurélien'''
  
===Partie 3: Solution Finale===
+
'''SAVOURET Jason'''

Version actuelle datée du 16 avril 2021 à 15:20



Présentation du projet

Le projet a pour objectif de réaliser un match entre 2 robots. Ceux-ci devront envoyer depuis leur terrain le plus de balles de tennis possible sans aller sur le terrain adverse.
Le terrain mesure 8 mètres par 4 et est séparé en 2 parties par une ligne médiane donc chaque robot aura un terrain d'approximativement 16m² pour se déplacer.

Une partie dure 90s, avant la fin du temps imparti le robot devra être immobile au niveau de la ligne médiane et avoir éclaté un ballon qu'il aura emporté avec lui au début du match.
Le vainqueur sera le robot avec le moins de balle sur son terrain.


Objectif du Projet

  • Réaliser un Robot capable de se déplacer dans son terrain.
  • Renvoyer des balles depuis son terrain jusqu'au terrain adverse.
  • Crever le ballon que l'on a emporté à l'arrêt devant la ligne médiane avant la fin du temps imparti.


Règlement

Voici ci-joint le règlement ainsi que les contraintes associées à la création du Projet.

   * règlement de la coupe de robotique

Contraintes et Caractéristiques imposées

Schéma du terrain.png

Les principales contraintes sont dues aux règles de la compétition.

  • Le robot doit être dimensionné selon 30x30x40cm.
  • Moteurs
    • Vitesse de rotation entre 600 à 800 tr/min max.
    • Moteur MFA 970d (imposé par l'IUT)
  • Châssis imposé par l'IUT
  • Le mécanisme lanceur de balle dépassera seulement pour envoyer la balle, il devra se replier après.
  • La batterie doit être en lithium Li-ion.


  • Aucune tension sur le robot ne doit dépasser 24V.
  • Les dimensions du terrain sont données sur ce schéma :

Réalisation

Découpage fonctionnel

Schéma fonctionnel robot geii.png

Afin de commencer le projet, nous avons dû séparer les parties essentielles du projet pour ensuite répartir les tâches.

  • On a séparé le travail en différent groupe fonctionnel
    • L' Alimentation
    • Le Déplacement
    • Le Système de renvoi des balles
    • Les Capteurs pour trouver les balles
    • Les Capteurs pour se repérer dans l'espace
    • Un Support ballon
    • Un Système de crevaison de ballon

Vous trouverez ci-joint en vignette le schéma fonctionnel de notre robot.

Répartition des tâches

  • Nous nous sommes répartis les tâches de la façon suivante:
    • Jason Savouret a pour tâches de s'occuper du repérage dans l'espace grâce à des capteurs.
    • Aurelien Noirault gère le système de renvoie des balles ainsi que le moyen de les repérer et de les attraper, le montage du robot (pièces et composants), l'alimentation ainsi que la maintenance.
    • Aurelien Laurens a pour mission de crée le système pour supporter le ballon et du système de crevaison associé pour la fin de la partie, le montage du robot (pièces et composants), l'alimentation ainsi que la maintenance et le Site Web.
    • Cécile Forgeot s'oriente sur toute la partie mobilité du robot en gérant la partie déplacement ainsi que la maintenance du robot

Repérage dans l'espace

Partie 1: Objectif

Boussole(MPU9250°
  • Le robot ne doit dépasser sous aucun prétexte la ligne médiane.
  • Le robot doit pouvoir se placer face au terrain adverse et connaître sa position vis à vis de celui-ci.

Partie 2: Recherche

Capteur SEN1010
Capteur CNY70
  • Afin de se repérer dans l'espace plusieurs choix ont été possible:
    • une boussole MPU9250 pour s’orienter vis à vis du camp adverse. Au démarrage le robot prendra en valeur initiale les coordonnées de la direction pour le camps adverses et ainsi il pourra connaître son orientation vis à vis du camp adverse.
    • un capteur de couleur SEN0101 afin de capter les couleurs du terrain. Son but serait de connaître la couleur sous le capteur afin de savoir s'il se situe au dessus d'une ligne blanche ou au dessus du sol (bleu foncé) du terrain. Avec ces information cela pourrait permettre au robot de se déplacer de manière autonome sur tout le terrain en analysant le terrain.
  • Dans le fonctionnement le capteur renvoie des valeurs pour connaître la composante de la couleur au dessus de laquelle il est. Grâce a une succession de tests on renvoie un état logique 1 ou 0.
    • 0 permet de dire que l'on est sur le terrain (bleu).
    • 1 permet de dire que l'on est sur une ligne blanche et donc possiblement la ligne médiane.

Néanmoins la multitude de ligne blanche ne permet pas d'être très efficace et va davantage nuire au bon fonctionnement plutôt qu'être bénéfique. En effet, le robot pourrait confondre une ligne médiane et une autre ligne du terrain donc cette solution n'est pas optimale.

  • Des capteurs infrarouge CNY70 pour savoir si il est sur le terrain ou sur la ligne médiane.

Partie 3: Solution adoptée

  • La boussole MPU9250 renvoie des valeurs qui permettent de calculer un angle en fonction de la position du robot. Au démarrage elle enregistre une valeur initiale d'angle qui sera donc la direction dans laquelle le camp adverse se situe car le robot sera placé face à celui-ci pour le début du match.
    • La boussole aura 2 buts:
      • S'il n'y a pas de balle devant le robot, la boussole enregistrera l'angle actuel puis le robot fera un tour sur lui-même sur la gauche jusqu'à retrouver sa position initiale en comparant son angle actuel à l'angle de début de tour et s'arrêtera de tourner s'il trouve une balle pour aller l'attraper.
      • Si le robot attrape une balle, la boussole comparera son angle avec celui du camps adverse, si le robot n'est pas dans la bonne direction il tournera sur la gauche jusqu'à se situé face au terrain adverse.
  • Nous adopterons aussi la solution d'utiliser 2 capteurs CNY70 placé à l'avant du robot dans les "mandibules" et 1 capteur juste derrière le système de lancer de balle. Les capteurs renverront chacun une valeur entre 0(clair) et 1023(foncée). En analysant en permanence les 3 capteurs et leurs valeurs, on établira une condition qui dira que si 2 capteurs renvoient un état logique 1 sachant que le robot pendant ce temps se déplace, cela reviendrait à dire que nous sommes sur la ligne médiane car les autres lignes sont assez fines donc on arrêtera le robot directement.

Gestion des balles

Partie 1: Objectif

  • Le robot doit être capable de repérer la balle
  • L'attraper
  • La renvoyer

Partie 2: Recherche

  • Dans le but de repérer la balle, 2 choix ont été trouvé:
    • L'utilisation d'un capteur de distance VL53L1X qui permet de balayer le terrain pour trouver des reliefs(balles) tout comme le système de sonar d'un sous marin. Seulement le capteur n'est pas du tout assez précis et un angle légèrement différent rend l'utilisation bien moins fiable. De plus le capteur pouvait confondre un mur et les balles vu que il ne cherchait qu'un relief.
    • Une caméra pixy2 qui permettrait d'enregistrer des formes pour pouvoir les retrouver.
  • En vue de l'attraper:
    • La réalisation d'une partie supplémentaire à l'avant du robot pour l'attraper et la bloquer.
    • Un servomoteur possédant une barre permettant de bloquer la balle.
  • Dans l'intention de renvoyer la balle:
    • L'emploi de 2 moteurs avec 1 mini roue chacun dans le principe d'un lanceur de tennis mais le soucis rencontré est la place disponible. Donc des modifications, comme le fait d'utiliser 1 seul moteur avec une rampe ont été essayées. Cependant le soucis de place toujours présent et de puissance est remarqué, l'idée de remplacer la mini roue par une pale avec ou sans rampe fut testée mais toujours sans réelle réussite dû au manque de place et de puissance.
    • L'emploi d'un moteur brushless avec une partie pour frapper la balle

Partie 3: Solution adoptée

  • Pour repérer la balle, la caméra pixy2 est un bon système. En lui faisant enregistrer la forme et la couleur d'une balle elle est capable sur un maximum d'un mètre en face d'elle de repérer la dites balle et ses coordonnées. Ainsi le robot se dirigera vers elle peu à peu. Si le robot ne voit pas de balle face à lui il tournera sur lui même dans un premier temps pour observer autour de lui s'il y a une balle ou non.
  • La partie pour attraper la balle sera composée d'une extension réalisée en modélisation 3D en forme d'entonnoir et d'un servomoteur avec une barre. Quand le robot repérera la balle il avancera dans sa direction. Grâce aux extensions des mandibules la balle se logera à l'avant du robot et le servomoteur enfermera la balle, ce qui empêchera la balle de partir et d'autres balles de rentrer.
  • Pour renvoyer la balle un moteur brushless possédant une extension dans le style d'une barre permettra de frapper la balle quand le moteur tournera. On alimentera et contrôlera le moteur avec un Roxxy Bl-control 712 BEC qui a été relié au moteur Brushless.

Crève ballon

Modélisation support-ballon

Partie 1: Objectif

  • Crée un support pour placer le ballon
  • Trouver un moyen pour crever le ballon

Partie 2: Recherche

Câblage arduino
  • Pour le support ballon il est nécessaire de trouver un moyen de fixer à minimum 30 cm du sol un ballon et une partie pour maintenir la pièce. La conception d'un modèle 3D fut donc nécessaire. Mais pour le maintenir une petite extension en haut de la colonne à tenté d'être faites mais quand le ballon bouge il y a des chances qu'il se détache et parte
  • Pour crever le ballon plusieurs idées ont été testé:
    • Un servomoteur HS-311 avec une extension en plastique afin d'y placé un moteur à courant continue avec une partie pointu seulement le moteur manque de couple pour crever le ballon donc cette solution n'est pas utilisable.
    • Un servomoteur HS-311 et une extension en plastique avec un servomoteur GS-9018 mais par volonté d'optimisation de ressources, de fil et de consommation on a pas choisis cette solution.
    • Un servomoteur GS-9018 qui par mouvement à 180° pourrait crever le ballon.

Partie 3: Solution adoptée

Système support et crève ballon
  • Une modélisation 3D d'une colonne a été réalisé à l'aide du logiciel Openscad, celle-ci possède 2 ouverture sur sa face afin de placer le servomoteur et l'autre permettant le câblage du servomoteur(schéma ci-contre de la modélisation). Un soucis a été rencontré en plus de maintenir le ballon durablement. Le ballon étant en plastique, il pouvait être poussé par le crève ballon et non être percé. Pour remédier au soucis lié au ballon, une pince a été placé au sommet de la colonne pour l'attraper et le garder maintenue et une barre à été ajouté sur le coté de la colonne pour bloquer le ballon.
  • Afin de percer le ballon, le servomoteur sera relié à un arduino (câblage ci-contre)et est équipé d'une extension réalisé en modélisation 3D afin de taper de coté le ballon en opposition à la barre qui sert à bloquer le ballon. Une pointe est placé au bout de cette extension, elle sera recouverte par un cache lors du transport pour ne représenté aucun danger et il sera enlevé une fois le robot sur le terrain.

Déplacement

Partie 1: Objectif

La partie moteur se doit d'être irréprochable. En fonction des données obtenues (capteurs, pixy, timer), les moteurs se mettent en marchent à une vitesse plus ou moins rapide.

Motor.png


  • Commander les moteurs grâce au MD13S
Cytron motor driver.jpg

Partie 2: Recherche

  • Pour déplacer le robot, 2 moteurs MA 970D sont imposés. Pour chaque moteur on utilise un pilote de Moteur MD13S.
  • Le MD13S a besoin d'une PWM et d'un pin normal (DIR). Pour brancher les moteurs, il y a une borne GND.
  • Pour tester le fonctionnement des moteurs nous avons utilisé un potentiomètre pour simuler les capteurs de ligne et la boussole.
  • La vitesse des moteurs est au minimum de 0 et au maximum de 255.
  • Pour initialiser les moteurs sur Arduino, il faut enregistrer la librairie "Cytron Motor Driver" puis on utilisera la commande "setSpeed()" par la suite.
  • Problème rencontré: les 2 moteurs ne tournent pas à la même vitesse pour la même consigne.

Partie 3: Solution adoptée

  • Pour permettre au robot de se déplacer, les bras des moteurs s'insèrent dans des roues.
  • Afin de remédier aux soucis de vitesse, nous avons remarqué que le problème était le manque de puissance. Avec une alimentation plus importante, le problème était réglé.
  • Pour le moteur de gauche, il est connecté au pins 3(PWM) et 4(DIR). Le moteur de droit quant à lui est connecté aux pins 6(PWM) et 7(DIR).
  • Voici un exemple de l'utilisation du MD13S :
        moteurG.setSpeed(0);
   	moteurD.setSpeed(0);
  • En ce qui concerne la vitesse (0 à 255), nous avons privilégié des vitesses inférieures à 100. En effet, au dessus de cette valeur, le robot en devient incontrôlable.

Programmation

Le robot fonctionne à l'aide d'un Arduino uno sur lequel on a connecté tous les composants. Chaque membre du groupe avait le code de sa partie puis nous les avons rassemblés de manière à que toutes les fonctions fonctionnent ensemble. Un chronomètre est initialisé grâce à la fonction millis ainsi qu'une boussole pour connaitre la position du terrain ennemie au début du match dans l'Arduino. Si le temps est inférieur à 85 s alors le robot sera en mode recherche de balle. Le robot tournera sur lui même en regardant avec la caméra pixy s'il voit une balle. Si le robot en trouve une, il ira la chercher puis la renvoyer dans le terrain adverse en se dirigeant grâce à la Boussole, face au terrain adverse. S'il n'en trouve pas alors il se déplacera puis effectuera la même démarche jusqu'à en trouver une. Si le temps est supérieur à 85s alors le robot montera à la ligne blanche et percera son ballon puis s'arrêtera de fonctionner.

Programme

#include<Pixy2.h>
#include<Servo.h>
#include <Wire.h>
#include <CytronMotorDriver.h>
#include <math.h>
#include <TimerOne.h>

#define ouvert 0
#define fermer 50

//boussole
#define	MPU9250_ADDRESS        	0x68
#define	MAG_ADDRESS            	0x0C

#define	GYRO_FULL_SCALE_250_DPS	0x00
#define	GYRO_FULL_SCALE_500_DPS	0x08
#define	GYRO_FULL_SCALE_1000_DPS   0x10
#define	GYRO_FULL_SCALE_2000_DPS   0x18

#define	ACC_FULL_SCALE_2_G    	0x00
#define	ACC_FULL_SCALE_4_G    	0x08
#define	ACC_FULL_SCALE_8_G    	0x10
#define	ACC_FULL_SCALE_16_G   	0x18

float AngleZ = 0;
int BonAngle = 1;
float AngleInit;
float AngleQuelconque = 0;

// Counter BOUSSOLE
long int cpt = 0;

//////////////////////////////////BOUSSOLE
// This function reads Nbytes bytes from I2C device at address Address.
// Put read bytes starting at register Register in the Data array.
void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.endTransmission();

  // Read Nbytes
  Wire.requestFrom(Address, Nbytes);
  uint8_t index = 0;
  while (Wire.available())
	Data[index++] = Wire.read();
}

// Write a byte (Data) in device (Address) at register (Register)
void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.write(Data);
  Wire.endTransmission();
}
// Initial time
long int ti;
volatile bool intFlag = false;
////////////////////////////BOUSSOLE

//pixy
Pixy2 pixy;
double x;
double y;

//Moteur
CytronMD moteurG(PWM_DIR, 3, 4); // PWM = broche 3, DIR = broche 4 / moteur GAUCHE
CytronMD moteurD(PWM_DIR, 6, 7); //PWM = broche 6, DIR = broche 7 / moteur DROIT

double var_inter;
double consigneG;
double consigneD;

// Manipulation Balle
Servo esc;
Servo blockBalle;

// Perce Ballon
Servo perceBallon;

int pos;
int i;

// Mesure temps
int temps;
const int t_max;


// Prototype fonction
void propulseBalle();
void finPartie();
void callback();




void setup() {
  pos = 0;
  i = 0;

  pixy.init();

  // init servo
  // perce ballon
  perceBallon.attach(9);
  perceBallon.write(pos);

  // block balle
  blockBalle.attach(10);
  blockBalle.write(ouvert);

  esc.attach(11);

  ////////////////////////// BOUSSOLE
  // Arduino initializations
  Wire.begin();
  Serial.begin(9600);

  // Set accelerometers low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS, 29, 0x06);
  // Set gyroscope low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS, 26, 0x06);


  // Configure gyroscope range
  I2CwriteByte(MPU9250_ADDRESS, 27, GYRO_FULL_SCALE_1000_DPS);
  // Configure accelerometers range
  I2CwriteByte(MPU9250_ADDRESS, 28, ACC_FULL_SCALE_4_G);
  // Set by pass mode for the magnetometers
  I2CwriteByte(MPU9250_ADDRESS, 0x37, 0x02);

  // Request continuous magnetometer measurements in 16 bits
  I2CwriteByte(MAG_ADDRESS, 0x0A, 0x16);

  // pinMode(13, OUTPUT);
  //pinMode(1, INPUT);
  Timer1.initialize(10000);     	// initialize timer1, and set a 1/2 second period
  Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt


  // Store initial time
  ti = millis();
}
//////////////////////////////BOUSSOLE
// Counter
void callback()
{
  intFlag = true;
  digitalWrite(13, digitalRead(13) ^ 1);
}

void loop() {

  //////////////////////BOUSSOLE
  while (!intFlag);
  intFlag = false;

  // Display time
  Serial.print (millis() - ti, DEC);
  Serial.print ("\t");

  delay(10);

  // _______________
  // ::: Counter :::

  // Display data counter
  //  Serial.print (cpt++,DEC);
  //  Serial.print ("\t");


  // ____________________________________
  // :::  accelerometer and gyroscope :::

  // Read accelerometer and gyroscope
  uint8_t Buf[14];
  I2Cread(MPU9250_ADDRESS, 0x3B, 14, Buf);

  // Create 16 bits values from 8 bits data

  // Accelerometer
  int16_t ax = -(Buf[0] << 8 | Buf[1]);
  int16_t ay = -(Buf[2] << 8 | Buf[3]);
  int16_t az = Buf[4] << 8 | Buf[5];

  // Gyroscope
  int16_t gx = -(Buf[8] << 8 | Buf[9]);
  int16_t gy = -(Buf[10] << 8 | Buf[11]);
  int16_t gz = Buf[12] << 8 | Buf[13];



  // Display values

  // Accelerometer
  /*Serial.print ("ax");
	Serial.print (ax,DEC);
	Serial.print ("\t");
	Serial.print ("ay");
	Serial.print (ay,DEC);
	Serial.print ("\t");
	Serial.print ("az");
	Serial.print (az,DEC);
	Serial.print ("\t");

	// Gyroscope
	Serial.print ("gx");
	Serial.print (gx,DEC);
	Serial.print ("\t");
	Serial.print ("gy");
	Serial.print (gy,DEC);
	Serial.print ("\t");
	Serial.print ("gz");
	Serial.print (gz,DEC);
	Serial.print ("\t");*/


  // _____________________
  // :::  Magnetometer :::


  // Read register Status 1 and wait for the DRDY: Data Ready

  uint8_t ST1;
  do
  {
	I2Cread(MAG_ADDRESS, 0x02, 1, &ST1);
  }
  while (!(ST1 & 0x01));

  // Read magnetometer data
  uint8_t Mag[7];
  I2Cread(MAG_ADDRESS, 0x03, 7, Mag);


  // Create 16 bits values from 8 bits data

  // Magnetometer
  int16_t mx = -(Mag[3] << 8 | Mag[2]);
  int16_t my = -(Mag[1] << 8 | Mag[0]);
  int16_t mz = -(Mag[5] << 8 | Mag[4]);


  // Magnetometer
  /*Serial.print ("mx+200");
	Serial.print (mx+200,DEC);
	Serial.print ("\t");
	Serial.print ("my-70");
	Serial.print (my-70,DEC);
	Serial.print ("\t");
	Serial.print ("mz-700");
	Serial.print (mz-700,DEC);
	Serial.print ("\t");*/




  AngleZ = atan2(my, mx) * (180 / PI);
  //3.14159265);
  if (AngleZ < 0) {
	AngleZ = AngleZ + 360;
  }

  delay(10);

  Serial.print ("Angle Z : ");
  Serial.print (AngleZ);
  Serial.print ("\t");

  delay(10);

  //ValeurBouton = digitalRead(1);
  //Serial.print ("valeur bouton :");
  // Serial.print (ValeurBouton);
  // Serial.print ("\t");

  delay(10);

  //if (ValeurBouton == 1) {
  //  BonAngle = 1;
  // } else {
  //  BonAngle = 0;
  //}

  Serial.print("Bon angle : ");
  Serial.print(BonAngle);
  Serial.print("    	");
  delay(10);

  if (BonAngle == 1) {
	AngleInit = AngleZ;
	BonAngle = 0;
  }

  delay(10);

  if (AngleZ >= AngleInit - 15 && AngleZ <= AngleInit + 15) {
	//Code de lancé de balle
	Serial.print("on peut lancer la balle");
  }

  // End of line
  Serial.println("    	");
  delay(10);







  // récupère données pixy
  pixy.ccc.getBlocks();

  if (temps < t_max)
  {
	if (pixy.ccc.numBlocks)
	{
  	x = pixy.ccc.blocks[0].m_x;
  	y = pixy.ccc.blocks[0].m_y;
  	if (y < 190)
  	{
    	consigneD = x / 316 * (-100) + 100;
    	var_inter = x / 316, 0;
    	consigneG = var_inter * 100;
    	moteurD.setSpeed(consigneD);
    	moteurG.setSpeed(consigneG);
  	}
  	else
  	{
    	moteurG.setSpeed(90);
    	moteurD.setSpeed(90);
    	delay(100);
    	moteurG.setSpeed(0);
    	moteurD.setSpeed(0);

    	propulseBalle();
  	}
	}
	else
	{
  	//pas un tour complet
  	AngleQuelconque = AngleZ;
  	if (AngleQuelconque < 350) {
    	if (AngleZ < AngleQuelconque && AngleZ > AngleQuelconque + 10) {
      	moteurG.setSpeed (0);
      	moteurD.setSpeed(100);
    	} else {
      	moteurG.setSpeed(100);
      	moteurD.setSpeed(100);
      	delay(500);
      	moteurG.setSpeed(0);
      	moteurD.setSpeed(0);
    	}
  	} else { //au dessus de 350
    	if (AngleZ < AngleQuelconque && AngleZ > int(AngleQuelconque + 10) % 360) {
      	moteurG.setSpeed (0);
      	moteurD.setSpeed(100);
    	} else {
      	moteurG.setSpeed(100);
      	moteurD.setSpeed(100);
      	delay(500);
      	moteurG.setSpeed(0);
      	moteurD.setSpeed(0);
    	}
  	}
	}
  }
  else
  {
	finPartie();
  }
  //pas en face
  if (AngleInit >= 355) {
	while (AngleZ < AngleInit - 5 && AngleZ > int(AngleInit + 5) % 360) {
  	moteurG.setSpeed(0);
  	moteurD.setSpeed(100);
	}
  }
  else {
	if (AngleInit <= 5) {
  	while (AngleZ < int(AngleInit - 5) % 360 && AngleZ > AngleInit + 5) {
    	moteurG.setSpeed(0);
    	moteurD.setSpeed(100);
  	}
	} else {
  	if (AngleInit < 355 && AngleInit > 5) {
    	while (AngleZ < AngleInit - 5 && AngleZ > AngleInit + 5) {
      	moteurG.setSpeed(0);
      	moteurD.setSpeed(100);
    	}
  	}
	}
  }

  if (AngleZ >= int(AngleInit - 5) % 360 && AngleZ <= int(AngleInit + 5) % 360) {
	moteurG.setSpeed(100);
	moteurD.setSpeed(100);
	delay(500);
	moteurG.setSpeed(0);
	moteurD.setSpeed(0);
  } else {

	//pas en retour position précedente

	if (AngleQuelconque < 350) {
  	if (AngleZ < AngleQuelconque && AngleZ > AngleQuelconque + 10) {
    	moteurG.setSpeed (0);
    	moteurD.setSpeed(100);
  	}
	} else { //au dessus de 350
  	if (AngleZ < AngleQuelconque && AngleZ > int(AngleQuelconque + 10) % 360) {
    	moteurG.setSpeed (0);
    	moteurD.setSpeed(100);
  	}
	}
  }
}


// Fonctions

void propulseBalle()
{
  // ferme servo
  blockBalle.write(fermer);

  //pas tour complet
  AngleQuelconque = AngleZ;
  if (AngleQuelconque < 350) {
	if (AngleZ < AngleQuelconque && AngleZ > AngleQuelconque + 10) {
  	moteurG.setSpeed (0);
  	moteurD.setSpeed(100);
	}
  } else { //au dessus de 350
	if (AngleZ < AngleQuelconque && AngleZ > int(AngleQuelconque + 10) % 360) {
  	moteurG.setSpeed (0);
  	moteurD.setSpeed(100);
	}
  }
  // OUVRE SERVO
  blockBalle.write(ouvert);
  esc.write(0);
  delay(1000);
  esc.write(180);
  delay(1000);
  esc.write(0);
  // Tourne le moteur
  esc.write(20);
}

void finPartie()
{
  //partie servomoteur qui crève le ballon
  while (i < 3) {
	for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
  	// in steps of 1 degree
  	perceBallon.write(pos);       	// tell servo to go to position in variable 'pos'
  	delay(5);                 	// waits 15ms for the servo to reach the position
	}
	for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
  	perceBallon.write(pos);       	// tell servo to go to position in variable 'pos'
  	delay(5);                 	// waits 15ms for the servo to reach the position
	}
	i++;

  }
}

Assemblage du Robot

Robot geii2.jpg
  • Le montage des différents systèmes et pièces du robot fut débuté tout d'abord par les grosses parties qui représentent la base du robot comme le bloc d'alimentation.
    • Le bloc d'alimentation ainsi que les différents réseaux d'alimentation
    • Bouton d'arrêt d'urgence
    • Moteur MA 970D
  • Puis après avoir fixé ces pièces et câblé, nous avons assemblé et fixé les parties supplémentaires du robot qui sont:
    • Les supports des pilotes Moteurs MD13S auxquels nous les avons fixés.
    • Les différents capteurs comme les 3 CNY70 et la boussole MPU9250.
    • le système de renvoi de balle.
    • Le support du ballon et avec le système de perçage de ballon.

Quand tous les derniers systèmes fut installé nous les avons reliés, câblés et alimentés.

Travaux à finir

  • Afin d'avoir un robot fonctionnel pour la compétition il reste encore quelque travaux à faire:
    • Test et mise au point du programme sur la partie recherche de balle.
    • Test et mise au point sur la partie "renvoie de balle".
    • Réglages divers.
    • Essaie du robot en situation de match pour observer le fonctionnement de chaque partie et si celle-ci ne présente pas de défaut ou dysfonctionnement sur le terrain.

FORGEOT Cécile

LAURENS Aurélien

NOIRAULT Aurélien

SAVOURET Jason