RobotRamasseur2014-2 : Différence entre versions
(→Capteur de pression) |
|||
(27 révisions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
+ | <include nopre noesc src="/home/pedago/ppeip/include/video-RobotRamasseur2-2014-iframe.html" /> | ||
+ | __TOC__ | ||
+ | <br style="clear: both;"> | ||
= Introduction = | = Introduction = | ||
Dans le cadre de notre bureau d'étude IMA, nous avions le choix entre plusieurs projets. Les différents projets étaient des robots joueurs, ramasseurs de balles, des buts ainsi qu'un arbitre, la finalité étant d'effectuer un match de football où les différents projets interviendraient. Ayant pris le projet "ramasseur de balle", notre but était de réaliser un robot en Lego, puis de le programmer en NXC (Not eXactly C), afin qu'il aille chercher la balle et la ramène au centre du terrain. | Dans le cadre de notre bureau d'étude IMA, nous avions le choix entre plusieurs projets. Les différents projets étaient des robots joueurs, ramasseurs de balles, des buts ainsi qu'un arbitre, la finalité étant d'effectuer un match de football où les différents projets interviendraient. Ayant pris le projet "ramasseur de balle", notre but était de réaliser un robot en Lego, puis de le programmer en NXC (Not eXactly C), afin qu'il aille chercher la balle et la ramène au centre du terrain. | ||
Ligne 33 : | Ligne 36 : | ||
== Les capteurs == | == Les capteurs == | ||
+ | Les capteurs sont très importants. En effet, ils nous permettent de faire réaliser des actions au robot en fonction de ce qu'ils "voient". Tout les capteurs doivent être initialisé : | ||
+ | SetSensorLowspeed(IN_1) et SetHTIRSeeker2Mode(IN_1, HTIR2_MODE_600) | ||
+ | *pour le capteur infrarouge. (MODE_1200 si on veut capteur du 1200Hz). | ||
+ | SetSensorUltrasonic(IN_2) | ||
+ | *pour le capteur d'ultrasons. | ||
+ | SetSensorMSPressure(IN_4) | ||
+ | *pour le capteur de pression. | ||
+ | SetSensorColorFull(IN_3) | ||
+ | *pour le capteur de couleur. | ||
+ | |||
+ | Voici donc les différent capteurs que nous utilisons. | ||
+ | |||
[[Fichier:Captcouleur.JPG|150px|thumb|left|Le capteur de couleur dans sa place finale]] | [[Fichier:Captcouleur.JPG|150px|thumb|left|Le capteur de couleur dans sa place finale]] | ||
Ligne 48 : | Ligne 63 : | ||
Au départ, le capteur était placé verticalement sur le bout de la partie fixe de la pince, juste pour détecter les obstacles, puis nous l'avons par la suite replacé horizontalement sur la base de la pince, à l'endroit du servomoteur et légèrement incliné vers l'avant, pour qu'il puisse détecter si la balle est au bon endroit. Nous avons choisi un angle spécial en faisait plusieurs essai : le capteur devait voir la balle assez proche, et en même temps ne pas détecter le sol. | Au départ, le capteur était placé verticalement sur le bout de la partie fixe de la pince, juste pour détecter les obstacles, puis nous l'avons par la suite replacé horizontalement sur la base de la pince, à l'endroit du servomoteur et légèrement incliné vers l'avant, pour qu'il puisse détecter si la balle est au bon endroit. Nous avons choisi un angle spécial en faisait plusieurs essai : le capteur devait voir la balle assez proche, et en même temps ne pas détecter le sol. | ||
+ | [[Fichier:Capteurir.JPG|150px|thumb|left|Capteur Infrarouge]] | ||
=== Capteur infrarouge === | === Capteur infrarouge === | ||
Ligne 54 : | Ligne 70 : | ||
Nous avions initialement placé le capteur à la place finale du capteur d'ultrasons, c'est-à-dire au centre de la pince, cependant nous avons pensé qu'il pourrait être gêné par ce qu'il y avait devant. Nous l'avons donc surélevé, en le laissant au centre de la pince, à l'aide d'une tige pour augmenter sa distance de détection. Nous avons placé comme pour le capteur de couleur, une collerette autour du capteur, car dans certains de nos essais, nous avons remarqué que le capteur captait bien la balle, mais les buts venait gêner lorsqu'ils étaient trop près. Le capteur ressemble donc à ceci : | Nous avions initialement placé le capteur à la place finale du capteur d'ultrasons, c'est-à-dire au centre de la pince, cependant nous avons pensé qu'il pourrait être gêné par ce qu'il y avait devant. Nous l'avons donc surélevé, en le laissant au centre de la pince, à l'aide d'une tige pour augmenter sa distance de détection. Nous avons placé comme pour le capteur de couleur, une collerette autour du capteur, car dans certains de nos essais, nous avons remarqué que le capteur captait bien la balle, mais les buts venait gêner lorsqu'ils étaient trop près. Le capteur ressemble donc à ceci : | ||
− | |||
=== Capteur de pression === | === Capteur de pression === | ||
− | Ce capteur permet d'annoncer au robot lorsqu'une pression est exercée sur celui-ci ou non. Il n'était pas indispensable au bon fonctionnement du robot, cependant il permet de créer des raccourcis au niveau de la programmation et d'avoir un robot plus complet au moment d'attraper la balle. En effet, le capteur permet de savoir si la balle est attrapée ou non lorsque le programme tourne, et le fait de pouvoir continuer à chercher la balle si le capteur ne détecte aucune pression permet d'éviter au robot d'entamer la suite du programme sans balle. Pour le placement, nous avons réussi à le coincer dans la partie fixe de la pince pour que la balle vienne appuyer dessus lorsque la pince se referme. Cependant c'est un capteur un peu capricieux qui demande de la rigueur, nous avons donc renforcé l'attache du capteur pour limiter le recul de celui-ci au maximum. | + | Ce capteur permet d'annoncer au robot lorsqu'une pression est exercée sur celui-ci ou non. Il n'était pas indispensable au bon fonctionnement du robot, cependant il permet de créer des raccourcis au niveau de la programmation et d'avoir un robot plus complet au moment d'attraper la balle. En effet, le capteur permet de savoir si la balle est attrapée ou non lorsque le programme tourne, et le fait de pouvoir continuer à chercher la balle si le capteur ne détecte aucune pression permet d'éviter au robot d'entamer la suite du programme sans balle. Le capteur de pression renvoie la valeur 0 lorsqu'il n'y a rien qui appuie dessus. Il renvoie 33 si une pression est exercée sur lui. |
+ | |||
+ | Pour le placement, nous avons réussi à le coincer dans la partie fixe de la pince pour que la balle vienne appuyer dessus lorsque la pince se referme. Cependant c'est un capteur un peu capricieux qui demande de la rigueur, nous avons donc renforcé l'attache du capteur pour limiter le recul de celui-ci au maximum. | ||
+ | <gallery> | ||
+ | file:capteurpress.JPG|Capteur de pression | ||
+ | file:fixationcapteur.JPG|Fixations renforcées du capteur | ||
+ | </gallery> | ||
== Robot final == | == Robot final == | ||
− | + | [[Fichier:Robotfinal.JPG|300px|thumb|center|Le robot final]] | |
− | |||
= La programmation = | = La programmation = | ||
Ligne 72 : | Ligne 92 : | ||
=== La fonction "Balle" === | === La fonction "Balle" === | ||
+ | La fonction balle est celle qui permet au robot de trouver la balle, grâce à l'infrarouge. Premièrement, il faut mettre le capteur en mode 600Hz. Ensuite, nous allons tester la valeur "dir" (voir partie sur le capteur IR), suivant cette valeur, le robot va s'orrienter dans une direction ou l'autre pour avoir la balle en face de lui. Une fois ceci fait, il va avancer et basculer dans la sous fonction "Attrape". | ||
+ | sub Balle() | ||
+ | { | ||
+ | SetSensorLowspeed(IN_1); | ||
+ | SetHTIRSeeker2Mode(IN_1, HTIR2_MODE_600); | ||
+ | int dir; | ||
+ | byte s1, s3, s5, s7, s9; | ||
+ | while(1) | ||
+ | { | ||
+ | int bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); | ||
+ | if (dir<5) | ||
+ | { | ||
+ | while (dir !=5) | ||
+ | { | ||
+ | bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); | ||
+ | OnFwd(OUT_A,-70); | ||
+ | OnFwd(OUT_B,70); | ||
+ | } | ||
+ | OnFwd(OUT_AB,100); | ||
+ | Attrape(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | while (dir != 5) | ||
+ | { | ||
+ | bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); | ||
+ | OnFwd(OUT_A,70); | ||
+ | OnFwd(OUT_B,-70); | ||
+ | } | ||
+ | OnFwd(OUT_AB,100); | ||
+ | Attrape(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
=== La fonction "Attrape" === | === La fonction "Attrape" === | ||
+ | Cette sous-fonction est celle qui permet à notre robot d'attraper la balle : l'action principale qui doit être réalisée. Dans un premier temps, nous utilisons la valeur renvoyée par le capteur d'ultrasons : de cette manière, dès que le robot se trouve assez proche de la balle (moins de 10cm), nous activons le moteur C, qui correspond à la pince, et cette dernière capture la balle. | ||
+ | sub Attrape() | ||
+ | { | ||
+ | SetSensorUltrasonic(IN_2); | ||
+ | int x = SensorUS(IN_2); | ||
+ | SetSensorMSPressure(IN_4); | ||
+ | int val = SensorMSPressure(IN_4); | ||
+ | if (x<10) | ||
+ | { | ||
+ | OnFwd(OUT_C,-50); | ||
+ | OnFwd(OUT_AB,0); | ||
+ | Wait(1000); | ||
+ | val = SensorMSPressure(IN_4); | ||
+ | Enfin, nous testons la valeur renvoyée pas le capteur de pression pour déterminer si le robot à la balle. Si la balle est attrapée, nous passons dans le sous programme suivant. Sinon, la pince se rouvre. | ||
+ | if (val>0) | ||
+ | { | ||
+ | Trouve(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | OnFwd(OUT_C,50); | ||
+ | } | ||
+ | } | ||
+ | } | ||
== Actions réalisées avec balle == | == Actions réalisées avec balle == | ||
=== La fonction "Trouve" === | === La fonction "Trouve" === | ||
+ | La fonction Trouve permet au robot, une fois la balle attrapée, de retrouver les lignes bleues du centre et basculer dans la fonction "Suivre". Le robot se contente juste de tourner légèrement à chaque fois qu'il se trouve face à un mur, et retombe donc forcément au bout d'un moment sur les lignes bleues. A la base, nous avions programmé le robot pour qu'il se dirige vers l'un des buts grâce à l'infrarouge, fasse demi-tour sur lui-même et qu'il détecte ensuite le but opposé pour avancer dans sa direction et ainsi retombe sur les lignes du centre. Mais à cause d'un problème de capteur, nous avons opté pour une solution plus simple. | ||
+ | |||
+ | sub Trouve() | ||
+ | { | ||
+ | SetSensorUltrasonic(IN_2); | ||
+ | while (1) | ||
+ | { | ||
+ | int x = SensorUS(IN_2); | ||
+ | int bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); | ||
+ | int cval; | ||
+ | unsigned int rawData[], normData[]; | ||
+ | int scaledData[]; | ||
+ | SetSensorColorFull(IN_3); | ||
+ | int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | if(x<22) | ||
+ | { | ||
+ | OnFwd(OUT_A, -50); | ||
+ | OnFwd(OUT_B, 50); | ||
+ | Wait(1800); | ||
+ | } | ||
+ | if (cval==2) | ||
+ | { | ||
+ | Suivre(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
=== La fonction "Suivre" === | === La fonction "Suivre" === | ||
+ | Ici, le robot est capable de suivre une des lignes bleues médianes. Une fois la pastille jaune détectée (centre du terrain), le robot va effectuer un angle droit pour se retrouver sur la ligne bleue perpendiculaire. Cette opération est répétée jusqu'au moment où le robot retombe sur sa base (détection du noir) pour basculer dans la fonction Place. Lors de cette manoeuvre, si à un quelconque moment le robot dévie de la ligne qu'il doit suivre, il bascule dans la fonction ChercheCouleur pour revenir sur celle-ci. | ||
+ | |||
+ | sub Suivre() | ||
+ | { | ||
+ | while (1) | ||
+ | { | ||
+ | int cval; | ||
+ | unsigned int rawData[], normData[]; | ||
+ | int scaledData[]; | ||
+ | SetSensorColorFull(IN_3); | ||
+ | int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | if (cval == 2) | ||
+ | { | ||
+ | while (cval == 2) | ||
+ | { | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | OnFwd(OUT_AB, 100); | ||
+ | if (cval == 4) | ||
+ | { | ||
+ | OnFwd(OUT_AB, 100); | ||
+ | Wait(1000); | ||
+ | OnFwd(OUT_A,-70); | ||
+ | OnFwd(OUT_B,70); | ||
+ | Wait(1000); | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | while (cval != 2) | ||
+ | { | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | OnFwd(OUT_A,-70); | ||
+ | OnFwd(OUT_B,70); | ||
+ | } | ||
+ | } | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | if (cval == 1) | ||
+ | { | ||
+ | Place(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | ChercheCouleur(); | ||
+ | } | ||
+ | } | ||
+ | return; | ||
+ | } | ||
=== La fonction "ChercheCouleur" === | === La fonction "ChercheCouleur" === | ||
+ | Grâce à cette fonction, le robot peut retrouver la ligne dont il suivait la trajectoire et de laquelle il avait légèrement dévié. En effet, le robot effectue des rotations d'abord d'un côté puis de l'autre avec des angles croissants jusqu'au moment où il détecte de nouveau la couleur bleue. Une fois l'action réalisée, on bascule de nouveau dans la fonction Suivre. | ||
+ | |||
+ | sub ChercheCouleur() | ||
+ | { | ||
+ | int cval; | ||
+ | unsigned int rawData[], normData[]; | ||
+ | int scaledData[]; | ||
+ | SetSensorColorFull(IN_3); | ||
+ | int i; | ||
+ | int n = 1; | ||
+ | int p = 1000; | ||
+ | int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | while (cval != 2) | ||
+ | { | ||
+ | for(i=0;i<10;i++) | ||
+ | { | ||
+ | OnFwd(OUT_A, 60); | ||
+ | OnFwd(OUT_B, -60); | ||
+ | Wait((n*p)/10); | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | if (cval==2) | ||
+ | {break;} | ||
+ | } | ||
+ | if (cval==2) | ||
+ | {break;} | ||
+ | for(i=0;i<20;i++) | ||
+ | { | ||
+ | OnFwd(OUT_B, 60); | ||
+ | OnFwd(OUT_A, -60); | ||
+ | Wait((n*p)/10); | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | } | ||
+ | n=n+1; | ||
+ | } | ||
+ | } | ||
− | === La fonction "Place" === | + | === La fonction "Place" === |
+ | Cette fonction permet au robot de déposer la balle au centre du terrain et d'aller se placer ensuite sur sa base. Pour cela, lorsque le robot est sur sa base, il effectue un demi-tour pour se diriger vers la pastille jaune au centre du terrain et y déposer la balle. Une fois cette opération faite, il recule jusqu'à temps de détecter du noir et d'être donc sur sa base. Nous avons fini par mettre une boucle infinie où le robot ne réalise aucune action car sa tâche se termine dans cette fonction. | ||
+ | sub Place() | ||
+ | { | ||
+ | int cval; | ||
+ | unsigned int rawData[], normData[]; | ||
+ | int scaledData[]; | ||
+ | SetSensorColorFull(IN_3); | ||
+ | int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | while(cval == 2) | ||
+ | { | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | OnFwd(OUT_AB, 70); | ||
+ | if (cval == 4) | ||
+ | { | ||
+ | OnFwd(OUT_A, 0); | ||
+ | OnFwd(OUT_B, 0); | ||
+ | OnFwd(OUT_C, 50); | ||
+ | OnFwd(OUT_A, -50); | ||
+ | OnFwd(OUT_B, -50); | ||
+ | Wait(2000); | ||
+ | OnFwd(OUT_A, -50); | ||
+ | OnFwd(OUT_B, 50); | ||
+ | Wait(1000); | ||
+ | } | ||
+ | if (cval == 1) | ||
+ | { | ||
+ | while (cval == 1) | ||
+ | { | ||
+ | result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); | ||
+ | OnFwd(OUT_AB,100); | ||
+ | } | ||
+ | OnFwd(OUT_A, -50); | ||
+ | OnFwd(OUT_B, 50); | ||
+ | Wait(4800); | ||
+ | while (1) | ||
+ | { | ||
+ | OnFwd(OUT_AB, 0); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | = Construction du terrain = | ||
+ | Arrivés à un certain stade dans ce bureau d'étude, nous étions obligé de faire des essais du programme sur le terrain final avec les bandes de couleur et les buts. Cependant rien n'était encore fait, et d'autres groupes étaient dans le même cas que nous. C'est donc pour cela que nous avons décidé de se lancer dans la construction du terrain ensemble. | ||
+ | Pour cela, nous avons utilisé 4 plaques identiques de 1,5m sur 1m sans les attacher les unes aux autres pour pouvoir ranger le terrain sans soucis. Nous avons ensuite pris les mesures pour placer les rubans adhésifs de couleurs différentes comme sur le plan établi avec soin et en accord avec tous les groupes. | ||
− | + | [[Fichier:Terrainbe.JPG|200px|thumb|center|Terrain final]] | |
− | |||
= Conclusion = | = Conclusion = | ||
− | + | Le bureau d'étude IMA nous a fourni une expérience intéressante. Effectivement, nous avons appris à gérer notre temps comme nous avions un travail à rendre après 40h de BE. Il fallait être efficace et ne pas perdre de temps sur des choses inutiles. Ensuite, il fallait également faire en fonction des contraintes liées au matériel (imprécision des capteurs) et des instructions fournies puisqu'il y avait un cahier des charges à respecter. Nous avons donc eu une idée de projet qui pourrait se réaliser dans nos prochaines années. Pour finir, le bureau d'étude n'a fait que conforter notre choix concernant le choix de notre spécialité pour l'année prochaine. |
Version actuelle datée du 28 mai 2015 à 17:33
Introduction
Dans le cadre de notre bureau d'étude IMA, nous avions le choix entre plusieurs projets. Les différents projets étaient des robots joueurs, ramasseurs de balles, des buts ainsi qu'un arbitre, la finalité étant d'effectuer un match de football où les différents projets interviendraient. Ayant pris le projet "ramasseur de balle", notre but était de réaliser un robot en Lego, puis de le programmer en NXC (Not eXactly C), afin qu'il aille chercher la balle et la ramène au centre du terrain.
La construction
La construction du robot est la première chose que nous avons faites. Cette étape nous semblait importante pour commencer car nous allions avoir une base matérielle sur laquelle travailler. En effet, savoir où sont placés les capteurs, et sur quelle entrée de notre micro-contrôleur était nécessaire avant de commencer a programmer. Les éléments à notre dispositions étaient :
- 3 servomoteurs
- Un capteur de couleurs, un d'ultrasons, un d'infrarouge et un de pression
- Un micro-contrôleur MindStorm
- Des pièces de Lego
Le châssis
Nous avons commencé par monter le "corps" de notre robot, en optant rapidement pour les chenilles étant donné que nous avions entendu que l'utilisation des roues poser problème dans certains cas. Le poids du micro-contrôleur nous a forcé à renforcer notre robot par le bas, en ajoutant des fixations. Nous avons au final réussi à trouver un bon compromis pour l'équilibre du robot, en répartissant uniformément toutes les charges à mettre sur le robot et en compensant le poids de la pince vers l'avant à l'aide d'une base arrière lourde. Nous avons veillé également à ne pas trop espacer les deux chenilles pour éviter que le robot ne s'écrase sous le poids du micro-contrôleur, que nous avons placé au centre du châssis, de façon verticale et légèrement incliné pour pouvoir faire les branchements aux différents capteurs sans encombres.
La pince
Notre robot étant un ramasseur de balle, il fallait qu'il soit équipé d'un système pour attraper la balle et la garder. Deux servomoteurs était déjà utilisés pour la mobilité du robot, nous avons alors opté pour une pince dont une partie serait articulée par le servomoteur restant, l'autre partie étant fixe. Par la suite, nous avons ajouté sur la pince des capteurs pour que le robot puisse interagir avec le monde extérieur, à savoir :
- Un capteur infrarouge
- Un capteur d'ultrasons
- Un capteur de pression
La pince avait alors la forme ci à droite.
Après quelque essais, nous nous sommes rendu compte que lorsque le robot avait la balle, cette dernière nous empêchait d'utiliser le capteur d'ultrasons. Il a donc fallu décentrer la pince pour laisser le champ libre au capteur d'ultrasons. Dans sa version finale, la pince se referme de telle façon que la balle se retrouve légèrement sur la gauche du robot en laissant le champ libre au capteur d'ultrasons.
Au final, le robot, avec la nouvelle pince, ressemble donc à cela :
Les capteurs
Les capteurs sont très importants. En effet, ils nous permettent de faire réaliser des actions au robot en fonction de ce qu'ils "voient". Tout les capteurs doivent être initialisé :
SetSensorLowspeed(IN_1) et SetHTIRSeeker2Mode(IN_1, HTIR2_MODE_600)
- pour le capteur infrarouge. (MODE_1200 si on veut capteur du 1200Hz).
SetSensorUltrasonic(IN_2)
- pour le capteur d'ultrasons.
SetSensorMSPressure(IN_4)
- pour le capteur de pression.
SetSensorColorFull(IN_3)
- pour le capteur de couleur.
Voici donc les différent capteurs que nous utilisons.
Capteur de couleurs
C'est le seul capteur qui se retrouve sur le châssis. Il nous permet de basculer dans la partie du programme voulue en détectant une certaine couleur. Par exemple, le robot peut suivre une bande de couleur grâce à ce capteur.
Nous l'avions dans un premier temps fixé sur l'arrière du robot. Cependant, lorsque ce dernier tournait, le capteur n'arrivait plus à détecter la ligne et le robot n'avançait plus. Le capteur de couleurs est donc passé à l'avant du robot. Afin de la placer correctement, nous avons du en plus prendre en compte la hauteur du capteur : en effet, si le capteur est trop haut, il a du mal a détecter les bonnes couleurs, ce qui pose un problème évident à l’exécution du programme.
Nous avons finalement ajouté une collerette sur le capteur afin que ce dernier puissent détecter les couleur avec encore plus de précision.
Capteur d'ultrasons
Ce capteur-ci offre la possibilité de détecter des obstacles qui pourraient se dresser sur le chemin du robot, comme les barrières qui délimitent le terrain. Pour nous, le capteur a une double utilisation étant donné qu'il est complémentaire avec le capteur infrarouge pour attraper la balle. En effet, comme le capteur infrarouge est défaillant à faible distance (il détecte la balle dans plusieurs direction et nous ne pouvons pas l'utiliser), le capteur à ultrasons voit alors si la balle est assez proche ou non pour être capturée.
Au départ, le capteur était placé verticalement sur le bout de la partie fixe de la pince, juste pour détecter les obstacles, puis nous l'avons par la suite replacé horizontalement sur la base de la pince, à l'endroit du servomoteur et légèrement incliné vers l'avant, pour qu'il puisse détecter si la balle est au bon endroit. Nous avons choisi un angle spécial en faisait plusieurs essai : le capteur devait voir la balle assez proche, et en même temps ne pas détecter le sol.
Capteur infrarouge
Le capteur infrarouge détecte la position de la balle et des buts à l'aide signaux envoyés par ceux-ci. Son rôle est d'orienter le robot vers la balle pour pouvoir aller ensuite la ramasser. La difficulté de cette tâche est de savoir distinguer les signaux envoyés par la balle de ceux envoyés par les buts, qui devront normalement être d'une fréquence différente (1200Hz pour les buts et 600Hz pour la balle).
Nous avions initialement placé le capteur à la place finale du capteur d'ultrasons, c'est-à-dire au centre de la pince, cependant nous avons pensé qu'il pourrait être gêné par ce qu'il y avait devant. Nous l'avons donc surélevé, en le laissant au centre de la pince, à l'aide d'une tige pour augmenter sa distance de détection. Nous avons placé comme pour le capteur de couleur, une collerette autour du capteur, car dans certains de nos essais, nous avons remarqué que le capteur captait bien la balle, mais les buts venait gêner lorsqu'ils étaient trop près. Le capteur ressemble donc à ceci :
Capteur de pression
Ce capteur permet d'annoncer au robot lorsqu'une pression est exercée sur celui-ci ou non. Il n'était pas indispensable au bon fonctionnement du robot, cependant il permet de créer des raccourcis au niveau de la programmation et d'avoir un robot plus complet au moment d'attraper la balle. En effet, le capteur permet de savoir si la balle est attrapée ou non lorsque le programme tourne, et le fait de pouvoir continuer à chercher la balle si le capteur ne détecte aucune pression permet d'éviter au robot d'entamer la suite du programme sans balle. Le capteur de pression renvoie la valeur 0 lorsqu'il n'y a rien qui appuie dessus. Il renvoie 33 si une pression est exercée sur lui.
Pour le placement, nous avons réussi à le coincer dans la partie fixe de la pince pour que la balle vienne appuyer dessus lorsque la pince se referme. Cependant c'est un capteur un peu capricieux qui demande de la rigueur, nous avons donc renforcé l'attache du capteur pour limiter le recul de celui-ci au maximum.
Robot final
La programmation
La programmation du robot a été réalisée exclusivement en langage NXC car on nous a déconseillé d'utiliser le langage graphique propre au micro-contrôleur, qui est assez limité.
Actions réalisées sans balle
La fonction "Balle"
La fonction balle est celle qui permet au robot de trouver la balle, grâce à l'infrarouge. Premièrement, il faut mettre le capteur en mode 600Hz. Ensuite, nous allons tester la valeur "dir" (voir partie sur le capteur IR), suivant cette valeur, le robot va s'orrienter dans une direction ou l'autre pour avoir la balle en face de lui. Une fois ceci fait, il va avancer et basculer dans la sous fonction "Attrape".
sub Balle() { SetSensorLowspeed(IN_1); SetHTIRSeeker2Mode(IN_1, HTIR2_MODE_600); int dir; byte s1, s3, s5, s7, s9; while(1) { int bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); if (dir<5) { while (dir !=5) { bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); OnFwd(OUT_A,-70); OnFwd(OUT_B,70); } OnFwd(OUT_AB,100); Attrape(); } else { while (dir != 5) { bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); OnFwd(OUT_A,70); OnFwd(OUT_B,-70); } OnFwd(OUT_AB,100); Attrape(); } } }
La fonction "Attrape"
Cette sous-fonction est celle qui permet à notre robot d'attraper la balle : l'action principale qui doit être réalisée. Dans un premier temps, nous utilisons la valeur renvoyée par le capteur d'ultrasons : de cette manière, dès que le robot se trouve assez proche de la balle (moins de 10cm), nous activons le moteur C, qui correspond à la pince, et cette dernière capture la balle.
sub Attrape() { SetSensorUltrasonic(IN_2); int x = SensorUS(IN_2); SetSensorMSPressure(IN_4); int val = SensorMSPressure(IN_4); if (x<10) { OnFwd(OUT_C,-50); OnFwd(OUT_AB,0); Wait(1000); val = SensorMSPressure(IN_4);
Enfin, nous testons la valeur renvoyée pas le capteur de pression pour déterminer si le robot à la balle. Si la balle est attrapée, nous passons dans le sous programme suivant. Sinon, la pince se rouvre.
if (val>0) { Trouve(); } else { OnFwd(OUT_C,50); } } }
Actions réalisées avec balle
La fonction "Trouve"
La fonction Trouve permet au robot, une fois la balle attrapée, de retrouver les lignes bleues du centre et basculer dans la fonction "Suivre". Le robot se contente juste de tourner légèrement à chaque fois qu'il se trouve face à un mur, et retombe donc forcément au bout d'un moment sur les lignes bleues. A la base, nous avions programmé le robot pour qu'il se dirige vers l'un des buts grâce à l'infrarouge, fasse demi-tour sur lui-même et qu'il détecte ensuite le but opposé pour avancer dans sa direction et ainsi retombe sur les lignes du centre. Mais à cause d'un problème de capteur, nous avons opté pour une solution plus simple.
sub Trouve() { SetSensorUltrasonic(IN_2); while (1) { int x = SensorUS(IN_2); int bVal = ReadSensorHTIRSeeker2AC(IN_1, dir, s1, s3, s5, s7, s9); int cval; unsigned int rawData[], normData[]; int scaledData[]; SetSensorColorFull(IN_3); int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); if(x<22) { OnFwd(OUT_A, -50); OnFwd(OUT_B, 50); Wait(1800); } if (cval==2) { Suivre(); } } }
La fonction "Suivre"
Ici, le robot est capable de suivre une des lignes bleues médianes. Une fois la pastille jaune détectée (centre du terrain), le robot va effectuer un angle droit pour se retrouver sur la ligne bleue perpendiculaire. Cette opération est répétée jusqu'au moment où le robot retombe sur sa base (détection du noir) pour basculer dans la fonction Place. Lors de cette manoeuvre, si à un quelconque moment le robot dévie de la ligne qu'il doit suivre, il bascule dans la fonction ChercheCouleur pour revenir sur celle-ci.
sub Suivre() { while (1) { int cval; unsigned int rawData[], normData[]; int scaledData[]; SetSensorColorFull(IN_3); int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); if (cval == 2) { while (cval == 2) { result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); OnFwd(OUT_AB, 100); if (cval == 4) { OnFwd(OUT_AB, 100); Wait(1000); OnFwd(OUT_A,-70); OnFwd(OUT_B,70); Wait(1000); result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); while (cval != 2) { result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); OnFwd(OUT_A,-70); OnFwd(OUT_B,70); } } result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); if (cval == 1) { Place(); } } } else { ChercheCouleur(); } } return; }
La fonction "ChercheCouleur"
Grâce à cette fonction, le robot peut retrouver la ligne dont il suivait la trajectoire et de laquelle il avait légèrement dévié. En effet, le robot effectue des rotations d'abord d'un côté puis de l'autre avec des angles croissants jusqu'au moment où il détecte de nouveau la couleur bleue. Une fois l'action réalisée, on bascule de nouveau dans la fonction Suivre.
sub ChercheCouleur() { int cval; unsigned int rawData[], normData[]; int scaledData[]; SetSensorColorFull(IN_3); int i; int n = 1; int p = 1000; int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); while (cval != 2) { for(i=0;i<10;i++) { OnFwd(OUT_A, 60); OnFwd(OUT_B, -60); Wait((n*p)/10); result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); if (cval==2) {break;} } if (cval==2) {break;} for(i=0;i<20;i++) { OnFwd(OUT_B, 60); OnFwd(OUT_A, -60); Wait((n*p)/10); result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); } n=n+1; } }
La fonction "Place"
Cette fonction permet au robot de déposer la balle au centre du terrain et d'aller se placer ensuite sur sa base. Pour cela, lorsque le robot est sur sa base, il effectue un demi-tour pour se diriger vers la pastille jaune au centre du terrain et y déposer la balle. Une fois cette opération faite, il recule jusqu'à temps de détecter du noir et d'être donc sur sa base. Nous avons fini par mettre une boucle infinie où le robot ne réalise aucune action car sa tâche se termine dans cette fonction.
sub Place() { int cval; unsigned int rawData[], normData[]; int scaledData[]; SetSensorColorFull(IN_3); int result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); while(cval == 2) { result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); OnFwd(OUT_AB, 70); if (cval == 4) { OnFwd(OUT_A, 0); OnFwd(OUT_B, 0); OnFwd(OUT_C, 50); OnFwd(OUT_A, -50); OnFwd(OUT_B, -50); Wait(2000); OnFwd(OUT_A, -50); OnFwd(OUT_B, 50); Wait(1000); } if (cval == 1) { while (cval == 1) { result = ReadSensorColorEx(IN_3, cval, rawData, normData, scaledData); OnFwd(OUT_AB,100); } OnFwd(OUT_A, -50); OnFwd(OUT_B, 50); Wait(4800); while (1) { OnFwd(OUT_AB, 0); } } } }
Construction du terrain
Arrivés à un certain stade dans ce bureau d'étude, nous étions obligé de faire des essais du programme sur le terrain final avec les bandes de couleur et les buts. Cependant rien n'était encore fait, et d'autres groupes étaient dans le même cas que nous. C'est donc pour cela que nous avons décidé de se lancer dans la construction du terrain ensemble. Pour cela, nous avons utilisé 4 plaques identiques de 1,5m sur 1m sans les attacher les unes aux autres pour pouvoir ranger le terrain sans soucis. Nous avons ensuite pris les mesures pour placer les rubans adhésifs de couleurs différentes comme sur le plan établi avec soin et en accord avec tous les groupes.
Conclusion
Le bureau d'étude IMA nous a fourni une expérience intéressante. Effectivement, nous avons appris à gérer notre temps comme nous avions un travail à rendre après 40h de BE. Il fallait être efficace et ne pas perdre de temps sur des choses inutiles. Ensuite, il fallait également faire en fonction des contraintes liées au matériel (imprécision des capteurs) et des instructions fournies puisqu'il y avait un cahier des charges à respecter. Nous avons donc eu une idée de projet qui pourrait se réaliser dans nos prochaines années. Pour finir, le bureau d'étude n'a fait que conforter notre choix concernant le choix de notre spécialité pour l'année prochaine.