COUPE ROBOTIQUE DES IUT : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
({{Vert|Systeme "Perçage du Ballon"}})
({{Rouge|CODE}})
 
(142 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
[[RobotGEII 16-17]]
 
                                              {{Rouge| <u>'''''Sommaire:'''''</u>}}         
 
  
# Présentation
+
Le wiki est actuellement en rédaction, certaines parties sont donc partiellement rédigées ou incomplètes.  
#*Présentation du projet
+
== ''COUPE ROBOTIQUE 2018'' ==
#*Cahier des charges fonctionnel
+
<br>
#*Solution techniques
 
# Étude et Réalisation des Différentes Parties
 
#*Alimentation et Régulation
 
#**Batterie
 
#**Moteurs de roues
 
#**Régulation de la tension d'alimentation
 
#*Contrôle des moteurs CC par un dual H-Bridge (L298P)
 
#**Principe de fonctionnement d'un H-Bridge (PONT-H)
 
#**Le composant L298N
 
#**Tests effectués avec un SHIELD Arduino (L298P)
 
#**Mode PWM
 
#*Positionnement du robot :Explication du principe
 
#**Approximation par des segments de droites
 
#*Estimation de la position du robot
 
#**Étude et Réalisation Carte Encodeurs
 
#**Roue codeuse
 
#**Valeur reçu par les capteurs  
 
#** Interruption et timer
 
#**suivons une ligne droite
 
#**suivons une consigne
 
#*Détection de balles de tennis
 
#*Caméra
 
#**Choix Caméra 
 
#**Caméra CMU cam 5
 
#** Programme de gestion du cap
 
#*Mise à l’arrêt du robot et le perçage du ballon
 
#**Capteur de "Mise à l’arrêt" du robot
 
#**Système "perçage du ballon"
 
#*Réalisation Carte des "Entrées et Sorties" et du pont H
 
#**Objectifs et Composants utilisés
 
#**Schéma électrique de la carte (Eagle)
 
#**Routage et Correspondance des pins (Eagle)
 
#**La commande des Moteurs de Roues(L298N H-Bridge)
 
#**Les signaux d'entrée et de sortie
 
#**La carte final et les connecteurs
 
#**Problèmes rencontrés :
 
#Code complet
 
#Vidéo de Démonstration
 
#Bibliographie/références
 
={{Rouge|Présentation}}=
 
=={{Vert|Présentation du projet}}==
 
Chaque année la France organise un concours robotique des GEII. Et ce concours exige un cahier des charges à respecter.L'objectif est de fabriquer un robot à partir des kits imposer: comprenant le châssis, les moteurs, les roues et la batterie.Ce robot doit être capable d'envoyer un maximum de balles de tennis dans le camp adverse,sans entrer dans le camp adverse et sans jamais contrôler plus d’une balle à la fois
 
=={{Vert|Cahier des charges fonctionnel}}==
 
  
 +
[[Fichier:Maus.png|cadre|droite]]
 +
<br>
 +
=== {{Bleu|Introduction}} ===
 +
<big>P</big>our la deuxième fois consécutive l'IUT de Troyes auxquelles nous appartenons va participé à la Coupe de France Robotique des Iut qui se déroule chaque années du Jeudi 9 au samedi 11 Juin lors du Festival de Robotique dans la ville de Cachan. L'année dernière le But de la Coupe étais de se déplacé d'un point A à un point B en évitant des obstacles. Cette année l'objectif est radicalement différent puisqu'il s'agit de joué au Tennis ! 
 +
Nous avons donc développé un robot répondant à une problématique et à un cahier des charges bien précis fixé par les organisateurs de la coupe. Je vous invite à consulté le règlement afin de bien comprendre le principe de la coupe de cette année.<br>
 +
Vous pouvez retrouvé ce règlement [http://www.gesi.asso.fr/coupe_robotique_des_iut/images/2018/reglement_Robotique_2018_V001.pdf ici]<br>
 +
Cette année nous devons donc joué au tennis, voici donc un bref résumé du déroulement de la coupe :<br>
  
 +
-Deux robots se font face sur un terrain de Tennis de dimension 8*4 m.<br>
 +
-Chaque robot à sur sont terrains un certain nombre de balles de Tennis par terre.<br>
 +
-Le centre de la piste est délimité par une ligne.<br>
 +
-Il y a deux ballons de chaque côtés des deux camps leurs explosions déclenche un surplus de balle dans le camp adverse.<br>
 +
-Un match dure 90 secondes.<br>
 +
-A la fin des 90 secondes l'envoi d'un projectile autre qu'une balle dans le camps adverses ajoute une balle supplémentaires dans le terrain adverses.
 +
Il Faut donc avoir le moins de balles possibles dans sont camps à la fin de la partie.<br>
 +
Voici un aperçu du terrain:<br>
 +
[[Fichier:Terrain concour.PNG |800px|cadre|centré]]
 +
<br>
 +
<br>
 +
==={{Bleu|Etudes}}===
 +
Il y a donc de nombreux But à atteindre, nous avons donc à l'aide d'un diagramme fonctionnelle décomposé tous ces Buts en Tâches à effectuées:
 +
[[Fichier:Analyse fonctionnelle.PNG|cadre|centré]]
  
 +
Cela nous à permis de définir les tâches que le robot doit effectué et les solutions techniques associées :<br>
 +
-Se déplacé => Deux moteurs commandés par un micro controleur Atmega 2560 via un pont en H l298n. <br>
 +
-Détecté les balles de Tennis => Première Caméra Pixy. <br>
 +
-Détecté la balise pour orienté le robot => Seconde Caméra Pixy. <br>
 +
-orientation de la deuxième caméra pixy => Moteur pas à pas.<br>
 +
-Détecté la proximité avec la balle et l'attrapée => Capteur de distance SHARP et Bras préhenseur. <br>
 +
-Propulsé la balle dans le camps adverse => Verrin. <br>
 +
-Atteindre les ballons situés en bordure du terrain => Bras rotatif. <br>
 +
-Faire éclaté les ballons en bordure du terrain => Arc électrique supporté par le bras rotatif nommé précédemment. <br>
 +
-Détecté les délimitations centrale du terrain => Capteur Cny70. <br>
 +
-Détecté la proximité avec les parois du terrain => Capteurs temps de vols. <br>
  
Schéma fonctionnel de degré II
 
  
 +
=== {{Bleu|Principe de fonctionnement }} ===
 +
Comme nous l'avons vus précédemment il y a de nombreuses taches à effectuées, elles doivent toutes êtres réalisées en synchronisme cela implique un fonctionnement assez complexe que je vais vous expliquer.<br>
 +
Tous d'abord la direction, comment le robot se dirige t'il ?  Le robot doit repérer les balles et les attrapées, pour ce faire la caméra pixy située à l'avant du robot va repérer les balles, selon la position de la balle dans le champ de vision de la caméra, c'elle si va renvoyé des informations à notre microcontrôleur. Le programme que contient le microcontrôleur va commandé les moteurs dans le but de maintenir la balle au centre du champs de vision de la caméra. Il va également tâché de faire grossir la balle dans l'objectif de la caméra, c'est à dire ce rapprocher de la balle.
 +
Une fois la balle arrivée à une certaine distance de la caméra (la balle remplis quasiment l'objectif de la caméra)  un capteur de distance infrarouge Sharp va détecter la présence de la balle à l'endroit voulus, le bras va ensuite ce refermer pour "capturé" la balle. Pendant toutes cette période la deuxième caméra Pixy n'est pas restée inactive, en effet pendant ce temps elle fixe en permanence une balise émettant une lumière rouge que nous avons préalablement posé en fin de piste c'est à dire à l'arrière de notre camps. Nous pouvons donc déterminé en fonction des mouvements que notre deuxième caméra pixy à effectué ou se situe l'arrière de notre terrain.
 +
Nous pouvons donc déterminé la direction dans laquelle notre robot doit envoyé la balle !
  
  
 +
==={{Bleu|Realisation}}===
 +
<br>
 +
==== {{Rouge|<big>PREMIER PROTOTYPE</big>}} ====
 +
<br>
 +
[[Fichier:Proto1.jpg|cadre|centré]]<br>
 +
====={{Bleu|Les différents éléments}}=====
 +
<br>
 +
Nous avons choisi de concevoir un chassi qui pourrais accueillir tous nos composants, nous ne savions pas à ce moment la leurs dimensionnement.
 +
Nous avons donc découpé en fonction du besoins des plaques de plastiques que nous avons assemblé. <br>
 +
Vous pouvez voir dans la photo précédente le robot complètement assemblé. <br>
 +
Ce robot ce déplace grâce à deux moteur fournis par les organisateurs de la coupe. <br>
 +
Ce sont deux moteurs Dunkermotoren G 42*25 qui permettent au robot de se mouvoir, vous pourrez retrouvé toutes leurs caractéristiques techniques [http://www.nrc.com.tw/CAT/Dunkermotoren/GR%20G/GR42x25.pdf ici]<br>
 +
Ces moteurs et l'intégralités des dispositifs du robot sont alimentés par une batterie également définie par les organisateur de la coupe :
 +
C'est une batterie 12 V avec une capacité de 7 Ah.<br>
  
 +
{{Bleu|Déplacement:}}<br>
 +
Ces deux moteurs sont donc contrôlés par un pont en H l298n, vous pourrez trouvez toutes les informations utiles concernant ce composant [https://www.sparkfun.com/datasheets/Robotics/L298_H_Bridge.pdf ici]
 +
Ce composant serras placé sur la carte principale du robot, en effet au lieu de faire une carte pour la gestion des moteurs, une autre pour la gestion des caméras etc nous avons choisi de tous centralisé sur un seul shield d'une arduino mega.
 +
Vous pouvez également distingué sur le Robot les deux caméras Pixys, une à l'avant, une autre à l'arrière pour la détection de la Balle, une description plus précise des Pixys serras faites plus en Avale en effet elles seront abordés dans la partie traitant du second prototype.
 +
Vous pouvez voir également à l'avant du Robot le bras servant à attrapé la balle.<br>
 +
Ce bras à été imprimé à l'aide de l'imprimante 3D de l'Iut, il épouse parfaitement les dimensions de la balle, une version améliorée de ce bras à été fabriqué pour le deuxième prototype. Ce bras à été réalisé à l'aide d'une logiciel Freecad, ce logiciel libre est facile à prendre en mains c'est pour cela que nous l'avons préférés à Solydworks (même si les futures pièces seront surement faites à l'aide de ce dernier logiciel). Pour crée cette pièce nous avons crée une esquisse 2D puis à l'aide de protusion et de perçage nous obtenons une pièce en 3 dimensions. Il suffit ensuite de l'exporter sous un fichier "MESH" que l'imprimante 3D peux lire. Il existe ensuite plusieurs logiciels pouvant lire ce fichier, pour notre part nous disposions de deux imprimantes, les pièces les plus petites ont été réalisées à l'aide du logiciel Repetier Host et de l'imprimante 3D microDelta original et les pièces les plus grandes ont été réalisées grâce au logiciel Cura et à l'imprimante 3D Witbox <br>
 +
{{Bleu|Bras préhenseur:}}<br>
  
 +
[[Fichier:Bras préhension balle.PNG|cadre|centré]]
  
 +
{{Bleu|Les capteurs Cny70:}}<br>
 +
Ces capteurs à pour but de détecter le milieu du terrain en effet notre robot n'as pas à empiéter sur le terrain de l'adversaire, nous avons donc conçu des petites cartes avec le capteurs et ce qui est nécessaire à sont fonctionnement dessus, seul bé mole nous allons devoirs inclinés les  Cny en effet notre robot ne doit pas dépasser la ligne, nous devons donc la détecté à l'avance. Encore une fois si vous avez besoins de précision concernant ce photo transistor suivez ce lien : [https://www.vishay.com/docs/83751/cny70.pdf ici]
 +
<br>
 +
{{Bleu|Le moteur Pas à Pas}}<br>
  
Schéma fonctionnelle 1er degres
+
Dans ce projet, on a voulu mettre un moteur pas à pas pour la rotation de la caméra pixy derrière afin de pouvoir tourner à 360° en effet les servos moteurs présent sur la caméra pixy ne nous permettent de tournés seulement à 180°.
 +
On a donc utilisé un contrôleur de moteur pas à pas TCA 3727.
  
  
 +
[[Fichier:Pins_TCA_3727.png|cadre|centré]]
  
=={{Vert|Solutions techniques}}==
 
Pour fabriquer ce robot nous avions plusieurs choix pour procéder à la détection des balles de tennis ainsi que le contrôle et direction du robot vers la ligne noir ...  , ainsi qu'au guidage vers la position (zone) du ballon . Nous avons choisi pour guider le robot un système hybride composé de roues codeuses et d'une caméra CMUCam Pixy, spécialisée dans la reconnaissance d'objets. La roue codeuse permettra d'effectuer le début du parcours, et sera remplacée par la caméra, plus précise, une fois la distance de détection atteinte. L'évitement des obstacles sera assuré par trois capteurs infrarouges SHARP GP2Y0A21YK0F, permettant la détection d'objets jusqu'à 80 centimètres de distance, qui, placés à l'avant du robot, permettront l'esquive si un obstacle est rencontré.
 
={{Rouge|Etude et Réalisation des Differentes Parties}}=
 
=={{Vert|Alimentation et Régulation}}==
 
==={{Bleu| Batterie}}===
 
La batterie est imposée :<br>
 
  
{| class="wikitable"
+
Le câblage du contrôleur TCA 3727 se trouve ci-dessous.
|-
 
|Tension || 12 V
 
|-
 
| Capacité || 7 Ah
 
|}
 
[[Fichier:Batterie_12V_7Ah.jpg|500px|thumb|center|Batterie]]
 
  
==={{Bleu|Moteurs de roues}}===
+
[[Fichier:Cablâge_moteur_pas_à_pas.png|cadre|centré]]
Les moteurs sont imposés.
 
* '''Caracteristique du moteur:'''
 
  
{| class="wikitable"
+
On peut commander le moteur en mode Full Step ou Half Step en envoyant des signaux à des entreés I10 I11 I20 I21.
|-
+
Exemple du full step :
|Marque ||  Dunkermotoren G 42*25
 
|-
 
| Tension ||  15V
 
|-
 
| In || 1.45 A
 
|-
 
| Ifm || 10.9A
 
|-
 
| Rpm || 3300 tr/mn
 
|}
 
  
 +
[[Fichier:Mode_full_step.png|cadre|centré]]
  
==={{Bleu|Régulation de la tension d'alimentation}}===
 
  
  
* '''Les besoins :'''
 
  
  
'''Pour Arduino MEGA:''' <br>
 
Caractéristiques techniques :
 
{| class="wikitable"
 
|-
 
|Operating Voltage||  5V
 
|-
 
| Input Voltage (recommended) ||  7-12V
 
|-
 
| Input Voltage (limit)|| 6-20V
 
|-
 
| Total output current MAX||800mA
 
|}
 
  
On constate qu'il est possible d'alimenter la carte Arduino MEGA directement avec la tension de la batterie ( 12.8V chargée). <br>
+
{{Bleu|Le générateur d'arc électriques}}<br>
Ce n'est toutefois pas recommandé, car le régulateur intégré dans l'Arduino chaufferait, ce qui pourrait endommager le microcontrôleur. <br>
+
Il est invisible ici car il est situé à l'intérieur du robot, ce petit générateur produit des petits arcs électriques en ionisant l'air, il  est commandé par un transistor Mosfet type N. Nous avons mesuré qu'il consomme au maximum de sont fonctionnement jusqu’à 3 Ampère, en effet plus l'arc électrique est grand plus la consommation de courant est grande. Après avoir effectué plusieurs tests nous en avons conclus que cette arc électrique étais suffisant pour faire éclater un ballon.
  
Solutions Alimentation Arduino MEGA:<br>
+
{{Bleu|Les capteurs temps de vols}}<br>
#  Tension d'alimentation inférieure à 12 V  <br>
 
#  Tension régulé de 5V qu'on fait venir directement sur les pattes VCC d'Arduino: <br>
 
Le courant maximum requis: 800mA
 
  
 +
Nous allons être amené à nous déplacé sur le terrain , il nous faut donc pouvoir en détecter les limites, comme nous l'avons déjà vus nous avons les Cny pour repérer la ligne délimitant le milieu du terrain mais nous avons aussi besoins de capteurs capables de détecter les rebords du terrain. Pour ce faire nous utiliserons des capteurs temps de vols VL53L0X. Vous pourrez trouvez toutes les informations concernant ce capteur. [http://www.st.com/resource/en/datasheet/vl53l0x.pdf ici] 
 +
 +
[[Fichier:Capteurs VL53L0X.jpg|vignette|centré]]
 +
<br>
 +
{{Bleu|Le système pneumatique}}<br>
 +
Pour propulsé la balle nous utiliserons donc un vérin, nous utiliserons un vérin mis à disposition par notre enseignant.
 +
Ce vérin à besoins pour fonctionner d'une réserve d'air comprimée, ne pouvant évidement pas monté un compresseur sur notre petit robot nous utiliserons des cartouches de co2 de 12 G avec tige filetée, elles ont l'avantages non négligeable d'être facilement transportable.
 +
Nous commanderons le fonctionnement de notre vérin à l'aide d'une électrovanne également fournie par notre enseignant, nous sommes actuellement à la recherche d’électrovannes plus petites.
 +
Voici quelques photos du système pneumatique :
 +
On peut voir le régulateur de pression à l'arrière du robot et le vérin démonté :
 +
[[Fichier:Regulateur_pression_vérin.jpg|vignette|centré]]
 +
Sur cette photo l'on peut voir l'ensemble du système pneumatique câblé, nous avons donc notre électrovanne commandé par la carte via un survolteur 12 -> 24V. Notre électrovanne est notre interrupteur dans notre circuit pneumatique.
 +
[[Fichier:Electrovanne.jpg|cadre|centré]]
  
'''Pour les Moteurs de Roues :'''<br>
 
 
# Tension maximum requise: 15V<br>
 
# Courant maximum requis: 3.2A  <br>
 
  
=={{Vert|Contrôle des moteurs CC par un dual H-Bridge (L298P)}}==
 
  
==={{Bleu|Principe de fonctionnement d'un H-Bridge (PONT-H)}}===
+
<br>
 +
====={{Bleu|<big>Le shield arduino mega</big>}}=====
  
Le pont-H est une structure utilisée en électronique de puissance pour:
+
Pour commandé tous ces actionneurs que ce soit les moteurs ou les bras servants à percés les ballons ou à attrapé les balles, ainsi que pour centralisé et réagir aux informations fournis par nos nombreux capteurs nous avons besoins d'un micro contrôleur avec un nombre de pattes et un nombre de timers important. Nous avons donc choisi le micro contrôleur Atmega 2560. En effet il réponds parfaitement à nos attentes, cependant nous devons également mettre en oeuvre un pont en H et plusieurs transistors mosfet qui ne sont pas présent sur la carte arduino Mega. Nous allons donc créée un shield à cette carte. Le shield le voici :
#controle moteurs
 
#convertisseurs et hacheurs
 
#onduleurs
 
  
 +
[[Fichier:CarteV1.jpg|vignette|centré]]
 +
[[Fichier:Carte_V1.png|cadre|centré]]
 +
 
  
* Principe:  On active les commutateurs avec differents cominaisons pour obtenir le branchement voulu. Le courant va circuler dans un sens ou dans l'autre dans le moteur, ce qui va permettre d'inverser les sens de rotation du moteur. Avec le pont-H on peut également varier la vitesse en modulant la tension aux bornes du moteur.    <br>
 
  
[[Fichier:Principe PONT-H.PNG|500px|thumb|left|Principe Pont-H]]  [[Fichier:Fréinage_Magnétique.png|200px|thumb|center|Freinage Magnétique]] <br>
 
  
Combinaisons de commutateurs possibles pour commander un moteur DC:
 
{| class="wikitable"
 
|-
 
|Sens + || Fermer A et D
 
|-
 
| Sens - || Fermer B et C
 
|-
 
| Freinage magnétique || A et C / B et D
 
|-
 
| Arret libre || A,B,C,D ouverts
 
|-
 
| Autres combinaison || INTERDITES
 
|}
 
  
==={{Bleu|Le composant L298N }}===
 
 
<br>
 
<br>
 +
C'est le premier shield que nous avons réalisés cependant nous avons rencontrés de nombreuses difficultés lors de sa fabrication, ces difficultés sont principalement du à un routage qui n’étais pas optimum, de très nombreux via ainsi que des piste dont la disposition ne facilitais pas le routage. Par exemple certains composants rendaient difficile le soudage des autres notamment à cause du manque de place. Cela rajouté à des erreurs de soudures ont rendus les essais de fonctionnements de cette cartes très laborieux. Finalement après une semaine à essayer de faire fonctionné correctement cette carte en vain nous avons décidé de fabriqué une version améliorée de celle si.<br>
 +
Voici donc la version corrigée de ce premier shield, le routage à été simplifié autant que possible, des nombreuses erreurs ont été corrigés et la disposition des pistes à été optimisé autant que possible. Nous avons également abordé la fabrication d'une manière différente en tirant les enseignement des erreurs de fabrication du premier shield. Par exemple nous avons soudé les composants traversants dans un ordre bien précis pour ne pas être gêner lors du soudage de ceux de l'un ou de l'autre.
 +
Voici donc le routage finale :<br>
 +
 +
[[Fichier:CarteV3.png|cadre|centré]]<br>
 +
Et voici la carte fabriqué :
 +
[[Fichier:CarteV2.jpg|cadre|centré]]<br>
  
Nous allons utiliser pour notre robot le composant L298N (traversant) qui a le meme principe de fonctionement que celui en CMS (L298P).Dans la figure suivante on peux voir le cablage du composant, les signaux de commande et les sorties d'alimentation MOTEUR.  
+
====={{Bleu|<big>La carte principale finale</big>}}=====
Dans le tableau nous avons les 4 modes possibles en actionnant les entrées logique C et D ainsi que Venable (PWM) pour varier la tension d'alimentation des moteurs (0-12V).  
+
Après avoir testé et utilisé le shield arduino fabriqué pour le premier prototype, il existait toujours des problèmes qui provoquaient un mauvais fonctionnement du robot. De plus, on voulait ajouter certains composants afin d’améliorer notre robot. Pour ce faire, on a décidé de créer une carte principale en utilisant  le micro-contrôleur ATMEGAG 2560 qui se trouve sur la carte Arduino MEGA pour fabriquer une carte qui est à la fois plus compatible et a beaucoup plus de places dans le but d’installer les autres dispositifs nécessaires (module XBEE, les transistors, etc).  
 +
Cette carte a été fabriquée en tirant  les enseignements des erreurs de fabrication des cartes précédente et le routage est optimisé le plus possible pour avoir une carte de qualité et facile à dépanner et tester.  
 +
Les entrées/sorties non utilisées sont aussi reliées à des connecteurs MOLEX pour un ajout complémentaire des modules en tant que les capteurs, les modules supplémentaires dans le futur sans le besoin de refabriquer une nouvelle carte.
 +
Par contre, lors de la fabrication de cette carte principale, on a eu aussi pas mal de problème avec la mise en place du micro -contrôleur sur la carte.
  
[[Fichier:Fréinage magnétique PONT H.PNG|900px|thumb|center|Operating L298N]]
+
Voici le routage de la carte :
 +
[[Fichier:Board_BOT+TOP.PNG|cadre|centré]]<br>
  
==={{Bleu|Tests éffectués avec un SHIELD Arduino (L298P) (}}===
 
Pour commander les moteurs nous allons utiliser le pont H L298P [ datasheet].
 
[[Fichier:L298-pinout.jpg|vignette|centré|L298P]]
 
  
Le composant est ci-dessous:
 
[[Fichier:POWERSO-20-SEMI-STM-FNT-MED.jpeg|vignette|centré|L298P]]
 
Pour faire des tests nous avons utlisé le '''Motor Shield For Arduino'''. En connectant ce shield  à l'arduino nous pouvons commander les deux moteurs (commande du sens et de la vitesse).
 
  
[[Fichier:ShildL298P.jpeg|vignette|centré|L298P]]
 
  
*'''PWM'''
+
Et voici la carte finie:
 +
[[Fichier:Carte_principale.jpg|vignette|centré]]<br>
  
Nous allons utiliser le shield en mode PWM, on placera donc les jumpers en conséquence.
 
  
[[Fichier:Arduino Shield4.png|vignette|centré|L298P]]
 
  
*'''Borne du moteur'''
 
  
Nous avons deux bornes (bleues) pour connecter les moteurs CC. Les connecteurs mâles derrière sont identiques à celui des bornes bleues.
 
  
[[Fichier:Arduino Shield5.png|vignette|centré|L298P]]
 
  
*'''PWRIN'''
 
  
Les moteurs peuvent être alimentés par une alimentation externe lorsque le courant du moteur dépasse les limites fournies par l'Arduino (Il est conseillé de séparer les alimentations d’Arduino et des moteurs). Le changement entre la puissance externe et l'Arduino est mis en œuvre par deux jumpers .<br>
+
====={{Thor_tank lors de la coupe robotique}}=====
 +
[[Fichier:Thor_tank_troyes.jpg|vignette|centré]]
  
'''PWRIN''': Alimentation externe.<br>
 
'''VIN''': Alimentation du Arduino.<br>
 
  
On placera donc les jumpers d’alimentation sur PWRIN.
 
  
[[Fichier:Arduino Shield6.png|vignette|centré]]
+
==== {{Rouge|<big>SECOND PROTOTYPE</big>}} ====
 +
====={{Rouge|Le Chassi en PLA}}=====
  
 +
Nous avons décidé à la suite de la réalisation du premier prototype de tenir compte au maximum des nécessité techniques que devais remplir le chassi, nous avons donc crée un châssi robuste en PLA sur lequel chacun des actionneurs serait fixé rapidement. Nous l'avons dessiné  sur Freecad et fabriqué à l'aide de l'imprimante 3D de l'iut. Il y a eu 3 versions différentes du châssi tous au long du projet voici donc quelques photos du chassi le plus récent une fois terminé :
 +
Sur freecad :
 +
[[Fichier:Chassi_vue_Supérieure.PNG|vignette|centré]]
 +
Et enfin imprimé :
 +
[[Fichier:Chassi.jpg|vignette|centré]]
 +
[[Fichier:Tourelle_assemblée.jpg|vignette|centré]]
  
On doit avoir quelque chose comme cela:
 
[[Fichier:Arduino Shield3.png|vignette|centré|L298P]]
 
  
*'''Signal de contrôle Tableau de vérité'''
+
====={{Rouge|Les deux caméras pixy}}=====
 +
[[Fichier:Pixy à l'avant.jpg|vignette|Pixy à l'avant]]
 +
La caméra Pixy est une caméra intelligente laquelle, principalement, fait un traitement d'images des objets qu'on garde dans leur mémoire. Cette caméra nous donne différentes informations telles que: les coordonnées X, Y du centre de l'objet, la largeur ainsi que la hauteur du carreau autour l'objet, la quantité d'objets détectés et leurs couleurs parmi des autres données. ''Vous pouvez avoir plus d'information ici http://www.cmucam.org/projects/cmucam5/wiki/Arduino_API''  
  
{| class="wikitable"
+
Pour ce projet on utilise deux caméras : La caméra positionnée devant du robot sera qui détecte les balles, également les deux ballons à coté du terrain et celle qui est derrière sera capable de nous donner l’angle entre la direction du robot et l’arrière du terrain. Cette dernière donnée nous aidera à envoyer les balles vers la direction correcte!
|-
 
! E1 !! M1 !! !! E2 !! M2 !! Texte de l’en-tête
 
|-
 
| L || X || Moteur 1 désactivé || L || X || Moteur 2 désactivé
 
|-
 
| H || H || Moteur 1 en arrière|| H || H || Moteur 2 en arrière
 
|-
 
| H || L || Moteur 1 en avant|| H || L || Moteur 2 en avant
 
|-
 
| PWM || X || Contrôle vitesse PWM || PWM || X || Contrôle vitesse PWM
 
|}
 
  
'''{{Rouge|NOTE:}}'''
+
[[Fichier:20180331 134152-min.jpg|vignette| Pixy à l'arrière]]
  
H: Niveau haut <br>
+
Pour la première caméra, elle est monté à l’inverse(important pour la programmation puisque cela change l’orientation de l’axe X!) avec qu’un seul servomoteur qui contrôle le mouvement en l’axe Y. Ce mouvement est fait simplement, tout d’abord pour la détection des balles du sol et après pour la détection des ballons.
L: Niveau bas <br>
+
Pourtant, la deuxième est montée sur deux servomoteurs qui contrôle le mouvement dans les deux axes. Il se trouve que si le robot est près de la balise on risque de la perdre, c’est pour cela qu’on utilise le mouvement en Y.
X: N'importe quel niveau.
 
  
==={{Vert|Mode PWM}}===
+
====={{Rouge|La carte principale}}=====
 +
==== {{Rouge|<big>CODE</big>}} ====
 +
{{boîte déroulante/début|titre=codeRobot}}
 +
<source lang=c>
  
 +
/*
 +
  Program challenge "Coupe Robotique des IUT 2018"
 +
  IUT de Troyes
 +
  June - 2018
 +
*/
 +
#include <avr/io.h>
 +
#include <avr/interrupt.h>
 +
#include <Wire.h>
 +
#include <SPI.h>
 +
#include <PixySPI_SS.h>
 +
#include "Adafruit_VL53L0X.h"
 +
#include <ServoTimer2.h>
  
{| class="wikitable"
 
|-
 
! Commande !! Moteur !! Pin Arduino !!Pin Atmega328p  !! Signification
 
|-
 
| M1 || Gauche || 4 || PD4 || Contrôle du sens de rotation
 
|-
 
| E1 (PWM) || Gauche  || 5 || PD5  || Contrôle de la vitesse de rotation
 
|-
 
| M2 || Droit || 7 || PD7  || Contrôle du sens de rotation
 
|-
 
| E2 (PWM) || Droit  || 6 || PD6  || Contrôle de la vitesse de rotation
 
|-
 
  
|}
+
#define topPWM            255      //Valeur Max du PWM Motors (8bits)
 +
#define X_center          160    //PixyBalls consigne
 +
#define sensor_ball        0  //sensor ball
  
 +
#define S1                1  //CNY70 left1
 +
#define S2                2  //CNY70 right1
 +
#define S3                3  //CNY70 left2
 +
#define S4                4  //CNY70 right2
  
*'''Exemple de code'''
+
#define PixyBalls        22  // camera for detect balls
 +
#define PixyDirection    23  // camera for the direction of the robot
  
 +
#define Eject_ball        36  // Eject ball
 +
#define Eject_cloth      38  // Eject cloth (pas utilisé)
 +
#define Explode_balloons  34  // set servo to explode balloons
 +
//servos Pixy direction
 +
#define X_CENTER        ((PIXY_MAX_X-PIXY_MIN_X)/2)
 +
#define Y_CENTER        ((PIXY_MAX_Y-PIXY_MIN_Y)/2)
  
Nous allons gérer les moteurs par des signaux PWM (-255 a 255), le signe moins (-) indique que le moteur fonctionne en marche arrière, et le signe plus (+) qu'il fonctionne en marche avant. Ce code nous permet de gérer les deux moteurs par la fonction setVitesse(vG,vD). Dans la suite nous allons l'utiliser pour gérer le déplacement du robot.
 
  
{{boîte déroulante/début|titre=Code exemple}}
 
<source lang=c>
 
#include <avr/io.h>//Librairie AVR
 
#define topPWM 255 //Valeur Max du PWM (8bits)
 
  
void initMoteur()//PWM sur PD5 et PD6
+
const int limit = 90;
{
+
bool start = false;
  //fpwm = fq / (topPWM * p)
+
bool balise = false;
  //fpwmi:fréquence du PWM
 
  //fq:fréquence du quark
 
  //topPWM: valeur maximum du PWM
 
  //p:prédiviseur
 
  
  //Déclaration de sorties
+
int s1 = 0;
  DDRD |= (1 << PD4);//Sens du moteur Gauche
+
int s2 = 0;
  DDRD |= (1 << PD5);//PWM du moteur Gauche
+
int s3 = 0;
  DDRD |= (1 << PD7);//Sens du moteur Droit
+
int s4 = 0;
  DDRD |= (1 << PD6);//PWM du moteur Droit
+
float new_s1 = 0;
 +
float new_s2 = 0;
 +
float new_s3 = 0;
 +
float new_s4 = 0;
  
  TCCR0B |= (1 << CS00) | (1 << CS01);//Prédiviseur P=64
+
int signature = 0;
 +
int timer = 0;
 +
int16_t size_max_balle = 0;
 +
int16_t size_max_ballon = 0;
 +
int16_t size = 0;
 +
bool caught_ball = false;
 +
//Cameras
 +
PixySPI_SS pixy1(PixyBalls);
 +
PixySPI_SS pixy2(PixyDirection);
  
  TCCR0A |= (1 << WGM00) | (1 << WGM01);//Mode FAST PWM
 
  
  TCCR0A |= 1 << COM0A1;//PWM sur OC0A
+
//Capteurs temps de vol
 +
Adafruit_VL53L0X sensor1 = Adafruit_VL53L0X();
 +
Adafruit_VL53L0X sensor2 = Adafruit_VL53L0X();
 +
Adafruit_VL53L0X sensor3 = Adafruit_VL53L0X();
 +
Adafruit_VL53L0X sensor4 = Adafruit_VL53L0X();
 +
//Servomoteurs
 +
ServoTimer2 ball;    // servo to catch balls
 +
ServoTimer2 arm;    // servo to move the arm to explode balloons
 +
ServoTimer2 ball_pixy;
 +
////////////////////////////////////////////////////////////////
 +
////////////////////////////////////////////////////////////////
 +
// Pantilt camera direction
 +
///////////////////////////////////////////////////////////////
 +
////////////////////////////////////////////////////////////////
 +
class ServoLoop
 +
{
 +
  public:
 +
    ServoLoop(int32_t pgain, int32_t dgain);
  
  TCCR0A |= 1 << COM0B1;//PWM sur OC0B
+
    void update(int32_t error);
  
  OCR0A = 0;//Valeur de comparaison pour A --> PD6
+
    int32_t m_pos;
 +
    int32_t m_prevError;
 +
    int32_t m_pgain;
 +
    int32_t m_dgain;
 +
};
  
  OCR0B = 0;//Valeur de comparaison pour B --> PD5
 
}
 
void setMoteurG(int16_t vit)//fonction pour gérer le moteur gauche
 
{
 
  if (vit < 0)
 
  {
 
    vit = -vit;
 
    PORTD |= (1 << PD4);//Moteur Gauche en arrière
 
  }
 
  else PORTD &= ~ (1 << PD4);//Moteur Gauche en avant
 
  
  if (vit > topPWM) vit = topPWM;//Si jamais on met une valeur supérieure à 255, la vitesse maximum sera 255
+
ServoLoop panLoop(300, 500);
 +
ServoLoop tiltLoop(500, 700);
  
   OCR0B = vit;//Action sur le PWM --> PD5
+
ServoLoop::ServoLoop(int32_t pgain, int32_t dgain)
 +
{
 +
   m_pos = PIXY_RCS_CENTER_POS;
 +
  m_pgain = pgain;
 +
  m_dgain = dgain;
 +
  m_prevError = 0x80000000L;
 
}
 
}
  
void setMoteurD(int16_t vit)//fonction pour gérer le moteur droit
+
void ServoLoop::update(int32_t error)
 
{
 
{
   if (vit < 0)
+
  long int vel;
 +
  char buf[32];
 +
   if (m_prevError != 0x80000000)
 
   {
 
   {
     vit = -vit;
+
     vel = (error * m_pgain + (error - m_prevError) * m_dgain) >> 10;
     PORTD |= (1 << PD7);//Moteur Droit en arrière
+
     //sprintf(buf, "%ld\n", vel);
 +
    //Serial.print(buf);
 +
    m_pos += vel;
 +
    if (m_pos > PIXY_RCS_MAX_POS)
 +
      m_pos = PIXY_RCS_MAX_POS;
 +
    else if (m_pos < PIXY_RCS_MIN_POS)
 +
      m_pos = PIXY_RCS_MIN_POS;
 
   }
 
   }
   else PORTD &= ~ (1 << PD7);//Moteur Droit en avant
+
   m_prevError = error;
 
 
  if (vit > topPWM) vit = topPWM;//Si jamais on met une valeur supérieure a 255, la vitesse maximum sera 255
 
 
 
  OCR0A = vit;//Action sur le PWM --> PD6
 
 
}
 
}
 
+
///////////////////////////////////////////////////////////////////////////
void setVitesse(int16_t vG, int16_t vD)//cette fonction nous permet gérer les deux moteurs avec "une seule" ligne
+
///////////////////////////////////////////////////////////////////////////
 +
// PixyDirection
 +
///////////////////////////////////////////////////////////////////////////
 +
///////////////////////////////////////////////////////////////////////////
 +
void direction()
 
{
 
{
  setMoteurD(vD);
 
  setMoteurG(vG);
 
}
 
  
int main()
+
  uint16_t blocks;
{
+
   int32_t panError, tiltError;
   initMoteur();
 
  
while(1)
+
   blocks = pixy2.getBlocks();
{
 
   setVitesse(100,100);//Exemple d’utilisation
 
}
 
}
 
  
</source>
+
  if (blocks)
{{boîte déroulante/fin}}
+
  {
 +
    panError = X_CENTER - pixy2.blocks[0].x;
 +
    tiltError = pixy2.blocks[0].y - Y_CENTER;
  
=={{Vert|Positionnement du robot: Explication du principe}}==
+
    panLoop.update(panError);
==={{Bleu|Approximation par des segments de droites}}===
+
    tiltLoop.update(tiltError);
  
Le positionnement du robot est obtenu ...
+
    pixy2.setServos(panLoop.m_pos, tiltLoop.m_pos);
 +
a    balise = true; //balise detectee
 +
  }
 +
  else balise = false;
 +
}
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
//SetMotors
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
void initMotor()//PWM on PE3 (Left) and PH3(Right)
 +
{
 +
  //fpwm = fq / (topPWM * p)
 +
  //fpwmi: frequency PWM
 +
  //fq: frequency quartz
 +
  //topPWM: value max PWM
 +
  //p: predivisor
  
=={{Vert|Estimation de la position du robot }}==
+
  //Declaration de sorties
 +
  DDRB |= (1 << PB6);//Sense motor left    12  in1
 +
  DDRB |= (1 << PB5);//Sense motor left    11  in2
 +
  DDRH |= (1 << PH3);//PWM motor left OC4A  6  enA
 +
  DDRH |= (1 << PH4);//Sense motor right    7  in3
 +
  DDRB |= (1 << PB4);//Sense motor right    10  in4
 +
  DDRH |= (1 << PH5);//PWM motor right OC4C 8  enB
  
==={{Bleu|Etude et Réalisation Carte Encodeurs}}===
 
  
 +
  //Timer4 PH3
  
 +
  TCCR4A |= (1 << WGM40);//Mode FAST PWM
 +
  TCCR4B |= (1 << WGM42);
  
 +
  TCCR4B |= (1 << CS40) | (1 << CS41);//divisor P=64
  
  
*'''CAPTEUR TCUT 1300'''.  Nous allons utiliser ce capteur il nous permettra d'avoir le sens et la vitesse de chaque roue.
+
  TCCR4A |= 1 << COM4A1;//PWM on OC4A
The TCUT1300X01 is a compact transmissive sensor that
 
includes an infrared emitter and two phototransistor
 
detectors, located face-to-face in a surface mount package.
 
  
[[Fichier:Tcut1300.PNG|400px|gauche]]
+
  TCCR4A |= 1 << COM4C1;//PWM on OC4C
  
[[Fichier: TCUT1300 1.PNG|200px|centre]]
+
  OCR4A = 0;//Value first comparison  --> PH3
  
 +
  OCR4C = 0;//Value first comparison --> PH5
 +
}
  
[[Fichier: Caracteristiques Tcut 1300.PNG|700px|gauche]]
 
  
 +
void setMotorL(int16_t speed)//function motor left
 +
{
 +
  if (speed < 0)
 +
  {
 +
    speed = -speed;
 +
    PORTB |= (1 << PB6);//Motor left : sense "-"
 +
    PORTB &= ~ (1 << PB5);
 +
  }
 +
  else {
 +
    PORTB &= ~ (1 << PB6);//Motor left : sense "+"
 +
    PORTB |= (1 << PB5);
 +
  }
 +
  if (speed > topPWM) speed = topPWM;//speed max
  
 +
  OCR4A = speed;//Action sur le PWM --> PE3
 +
}
  
 +
void setMotorR(int16_t speed)//function motor right
 +
{
 +
  if (speed < 0)
 +
  {
 +
    speed = -speed;
 +
    PORTH &= ~ (1 << PH4); //Motor right : sense "-"
 +
    PORTB |=  (1 << PB4);
 +
  }
 +
  else
 +
  {
 +
    PORTH |= (1 << PH4); //Motor left : sense "+"
 +
    PORTB &= ~ (1 << PB4);
 +
  }
  
 +
  if (speed > topPWM) speed = topPWM;//speed max
  
 +
  OCR4C = speed;//Action sur le PWM --> PH3
 +
}
  
 +
void setSpeed(int16_t vL, int16_t vR)//only one function for 2 motors
 +
{
 +
  setMotorL(vL);
 +
  setMotorR(vR);
 +
}
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
// play time = 90s
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
void timer_90s()
 +
{
 +
  //Tt1=(n*p)/fq
 +
  //n=Tt1*fq/p
 +
  //Tt1: periode du timer
 +
  //n=valuer de comparaison (OCR1A)
 +
  //p:prediviseur
 +
  //fq:frequence du quark (arduino Mega 16Mhz)
  
 +
  TCCR1B |= (1 << CS10) | (1 << CS12); //p=1024
  
 +
  TCCR1B |= 1 << WGM12; //RAZ mode CTC
  
 +
  TIMSK1 |= 1 << OCIE1A; //Autorisation d'interruption de comparaison A
  
 +
  OCR1A = 15625; //Comparaison , Tt1=1s,
 +
}
  
 +
ISR(TIMER1_COMPA_vect)
 +
{
 +
  timer++;
 +
  //PORTB^=1<<PB7; activar verin para la tela blanca
 +
}
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
// setCameras
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
void setCameras() {
  
 +
  //pixy2.init();
 +
  pinMode(PixyBalls, OUTPUT); // Slave output PixyBalls
 +
  pinMode(PixyDirection, OUTPUT); // Slave output PixyDirection
  
 +
  digitalWrite(PixyBalls, HIGH); // desactivation PixyBalls
 +
  digitalWrite(PixyBalls, HIGH); // desactivation PixyDirection
  
 +
  pixy1.init();
 +
  pixy2.init();
  
 +
}
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
// PixyBalls
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
void Pixy_tracking() {
 +
  int signature = 0;
  
 +
  //unsigned int16_t size_max_balle = 0;
 +
  //unsigned int16_t size_max_ballon = 0;
 +
  uint32_t size_balle = 0;
 +
  uint16_t posX  = 0;
 +
  //static int i = 0;
 +
  int blocks;
 +
  blocks    = pixy1.getBlocks();
 +
  // grab blocks!
 +
  if (blocks)
 +
  {
 +
    signature        = pixy1.blocks[0].signature;
 +
    posX            = pixy1.blocks[0].x;
 +
    size_balle      = pixy1.blocks[0].width; * pixy1.blocks[0].height;
 +
  }
 +
  /*else
 +
  {
 +
    posX = 0;
 +
    size_balle = 0;
 +
  }*/
 +
  //Serial.println(sizeta /256)
 +
}
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
// Activation capteurs temps de vol protocol I2C
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
void configAddress() {
 +
  pinMode(44, OUTPUT);
 +
  pinMode(45, OUTPUT);
 +
  pinMode(46, OUTPUT);
 +
  pinMode(47, OUTPUT);
  
{{boîte déroulante/début|titre=Code example}}
+
  digitalWrite(47, HIGH);
<source lang=c>
+
  digitalWrite(46, LOW);
 +
  digitalWrite(45, LOW);
 +
  digitalWrite(44, LOW);
 +
  sensor1.setAddress(30);
 +
  sensor1.begin(30);
 +
  delay(10);
 +
// Serial.println("1 device");
  
 +
  digitalWrite(47, HIGH);
 +
  digitalWrite(46, HIGH);
 +
  digitalWrite(45, LOW);
 +
  digitalWrite(44, LOW);
 +
  sensor2.setAddress(31);
 +
  sensor2.begin(31);
 +
  delay(10);
 +
//  Serial.println("2 device");
  
 +
  digitalWrite(47, HIGH);
 +
  digitalWrite(46, HIGH);
 +
  digitalWrite(45, HIGH);
 +
  digitalWrite(44, LOW);
 +
  sensor3.setAddress(32);
 +
  sensor3.begin(32);
 +
  delay(10);
 +
//Serial.println("3 device");
  
 +
  digitalWrite(47, HIGH);
 +
  digitalWrite(46, HIGH);
 +
  digitalWrite(45, HIGH);
 +
  digitalWrite(44, HIGH);
 +
  sensor3.setAddress(32);
 +
  sensor4.setAddress(33);
 +
  sensor4.begin(33);
 +
  delay(10);
 +
  //Serial.println("4 device");
 +
}
  
</source>
+
void sensorRead() {
{{boîte déroulante/fin}}
 
  
*'''TIMER 1'''
+
  VL53L0X_RangingMeasurementData_t measure1; // mesure prope de la librairie
 +
  VL53L0X_RangingMeasurementData_t measure2;
 +
  VL53L0X_RangingMeasurementData_t measure3;
 +
  VL53L0X_RangingMeasurementData_t measure4;
  
 +
  sensor1.rangingTest(&measure1, false);
 +
  sensor2.rangingTest(&measure2, false);
 +
  sensor3.rangingTest(&measure3, false);
 +
  sensor4.rangingTest(&measure4, false);
  
 +
  s1 = measure1.RangeMilliMeter;
 +
  //delay(30);
 +
  s2 = measure2.RangeMilliMeter;
 +
  //delay(30);
 +
  s3 = measure3.RangeMilliMeter;
 +
  //delay(30);
 +
  s4 = measure4.RangeMilliMeter;
 +
  delay(30);  // mesure rapide, on a des autres posibilitées
 +
}
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
// Détection des obstacles(limites du terrain)
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
void robot_movement() {
  
 +
  if ( s1 <= limit) new_s1 = 0.55 * limit; // détection de la limite du terrain
 +
  else new_s1 = 0;
  
==={{Bleu|Suivons une ligne droite}}===
+
  if ( s2 <= limit) new_s2 = 3.2* limit;
 +
  else new_s2 = 0;
  
 +
  if ( s3 <= limit) new_s3 = 3.2* limit;
 +
  else new_s3 = 0;
  
{{boîte déroulante/début|titre=Code de Suivons une ligne droite}}
+
  if ( s4 <= limit) new_s4 = 0.55 * limit;
<source lang=c>
+
  else new_s4 = 0;
 
+
  //Serial.print(new_s1); Serial.print(" "); Serial.print(new_s2); Serial.print(" "); Serial.print(new_s3); Serial.print(" "); Serial.print(new_s4); Serial.println();
 
+
}
 
+
//////////////////////////////////////////////////////////////////
</source>
+
//////////////////////////////////////////////////////////////////
{{boîte déroulante/fin}}
+
//Movement Intégrateur
 
+
//////////////////////////////////////////////////////////////////
==={{Bleu|Suivons une consigne}}===
+
//////////////////////////////////////////////////////////////////
 +
void go()
 +
{
 +
  sensorRead();
 +
  robot_movement();
 +
  int leftSpeed  = ;
 +
  int rightSpeed = ;
 +
/*
 +
    int leftSpeed  = constrain(180 + posX / 2.0 - 80 - size_balle /256  , 110, 200);
 +
    int rightSpeed = constrain(180 - posX / 2.0 + 80 - size_balle /256  , 110, 200);
 +
    setSpeed(leftSpeed, rightSpeed);*/
 +
    //Serial.print(leftSpeed); Serial.print("  ");Serial.print(rightSpeed);Serial.println();
 +
    int speedL = constrain(180 + new_s1 - new_s2 - new_s3 - new_s4 + posX / 2.0 - 80 - size_balle /256, -180, 200);
 +
    int speedR = constrain(180 - new_s1 - new_s2 - new_s3 + new_s4 - posX / 2.0 + 80 - size_balle /256, -180, 200);
 +
    //Serial.print(speedL);Serial.print(" ");Serial.print(speedR);Serial.println();
 +
    setSpeed(speedL, speedR);
 +
}
  
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
 +
// Set servos
 +
//////////////////////////////////////////////////////////////////
 +
//////////////////////////////////////////////////////////////////
  
{{boîte déroulante/début|titre=ws2812_config.h}}
+
void setServo()
<source lang=c>
 
 
 
 
 
 
 
</source>
 
{{boîte déroulante/fin}}
 
 
 
=={{Vert|Detection des balles de tennis}}==
 
=={{Vert|Caméra }}==
 
==={{Bleu|Choix camera}}===
 
Nous avons testé 3 cameras différentes, la PiCam, la CMUCam3
 
et la CMUCam5 Pixy
 
[[Fichier:Cmu Cam 3.jpeg|vignette|centré]]
 
[[Fichier:Cmu Cam 5.jpeg|vignette|vignette|centré]]
 
<br>
 
Nous avons choisi d'utiliser la CMUCam 5 http:.. site CMU cam 5 car elle est beaucoup plus simple d'utilisation que les deux autres. En effet, celle ci dispose d'une interface dre réglage, PixyMon, lui permettant d'enregistrer les signatures des objets à détecter, et de régler l'acquisition pour restreindre la détection à ces signatures précises. De plus, celle ci dispose d'un support mû par des servomoteurs permettant d'élargir son champ de vision.
 
 
 
==={{vert|Camera CMU cam 5}}===
 
 
 
Tout d’abord nous avons réalisé une simple reconnaissance d'objet grâce au logiciel, il suffit pour cela de sélectionner l'objet en question via une interface, Pixymon.
 
Nous avons ensuite choisi d'utiliser une balise lumineuse pour que la camera la repère le plus loin possible.
 
balise test.
 
 
 
 
 
 
 
 
 
Grâce à cette balise nous avons pu déterminer la distance maximale de détection avec une balise de taille réglementaire. Nous avons ainsi déterminé que la balise était capable d'effectuer une détection à approximativement 6m.
 
 
 
==={{Vert|Programme de gestion du cap}}===
 
 
 
Nous avons réalisé un programme permettant de récupérer la position en X d'un objet par rapport à la caméra
 
<br>
 
{{boîte déroulante/début|titre=Code exemple}}
 
<source lang=c>
 
//////////////////////////////////////////
 
// Fonction cap
 
//////////////////////////////////////////
 
/**************************************************************
 
 
 
Description : indique le cap à suivre grace à la camera Pixy.
 
Entrées : Aucune
 
Sorties : Un int allant de -160 à 160. Une valeur nulle indique
 
          que la cible se trouve au centre du champ de vision
 
          de Pixy. Une valeur positive indique que la cible se
 
          trouve à droite de Pixy, une valeur négative indique
 
          la gauche.
 
***************************************************************/
 
 
 
int cap()
 
 
{
 
{
   int compteur1;
+
   ball_pixy.attach(27);
  uint16_t blocks;
+
   ball.attach(32);
  /*Récupération des "blocs". Un bloc est une zone rectangulaire
+
   arm.attach(25);
  définie par Pixy, possedant plusieurs caractéristiques (hauteur,
 
  position en x/y, couleur...)*/
 
   blocks = pixy.getBlocks();
 
   /*Dans le cas ou un bloc est détecté, la caméra renverra la
 
  position en x de celui ci. La valeur est centrée en zero.*/
 
  if (blocks)
 
  {
 
    return(pixy.blocks[0].x );
 
  }   
 
 
}
 
}
 +
int inte = 0;
 +
void setup()
 +
{
 +
  pinMode(33, INPUT_PULLUP);
 +
  timer_90s();                //timer 90sec
 +
  initMotor();              //set Motors
 +
  Wire.begin();              //connection I2C
 +
  //Serial1.begin(9600);
 +
  configAddress();
 +
  setServo();
 +
  sei();                      //timer1
 +
  //Serial1.print("Start...");
  
</source>
+
  setCameras();                //déclaration des cameras Balles et Direction
{{boîte déroulante/fin}}
 
<br>
 
Cette fonction a été testée avec le main suivant
 
<br>
 
  
{{boîte déroulante/début|titre=Code exemple}}
+
  pinMode(sensor_ball, INPUT);
<source lang=c>
+
  //Commande de transitors MOSFET
#include <SPI.h> 
+
  pinMode(Eject_ball, OUTPUT);
#include <Pixy.h>
+
  pinMode(Eject_cloth, OUTPUT);
 +
  pinMode(Explode_balloons, OUTPUT);
  
Pixy pixy;
+
  ball.write(4); // etat Initialize
 +
  arm.write(100);
 +
  ball_pixy.write(130);
 +
  while(inte == 0)inte = digitalRead(33);
 +
  start = true;
 +
}
  
void setup()
+
void loop()
 
{
 
{
  Serial.begin(9600);
 
  Serial.print("Starting...\n");
 
  pixy.init();
 
}
 
  
  
int cap()
+
   if (start)
{
 
  int compteur1;
 
  uint16_t blocks;
 
  blocks = pixy.getBlocks();
 
   if ((blocks) && (pixy.blocks[0].x != 0))
 
 
   {
 
   {
     return(pixy.blocks[0].x );
+
     Pixy_tracking();
  }  
+
    if (timer <= 70 && signature == 1)
}
+
    {
 +
      go();
 +
      int mes_sensor_ball = analogRead(sensor_ball);
 +
      if (mes_sensor_ball >= 430)
 +
      {
 +
        ball.write(53); // on attrape la balle
 +
        caught_ball = true; //on a une balle dans
 +
      }
 +
      while (caught_ball) //mesure du capteur des balles
 +
      {
 +
        setSpeed(0, 0);
 +
        if(balise)
 +
        {
 +
        if (panLoop.m_pos > 750L)
 +
        {
 +
          setSpeed(180, 0);
 +
          delay(1000);
 +
          setSpeed(0, 0);
 +
          ball.write(4); // On enleve le bras qui attrapait la balle
 +
          delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
 +
          digitalWrite(Eject_ball, HIGH); //on tire la balle
 +
          delay(10);
 +
          digitalWrite(Eject_ball, LOW);
 +
          caught_ball = false;
 +
        }
 +
        else if (panLoop.m_pos < 250L)
 +
        {
  
void loop()
+
        setSpeed(180, 0);
{  
+
        delay(1000);
   delay(100);
+
        setSpeed(0, 0);
  Serial.println(cap());
+
        ball.write(4); // On enleve le bras qui attrapait la balle
   delay(500);
+
        delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
 +
        digitalWrite(Eject_ball, HIGH); //on tire la balle
 +
        delay(10);
 +
        digitalWrite(Eject_ball, LOW);
 +
        caught_ball = false;
 +
      }
 +
        else
 +
        {
 +
          ball.write(4); // On enleve le bras qui attrapait la balle
 +
          delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
 +
          digitalWrite(Eject_ball, HIGH); //on tire la balle
 +
          delay(10);
 +
          digitalWrite(Eject_ball, LOW);
 +
          caught_ball = false;
 +
        }
 +
      }
 +
      else
 +
      {
 +
        setSpeed(200, 0);
 +
        delay(2000);  //delay necessaire pour faire une demi tour
 +
        setSpeed(0, 0);
 +
        ball.write(4); // On enleve le bras qui attrapait la balle
 +
        delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
 +
        digitalWrite(Eject_ball, HIGH); //on tire la balle
 +
        delay(10);
 +
        digitalWrite(Eject_ball, LOW);
 +
        caught_ball = false;
 +
      }
 +
      }
 +
    }
 +
    else if (timer > 70 && signature == 2)
 +
    {
 +
      ball_pixy.write(53);   //valor pour laisser de voir des balles et commencer à voir les balloons
 +
      go();
 +
      if(size_max_balle >= 456) //determiné cette Valeur
 +
      {
 +
        setSpeed(0,0); //arret du robot_movement
 +
        arm.write(170); //mettre en position le servos
 +
        digitalWrite(Explode_balloons, HIGH);
 +
        delay(10);
 +
        digitalWrite(Explode_balloons, LOW);
 +
        arm.write(100); //mettre en position le servos
 +
      }
 +
    }
 +
    else if (timer >= 90){setSpeed(0, 0); while(true);// Au bout de 90sec on arrete le jeu :)}
 +
   }
 +
  else setSpeed(0, 0);// Arrêté avant de commencer
 
}
 
}
</source>
 
{{boîte déroulante/fin}}
 
<br>
 
Il est nécessaire d'appeler les bibliothèques SPI.h et Pixy.h, et de déclarer et d'initialiser Pixy dans le setup. Ceprogramme ne permet cepandant pas l'usage des servomoteurs, limitant le champ de vision.
 
 
=={{Vert|Mise à l’arrêt du robot et le perçage du ballon}}==
 
 
La mise à l’arrêt du robot et le perçage du ballon doivent avoir lieu simultanément. Cela doit se produire quand le robot est arrivé dans le coin opposé.
 
 
 
==={{Bleu|Capteur de "Mise à l’arrêt" du robot}}===
 
 
Pour se diriger vers le bon coin, le robot est guidé par les roues codeuses et par la caméra qui suit la couleur jaune des balles de tennis présente dans son camp. Maintenant qu'il est guidé dans la bonne direction, nous devons procéder à une  mise à l’arrêt rapide des qu il franchi le camp adverse en détectant la ligne noir qui sépare ces deux dernières à l'aide du CNY70 qui nous permettra d’arrêter le robot afin qu'il effectue un retour en arrière pour chercher les autres balles présentent dans son camp  .
 
 
[[Fichier:Principe.PNG|300px|centre]]
 
 
 
 
*'''Le capteur CNY70''' : 
 
Nous pourrons utiliser ce capteur infrarouge pour détecter la couleur du sol.
 
 
 
[[Fichier:CNY 70.PNG|400px|gauche]] [[Fichier:Sd.PNG|300px|centre]]
 
 
 
 
 
 
 
 
 
*'''Schéma et dimensionement des composants'''
 
 
 
Emetteur: If = 20mA (Vf = 1.15V), Re = (5V-Vf)/If = 195 ohm.
 
 
Collecteur: Ic = 0.5mA (pour If = 20mA, Vce = 5V, d = 2mm), Rc = Vce /Ic = 10 kohm.
 
 
Nous devons obtenir les signaux correspondents:
 
 
{| class="wikitable"
 
|-
 
|Sol noir/surface non reflechissante || env 0 V
 
|-
 
| Sol bleu || env 3 V
 
|-
 
| Sol blanc/surface bien reflechissante || env 5 V
 
|}
 
*'''Schéma électrique, routage en Eagle et fabrication de la carte'''
 
 
 
[[Fichier:Schéma CNY70 .png|250px|gauche]]  [[Fichier:Image2 CNY70.jpg|180px|droite]] [[Fichier:Board CNY70.PNG|200px|centre]]
 
[[Fichier:Image1 CNY70.jpg|180px|gauche]]
 
 
 
 
 
 
<br>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
=={{Vert|Systeme "Perçage du Ballon"}}==
 
 
<br>
 
 
*'''La partie mécanique'''
 
 
a remplir ...
 
 
 
 
 
[[Fichier:Perçage 1.png|300px|centre]]
 
 
=={{Rouge|Système de Contrôle et Lancement du Ballon (Tennis) }}==
 
 
 
 
[[Fichier:Réservoir.jpg|180px|gauche]][[Fichier:Pression .jpg|180px|droite]][[Fichier:Ralonge .jpg|180px|centre]]
 
 
[[Fichier:Accord .jpg|180px|gauche]]
 
 
[[Fichier:Controle ballon.jpg|180px|gauche]][[Fichier:Vérin.jpg|180px|droite]][[Fichier:Méca.png|180px|centre]]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
=={{Vert|Réalisation Carte des "Entrées et Sorties" et du Pont H  }}==
 
<br>
 
==={{Bleu|Objectifs et Composants utilisés )}}===
 
 
 
* '''Objectif:'''  concevoir une carte compacte qui va héberger le composant L298N pour le contrôle des moteurs ainsi que toutes les entrées et les sorties.La carte devra s’emboîter sur la carte Arduino MEGA.  <br>
 
 
 
{| class="wikitable"
 
!Les Entrées !! Les Sorties
 
|-
 
| Alimentation (5V) || Moteur Gauche
 
|-
 
| Alimentation moteurs (12V) ||  Moteur Droit
 
|-
 
| Encodeurs (TCUT1300) || Commande perçage Ballon
 
|-
 
| Camera (CMUCam 5) || 
 
|-
 
| 3 capteurs obstacles (IR) ||
 
|-
 
| Couleur Sol (CNY70) ||
 
|-
 
| PWM Moteurs ||
 
|-
 
| Sens rotation Moteurs ||
 
|-
 
|}
 
<br>
 
 
* ''' Références des composants utilisés:<br>'''
 
 
{| class="wikitable"
 
!Qté !! Nom !! Référence Eagle
 
|-
 
| 1 || Dual H-Bridge || L298n 
 
|-
 
| 1 || Radiateur || pour L298n
 
|-
 
| 4 || Résistance || 1 ohm package 207/10
 
|-
 
| 8 || Diode  || 1N4004
 
|-
 
| 2 || Condensateur || E 1.8-4 package 100nF
 
|-
 
| 1 || Connecteur ISP || AVR-ISP-6
 
|-
 
| 1 || Connecteur || Farnell 6 pins CMS
 
|-
 
| 6 || Connecteur  || Molex 2 pins 22-27-2021-02 traversant
 
|-
 
| 3 || Connecteur || Molex 3 pins 22-27-2031-03 traversant
 
|-
 
|}
 
<br>
 
 
==={{Vert|Schéma électrique de la carte (Eagle)}}===
 
 
 
[[Fichier:Schéma Electrique.PNG|950px|thumb|center|Schéma Complet]]
 
 
 
 
==={{Vert|Routage et correspondance des pins (Eagle)}}===
 
 
 
[[Fichier:Carte Principale.png|950px|thumb|center|Schéma Complet]]
 
 
==={{Vert|La commande des Moteurs de Roues (L298n H-Bridge)}}===
 
 
==={{Vert|Les signaux d'entrée et de sortie}}===
 
 
==={{Vert|La carte finale et les connecteurs}}===
 
 
 
[[Fichier:CartePrincipale.jpg|700px|thumb|center|Figure 1 La carte finale ]] <br>
 
 
[[Fichier:Carte1.jpg|350px|thumb|gauche|Figure 2 Carte Récto]] [[Fichier:Carte 2.jpg|350px|thumb|droite|Figure 3 La carte Vérso avec un défaut ]]<br>
 
 
 
 
 
 
 
 
 
<br>
 
 
 
 
 
 
 
 
 
 
[[Fichier:Robotgeii.jpg|700px|thumb|center|Figure 4 Montage sur le Robot ]] <br>
 
 
==={{Vert|Problèmes rencontrés: }}===
 
 
a remplir
 
 
# après la fabrication de la carte <br>
 
# après avoir soudé tous les composants <br>
 
De même se servir toujours de l'oscilloscope pour visualiser les différents signaux en temps réel.
 
 
={{Rouge|Code complet}}=
 
 
Pour gérer les différents fonctionalités du robot nous avons utilisé le code suivant:
 
 
 
{{boîte déroulante/début|titre=Code exemple}}
 
a remplir ..
 
 
</source>
 
</source>
 
{{boîte déroulante/fin}}
 
{{boîte déroulante/fin}}
  
={{Rouge|Vidéo de Démonstration}}=
+
<big>Liens vers la compétition de l'année passée : </big>[[RobotGEII 16-17]]

Version actuelle datée du 20 juin 2018 à 19:31

Le wiki est actuellement en rédaction, certaines parties sont donc partiellement rédigées ou incomplètes.

COUPE ROBOTIQUE 2018


Maus.png


Introduction

Pour la deuxième fois consécutive l'IUT de Troyes auxquelles nous appartenons va participé à la Coupe de France Robotique des Iut qui se déroule chaque années du Jeudi 9 au samedi 11 Juin lors du Festival de Robotique dans la ville de Cachan. L'année dernière le But de la Coupe étais de se déplacé d'un point A à un point B en évitant des obstacles. Cette année l'objectif est radicalement différent puisqu'il s'agit de joué au Tennis ! Nous avons donc développé un robot répondant à une problématique et à un cahier des charges bien précis fixé par les organisateurs de la coupe. Je vous invite à consulté le règlement afin de bien comprendre le principe de la coupe de cette année.
Vous pouvez retrouvé ce règlement ici
Cette année nous devons donc joué au tennis, voici donc un bref résumé du déroulement de la coupe :

-Deux robots se font face sur un terrain de Tennis de dimension 8*4 m.
-Chaque robot à sur sont terrains un certain nombre de balles de Tennis par terre.
-Le centre de la piste est délimité par une ligne.
-Il y a deux ballons de chaque côtés des deux camps leurs explosions déclenche un surplus de balle dans le camp adverse.
-Un match dure 90 secondes.
-A la fin des 90 secondes l'envoi d'un projectile autre qu'une balle dans le camps adverses ajoute une balle supplémentaires dans le terrain adverses. Il Faut donc avoir le moins de balles possibles dans sont camps à la fin de la partie.
Voici un aperçu du terrain:

Terrain concour.PNG



Etudes

Il y a donc de nombreux But à atteindre, nous avons donc à l'aide d'un diagramme fonctionnelle décomposé tous ces Buts en Tâches à effectuées:

Analyse fonctionnelle.PNG

Cela nous à permis de définir les tâches que le robot doit effectué et les solutions techniques associées :
-Se déplacé => Deux moteurs commandés par un micro controleur Atmega 2560 via un pont en H l298n.
-Détecté les balles de Tennis => Première Caméra Pixy.
-Détecté la balise pour orienté le robot => Seconde Caméra Pixy.
-orientation de la deuxième caméra pixy => Moteur pas à pas.
-Détecté la proximité avec la balle et l'attrapée => Capteur de distance SHARP et Bras préhenseur.
-Propulsé la balle dans le camps adverse => Verrin.
-Atteindre les ballons situés en bordure du terrain => Bras rotatif.
-Faire éclaté les ballons en bordure du terrain => Arc électrique supporté par le bras rotatif nommé précédemment.
-Détecté les délimitations centrale du terrain => Capteur Cny70.
-Détecté la proximité avec les parois du terrain => Capteurs temps de vols.


Principe de fonctionnement

Comme nous l'avons vus précédemment il y a de nombreuses taches à effectuées, elles doivent toutes êtres réalisées en synchronisme cela implique un fonctionnement assez complexe que je vais vous expliquer.
Tous d'abord la direction, comment le robot se dirige t'il ? Le robot doit repérer les balles et les attrapées, pour ce faire la caméra pixy située à l'avant du robot va repérer les balles, selon la position de la balle dans le champ de vision de la caméra, c'elle si va renvoyé des informations à notre microcontrôleur. Le programme que contient le microcontrôleur va commandé les moteurs dans le but de maintenir la balle au centre du champs de vision de la caméra. Il va également tâché de faire grossir la balle dans l'objectif de la caméra, c'est à dire ce rapprocher de la balle. Une fois la balle arrivée à une certaine distance de la caméra (la balle remplis quasiment l'objectif de la caméra) un capteur de distance infrarouge Sharp va détecter la présence de la balle à l'endroit voulus, le bras va ensuite ce refermer pour "capturé" la balle. Pendant toutes cette période la deuxième caméra Pixy n'est pas restée inactive, en effet pendant ce temps elle fixe en permanence une balise émettant une lumière rouge que nous avons préalablement posé en fin de piste c'est à dire à l'arrière de notre camps. Nous pouvons donc déterminé en fonction des mouvements que notre deuxième caméra pixy à effectué ou se situe l'arrière de notre terrain. Nous pouvons donc déterminé la direction dans laquelle notre robot doit envoyé la balle !


Realisation


PREMIER PROTOTYPE


Proto1.jpg

Les différents éléments


Nous avons choisi de concevoir un chassi qui pourrais accueillir tous nos composants, nous ne savions pas à ce moment la leurs dimensionnement. Nous avons donc découpé en fonction du besoins des plaques de plastiques que nous avons assemblé.
Vous pouvez voir dans la photo précédente le robot complètement assemblé.
Ce robot ce déplace grâce à deux moteur fournis par les organisateurs de la coupe.
Ce sont deux moteurs Dunkermotoren G 42*25 qui permettent au robot de se mouvoir, vous pourrez retrouvé toutes leurs caractéristiques techniques ici
Ces moteurs et l'intégralités des dispositifs du robot sont alimentés par une batterie également définie par les organisateur de la coupe : C'est une batterie 12 V avec une capacité de 7 Ah.

Déplacement:
Ces deux moteurs sont donc contrôlés par un pont en H l298n, vous pourrez trouvez toutes les informations utiles concernant ce composant ici Ce composant serras placé sur la carte principale du robot, en effet au lieu de faire une carte pour la gestion des moteurs, une autre pour la gestion des caméras etc nous avons choisi de tous centralisé sur un seul shield d'une arduino mega. Vous pouvez également distingué sur le Robot les deux caméras Pixys, une à l'avant, une autre à l'arrière pour la détection de la Balle, une description plus précise des Pixys serras faites plus en Avale en effet elles seront abordés dans la partie traitant du second prototype. Vous pouvez voir également à l'avant du Robot le bras servant à attrapé la balle.
Ce bras à été imprimé à l'aide de l'imprimante 3D de l'Iut, il épouse parfaitement les dimensions de la balle, une version améliorée de ce bras à été fabriqué pour le deuxième prototype. Ce bras à été réalisé à l'aide d'une logiciel Freecad, ce logiciel libre est facile à prendre en mains c'est pour cela que nous l'avons préférés à Solydworks (même si les futures pièces seront surement faites à l'aide de ce dernier logiciel). Pour crée cette pièce nous avons crée une esquisse 2D puis à l'aide de protusion et de perçage nous obtenons une pièce en 3 dimensions. Il suffit ensuite de l'exporter sous un fichier "MESH" que l'imprimante 3D peux lire. Il existe ensuite plusieurs logiciels pouvant lire ce fichier, pour notre part nous disposions de deux imprimantes, les pièces les plus petites ont été réalisées à l'aide du logiciel Repetier Host et de l'imprimante 3D microDelta original et les pièces les plus grandes ont été réalisées grâce au logiciel Cura et à l'imprimante 3D Witbox
Bras préhenseur:

Bras préhension balle.PNG

Les capteurs Cny70:
Ces capteurs à pour but de détecter le milieu du terrain en effet notre robot n'as pas à empiéter sur le terrain de l'adversaire, nous avons donc conçu des petites cartes avec le capteurs et ce qui est nécessaire à sont fonctionnement dessus, seul bé mole nous allons devoirs inclinés les Cny en effet notre robot ne doit pas dépasser la ligne, nous devons donc la détecté à l'avance. Encore une fois si vous avez besoins de précision concernant ce photo transistor suivez ce lien : ici
Le moteur Pas à Pas

Dans ce projet, on a voulu mettre un moteur pas à pas pour la rotation de la caméra pixy derrière afin de pouvoir tourner à 360° en effet les servos moteurs présent sur la caméra pixy ne nous permettent de tournés seulement à 180°. On a donc utilisé un contrôleur de moteur pas à pas TCA 3727.


Pins TCA 3727.png


Le câblage du contrôleur TCA 3727 se trouve ci-dessous.

Cablâge moteur pas à pas.png

On peut commander le moteur en mode Full Step ou Half Step en envoyant des signaux à des entreés I10 I11 I20 I21. Exemple du full step :

Mode full step.png




Le générateur d'arc électriques
Il est invisible ici car il est situé à l'intérieur du robot, ce petit générateur produit des petits arcs électriques en ionisant l'air, il est commandé par un transistor Mosfet type N. Nous avons mesuré qu'il consomme au maximum de sont fonctionnement jusqu’à 3 Ampère, en effet plus l'arc électrique est grand plus la consommation de courant est grande. Après avoir effectué plusieurs tests nous en avons conclus que cette arc électrique étais suffisant pour faire éclater un ballon.

Les capteurs temps de vols

Nous allons être amené à nous déplacé sur le terrain , il nous faut donc pouvoir en détecter les limites, comme nous l'avons déjà vus nous avons les Cny pour repérer la ligne délimitant le milieu du terrain mais nous avons aussi besoins de capteurs capables de détecter les rebords du terrain. Pour ce faire nous utiliserons des capteurs temps de vols VL53L0X. Vous pourrez trouvez toutes les informations concernant ce capteur. ici

Capteurs VL53L0X.jpg


Le système pneumatique
Pour propulsé la balle nous utiliserons donc un vérin, nous utiliserons un vérin mis à disposition par notre enseignant. Ce vérin à besoins pour fonctionner d'une réserve d'air comprimée, ne pouvant évidement pas monté un compresseur sur notre petit robot nous utiliserons des cartouches de co2 de 12 G avec tige filetée, elles ont l'avantages non négligeable d'être facilement transportable. Nous commanderons le fonctionnement de notre vérin à l'aide d'une électrovanne également fournie par notre enseignant, nous sommes actuellement à la recherche d’électrovannes plus petites. Voici quelques photos du système pneumatique :

On peut voir le régulateur de pression à l'arrière du robot et le vérin démonté :
Regulateur pression vérin.jpg

Sur cette photo l'on peut voir l'ensemble du système pneumatique câblé, nous avons donc notre électrovanne commandé par la carte via un survolteur 12 -> 24V. Notre électrovanne est notre interrupteur dans notre circuit pneumatique.

Electrovanne.jpg



Le shield arduino mega

Pour commandé tous ces actionneurs que ce soit les moteurs ou les bras servants à percés les ballons ou à attrapé les balles, ainsi que pour centralisé et réagir aux informations fournis par nos nombreux capteurs nous avons besoins d'un micro contrôleur avec un nombre de pattes et un nombre de timers important. Nous avons donc choisi le micro contrôleur Atmega 2560. En effet il réponds parfaitement à nos attentes, cependant nous devons également mettre en oeuvre un pont en H et plusieurs transistors mosfet qui ne sont pas présent sur la carte arduino Mega. Nous allons donc créée un shield à cette carte. Le shield le voici :

CarteV1.jpg
Carte V1.png




C'est le premier shield que nous avons réalisés cependant nous avons rencontrés de nombreuses difficultés lors de sa fabrication, ces difficultés sont principalement du à un routage qui n’étais pas optimum, de très nombreux via ainsi que des piste dont la disposition ne facilitais pas le routage. Par exemple certains composants rendaient difficile le soudage des autres notamment à cause du manque de place. Cela rajouté à des erreurs de soudures ont rendus les essais de fonctionnements de cette cartes très laborieux. Finalement après une semaine à essayer de faire fonctionné correctement cette carte en vain nous avons décidé de fabriqué une version améliorée de celle si.
Voici donc la version corrigée de ce premier shield, le routage à été simplifié autant que possible, des nombreuses erreurs ont été corrigés et la disposition des pistes à été optimisé autant que possible. Nous avons également abordé la fabrication d'une manière différente en tirant les enseignement des erreurs de fabrication du premier shield. Par exemple nous avons soudé les composants traversants dans un ordre bien précis pour ne pas être gêner lors du soudage de ceux de l'un ou de l'autre. Voici donc le routage finale :

CarteV3.png

Et voici la carte fabriqué :

CarteV2.jpg

La carte principale finale

Après avoir testé et utilisé le shield arduino fabriqué pour le premier prototype, il existait toujours des problèmes qui provoquaient un mauvais fonctionnement du robot. De plus, on voulait ajouter certains composants afin d’améliorer notre robot. Pour ce faire, on a décidé de créer une carte principale en utilisant le micro-contrôleur ATMEGAG 2560 qui se trouve sur la carte Arduino MEGA pour fabriquer une carte qui est à la fois plus compatible et a beaucoup plus de places dans le but d’installer les autres dispositifs nécessaires (module XBEE, les transistors, etc). Cette carte a été fabriquée en tirant les enseignements des erreurs de fabrication des cartes précédente et le routage est optimisé le plus possible pour avoir une carte de qualité et facile à dépanner et tester. Les entrées/sorties non utilisées sont aussi reliées à des connecteurs MOLEX pour un ajout complémentaire des modules en tant que les capteurs, les modules supplémentaires dans le futur sans le besoin de refabriquer une nouvelle carte. Par contre, lors de la fabrication de cette carte principale, on a eu aussi pas mal de problème avec la mise en place du micro -contrôleur sur la carte.

Voici le routage de la carte :

Board BOT+TOP.PNG



Et voici la carte finie:

Carte principale.jpg




Modèle:Thor tank lors de la coupe robotique
Thor tank troyes.jpg


SECOND PROTOTYPE

Le Chassi en PLA

Nous avons décidé à la suite de la réalisation du premier prototype de tenir compte au maximum des nécessité techniques que devais remplir le chassi, nous avons donc crée un châssi robuste en PLA sur lequel chacun des actionneurs serait fixé rapidement. Nous l'avons dessiné sur Freecad et fabriqué à l'aide de l'imprimante 3D de l'iut. Il y a eu 3 versions différentes du châssi tous au long du projet voici donc quelques photos du chassi le plus récent une fois terminé : Sur freecad :

Chassi vue Supérieure.PNG

Et enfin imprimé :

Chassi.jpg
Tourelle assemblée.jpg


Les deux caméras pixy
Pixy à l'avant

La caméra Pixy est une caméra intelligente laquelle, principalement, fait un traitement d'images des objets qu'on garde dans leur mémoire. Cette caméra nous donne différentes informations telles que: les coordonnées X, Y du centre de l'objet, la largeur ainsi que la hauteur du carreau autour l'objet, la quantité d'objets détectés et leurs couleurs parmi des autres données. Vous pouvez avoir plus d'information ici http://www.cmucam.org/projects/cmucam5/wiki/Arduino_API

Pour ce projet on utilise deux caméras : La caméra positionnée devant du robot sera qui détecte les balles, également les deux ballons à coté du terrain et celle qui est derrière sera capable de nous donner l’angle entre la direction du robot et l’arrière du terrain. Cette dernière donnée nous aidera à envoyer les balles vers la direction correcte!

Pixy à l'arrière

Pour la première caméra, elle est monté à l’inverse(important pour la programmation puisque cela change l’orientation de l’axe X!) avec qu’un seul servomoteur qui contrôle le mouvement en l’axe Y. Ce mouvement est fait simplement, tout d’abord pour la détection des balles du sol et après pour la détection des ballons. Pourtant, la deuxième est montée sur deux servomoteurs qui contrôle le mouvement dans les deux axes. Il se trouve que si le robot est près de la balise on risque de la perdre, c’est pour cela qu’on utilise le mouvement en Y.

La carte principale

CODE

codeRobot

/*
  Program challenge "Coupe Robotique des IUT 2018"
  IUT de Troyes
  June - 2018
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <Wire.h>
#include <SPI.h>
#include <PixySPI_SS.h>
#include "Adafruit_VL53L0X.h"
#include <ServoTimer2.h>


#define topPWM            255       //Valeur Max du PWM Motors (8bits)
#define X_center          160     //PixyBalls consigne
#define sensor_ball        0   //sensor ball

#define S1                 1   //CNY70 left1
#define S2                 2   //CNY70 right1
#define S3                 3   //CNY70 left2
#define S4                 4   //CNY70 right2

#define PixyBalls         22   // camera for detect balls
#define PixyDirection     23   // camera for the direction of the robot

#define Eject_ball        36   // Eject ball
#define Eject_cloth       38   // Eject cloth (pas utilisé)
#define Explode_balloons  34   // set servo to explode balloons
//servos Pixy direction
#define X_CENTER        ((PIXY_MAX_X-PIXY_MIN_X)/2)
#define Y_CENTER        ((PIXY_MAX_Y-PIXY_MIN_Y)/2)



const int limit = 90;
bool start = false;
bool balise = false;

int s1 = 0;
int s2 = 0;
int s3 = 0;
int s4 = 0;
float new_s1 = 0;
float new_s2 = 0;
float new_s3 = 0;
float new_s4 = 0;

int signature = 0;
int timer = 0;
int16_t size_max_balle = 0;
int16_t size_max_ballon = 0;
int16_t size = 0;
bool caught_ball = false;
//Cameras
PixySPI_SS pixy1(PixyBalls);
PixySPI_SS pixy2(PixyDirection);


//Capteurs temps de vol
Adafruit_VL53L0X sensor1 = Adafruit_VL53L0X();
Adafruit_VL53L0X sensor2 = Adafruit_VL53L0X();
Adafruit_VL53L0X sensor3 = Adafruit_VL53L0X();
Adafruit_VL53L0X sensor4 = Adafruit_VL53L0X();
//Servomoteurs
ServoTimer2 ball;    // servo to catch balls
ServoTimer2 arm;     // servo to move the arm to explode balloons
ServoTimer2 ball_pixy;
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// Pantilt camera direction
///////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
class ServoLoop
{
  public:
    ServoLoop(int32_t pgain, int32_t dgain);

    void update(int32_t error);

    int32_t m_pos;
    int32_t m_prevError;
    int32_t m_pgain;
    int32_t m_dgain;
};


ServoLoop panLoop(300, 500);
ServoLoop tiltLoop(500, 700);

ServoLoop::ServoLoop(int32_t pgain, int32_t dgain)
{
  m_pos = PIXY_RCS_CENTER_POS;
  m_pgain = pgain;
  m_dgain = dgain;
  m_prevError = 0x80000000L;
}

void ServoLoop::update(int32_t error)
{
  long int vel;
  char buf[32];
  if (m_prevError != 0x80000000)
  {
    vel = (error * m_pgain + (error - m_prevError) * m_dgain) >> 10;
    //sprintf(buf, "%ld\n", vel);
    //Serial.print(buf);
    m_pos += vel;
    if (m_pos > PIXY_RCS_MAX_POS)
      m_pos = PIXY_RCS_MAX_POS;
    else if (m_pos < PIXY_RCS_MIN_POS)
      m_pos = PIXY_RCS_MIN_POS;
  }
  m_prevError = error;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// PixyDirection
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void direction()
{

  uint16_t blocks;
  int32_t panError, tiltError;

  blocks = pixy2.getBlocks();

  if (blocks)
  {
    panError = X_CENTER - pixy2.blocks[0].x;
    tiltError = pixy2.blocks[0].y - Y_CENTER;

    panLoop.update(panError);
    tiltLoop.update(tiltError);

    pixy2.setServos(panLoop.m_pos, tiltLoop.m_pos);
a    balise = true; //balise detectee
  }
  else balise = false;
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//SetMotors
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void initMotor()//PWM on PE3 (Left) and PH3(Right)
{
  //fpwm = fq / (topPWM * p)
  //fpwmi: frequency PWM
  //fq: frequency quartz
  //topPWM: value max PWM
  //p: predivisor

  //Declaration de sorties
  DDRB |= (1 << PB6);//Sense motor left     12   in1
  DDRB |= (1 << PB5);//Sense motor left     11  in2
  DDRH |= (1 << PH3);//PWM motor left OC4A  6   enA
  DDRH |= (1 << PH4);//Sense motor right    7   in3
  DDRB |= (1 << PB4);//Sense motor right    10   in4
  DDRH |= (1 << PH5);//PWM motor right OC4C 8   enB


  //Timer4 PH3

  TCCR4A |= (1 << WGM40);//Mode FAST PWM
  TCCR4B |= (1 << WGM42);

  TCCR4B |= (1 << CS40) | (1 << CS41);//divisor P=64


  TCCR4A |= 1 << COM4A1;//PWM on OC4A

  TCCR4A |= 1 << COM4C1;//PWM on OC4C

  OCR4A = 0;//Value first comparison  --> PH3

  OCR4C = 0;//Value first comparison --> PH5
}


void setMotorL(int16_t speed)//function motor left
{
  if (speed < 0)
  {
    speed = -speed;
    PORTB |= (1 << PB6);//Motor left : sense "-"
    PORTB &= ~ (1 << PB5);
  }
  else {
    PORTB &= ~ (1 << PB6);//Motor left : sense "+"
    PORTB |= (1 << PB5);
  }
  if (speed > topPWM) speed = topPWM;//speed max

  OCR4A = speed;//Action sur le PWM --> PE3
}

void setMotorR(int16_t speed)//function motor right
{
  if (speed < 0)
  {
    speed = -speed;
    PORTH &= ~ (1 << PH4); //Motor right : sense "-"
    PORTB |=  (1 << PB4);
  }
  else
  {
    PORTH |= (1 << PH4); //Motor left : sense "+"
    PORTB &= ~ (1 << PB4);
  }

  if (speed > topPWM) speed = topPWM;//speed max

  OCR4C = speed;//Action sur le PWM --> PH3
}

void setSpeed(int16_t vL, int16_t vR)//only one function for 2 motors
{
  setMotorL(vL);
  setMotorR(vR);
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// play time = 90s
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void timer_90s()
{
  //Tt1=(n*p)/fq
  //n=Tt1*fq/p
  //Tt1: periode du timer
  //n=valuer de comparaison (OCR1A)
  //p:prediviseur
  //fq:frequence du quark (arduino Mega 16Mhz)

  TCCR1B |= (1 << CS10) | (1 << CS12); //p=1024

  TCCR1B |= 1 << WGM12; //RAZ mode CTC

  TIMSK1 |= 1 << OCIE1A; //Autorisation d'interruption de comparaison A

  OCR1A = 15625; //Comparaison , Tt1=1s,
}

ISR(TIMER1_COMPA_vect)
{
  timer++;
  //PORTB^=1<<PB7; activar verin para la tela blanca
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// setCameras
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void setCameras() {

  //pixy2.init();
  pinMode(PixyBalls, OUTPUT); // Slave output PixyBalls
  pinMode(PixyDirection, OUTPUT); // Slave output PixyDirection

  digitalWrite(PixyBalls, HIGH); // desactivation PixyBalls
  digitalWrite(PixyBalls, HIGH); // desactivation PixyDirection

  pixy1.init();
  pixy2.init();

}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// PixyBalls
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void Pixy_tracking() {
  int signature = 0;

  //unsigned int16_t size_max_balle = 0;
  //unsigned int16_t size_max_ballon = 0;
  uint32_t size_balle = 0;
  uint16_t posX   = 0;
  //static int i = 0;
  int blocks;
  blocks     = pixy1.getBlocks();
  // grab blocks!
  if (blocks)
  {
    signature        = pixy1.blocks[0].signature;
    posX             = pixy1.blocks[0].x;
    size_balle       = pixy1.blocks[0].width; * pixy1.blocks[0].height;
  }
  /*else
  {
    posX = 0;
    size_balle = 0;
  }*/
  //Serial.println(sizeta /256)
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Activation capteurs temps de vol protocol I2C
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void configAddress() {
  pinMode(44, OUTPUT);
  pinMode(45, OUTPUT);
  pinMode(46, OUTPUT);
  pinMode(47, OUTPUT);

  digitalWrite(47, HIGH);
  digitalWrite(46, LOW);
  digitalWrite(45, LOW);
  digitalWrite(44, LOW);
  sensor1.setAddress(30);
  sensor1.begin(30);
  delay(10);
//  Serial.println("1 device");

  digitalWrite(47, HIGH);
  digitalWrite(46, HIGH);
  digitalWrite(45, LOW);
  digitalWrite(44, LOW);
  sensor2.setAddress(31);
  sensor2.begin(31);
  delay(10);
//  Serial.println("2 device");

  digitalWrite(47, HIGH);
  digitalWrite(46, HIGH);
  digitalWrite(45, HIGH);
  digitalWrite(44, LOW);
  sensor3.setAddress(32);
  sensor3.begin(32);
  delay(10);
//Serial.println("3 device");

  digitalWrite(47, HIGH);
  digitalWrite(46, HIGH);
  digitalWrite(45, HIGH);
  digitalWrite(44, HIGH);
  sensor3.setAddress(32);
  sensor4.setAddress(33);
  sensor4.begin(33);
  delay(10);
  //Serial.println("4 device");
}

void sensorRead() {

  VL53L0X_RangingMeasurementData_t measure1; // mesure prope de la librairie
  VL53L0X_RangingMeasurementData_t measure2;
  VL53L0X_RangingMeasurementData_t measure3;
  VL53L0X_RangingMeasurementData_t measure4;

  sensor1.rangingTest(&measure1, false);
  sensor2.rangingTest(&measure2, false);
  sensor3.rangingTest(&measure3, false);
  sensor4.rangingTest(&measure4, false);

  s1 = measure1.RangeMilliMeter;
  //delay(30);
  s2 = measure2.RangeMilliMeter;
  //delay(30);
  s3 = measure3.RangeMilliMeter;
  //delay(30);
  s4 = measure4.RangeMilliMeter;
  delay(30);  // mesure rapide, on a des autres posibilitées
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Détection des obstacles(limites du terrain)
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void robot_movement() {

  if ( s1 <= limit) new_s1 = 0.55 * limit; // détection de la limite du terrain
  else new_s1 = 0;

  if ( s2 <= limit) new_s2 = 3.2* limit;
  else new_s2 = 0;

  if ( s3 <= limit) new_s3 = 3.2* limit;
  else new_s3 = 0;

  if ( s4 <= limit) new_s4 = 0.55 * limit;
  else new_s4 = 0;
  //Serial.print(new_s1); Serial.print(" "); Serial.print(new_s2); Serial.print(" "); Serial.print(new_s3); Serial.print(" "); Serial.print(new_s4); Serial.println();
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//Movement Intégrateur
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void go()
{
  sensorRead();
  robot_movement();
  int leftSpeed  = ;
  int rightSpeed = ;
/*
    int leftSpeed  = constrain(180 + posX / 2.0 - 80 - size_balle /256  , 110, 200);
    int rightSpeed = constrain(180 - posX / 2.0 + 80 - size_balle /256  , 110, 200);
    setSpeed(leftSpeed, rightSpeed);*/
    //Serial.print(leftSpeed); Serial.print("   ");Serial.print(rightSpeed);Serial.println();
    int speedL = constrain(180 + new_s1 - new_s2 - new_s3 - new_s4 + posX / 2.0 - 80 - size_balle /256, -180, 200);
    int speedR = constrain(180 - new_s1 - new_s2 - new_s3 + new_s4 - posX / 2.0 + 80 - size_balle /256, -180, 200);
    //Serial.print(speedL);Serial.print(" ");Serial.print(speedR);Serial.println();
    setSpeed(speedL, speedR);
}

//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Set servos
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

void setServo()
{
  ball_pixy.attach(27);
  ball.attach(32);
  arm.attach(25);
}
int inte = 0;
void setup()
{
  pinMode(33, INPUT_PULLUP);
  timer_90s();                //timer 90sec
  initMotor();               //set Motors
  Wire.begin();              //connection I2C
  //Serial1.begin(9600);
  configAddress();
  setServo();
  sei();                       //timer1
  //Serial1.print("Start...");

  setCameras();                //déclaration des cameras Balles et Direction

  pinMode(sensor_ball, INPUT);
  //Commande de transitors MOSFET
  pinMode(Eject_ball, OUTPUT);
  pinMode(Eject_cloth, OUTPUT);
  pinMode(Explode_balloons, OUTPUT);

  ball.write(4); // etat Initialize
  arm.write(100);
  ball_pixy.write(130);
  while(inte == 0)inte = digitalRead(33);
  start = true;
}

void loop()
{


  if (start)
  {
    Pixy_tracking();
    if (timer <= 70 && signature == 1)
    {
      go();
      int mes_sensor_ball = analogRead(sensor_ball);
      if (mes_sensor_ball >= 430)
      {
        ball.write(53); // on attrape la balle
        caught_ball = true; //on a une balle dans
      }
      while (caught_ball) //mesure du capteur des balles
      {
        setSpeed(0, 0);
        if(balise)
        {
        if (panLoop.m_pos > 750L)
        {
          setSpeed(180, 0);
          delay(1000);
          setSpeed(0, 0);
          ball.write(4); // On enleve le bras qui attrapait la balle
          delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
          digitalWrite(Eject_ball, HIGH); //on tire la balle
          delay(10);
          digitalWrite(Eject_ball, LOW);
          caught_ball = false;
        }
        else if (panLoop.m_pos < 250L)
        {

        setSpeed(180, 0);
        delay(1000);
        setSpeed(0, 0);
        ball.write(4); // On enleve le bras qui attrapait la balle
        delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
        digitalWrite(Eject_ball, HIGH); //on tire la balle
        delay(10);
        digitalWrite(Eject_ball, LOW);
        caught_ball = false;
      }
        else
        {
          ball.write(4); // On enleve le bras qui attrapait la balle
          delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
          digitalWrite(Eject_ball, HIGH); //on tire la balle
          delay(10);
          digitalWrite(Eject_ball, LOW);
          caught_ball = false;
        }
      }
      else
      {
        setSpeed(200, 0);
        delay(2000);  //delay necessaire pour faire une demi tour
        setSpeed(0, 0);
        ball.write(4); // On enleve le bras qui attrapait la balle
        delay(250);  //!!!!!!!!AAAATTTTEEEENNNTTTTIOOOOONNN!!!!! changer ce temps il faut le mesure
        digitalWrite(Eject_ball, HIGH); //on tire la balle
        delay(10);
        digitalWrite(Eject_ball, LOW);
        caught_ball = false;
      }
      }
    }
    else if (timer > 70 && signature == 2)
    {
      ball_pixy.write(53);   //valor pour laisser de voir des balles et commencer à voir les balloons
      go();
      if(size_max_balle >= 456) //determiné cette Valeur
      {
        setSpeed(0,0); //arret du robot_movement
        arm.write(170); //mettre en position le servos
        digitalWrite(Explode_balloons, HIGH);
        delay(10);
        digitalWrite(Explode_balloons, LOW);
        arm.write(100); //mettre en position le servos
      }
    }
    else if (timer >= 90){setSpeed(0, 0); while(true);// Au bout de 90sec on arrete le jeu :)}
  }
  else setSpeed(0, 0);// Arrêté avant de commencer
}

Liens vers la compétition de l'année passée : RobotGEII 16-17