IMA4 2018/2019 P3 : Différence entre versions

De Wiki de Projets IMA
(Semaine 2 et 3)
(Documents rendus)
 
(106 révisions intermédiaires par le même utilisateur non affichées)
Ligne 42 : Ligne 42 :
 
==Choix techniques : matériel et logiciel==
 
==Choix techniques : matériel et logiciel==
  
 
+
Les différents composants CMS seront de préférence de taille 0603 (1608 metric).
 
Matériel :
 
Matériel :
 
*1*Gyroscope et accéléromètre MPU6050 [https://fr.farnell.com/invensense/mpu-6050/gyroscope-accelero-6-axes-i2c/dp/1864742/ ]
 
*1*Gyroscope et accéléromètre MPU6050 [https://fr.farnell.com/invensense/mpu-6050/gyroscope-accelero-6-axes-i2c/dp/1864742/ ]
Ligne 48 : Ligne 48 :
 
*2*Capteur de souris optique
 
*2*Capteur de souris optique
 
*1*ATMEGA328PU [https://fr.farnell.com/atmel/atmega328-pu/micro-8-bits-avr-32k-flash-28pdip/dp/1972087?st=ATMEGA328P/ ]
 
*1*ATMEGA328PU [https://fr.farnell.com/atmel/atmega328-pu/micro-8-bits-avr-32k-flash-28pdip/dp/1972087?st=ATMEGA328P/ ]
*1*Contrôleur moteur [https://www.robotshop.com/eu/fr/controleur-deux-moteurs-dc-3a-5v-28v-pololu-tb6612fng.html?gclid=CjwKCAjworfdBRA7EiwAKX9HeNKQ9krFFOPBErCeFhN4g3-08qhqQMsPwlIKRPsNFpXd4NOrt0RSwBoC8_gQAvD_BwE/ ]
+
*1*Régulateur de tension 9-5V [https://www.mouser.fr/ProductDetail/Texas-Instruments/LM1117IMPX-50-NOPB?qs=sGAEpiMZZMsGz1a6aV8DcCERHZHPu4lvRjG0WFCuZBk%3d ]
*1*Régulateur de tension [https://www.mouser.fr/ProductDetail/Texas-Instruments/LM338T-NOPB?qs=sGAEpiMZZMvu8NZDyZ4K0czVwi%2feZmTa ]
+
*1 Régulateur de tension 9-3.3V [https://www.mouser.fr/ProductDetail/Texas-Instruments/UA78M33CDCYRG3?qs=sGAEpiMZZMtUqDgmOWBjgCb759GUAfeoDL97C8Znw8M%3d]
*13*Condensateur 100nF [https://fr.farnell.com/multicomp/mc0201x104k6r3ct/condensateur-mlcc-x5r-100nf-6/dp/2320753/ ]
+
*12*Condensateur 100nF [https://fr.farnell.com/multicomp/mc0603b104j160ct/condensateur-0-1-f-16v-5-x7r-0603/dp/2320813 ]
 
*2*Condensateur 10uF [http://fr.farnell.com/wurth-elektronik/885012106006/condesateur-mlcc-x5r-10uf-6-3v/dp/2495147/ ]
 
*2*Condensateur 10uF [http://fr.farnell.com/wurth-elektronik/885012106006/condesateur-mlcc-x5r-10uf-6-3v/dp/2495147/ ]
 
*1*Condensateur 2.2nF [https://fr.farnell.com/murata/grt1885c1h222ja02d/cond-2200pf-50v-5-c0g-np0-0603/dp/2672140?st=condensateur%20cms%202.2nF/ ]
 
*1*Condensateur 2.2nF [https://fr.farnell.com/murata/grt1885c1h222ja02d/cond-2200pf-50v-5-c0g-np0-0603/dp/2672140?st=condensateur%20cms%202.2nF/ ]
*1*Condensateur 10nF [https://fr.farnell.com/w/c/composants-passifs/condensateurs/condensateurs-ceramiques/prl/resultats?st=condensateur+cms+10nF/ ]
+
*1*Condensateur 10nF [https://fr.farnell.com/avx/06031c103jat2a/cond-0-01-f-100v-5-x7r-0603/dp/1833876?st=condensateur%20cms%2010nF/ ]
 
*2*Condensateur 22pF [https://www.mouser.fr/ProductDetail/AVX/06036A220KAT2A?qs=%2fha2pyFadujFAMWcscuzNxoi2Xvu%2fcfD8lvTtKLZ6rzLbCl2Yyy9Kg%3d%3d ]
 
*2*Condensateur 22pF [https://www.mouser.fr/ProductDetail/AVX/06036A220KAT2A?qs=%2fha2pyFadujFAMWcscuzNxoi2Xvu%2fcfD8lvTtKLZ6rzLbCl2Yyy9Kg%3d%3d ]
 
*1*Rectifier Diode [https://www.mouser.fr/ProductDetail/Vishay-Semiconductors/GL34G-E3-83?qs=%2fha2pyFaduhcwkEZbW1d2CZAGmWr2%2fNAC5qtPDBJR27vWTljBHmHKA%3d%3d ]
 
*1*Rectifier Diode [https://www.mouser.fr/ProductDetail/Vishay-Semiconductors/GL34G-E3-83?qs=%2fha2pyFaduhcwkEZbW1d2CZAGmWr2%2fNAC5qtPDBJR27vWTljBHmHKA%3d%3d ]
 
*2*Servomoteur [https://www.robotshop.com/eu/fr/micro-servomoteur-9g-48v.html/ ]
 
*2*Servomoteur [https://www.robotshop.com/eu/fr/micro-servomoteur-9g-48v.html/ ]
*1*FA238 [http://www.mouser.fr/ProductDetail/Epson-Timing/TSX-3225-160000MF09Z-AC3/?qs=sGAEpiMZZMsBj6bBr9Q9acukpafrIaZ1%2fpqCtYImzz0%3d ]
 
 
*1*émetteur infrarouge [https://www.mouser.fr/ProductDetail/OSRAM-Opto-Semiconductors/SFH-4845?qs=%2fha2pyFadugjIA4ylihU12jGSA%252bzbOUlwVVqnWGUzCE%3d ]
 
*1*émetteur infrarouge [https://www.mouser.fr/ProductDetail/OSRAM-Opto-Semiconductors/SFH-4845?qs=%2fha2pyFadugjIA4ylihU12jGSA%252bzbOUlwVVqnWGUzCE%3d ]
 
*2*Résistance 1kΩ [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ102/?qs=sGAEpiMZZMu61qfTUdNhG1IKPAnaLGejvfM9hA7acow%3d ]
 
*2*Résistance 1kΩ [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ102/?qs=sGAEpiMZZMu61qfTUdNhG1IKPAnaLGejvfM9hA7acow%3d ]
 +
*2*Résistance 4.7kΩ [https://www.mouser.fr/ProductDetail/Vishay/CRCW06034K70FKEAC?qs=sGAEpiMZZMvdGkrng054t0DrEhLhGh8gO8ZrWRPm7giXEfb8HIJ%252bcg%3d%3d ]
 
*8*Résistance 220Ω [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ221/?qs=sGAEpiMZZMu61qfTUdNhG1IKPAnaLGejce8FZC1%2fFYU%3d ]
 
*8*Résistance 220Ω [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ221/?qs=sGAEpiMZZMu61qfTUdNhG1IKPAnaLGejce8FZC1%2fFYU%3d ]
 
*1*Résistance 330Ω [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ331/?qs=sGAEpiMZZMu61qfTUdNhG1IKPAnaLGejYH%2fBWzzt0Tg%3d ]  
 
*1*Résistance 330Ω [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ331/?qs=sGAEpiMZZMu61qfTUdNhG1IKPAnaLGejYH%2fBWzzt0Tg%3d ]  
Ligne 65 : Ligne 65 :
 
*1*Résistance 1MΩ [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ105/?qs=sGAEpiMZZMu61qfTUdNhG79AcIiSWYOgHx87yIE%2f9KKMdGhl9FJu5g%3d%3d ]
 
*1*Résistance 1MΩ [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/ESR03EZPJ105/?qs=sGAEpiMZZMu61qfTUdNhG79AcIiSWYOgHx87yIE%2f9KKMdGhl9FJu5g%3d%3d ]
 
*1*Résistance 470Ω [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/KTR03EZPJ471/?qs=sGAEpiMZZMu61qfTUdNhGwzMi690UM7UxxZFBtRl4vg%3d ]
 
*1*Résistance 470Ω [http://www.mouser.fr/ProductDetail/ROHM-Semiconductor/KTR03EZPJ471/?qs=sGAEpiMZZMu61qfTUdNhGwzMi690UM7UxxZFBtRl4vg%3d ]
*1*Interrupteur [http://www.mouser.fr/ProductDetail/ALPS/SKQGADE010/?qs=sGAEpiMZZMsqIr59i2oRcrO5GDYRXDIX6cdtN26xmPE%3d ]
+
*3*Résistance 56Ω [https://fr.farnell.com/yageo/rc0603fr-0756rl/res-couche-epaisse-56r-1-0-1w/dp/9238336 ]
*1*Interface USB [https://www.mouser.fr/ProductDetail/FTDI/FT232RL-REEL/?qs=sGAEpiMZZMs5ceO8zL%252bTxyQLQIH6hE7q ]
+
*1*Appuie Bouton [http://www.mouser.fr/ProductDetail/ALPS/SKQGADE010/?qs=sGAEpiMZZMsqIr59i2oRcrO5GDYRXDIX6cdtN26xmPE%3d ]
 
*1*Quartz [http://www.mouser.fr/ProductDetail/ECS/ECS-160-20-3X-TR/?qs=sGAEpiMZZMvAbnEMxb34PZ9bYWrwSXiB ]
 
*1*Quartz [http://www.mouser.fr/ProductDetail/ECS/ECS-160-20-3X-TR/?qs=sGAEpiMZZMvAbnEMxb34PZ9bYWrwSXiB ]
 
*3*Récepteur infrarouge [http://www.mouser.fr/ProductDetail/Vishay-Semiconductors/TSOP38238/?qs=sGAEpiMZZMvAL21a%2fDhxMtgKho2n4%2fgBkajAZHPY5lE%3d ]
 
*3*Récepteur infrarouge [http://www.mouser.fr/ProductDetail/Vishay-Semiconductors/TSOP38238/?qs=sGAEpiMZZMvAL21a%2fDhxMtgKho2n4%2fgBkajAZHPY5lE%3d ]
Ligne 86 : Ligne 86 :
  
  
[[Fichier:graph.png|frame|center|1000px|Diagramme de Gantt ]]
+
[[Fichier:graph2.png|vignette|center|1000px|Diagramme de Gantt ]]
  
 
=Réalisation du Projet=
 
=Réalisation du Projet=
Ligne 92 : Ligne 92 :
  
 
{| class="wikitable"
 
{| class="wikitable"
!Tâche !! Heures S1 !! Heures S2 !! Heures S3 !! Heures S4 !! Heures S5 !! Heures S6 !! Heures S7 !! Heures S8 !! Heures S9 !! Heures S10 !! Total
+
!Tâche !! Heures S1 !! Heures S2 !! Heures S3 !! Heures S4 !! Heures S5 !! Heures S6 !! Heures S7 !! Heures S8 !! Heures S9 !! Heures S10 !! Heures S11 !! Heures S12 !! Heures S13!! Total
 
|-
 
|-
 
| Analyse du projet  
 
| Analyse du projet  
 
| 12
 
| 12
|
+
| 12
|
+
| 16
|
+
| 12
|
+
| 12
|
+
| 12
|
+
| 8
|
+
| 16
|
+
| 16
|
+
| 30
|
+
| 30
 +
| 40
 +
| 30
 +
| 236
 
|}
 
|}
  
Ligne 127 : Ligne 130 :
 
[[Fichier:mpu.png|frame|right|100px| Orientation et polarité des axes ]]  
 
[[Fichier:mpu.png|frame|right|100px| Orientation et polarité des axes ]]  
 
La semaine deux m'a permis de confirmer mes choix de capteurs pour le robot qui seront les suivants :
 
La semaine deux m'a permis de confirmer mes choix de capteurs pour le robot qui seront les suivants :
*un gyroscope MPU6050 qui permet d'obtenir des informations en accélération linéaire et en vitesse de rotation pour le robot. Ce capteur est très souvent bruité, il faudra donc réaliser un filtrage du bruit avant de pouvoir analyser les données envoyées par un bus I2C compatible avec arduino. Ces données sont envoyées de la manière suivante :
+
*un gyroscope MPU6050 qui permet d'obtenir des informations en accélération linéaire et en vitesse de rotation pour le robot. Ce capteur est très souvent bruité, il faudra donc réaliser un filtrage du bruit avant de pouvoir analyser les données envoyées par un bus I2C compatible avec arduino. D'après la fiche constructeur, on a les données suivantes :
 +
**Sa tension d'alimentation est comprise entre 2.375V et 3.45V
 +
**Il utilise le bus I2C
 +
**Il est constitué d'un accéléromètre 3 axes ET d'un gyroscope 3 axes
 +
**Il utilise les interruptions
 +
**Le gyroscope a une précision allant jusqu'à ±2000°/sec
 +
**Le gyroscope a une consommation nominale de 3.6mA
 +
**L'accéléromètre a une précision allant jusqu'à ±16g
 +
 
 +
Ces données sont envoyées de la manière suivante :
  
 
{| class="wikitable"
 
{| class="wikitable"
Ligne 133 : Ligne 145 :
 
| AcY = 4624   
 
| AcY = 4624   
 
| AcZ = -14732   
 
| AcZ = -14732   
| Tmp = 20.34
+
| Temperature = 20.34
 
| GyX = 15.49   
 
| GyX = 15.49   
 
| GyY = 17.43
 
| GyY = 17.43
Ligne 144 : Ligne 156 :
  
 
<u>Type de capteur:</u>
 
<u>Type de capteur:</u>
 +
*Le type de capteur
 +
Il existe 3 types de souris composées de capteurs différents qui assurent le bon fonctionnement des souris :
 +
**1. La souris mécanique contient une boule de contact reliée à des rouleaux qui assurent l'odométrie de la souris. Ce système a pour avantage d'être utilisable sur différents types de surfaces tant que la boule de contact est en contact avec le support.
 +
**2. La souris optique qui elle possède une petite caméra et d'un système de traitement d'image qui permet d'analyser les variations de nuance de la surface éclairé par la led de la souris. En analysant ainsi les variations de nuances, il est possible de reconstituer le déplacement de la souris. Le mieux est de positionner la souris à quelques millimètres du sol.
 +
**3. La souris laser qui possède le même type de caméra qui analyse la surface sur laquelle la souris repose à ceci prêt que la source lumineuse est une source laser. Cette souris permet une meilleure précision et une plus grande adaptabilité aux surfaces. La souris peut être positionnée plus éloignée du sol ce qui présente plusieurs avantages.
  
Il existe 3 types de souris composées de capteurs différents qui assurent le bon fonctionnement des souris :
+
 
*1. La souris mécanique contient une boule de contact reliée à des rouleaux qui assurent l'odométrie de la souris. Ce système a pour avantage d'être utilisable sur différents types de surfaces tant que la boule de contact est en contact avec le support.
+
*Son type de connexion
*2. La souris optique qui elle possède une petite caméra et d'un système de traitement d'image qui permet d'analyser les variations de nuance de la surface éclairé par la led de la souris. En analysant ainsi les variations de nuances, il est possible de reconstituer le déplacement de la souris. Le mieux est de positionner la souris à quelques millimètres du sol.
+
**1. Connectique PS2 : C'est l'une des plus anciennes connectiques de souris, et l'une des plus facile à lire. Il existe en effet de multiples tutoriels montrant comment lire ces données.
*3. La souris laser qui possède le même type de caméra qui analyse la surface sur laquelle la souris repose à ceci prêt que la source lumineuse est une source laser. Cette souris permet une meilleure précision et une plus grande adaptabilité aux surfaces. La souris peut être positionnée plus éloignée du sol ce qui présente plusieurs avantages.
+
**2. Connectique USB : l'USB est particulièrement embêtant à lire en brut. Mais certaines souris anciennes réalisent en fait une conversion PS2-->USB en interne. On peut donc récupérer des données en se reliant aux pins qui gèrent le transport de données sous PS2.
 +
**3. Souris sans fil : Ce type de connecteur ne nous intéresse pas car demande trop de ports pour être lu (deux fiches usb et j'en passe).
  
  
Pour la commande du robot, nous utiliserons une petite manette infrarouge programmable qui devra réaliser les fonctions suivantes :  
+
En poursuivant mes recherches, j'ai pu découvrir des possibilités d'application très intéressantes. Notamment le fait qu'il suffit de changer la focale de la lentille afin de régler la hauteur à laquelle nous positionnons le capteur pour rendre ce test efficace pour différentes positions. On découvre cette méthode dans [https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4481980/ l'article suivant] qui propose l'utilisation d'une lentille afocale afin de réduire les erreurs obtenues par la position selon l'axe Z du capteur. [https://hackteria.org/wiki/Hacked_Optical_Mouse/ Cet autre article] explique comment "hacker" sa souris. L'avantage de l'utilisation d'une souris comme capteur odométrique est aussi exposé dans [https://www.techbriefs.com/component/content/article/tb/techbriefs/electronics-and-computers/216/ cet autre article] de la NASA qui explique notamment l'alternative aux systèmes de capteurs s'inspirant de la vision des insectes pour se repérer depuis un drone volant par l'utilisation de capteurs de souris qui ont pour avantage de permettre une réduction du coût, poids embarqué, l'énergie utilisée et de la simplicité avec laquelle on peut en ajouter et placer en parallèle.
 +
''Mots clés optimaux : optical flow navigation mouse''
 +
*Pour la commande du robot, nous utiliserons une petite manette infrarouge programmable qui devra réaliser les fonctions suivantes :  
 
** Un bouton pour accélérer par palier
 
** Un bouton pour accélérer par palier
 
** Un bouton pour décélérer par palier
 
** Un bouton pour décélérer par palier
Ligne 167 : Ligne 187 :
 
==Semaine 4, 5 et 6==
 
==Semaine 4, 5 et 6==
 
<p align="justify">
 
<p align="justify">
[[Fichier:fonctionrobot.png|vignette|center| Schéma de fonctionnement ]]
+
[[Fichier:fonctionrobot2.png|vignette|center| Schéma de fonctionnement ]]
 
Les semaines suivantes concernent la création du PCB. J'ai tout d'abords fais l'erreur de réaliser un schéma sous draw.io ce qui m'a fait perdre du temps sur le début de la semaine puis je suis passé directement sur altium afin de réaliser le schéma de mon circuit. La stratégie adoptée ici est de reprendre les footprints déjà existants sur internet afin de simplifier la tâche puis de vérifier que les données simulées sous Altium correspondent bien à nos composants.
 
Les semaines suivantes concernent la création du PCB. J'ai tout d'abords fais l'erreur de réaliser un schéma sous draw.io ce qui m'a fait perdre du temps sur le début de la semaine puis je suis passé directement sur altium afin de réaliser le schéma de mon circuit. La stratégie adoptée ici est de reprendre les footprints déjà existants sur internet afin de simplifier la tâche puis de vérifier que les données simulées sous Altium correspondent bien à nos composants.
Ce qui a été fait sur la carte :
+
J'ai ensuite passé une grande partie de mon temps à trouver les bonnes datasheets dans le but de trouver les schémas de montage associés aux composants utilisés dans la réalisation du robot.
*MPU6050
+
Le schéma de l'ATMEGA utilisé est le suivant : [[Fichier:schematmega.jpg|vignette|center| Schéma de l'ATMEGA238P-AU]]
*Alimentation
+
Ce schéma a pour avantage de mettre en relation les pins de l'ATMEGA avec les pins de la funduino ce qui facilite l'interconnexion notamment lors du bootloader ou du téléversement des données ainsi que pour la programmation du uP.
*Driver
+
 
*Clock
 
*Reset
 
  
Il manque :
 
*Des headers
 
*Préparer les récepteurs infrarouges
 
*Interface usb
 
*connecteur usb
 
*régulateur de tension 5V-->3.3V
 
*Souris
 
  
 +
Les schémas actuels sont les suivants :
 
[[Média:schematicsa.pdf | Schematic du projet en cours]]
 
[[Média:schematicsa.pdf | Schematic du projet en cours]]
 
</p>
 
</p>
Ligne 189 : Ligne 201 :
 
==Semaine 7==
 
==Semaine 7==
 
<p align="justify">
 
<p align="justify">
Pour la semaine de vacances il est prévu que je fasse les choses suivantes :
+
 
*Chassis
+
La semaine 7 est celle des vacances, j'en ai profité pour mettre à jour le wiki ainsi que commencer des petits test sur les récepteurs infrarouges.
*PCB à finir (avant avis de Mr Boé)
+
</p>
*Analyse des données reçues par les souris
+
 
*Expliciter le wiki sur les choix faits pour la carte et présenter les parties recherches sur les composants
+
==Semaine 8 et 9==
 +
<p align="justify">
 +
J'ai poursuivis la réalisation du PCB durant ces deux dernières semaines en terminant le schématique du montage et en réalisant un premier routage de la carte. J'ai d'abord voulu essayer de router la carte en utilisant l'auto routage mais j'ai vite remarqué qu'il complexifiait plus le montage qu'autre chose. De plus, les "déchets" c'est à dire des pistes inutiles étaient présentes en plus grand nombre. J'ai donc tout repris et réalisé un routage à la main plus propre. Je suis ensuite entré en contact avec Monsieur Boé qui m'a aidé à corriger les défauts du schématique et du PCB.
 +
Il a fallu que je modifie le placement de mes composants notamment le quartz qui doit être écarté de toutes pistes si possible afin de ne pas avoir de bruitage de signal. Les capacités de découplage étaient aussi très éloignées des composants à découpler. Il m'a donc fallu poursuivre les modifications pendant les deux semaines qui ont suivi avant d'avoir un résultat fonctionnel en théorie.
 +
Pendant cette période j'ai donc travaillé sur mon PCB la journée puis une fois les fichiers Altiums corrigés, j'ai entamé la réalisation d'un premier prototype à l'aide d'une ATMEGA328p et d'une funduino. Cela m'a permit d'avancer sur la programmation du robot en prévision de la finalisation du prototype avec PCB nous pouvons voir le bon fonctionnement du robot sur le [https://youtu.be/1-5X6hwA0i0/ lien ci contre]
 +
 
 
</p>
 
</p>
 +
 +
==Semaine 10==
 +
<p align="justify">
 +
====Réalisation du châssis====
 +
Le châssis a été réalisé sous le logiciel Onshape qui est un logiciel de CAO libre de droit. La réalisation des pièces en context permet de diminuer grandement le nombre d'erreurs de dimension et permet une réalisation plus rapide des pièces à créer. Une fois le châssis réalisé sous Onshape il ne reste plus qu'à se rendre dans les "Parts" qui nous intéressent, faire un clic droit sur la face de la pièce qui nous intéresse (attention à ne pas cliquer sur le côté de la pièce sinon on imprime l'épaisseur et non notre face) puis séléctionner Export As DXF(Attention, Onshape doit être en Inch pour l'exportation sinon des problèmes de dimension apparaissent sous Inkscape).
 +
Une fois le fichier prêt, il suffit de l'ouvrir sous Inkscape et de placer les pièces sur le support pour enfin aller découper le support.
 +
</p>
 +
[[Fichier:onshape_proj.png|vignette|left| Modèle sous Onshape]]
 +
[[Fichier:inkscape_proj.png|vignette|center| Résultat sous Inkscape]]
 +
[[Fichier:impressionchass.jpg|vignette|center| Après l'impression]]
 +
 +
J'ai ensuite poursuivi mes modifications de PCB jusqu'à le finaliser pour lancer son impression. Le résultat sous Altium est le suivant :
 +
[[Fichier:circuitrobot.png|vignette|center| Routage fini du PCB sous Altium]]
 +
 +
==Semaine 11==
 +
 +
====Tests du MPU6050====
 +
crédits au site [https://www.firediy.fr/article/calibrer-le-capteur-mpu6050-avec-un-arduino-drone-ch-5] pour avoir proposé une méthode simple de calibration du gyroscope. Et à Luis Rodenas pour son code de calibration
 +
 +
Nous allons commencer par effectuer des tests sur le MPU6050 format carte.
 +
*La première étape est d'effectuer une calibration propre au capteur. Cette calibration est peut se trouver à l'aide du programme suivant :
 +
*<p align="justify">
 +
  // I2Cdev and MPU6050 must be installed as libraries
 +
  #include "I2Cdev.h"
 +
  #include "MPU6050.h"
 +
  #include "Wire.h"
 +
 +
///////////////////////////////////  CONFIGURATION  /////////////////////////////
 +
  //Change this 3 variables if you want to fine tune the skecth to your needs.
 +
 +
  int buffersize=1000;    //Amount of readings used to average, make it higher to get more precision but sketch will be slower  (default:1000)
 +
  int acel_deadzone=8;    //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge  (default:8)
 +
  int giro_deadzone=1;    //Giro error allowed, make it lower to get more precision, but sketch may not converge  (default:1)
 +
 +
  // default I2C address is 0x68
 +
  // specific I2C addresses may be passed as a parameter here
 +
  // AD0 low = 0x68 (default for InvenSense evaluation board)
 +
  // AD0 high = 0x69
 +
  //MPU6050 accelgyro;
 +
  MPU6050 accelgyro(0x68); // <-- use for AD0 high
 +
 +
  int16_t ax, ay, az,gx, gy, gz;
 +
 +
  int mean_ax,mean_ay,mean_az,mean_gx,mean_gy,mean_gz,state=0;
 +
  int ax_offset,ay_offset,az_offset,gx_offset,gy_offset,gz_offset;
 +
 +
///////////////////////////////////  SETUP  ////////////////////////////////////
 +
 +
  void setup() {
 +
  // join I2C bus (I2Cdev library doesn't do this automatically)
 +
  Wire.begin();
 +
  // COMMENT NEXT LINE IF YOU ARE USING ARDUINO DUE
 +
  TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Leonardo measured 250kHz.
 +
 +
  // initialize serial communication
 +
  Serial.begin(115200);
 +
 +
  // initialize device
 +
  accelgyro.initialize();
 +
 +
  // wait for ready
 +
  while (Serial.available() && Serial.read()); // empty buffer
 +
  while (!Serial.available()){
 +
    Serial.println(F("Send any character to start sketch.\n"));
 +
    delay(1500);
 +
  }
 +
  while (Serial.available() && Serial.read()); // empty buffer again
 +
 +
  // start message
 +
  Serial.println("\nMPU6050 Calibration Sketch");
 +
  delay(2000);
 +
  Serial.println("\nYour MPU6050 should be placed in horizontal position, with package letters facing up. \nDon't touch it until you see a finish message.\n");
 +
  delay(3000);
 +
  // verify connection
 +
  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
 +
  delay(1000);
 +
  // reset offsets
 +
  accelgyro.setXAccelOffset(0);
 +
  accelgyro.setYAccelOffset(0);
 +
  accelgyro.setZAccelOffset(0);
 +
  accelgyro.setXGyroOffset(0);
 +
  accelgyro.setYGyroOffset(0);
 +
  accelgyro.setZGyroOffset(0);
 +
  }
 +
 +
///////////////////////////////////  LOOP  ////////////////////////////////////
 +
  void loop() {
 +
  if (state==0){
 +
    Serial.println("\nReading sensors for first time...");
 +
    meansensors();
 +
    state++;
 +
    delay(1000);
 +
  }
 +
 +
  if (state==1) {
 +
    Serial.println("\nCalculating offsets...");
 +
    calibration();
 +
    state++;
 +
    delay(1000);
 +
  }
 +
 +
  if (state==2) {
 +
    meansensors();
 +
    Serial.println("\nFINISHED!");
 +
    Serial.print("\nSensor readings with offsets:\t");
 +
    Serial.print(mean_ax);
 +
    Serial.print("\t");
 +
    Serial.print(mean_ay);
 +
    Serial.print("\t");
 +
    Serial.print(mean_az);
 +
    Serial.print("\t");
 +
    Serial.print(mean_gx);
 +
    Serial.print("\t");
 +
    Serial.print(mean_gy);
 +
    Serial.print("\t");
 +
    Serial.println(mean_gz);
 +
    Serial.print("Your offsets:\t");
 +
    Serial.print(ax_offset);
 +
    Serial.print("\t");
 +
    Serial.print(ay_offset);
 +
    Serial.print("\t");
 +
    Serial.print(az_offset);
 +
    Serial.print("\t");
 +
    Serial.print(gx_offset);
 +
    Serial.print("\t");
 +
    Serial.print(gy_offset);
 +
    Serial.print("\t");
 +
    Serial.println(gz_offset);
 +
    Serial.println("\nData is printed as: acelX acelY acelZ giroX giroY giroZ");
 +
    Serial.println("Check that your sensor readings are close to 0 0 16384 0 0 0");
 +
    Serial.println("If calibration was succesful write down your offsets so you can set them in your projects using something similar to mpu.setXAccelOffset(youroffset)");
 +
    while (1);
 +
  }
 +
  }
 +
 +
///////////////////////////////////  FUNCTIONS  ////////////////////////////////////
 +
 +
  void meansensors(){
 +
  long i=0,buff_ax=0,buff_ay=0,buff_az=0,buff_gx=0,buff_gy=0,buff_gz=0;
 +
 +
  while (i<(buffersize+101)){
 +
    // read raw accel/gyro measurements from device
 +
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
 +
 +
    if (i>100 && i<=(buffersize+100)){ //First 100 measures are discarded
 +
      buff_ax=buff_ax+ax;
 +
      buff_ay=buff_ay+ay;
 +
      buff_az=buff_az+az;
 +
      buff_gx=buff_gx+gx;
 +
      buff_gy=buff_gy+gy;
 +
      buff_gz=buff_gz+gz;
 +
    }
 +
    if (i==(buffersize+100)){
 +
      mean_ax=buff_ax/buffersize;
 +
      mean_ay=buff_ay/buffersize;
 +
      mean_az=buff_az/buffersize;
 +
      mean_gx=buff_gx/buffersize;
 +
      mean_gy=buff_gy/buffersize;
 +
      mean_gz=buff_gz/buffersize;
 +
    }
 +
    i++;
 +
    delay(2); //Needed so we don't get repeated measures
 +
  }
 +
  }
 +
 +
  void calibration(){
 +
  ax_offset=-mean_ax/8;
 +
  ay_offset=-mean_ay/8;
 +
  az_offset=(16384-mean_az)/8;
 +
 +
  gx_offset=-mean_gx/4;
 +
  gy_offset=-mean_gy/4;
 +
  gz_offset=-mean_gz/4;
 +
  while (1){
 +
    int ready=0;
 +
    accelgyro.setXAccelOffset(ax_offset);
 +
    accelgyro.setYAccelOffset(ay_offset);
 +
    accelgyro.setZAccelOffset(az_offset);
 +
 +
    accelgyro.setXGyroOffset(gx_offset);
 +
    accelgyro.setYGyroOffset(gy_offset);
 +
    accelgyro.setZGyroOffset(gz_offset);
 +
 +
    meansensors();
 +
    Serial.println("...");
 +
 +
    if (abs(mean_ax)<=acel_deadzone) ready++;
 +
    else ax_offset=ax_offset-mean_ax/acel_deadzone;
 +
 +
    if (abs(mean_ay)<=acel_deadzone) ready++;
 +
    else ay_offset=ay_offset-mean_ay/acel_deadzone;
 +
 +
    if (abs(16384-mean_az)<=acel_deadzone) ready++;
 +
    else az_offset=az_offset+(16384-mean_az)/acel_deadzone;
 +
 +
    if (abs(mean_gx)<=giro_deadzone) ready++;
 +
    else gx_offset=gx_offset-mean_gx/(giro_deadzone+1);
 +
 +
    if (abs(mean_gy)<=giro_deadzone) ready++;
 +
    else gy_offset=gy_offset-mean_gy/(giro_deadzone+1);
 +
 +
    if (abs(mean_gz)<=giro_deadzone) ready++;
 +
    else gz_offset=gz_offset-mean_gz/(giro_deadzone+1);
 +
 +
    if (ready==6) break;
 +
  }
 +
  }</p>
 +
 +
Ce code a pour objectif de lire les 100 premières données brutes avec un pas de temps de 2ms en sortie du gyroscope afin de trouver une valeur d'état initial moyenne. On vérifie ensuite que ces données ne sont pas trop éloignées les unes des autres puis on créer l'offset adéquat à notre capteur.
 +
Il faut effectuer cette calibration pour chaque nouveau capteur car chacun va différer.
 +
[[Fichier:calibgyro.jpg|vignette|center|Calibration du gyroscope à l'aide d'un niveau]]
 +
Les résultat obtenus pour le gyroscope sous forme de carte sont les suivants :
 +
{| class="wikitable"
 +
| AcX = 526 
 +
| AcY = -467
 +
| AcZ = 1722 
 +
| GyX = 99
 +
| GyY = 14
 +
| GyZ = -3
 +
|}
 +
 +
==Semaine 12==
 +
====Réglage des servo moteurs====
 +
<p align="justify">
 +
Nous allons maintenant nous intéresser aux servomoteurs. Il faut, dans un premier temps les calibrer à l'aide de la vis à l'arrière des servomoteurs. Pour les tester, il suffit d'exécuter le programme suivant :
 +
</p>
 +
*<p align="justify">
 +
  #include "Servo.h"
 +
 +
  Servo myservo;
 +
 +
  void setup(){
 +
    myservo.attach(9);
 +
    myservo.write(90);
 +
  }
 +
 +
  void loop(){
 +
  }
 +
</p>
 +
<p align="justify">
 +
Les valeurs de commande des moteurs vont de 0 (avancer dans le sens des aiguilles d'une montre) à 180 (avancer dans le sens inverse des aiguilles d'une montre). En fixant cette valeur à 90, cela signifie que le moteur est à l'arrêt. La roue est donc immobile et il est possible de régler la vis afin d'avoir effectivement un arrêt du moteur à 90.
 +
</p>
 +
====Programmation des commandes du robot====
 +
<p align="justify">
 +
En attendant que le circuit soit imprimé, j'ai réalisé la commande infrarouge des différentes fonctions du robot à l'aide de la télécommande suivante :
 +
 +
[[Fichier:remote_robot.png|vignette|left| Télécommande du robot ]] 
 +
 +
Les boutons sont associés aux codes et fonctions suivantes :
 +
**1 : 0xA25D associé au bouton ON/OFF du système IR
 +
**2 : 0x02FD associé au bouton tourner à gauche de 10°
 +
**3 : 0xC23D associé au bouton tourner à droite de 10°
 +
**4 : 0xA857 associé au bouton décélérer de 10 (vitesse va de 0 à 90 en absolue)
 +
**5 : 0x906F associé au bouton accélérer de 10 (vitesse va de 0 à 90 en absolue)
 +
 +
 +
Le code pour réaliser les différentes actions est le suivant :
 +
  #include <IRremote.h>
 +
  #include <Servo.h>
 +
  int RECV_PIN = 2;
 +
  int outputmotG = 9; //cmd moteur gauche
 +
  int outputmotD = 10; //cmd moteur droite)
 +
  int VmotG = 90;
 +
  int VmotD = 90;
 +
  int isON = 0;
 +
  Servo ServoG;
 +
  Servo ServoD;
 +
  #define codeG  0x2FD //aller à gauche
 +
  #define codeD  0xC23D// aller à droite
 +
  #define ONOFF  0xA25D //ONOFF button
 +
  #define accel 0x906F //acceleration par palier
 +
  #define decel 0xA857 //décélération par palier
 +
  IRrecv irrecv(RECV_PIN);
 +
  decode_results results;
 +
 +
  void setup()
 +
  {
 +
 +
    Serial.begin(9600);
 +
    irrecv.enableIRIn(); // Start the receiver
 +
    pinMode(outputmotG,OUTPUT);
 +
    pinMode(outputmotD,OUTPUT);
 +
    ServoG.attach(9);
 +
    ServoD.attach(10);
 +
    ServoG.write(VmotG); //
 +
    ServoD.write(VmotD);
 +
  }
 +
 +
 +
  void loop(){
 +
    if (irrecv.decode(&results)) {
 +
      unsigned int value = results.value;
 +
      switch(value) {
 +
fonction 1 :
 +
      case ONOFF :
 +
      if (isON == 0){
 +
      isON = 1;
 +
      ServoG.write(VmotG); //
 +
      ServoD.write(VmotD);}
 +
      else {
 +
        isON = 0;
 +
        VmotG=90;
 +
        VmotD=90;
 +
      }
 +
      break;
 +
fonction 3 :
 +
    case codeD :
 +
      if(isON == 1) { //
 +
        ServoD.write(VmotD*19.0/18);
 +
        ServoG.write(VmotG*19.0/18); //
 +
        delay(1000);
 +
      }
 +
      break;
 +
fonction 2 :
 +
      case codeG :
 +
      if(isON == 1) { //
 +
        ServoG.write(VmotG*17.0/18);
 +
        ServoD.write(VmotD*17.0/18);
 +
        delay(1000);
 +
      }
 +
      break;
 +
fonction 5 :
 +
    case accel :
 +
    if (VmotG<=170){
 +
      VmotG = VmotG+10;
 +
      VmotD = VmotD-10;
 +
      ServoG.write(VmotG);
 +
      ServoD.write(VmotD);
 +
      }
 +
      break;
 +
fonction 4 :
 +
      case decel :
 +
      if (VmotG>=10){
 +
        VmotG = VmotG-10;
 +
        VmotD = VmotD+10;
 +
        ServoG.write(VmotG);
 +
        ServoD.write(VmotD);
 +
      }
 +
      break;
 +
    }
 +
remise à la vitesse normale des moteurs
 +
      ServoD.write(VmotD);
 +
      ServoG.write(VmotG);
 +
      Serial.println(value,HEX); // you can comment this line
 +
      irrecv.resume(); // Receive the next value
 +
    }
 +
  }
 +
 +
[[Fichier:montage_ir_cmd.jpg|vignette|center| Montage de la commande infrarouge du robot ]]
 +
 +
 +
On peut observer ici le bon fonctionnement des commandes.
 +
NB : dans cette vidéo le commentaire tourner à gauche et tourner à droite est inversé.
 +
[https://www.youtube.com/watch?v=1-5X6hwA0i0&feature=youtu.be| Tests des commandes sans régulation du robot.]
 +
 +
====Partie électronique====
 +
J'ai finalement pu réaliser l'impression de mon PCB cette semaine. Ce PCB est nécessaire à la réalisation de mon prototype2(PIP2) afin de pouvoir satisfaire aux exigences demandées au début de ce projet.
 +
[[Fichier:cartenue.jpg|vignette|center|Carte une fois tirée]]
 +
Suite à cela, j'ai soudé les composants CMS ainsi que les traversants les deux jours qui ont suivi.
 +
[[Fichier:cartesoude.jpg|vignette|center|Carte soudée]]
 +
 +
 +
Malheureusement, une grande partie du PCB était en court circuit. De plus certaines pistes semblaient avoir sauté lors de l'impression du PCB. Il m'a donc fallu un temps considérable pour corriger ces erreurs.
 +
Les différentes méthodes de réparation sont les suivantes :
 +
*Pour les pistes non soudées, il suffit de faire un pont (au top du circuit afin de ne pas écraser le pont une fois placé) à l'aide de fil de cuivre soudé entre les deux extrémités de la piste coupée.
 +
*Détermination des courts circuits :
 +
**1.Pour déterminer un court circuit, le mieux est de regarder à l'aide du mode "diode" du multimètre. En comparant par exemple la masse avec les autres pistes, on peut alors voir où se situent les problèmes. Pour ma part, le court circuit se trouvait sur la piste du 5V ainsi que d'autres pins de l'ATmega.
 +
**2. Une fois que les pistes en court circuit sont déterminées, on étudie à l’œil les soudures potentiellement mauvaises. Il faut ensuite les corriger à l'aide de tresse à dessouder ou du fer en passant celui ci dans la gravure qui entoure la zone à de soudure.
 +
**3. Si cela ne suffit toujours pas, on étudie le PCB sous altium ou un autre logiciel afin de voir quelles vias retirer pour tester la présence ou non de courts circuits. Si aucune vias n'est présente sur la zone, on coupe la piste à l'aide d'un cutter. On peut alors tester les pistes afin de réduire les possibilités à un composant. Avec moins de chance, on voit que le court circuit est situé sur un composant en CMS qu'il faut alors déssouder et replacer.
 +
**4. Pour retirer et replacer le composant, il suffit de faire chauffer les soudures et de retirer le composant rapidement. Ensuite, on utilise la tresse à déssouder pour nettoyer les pistes. On replace ensuite le composant à l'endroit où il doit être, on le maintient en position avec un tournevis par exemple et on ressoude d'un coté avec l'étain encore présent sur la piste afin de le bloquer sur sa position. On ajoute ensuite un peu d'étain sur les côtés du composant et on vérifie que le court circuit a disparu.
 +
**5 Cas spécial, j'avais ma clock à la masse. Pour la désouder, on ne peut pas retirer de force le composant en le chauffant sur les côtés car la masse est un très bon dissipateur thermique. Si on tire de force dessus on peut très bien arracher la piste en dessous. Il faut donc pour cela mettre de l'étain au niveau de chaque patte du composant pour faciliter la chauffe des soudures sous le composant. On peut ensuite le retirer et procéder à la soudure du composant.
 +
On obtient alors un résultat peut propre mais fonctionnel à modifier dans les prochaines conceptions.
 +
A noter qu'il y a une erreur dans les connexions du PCB actuel. Il suffit de un ou deux récepteurs IR pour le robot et il faut les placer sur une pin digitale et non analogique si on veut pouvoir récupérer les codes de la télécommande. J'ai donc du couper une piste et faire un pont entre la pin de sortie du récepteur IR et la pin digitale de l'ATMEGA.
 +
 +
====Bootloader et téléversement du programme====
 +
j'ai réalisé le bootloader à l'aide d'une ATMEGA328P sur funduino et du schéma suivant :
 +
[[Fichier:Bootloadamega.jpg|vignette|center|Schéma d'interfaçage entre l'atmega externe et celle du PCB]]
 +
 +
Pour la partie téléversement, il faut connecter les pins suivantes :
 +
*gnd-->gnd
 +
*V-->5V
 +
*tx-->rx
 +
*rx-->tx
 +
*reset-->reset
 +
[[Fichier:Televers.png|vignette|center|Téléversement sur l'ATMEGA du PCB]]
 +
Pour se faire, le plus simple est de prévoir des pattes pour ces pins sur le PCB pour faciliter les connexions notamment pour le téléversement des données qui nécessite de se connecter souvent.
 +
 +
==Semaine 13==
 +
 +
Lors de cette semaine, je me suis occupé de terminer le robot ainsi que la connexion entre le PCB et le gyroscope.
 +
Le programme sans régulation a fonctionné sur le PCB. Néanmoins, avant de le faire fonctionner il semblait ne pas démarrer lorsque le PCB était alimenté par la pile. En utilisant l'alimentation de la funduino par contre, on remarque que le programme fonctionne bien. Avant de changer de batterie, j'ai d'abord regardé si les fils pour l'alimentation étaient encore bons et je les ai donc changés pour vérifier s'il étaient ou oui ou non suffisants pour faire passer le courant nécessaire au système. Après avoir vu que ce n'était pas le cas, j'ai changé la batterie qui était bien en cause ici. De plus, la led me servant de protection pour l'alimentation baissait trop le courant. J'ai donc du la retirer et faire un pont.
 +
 +
Il reste encore à tester le programme avec régulation sur le robot.
 +
Pour cette régulation, nous allons nous intéresser à l'axe selon lequel notre robot est orienté. Si l'on va tout droit, on garde la donnée d'angle enregistrée au début du programme et on la compare ensuite constamment à notre position réelle afin que le robot respecte bien la trajectoire prescrite. Pour récupérer cette valeur d'angle on se sert d'un gyroscope MPU6050 qui renvoie les données sous forme de vitesse angulaire et d'accélération. Ici, la valeur qui nous intéresse est la valeur d'angle selon l'axe z (hauteur).
 +
[[Fichier:angle.png]]
 +
*La commande est donc ajoutée dans le code. On sauvegarde notre valeur d'angle en mise en route du robot grâce au bouton ON/OFF et on modifie cette valeur uniquement lors des appuis bouton gauche/droite. Si l'un de ces deux boutons est pressé, on modifie alors la valeur de commande de + ou - 10°. Par la suite, la valeur de vitesse des moteurs prend en compte la différence entre consigne et valeur réelle pour ajuster la répartition de puissance des moteurs. Si l'angle observé est plus faible que l'angle de consigne, on décélère la roue gauche et on accélère la roue droite. Dans le cas inverse, on fait l'inverse.
 +
*Pour ce qui est du gyroscope, les données sont reçues et stockées dans un buffer FIFO.
 +
Le code modifié (sans la partie traitement des données du MPU) est le suivant :
 +
  if (irrecv.decode(&results)) {
 +
    unsigned int value = results.value;
 +
    switch(value) {
 +
on prend ici la valeur actuelle de l'angle theta0
 +
 +
    case ONOFF :
 +
    if (isON == 0){
 +
    isON = 1;
 +
    ServoG.write(VmotG); //
 +
    ServoD.write(VmotD);
 +
    direc=ypr[0]*180.0/M_PI;
 +
    }
 +
    else {
 +
      isON = 0;
 +
      VmotG=90;
 +
      VmotD=90;
 +
      ServoG.write(VmotG); //
 +
      ServoD.write(VmotD);
 +
    }
 +
    break;
 +
 +
On va ici modifier nos valeurs de consigne 
 +
    case codeD :
 +
      if(isON==1){
 +
      direc+=10;
 +
      }
 +
   
 +
    break;
 +
 +
    case codeG :
 +
      if(isON==1){
 +
      direc-=10;
 +
      }
 +
   
 +
    break;
 +
 +
    case accel :
 +
    if (VmotG<=170 && isON==1){
 +
      VmotG = VmotG+10;
 +
      VmotD = VmotD-10;
 +
      ServoG.write(VmotG);
 +
      ServoD.write(VmotD);
 +
      }
 +
   
 +
    break;
 +
 +
      case decel :
 +
      if (VmotG>=10 && isON==1){
 +
        VmotG = VmotG-10;
 +
        VmotD = VmotD+10;
 +
        ServoG.write(VmotG);
 +
        ServoD.write(VmotD);
 +
        }
 +
     
 +
  break;
 +
  }   
 +
  Serial.println(value,HEX);
 +
  irrecv.resume();
 +
  }
 +
on applique ici les modifications de trajectoire en fonction de l'angle actuel et de la consigne. On ajoute un coefficient de telle sorte que la valeur appliquée au servomoteur soit comprise entre 0 et 180 degrés. Ce coefficient est équivalent à un gain proportionnel d'un PID et a pour valeur 1/36.
 +
 +
  if(isON==1){
 +
  ServoG.write(VmotG + (direc-ypr[0]*180.0/M_PI)/36);
 +
  ServoD.write(VmotD + (direc-ypr[0]*180.0/M_PI)/36);
 +
  Serial.println(VmotD);
 +
  Serial.println(VmotG);
 +
  }
 +
 +
 +
Pour ce qui est de la partie traitement des données envoyées par le gyroscope, le principe est simple : Le gyroscope communique par interruption avec l'ATMEGA, il envoie un bus de données de 42 bytes à chaque interruptions. On vérifie tout d'abord que le message est complet puis on le stock dans un buffer FIFO (first in first out) qui stocke les données en attente de traitement par l'ATMEGA. Le programme n'est pas trop important donc chaque boucle est rapide à s’exécuter de sorte que le retard entre l'acquisition de la donnée et la lecture de cette même donnée est assez faible. Dans le cas contraire, on pourrait observer un retard dans la régulation du robot. L'intérêt d'avoir un buffer de capacité assez faible est que l'on va limiter ce retard en stockant la valeur envoyée par le gyroscope seulement si le buffer n'est pas plein. Cela va nous faire perdre des données mais limiter le retard entre acquisition et lecture. Ce genre de problème est moins visible en régulation de position qu'en balancement car le système en balancement est plus instable que le système sans balancement(à l'arrêt, le pendule inversé est en position d'équilibre instable alors que sans le système de balancement, le système est à un point d'équilibre stable grâce à la roue folle et la cale.). Si l'instabilité est plus importante, la qualité des données capteurs est elle aussi plus importante tout comme son actualisation. Le code est présent en annexe dans le fichier arduino "avec régulation"
 +
*On peut voir sur cette vidéo que le robot est bien fonctionnel et régule bien en position : [[Média:Test angle.mp4]]
 +
 +
==Correctifs de soutenance==
 +
 +
Je vais ici essayer de mieux répondre aux questions posés lors de la soutenance.
 +
 +
*1. Le robot est sur deux étages alors que nous sommes censés réduire son centre de gravité car au départ de la conception je prévoyais d'utiliser les capteurs de souris sous le robot en plus du gyroscope ce qui aurait bien abaissé le centre de gravité. Le PCB est situé en haut car son poids reste faible et le gyroscope présent sur le PCB aura des valeurs plus précises lors de l'auto balancement car en hauteur les variations de valeurs de vitesse angulaire ainsi que d'accélération sont plus facilement observables. De plus, avoir deux étages permet de se rapprocher des équations d'un pendule inversé ce qui permet d'avoir un modèle du système que l'on peut réguler par la suite en s'appuyant sur ces mêmes équations. Comme l'auto balancement ainsi que les capteurs de souris n'ont pas été utilisés, la conception est donc moins optimisée pour le prototype actuel.
 +
*2. Si l'on arrive à sauvegarder les valeurs du gyroscope en boucle ouverte ainsi que les valeurs de vitesse angulaires envoyées aux moteurs, il possible lorsque l'on ne régule pas le robot c'est à dire lorsque le système est en boucle ouverte, d'utiliser la toolbox de matlab "System identification" qui récupère les valeurs d'entrée du système ainsi que ses valeurs de sortie pour déterminer une valeur approchée des composantes du système selon un modèle mathématique préalablement sélectionné.
 +
*3. Le choix de ne pas utiliser les capteurs de souris plus faciles à mettre en place et plus fiables que le gyroscope est dû au fait de l'une des évolutions possibles du système c'est à dire son auto balancement. Les souris n'apportent pas d'information sur l'orientation du robot à l'instar du gyroscope. Les souris auraient donc étaient utilisées dans le but d'affiner la valeur d'orientation du robot en position en les recoupant aux valeurs obtenues par le gyroscope.
  
 
==Références==
 
==Références==
Ligne 204 : Ligne 698 :
 
*[https://www.youtube.com/watch?v=9W5S5nqRegU/ exemple de robot à bascule]
 
*[https://www.youtube.com/watch?v=9W5S5nqRegU/ exemple de robot à bascule]
 
*[http://www8.cs.umu.se/research/ifor/dl/Optical%20flow/IJCAS_v2_n4_pp485-493.pdf Lee, S., Song, J.-B.: Mobile Robot Localization Using Optical Flow Sensors.]
 
*[http://www8.cs.umu.se/research/ifor/dl/Optical%20flow/IJCAS_v2_n4_pp485-493.pdf Lee, S., Song, J.-B.: Mobile Robot Localization Using Optical Flow Sensors.]
 +
 +
 +
 +
==Documents rendus==
 +
 +
Rapport : [[Fichier:Rapport de projet IMA4bid.pdf]]
 +
 +
Diapo de soutenance : [[Fichier:PresentationIMA4bis.pdf]]
 +
 +
Fichier Altium du robot : [[Fichier:Fichier Altium.zip]]
 +
 +
Code du robot : [[Fichier:Fichier Arduino.zip]]
 +
 +
[https://youtu.be/7hSTty0voA0 Vidéo de présentation du projet 720p]
 +
 +
Vidéo basse qualité : [[Media:Video_de_presentationP3.mp4]]
  
 
=Documents Rendus=
 
=Documents Rendus=

Version actuelle datée du 18 janvier 2019 à 11:52



Présentation générale

Nom du projet : Robot régulé Hugo Delbroucq Encadrants : M. Redon ; M.Boé ; M. Vantroys

Description

Le projet consiste à construire un petit robot en s'appuyant sur les projets déjà réalisés sur ce thème et à réguler ses déplacements afin d'avoir des trajectoires sans erreur par rapport à la consigne. De plus, le projet aura pour ambition la réalisation d'un robot pouvant se relever d'une position d'attente et de rester en équilibre en position "debout". Cette partie s’appuiera sur des recherches faites sur le sujet dans un article concernant les robots à bascule sous arduino. La commande se fera tout d'abord à l'aide d'une télécommande infra rouge dans un premier temps puis si le temps le permet à l'aide d'un module bluetooth et d'une application.

Objectifs

Les objectifs vont être :

  • d'améliorer la conception des circuits existants déjà sur le sujet.
  • réaliser la commande à l'aide d'une télécommande infrarouge puis à l'aide d'une application android si le temps le permet.
  • Régulation :
    • régulation des roues afin de suivre la consigne sans erreur ni oscillation.
    • régulation du bras balancier afin de conserver le robot proche de son point d'équilibre instable (position debout).

Préparation du projet

Cahier des charges

1) Actions

Le robot doit pouvoir assurer les commandes suivantes :

  • faire une marche avant rectiligne
  • faire une marche arrière rectiligne
  • réaliser des virages d'un angle donné
  • rester en équilibre lors de la durée du fonctionnement

2) Environnement

  • le sol doit être lisse
  • le sol doit avoir une inclinaison maximale de 1%
  • l'environnement doit être sans vent

3) Alimentation

L'alimentation se fera à l'aide d'une pile reliée à un interrupteur

Choix techniques : matériel et logiciel

Les différents composants CMS seront de préférence de taille 0603 (1608 metric). Matériel :

  • 1*Gyroscope et accéléromètre MPU6050 [1]
  • 2*Roue [2]
  • 2*Capteur de souris optique
  • 1*ATMEGA328PU [3]
  • 1*Régulateur de tension 9-5V [4]
  • 1 Régulateur de tension 9-3.3V [5]
  • 12*Condensateur 100nF [6]
  • 2*Condensateur 10uF [7]
  • 1*Condensateur 2.2nF [8]
  • 1*Condensateur 10nF [9]
  • 2*Condensateur 22pF [10]
  • 1*Rectifier Diode [11]
  • 2*Servomoteur [12]
  • 1*émetteur infrarouge [13]
  • 2*Résistance 1kΩ [14]
  • 2*Résistance 4.7kΩ [15]
  • 8*Résistance 220Ω [16]
  • 1*Résistance 330Ω [17]
  • 3*Résistance 10kΩ [18]
  • 1*Résistance 1MΩ [19]
  • 1*Résistance 470Ω [20]
  • 3*Résistance 56Ω [21]
  • 1*Appuie Bouton [22]
  • 1*Quartz [23]
  • 3*Récepteur infrarouge [24]
  • 3*Pile 9V [25]

Liste des tâches à effectuer

  • Lister le matériel
  • faire les différents circuits imprimés du robot
  • traiter les données du gyroscope
  • traiter les données du capteur de souris laser
  • réaliser un premier prototype avec la régulation en position
  • mettre en place la commande par télécommande infrarouge
  • réaliser le montage avec le bras à bascule
  • équilibrer le robot
  • faire une application android et la connexion bluetooth (penser à l'intégrer au système)

Calendrier prévisionnel

Diagramme de Gantt

Réalisation du Projet

Feuille d'heures

Tâche Heures S1 Heures S2 Heures S3 Heures S4 Heures S5 Heures S6 Heures S7 Heures S8 Heures S9 Heures S10 Heures S11 Heures S12 Heures S13 Total
Analyse du projet 12 12 16 12 12 12 8 16 16 30 30 40 30 236

Semaine 1

Régulation

Contrairement à la régulation des roues afin de conserver le robot en équilibre comme on peut le voir ici, il va nous falloir utiliser un bras afin d'avoir deux types de régulation indépendantes :

    • une pour les roues : la position
    • la seconde pour un bras transversale : l'équilibre
La première des choses à effectuer va être la régulation de la position. On utilisera un bras et une roue folle afin d'avoir un appui temporaire. Par la suite, on pourra installer un bras transversal et sa régulation par la suite en pensant la construction du châssis en fonction ou bien ajouter la régulation directement sur les roues afin de simplifier le montage. Les capteurs utilisés seront :
  • Deux capteurs de type souris optique placé sous le robot pour contrôler la position
  • Un gyroscope GY71 MPU5060 6 axes afin de réguler l'équilibre du robot

Semaine 2 et 3

Orientation et polarité des axes

La semaine deux m'a permis de confirmer mes choix de capteurs pour le robot qui seront les suivants :

  • un gyroscope MPU6050 qui permet d'obtenir des informations en accélération linéaire et en vitesse de rotation pour le robot. Ce capteur est très souvent bruité, il faudra donc réaliser un filtrage du bruit avant de pouvoir analyser les données envoyées par un bus I2C compatible avec arduino. D'après la fiche constructeur, on a les données suivantes :
    • Sa tension d'alimentation est comprise entre 2.375V et 3.45V
    • Il utilise le bus I2C
    • Il est constitué d'un accéléromètre 3 axes ET d'un gyroscope 3 axes
    • Il utilise les interruptions
    • Le gyroscope a une précision allant jusqu'à ±2000°/sec
    • Le gyroscope a une consommation nominale de 3.6mA
    • L'accéléromètre a une précision allant jusqu'à ±16g

Ces données sont envoyées de la manière suivante :

AcX = 117 AcY = 4624 AcZ = -14732 Temperature = 20.34 GyX = 15.49 GyY = 17.43 GyZ = 0.01

Les valeurs qui nous intéresserons particulièrement sont GyY (pour l'équilibrage du robot), AcX et AcY pour confirmer la vitesse du robot. Si le MPU6050 renvoie des données de bonnes qualité on pourra aussi faire un contrôle de l'orientaiton du robot via GyZ.

  • Ce capteur pouvant être plus ou moins bruité, il nous faut un autre capteur pour s'assurer de la fiabilité des résultats fournis par les capteurs. Nous allons donc ajouter deux capteurs de souris optique usb qui vont nous permettre de connaitre la position de notre robot en fonction de deux axes. Cette méthode est assez répandu du fait de sa précision et de sa mise en oeuvre peut coûteuse. Afin de faciliter le traitement des données et éviter les mauvaises surprises, nous allons prendre 2 souris identiques.

L'idéal serait de prendre des souris avec des connecteurs ps2 car fonctionnent mieux sous arduino mais les seules souris optiques disponibles étaient avec connectique usb. Le D+ et le D- renvoient les mêmes états inversés afin d'avoir une comparaison et d'éliminer le bruit qui pourrait gêner la communication.

Fonctionnement des différents types de souris

Type de capteur:

  • Le type de capteur

Il existe 3 types de souris composées de capteurs différents qui assurent le bon fonctionnement des souris :

    • 1. La souris mécanique contient une boule de contact reliée à des rouleaux qui assurent l'odométrie de la souris. Ce système a pour avantage d'être utilisable sur différents types de surfaces tant que la boule de contact est en contact avec le support.
    • 2. La souris optique qui elle possède une petite caméra et d'un système de traitement d'image qui permet d'analyser les variations de nuance de la surface éclairé par la led de la souris. En analysant ainsi les variations de nuances, il est possible de reconstituer le déplacement de la souris. Le mieux est de positionner la souris à quelques millimètres du sol.
    • 3. La souris laser qui possède le même type de caméra qui analyse la surface sur laquelle la souris repose à ceci prêt que la source lumineuse est une source laser. Cette souris permet une meilleure précision et une plus grande adaptabilité aux surfaces. La souris peut être positionnée plus éloignée du sol ce qui présente plusieurs avantages.


  • Son type de connexion
    • 1. Connectique PS2 : C'est l'une des plus anciennes connectiques de souris, et l'une des plus facile à lire. Il existe en effet de multiples tutoriels montrant comment lire ces données.
    • 2. Connectique USB : l'USB est particulièrement embêtant à lire en brut. Mais certaines souris anciennes réalisent en fait une conversion PS2-->USB en interne. On peut donc récupérer des données en se reliant aux pins qui gèrent le transport de données sous PS2.
    • 3. Souris sans fil : Ce type de connecteur ne nous intéresse pas car demande trop de ports pour être lu (deux fiches usb et j'en passe).


En poursuivant mes recherches, j'ai pu découvrir des possibilités d'application très intéressantes. Notamment le fait qu'il suffit de changer la focale de la lentille afin de régler la hauteur à laquelle nous positionnons le capteur pour rendre ce test efficace pour différentes positions. On découvre cette méthode dans l'article suivant qui propose l'utilisation d'une lentille afocale afin de réduire les erreurs obtenues par la position selon l'axe Z du capteur. Cet autre article explique comment "hacker" sa souris. L'avantage de l'utilisation d'une souris comme capteur odométrique est aussi exposé dans cet autre article de la NASA qui explique notamment l'alternative aux systèmes de capteurs s'inspirant de la vision des insectes pour se repérer depuis un drone volant par l'utilisation de capteurs de souris qui ont pour avantage de permettre une réduction du coût, poids embarqué, l'énergie utilisée et de la simplicité avec laquelle on peut en ajouter et placer en parallèle. Mots clés optimaux : optical flow navigation mouse

  • Pour la commande du robot, nous utiliserons une petite manette infrarouge programmable qui devra réaliser les fonctions suivantes :
    • Un bouton pour accélérer par palier
    • Un bouton pour décélérer par palier
    • Un bouton ON/OFF
    • Un bouton pour tourner à gauche
    • Un bouton pour tourner à droite

Après réflexion, la partie "pendule inversé" se réalisera par contrôle direct sur les roues couplé à la commande déjà existante sur la position du robot. Cela afin d'éviter d'ajouter des parties en plus au robot en cours de réalisation

Il m'a fallu ensuite me décider sur le dimensionnement des composants à prendre pour la réalisation du circuit. En m'appuyant sur les anciens projets réalisés sur ce robot ainsi que la datasheet des composants que j'ai pris qui différent des anciens projets ( régulateur de tension, gyroscope et capteur optique), j'ai sélectionné le matériel nécessaire pour la réalisation du robot. Le matériel sélectionné est similaire au projet de be ima et au stage d'une étudiante de l'an passé si ce n'est le régulateur de tension 5V qui admet un courant supérieur en entrée. En effet, les deux servomoteurs acceptent de recevoir 2*3A donc j'ai décidé de prendre un régulateur 5V 6A afin d'optimiser la puissance reçue par les moteurs.

Semaine 4, 5 et 6

Schéma de fonctionnement

Les semaines suivantes concernent la création du PCB. J'ai tout d'abords fais l'erreur de réaliser un schéma sous draw.io ce qui m'a fait perdre du temps sur le début de la semaine puis je suis passé directement sur altium afin de réaliser le schéma de mon circuit. La stratégie adoptée ici est de reprendre les footprints déjà existants sur internet afin de simplifier la tâche puis de vérifier que les données simulées sous Altium correspondent bien à nos composants. J'ai ensuite passé une grande partie de mon temps à trouver les bonnes datasheets dans le but de trouver les schémas de montage associés aux composants utilisés dans la réalisation du robot.

Le schéma de l'ATMEGA utilisé est le suivant :
Schéma de l'ATMEGA238P-AU

Ce schéma a pour avantage de mettre en relation les pins de l'ATMEGA avec les pins de la funduino ce qui facilite l'interconnexion notamment lors du bootloader ou du téléversement des données ainsi que pour la programmation du uP.


Les schémas actuels sont les suivants : Schematic du projet en cours

Semaine 7

La semaine 7 est celle des vacances, j'en ai profité pour mettre à jour le wiki ainsi que commencer des petits test sur les récepteurs infrarouges.

Semaine 8 et 9

J'ai poursuivis la réalisation du PCB durant ces deux dernières semaines en terminant le schématique du montage et en réalisant un premier routage de la carte. J'ai d'abord voulu essayer de router la carte en utilisant l'auto routage mais j'ai vite remarqué qu'il complexifiait plus le montage qu'autre chose. De plus, les "déchets" c'est à dire des pistes inutiles étaient présentes en plus grand nombre. J'ai donc tout repris et réalisé un routage à la main plus propre. Je suis ensuite entré en contact avec Monsieur Boé qui m'a aidé à corriger les défauts du schématique et du PCB. Il a fallu que je modifie le placement de mes composants notamment le quartz qui doit être écarté de toutes pistes si possible afin de ne pas avoir de bruitage de signal. Les capacités de découplage étaient aussi très éloignées des composants à découpler. Il m'a donc fallu poursuivre les modifications pendant les deux semaines qui ont suivi avant d'avoir un résultat fonctionnel en théorie. Pendant cette période j'ai donc travaillé sur mon PCB la journée puis une fois les fichiers Altiums corrigés, j'ai entamé la réalisation d'un premier prototype à l'aide d'une ATMEGA328p et d'une funduino. Cela m'a permit d'avancer sur la programmation du robot en prévision de la finalisation du prototype avec PCB nous pouvons voir le bon fonctionnement du robot sur le lien ci contre

Semaine 10

Réalisation du châssis

Le châssis a été réalisé sous le logiciel Onshape qui est un logiciel de CAO libre de droit. La réalisation des pièces en context permet de diminuer grandement le nombre d'erreurs de dimension et permet une réalisation plus rapide des pièces à créer. Une fois le châssis réalisé sous Onshape il ne reste plus qu'à se rendre dans les "Parts" qui nous intéressent, faire un clic droit sur la face de la pièce qui nous intéresse (attention à ne pas cliquer sur le côté de la pièce sinon on imprime l'épaisseur et non notre face) puis séléctionner Export As DXF(Attention, Onshape doit être en Inch pour l'exportation sinon des problèmes de dimension apparaissent sous Inkscape). Une fois le fichier prêt, il suffit de l'ouvrir sous Inkscape et de placer les pièces sur le support pour enfin aller découper le support.

Modèle sous Onshape
Résultat sous Inkscape
Après l'impression

J'ai ensuite poursuivi mes modifications de PCB jusqu'à le finaliser pour lancer son impression. Le résultat sous Altium est le suivant :

Routage fini du PCB sous Altium

Semaine 11

Tests du MPU6050

crédits au site [26] pour avoir proposé une méthode simple de calibration du gyroscope. Et à Luis Rodenas pour son code de calibration

Nous allons commencer par effectuer des tests sur le MPU6050 format carte.

  • La première étape est d'effectuer une calibration propre au capteur. Cette calibration est peut se trouver à l'aide du programme suivant :
 // I2Cdev and MPU6050 must be installed as libraries
 #include "I2Cdev.h"
 #include "MPU6050.h"
 #include "Wire.h"

/////////////////////////////////// CONFIGURATION /////////////////////////////

 //Change this 3 variables if you want to fine tune the skecth to your needs.
 int buffersize=1000;     //Amount of readings used to average, make it higher to get more precision but sketch will be slower  (default:1000)
 int acel_deadzone=8;     //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge  (default:8)
 int giro_deadzone=1;     //Giro error allowed, make it lower to get more precision, but sketch may not converge  (default:1)
 // default I2C address is 0x68
 // specific I2C addresses may be passed as a parameter here
 // AD0 low = 0x68 (default for InvenSense evaluation board)
 // AD0 high = 0x69
 //MPU6050 accelgyro;
 MPU6050 accelgyro(0x68); // <-- use for AD0 high
 int16_t ax, ay, az,gx, gy, gz;
 int mean_ax,mean_ay,mean_az,mean_gx,mean_gy,mean_gz,state=0;
 int ax_offset,ay_offset,az_offset,gx_offset,gy_offset,gz_offset;

/////////////////////////////////// SETUP ////////////////////////////////////

 void setup() {
 // join I2C bus (I2Cdev library doesn't do this automatically)
 Wire.begin();
 // COMMENT NEXT LINE IF YOU ARE USING ARDUINO DUE
 TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Leonardo measured 250kHz.
 // initialize serial communication
 Serial.begin(115200);
 // initialize device
 accelgyro.initialize();
 // wait for ready
 while (Serial.available() && Serial.read()); // empty buffer
 while (!Serial.available()){
   Serial.println(F("Send any character to start sketch.\n"));
   delay(1500);
 }
 while (Serial.available() && Serial.read()); // empty buffer again
 // start message
 Serial.println("\nMPU6050 Calibration Sketch");
 delay(2000);
 Serial.println("\nYour MPU6050 should be placed in horizontal position, with package letters facing up. \nDon't touch it until you see a finish message.\n");
 delay(3000);
 // verify connection
 Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
 delay(1000);
 // reset offsets
 accelgyro.setXAccelOffset(0);
 accelgyro.setYAccelOffset(0);
 accelgyro.setZAccelOffset(0);
 accelgyro.setXGyroOffset(0);
 accelgyro.setYGyroOffset(0);
 accelgyro.setZGyroOffset(0);
 }

/////////////////////////////////// LOOP ////////////////////////////////////

 void loop() {
 if (state==0){
   Serial.println("\nReading sensors for first time...");
   meansensors();
   state++;
   delay(1000);
 }
 if (state==1) {
   Serial.println("\nCalculating offsets...");
   calibration();
   state++;
   delay(1000);
 }
 if (state==2) {
   meansensors();
   Serial.println("\nFINISHED!");
   Serial.print("\nSensor readings with offsets:\t");
   Serial.print(mean_ax);
   Serial.print("\t");
   Serial.print(mean_ay);
   Serial.print("\t");
   Serial.print(mean_az);
   Serial.print("\t");
   Serial.print(mean_gx);
   Serial.print("\t");
   Serial.print(mean_gy);
   Serial.print("\t");
   Serial.println(mean_gz);
   Serial.print("Your offsets:\t");
   Serial.print(ax_offset);
   Serial.print("\t");
   Serial.print(ay_offset);
   Serial.print("\t");
   Serial.print(az_offset);
   Serial.print("\t");
   Serial.print(gx_offset);
   Serial.print("\t");
   Serial.print(gy_offset);
   Serial.print("\t");
   Serial.println(gz_offset);
   Serial.println("\nData is printed as: acelX acelY acelZ giroX giroY giroZ");
   Serial.println("Check that your sensor readings are close to 0 0 16384 0 0 0");
   Serial.println("If calibration was succesful write down your offsets so you can set them in your projects using something similar to mpu.setXAccelOffset(youroffset)");
   while (1);
 }
 }

/////////////////////////////////// FUNCTIONS ////////////////////////////////////

 void meansensors(){
 long i=0,buff_ax=0,buff_ay=0,buff_az=0,buff_gx=0,buff_gy=0,buff_gz=0;
 while (i<(buffersize+101)){
   // read raw accel/gyro measurements from device
   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
   if (i>100 && i<=(buffersize+100)){ //First 100 measures are discarded
     buff_ax=buff_ax+ax;
     buff_ay=buff_ay+ay;
     buff_az=buff_az+az;
     buff_gx=buff_gx+gx;
     buff_gy=buff_gy+gy;
     buff_gz=buff_gz+gz;
   }
   if (i==(buffersize+100)){
     mean_ax=buff_ax/buffersize;
     mean_ay=buff_ay/buffersize;
     mean_az=buff_az/buffersize;
     mean_gx=buff_gx/buffersize;
     mean_gy=buff_gy/buffersize;
     mean_gz=buff_gz/buffersize;
   }
   i++;
   delay(2); //Needed so we don't get repeated measures
 }
 }
 void calibration(){
 ax_offset=-mean_ax/8;
 ay_offset=-mean_ay/8;
 az_offset=(16384-mean_az)/8;
 gx_offset=-mean_gx/4;
 gy_offset=-mean_gy/4;
 gz_offset=-mean_gz/4;
 while (1){
   int ready=0;
   accelgyro.setXAccelOffset(ax_offset);
   accelgyro.setYAccelOffset(ay_offset);
   accelgyro.setZAccelOffset(az_offset);
   accelgyro.setXGyroOffset(gx_offset);
   accelgyro.setYGyroOffset(gy_offset);
   accelgyro.setZGyroOffset(gz_offset);
   meansensors();
   Serial.println("...");
   if (abs(mean_ax)<=acel_deadzone) ready++;
   else ax_offset=ax_offset-mean_ax/acel_deadzone;
   if (abs(mean_ay)<=acel_deadzone) ready++;
   else ay_offset=ay_offset-mean_ay/acel_deadzone;
   if (abs(16384-mean_az)<=acel_deadzone) ready++;
   else az_offset=az_offset+(16384-mean_az)/acel_deadzone;
   if (abs(mean_gx)<=giro_deadzone) ready++;
   else gx_offset=gx_offset-mean_gx/(giro_deadzone+1);
   if (abs(mean_gy)<=giro_deadzone) ready++;
   else gy_offset=gy_offset-mean_gy/(giro_deadzone+1);
   if (abs(mean_gz)<=giro_deadzone) ready++;
   else gz_offset=gz_offset-mean_gz/(giro_deadzone+1);
   if (ready==6) break;
 }
}

Ce code a pour objectif de lire les 100 premières données brutes avec un pas de temps de 2ms en sortie du gyroscope afin de trouver une valeur d'état initial moyenne. On vérifie ensuite que ces données ne sont pas trop éloignées les unes des autres puis on créer l'offset adéquat à notre capteur. Il faut effectuer cette calibration pour chaque nouveau capteur car chacun va différer.

Calibration du gyroscope à l'aide d'un niveau

Les résultat obtenus pour le gyroscope sous forme de carte sont les suivants :

AcX = 526 AcY = -467 AcZ = 1722 GyX = 99 GyY = 14 GyZ = -3

Semaine 12

Réglage des servo moteurs

Nous allons maintenant nous intéresser aux servomoteurs. Il faut, dans un premier temps les calibrer à l'aide de la vis à l'arrière des servomoteurs. Pour les tester, il suffit d'exécuter le programme suivant :

 #include "Servo.h"
 Servo myservo;
 void setup(){
   myservo.attach(9);
   myservo.write(90);
 }
 void loop(){
 }

Les valeurs de commande des moteurs vont de 0 (avancer dans le sens des aiguilles d'une montre) à 180 (avancer dans le sens inverse des aiguilles d'une montre). En fixant cette valeur à 90, cela signifie que le moteur est à l'arrêt. La roue est donc immobile et il est possible de régler la vis afin d'avoir effectivement un arrêt du moteur à 90.

Programmation des commandes du robot

En attendant que le circuit soit imprimé, j'ai réalisé la commande infrarouge des différentes fonctions du robot à l'aide de la télécommande suivante :

Télécommande du robot

Les boutons sont associés aux codes et fonctions suivantes :

    • 1 : 0xA25D associé au bouton ON/OFF du système IR
    • 2 : 0x02FD associé au bouton tourner à gauche de 10°
    • 3 : 0xC23D associé au bouton tourner à droite de 10°
    • 4 : 0xA857 associé au bouton décélérer de 10 (vitesse va de 0 à 90 en absolue)
    • 5 : 0x906F associé au bouton accélérer de 10 (vitesse va de 0 à 90 en absolue)


Le code pour réaliser les différentes actions est le suivant :

 #include <IRremote.h>
 #include <Servo.h>
 int RECV_PIN = 2;
 int outputmotG = 9; //cmd moteur gauche
 int outputmotD = 10; //cmd moteur droite)
 int VmotG = 90;
 int VmotD = 90;
 int isON = 0;
 Servo ServoG;
 Servo ServoD;
 #define codeG  0x2FD //aller à gauche
 #define codeD  0xC23D// aller à droite
 #define ONOFF  0xA25D //ONOFF button
 #define accel 0x906F //acceleration par palier
 #define decel 0xA857 //décélération par palier
 IRrecv irrecv(RECV_PIN);
 decode_results results;
 void setup()
 {
   Serial.begin(9600);
   irrecv.enableIRIn(); // Start the receiver
   pinMode(outputmotG,OUTPUT);
   pinMode(outputmotD,OUTPUT);
   ServoG.attach(9);
   ServoD.attach(10);
   ServoG.write(VmotG); //
   ServoD.write(VmotD);
 } 


 void loop(){
   if (irrecv.decode(&results)) {
     unsigned int value = results.value;
     switch(value) {

fonction 1 :

     case ONOFF :
     if (isON == 0){
     isON = 1;
     ServoG.write(VmotG); //
     ServoD.write(VmotD);} 
     else {
       isON = 0;
       VmotG=90;
       VmotD=90;
     }
     break;

fonction 3 :

    case codeD :
     if(isON == 1) { //
       ServoD.write(VmotD*19.0/18);
       ServoG.write(VmotG*19.0/18); //
       delay(1000);
     }
     break;

fonction 2 :

     case codeG :
     if(isON == 1) { //
       ServoG.write(VmotG*17.0/18);
       ServoD.write(VmotD*17.0/18); 
       delay(1000);
     }
     break;

fonction 5 :

    case accel :
    if (VmotG<=170){
      VmotG = VmotG+10;
      VmotD = VmotD-10;
      ServoG.write(VmotG);
      ServoD.write(VmotD);
     }
     break;

fonction 4 :

     case decel :
     if (VmotG>=10){
       VmotG = VmotG-10;
       VmotD = VmotD+10;
       ServoG.write(VmotG);
       ServoD.write(VmotD);
     }
     break;
   }

remise à la vitesse normale des moteurs

     ServoD.write(VmotD);
     ServoG.write(VmotG);
     Serial.println(value,HEX); // you can comment this line
     irrecv.resume(); // Receive the next value
   }
 }
Montage de la commande infrarouge du robot


On peut observer ici le bon fonctionnement des commandes. NB : dans cette vidéo le commentaire tourner à gauche et tourner à droite est inversé. Tests des commandes sans régulation du robot.

Partie électronique

J'ai finalement pu réaliser l'impression de mon PCB cette semaine. Ce PCB est nécessaire à la réalisation de mon prototype2(PIP2) afin de pouvoir satisfaire aux exigences demandées au début de ce projet.

Carte une fois tirée

Suite à cela, j'ai soudé les composants CMS ainsi que les traversants les deux jours qui ont suivi.

Carte soudée


Malheureusement, une grande partie du PCB était en court circuit. De plus certaines pistes semblaient avoir sauté lors de l'impression du PCB. Il m'a donc fallu un temps considérable pour corriger ces erreurs. Les différentes méthodes de réparation sont les suivantes :

  • Pour les pistes non soudées, il suffit de faire un pont (au top du circuit afin de ne pas écraser le pont une fois placé) à l'aide de fil de cuivre soudé entre les deux extrémités de la piste coupée.
  • Détermination des courts circuits :
    • 1.Pour déterminer un court circuit, le mieux est de regarder à l'aide du mode "diode" du multimètre. En comparant par exemple la masse avec les autres pistes, on peut alors voir où se situent les problèmes. Pour ma part, le court circuit se trouvait sur la piste du 5V ainsi que d'autres pins de l'ATmega.
    • 2. Une fois que les pistes en court circuit sont déterminées, on étudie à l’œil les soudures potentiellement mauvaises. Il faut ensuite les corriger à l'aide de tresse à dessouder ou du fer en passant celui ci dans la gravure qui entoure la zone à de soudure.
    • 3. Si cela ne suffit toujours pas, on étudie le PCB sous altium ou un autre logiciel afin de voir quelles vias retirer pour tester la présence ou non de courts circuits. Si aucune vias n'est présente sur la zone, on coupe la piste à l'aide d'un cutter. On peut alors tester les pistes afin de réduire les possibilités à un composant. Avec moins de chance, on voit que le court circuit est situé sur un composant en CMS qu'il faut alors déssouder et replacer.
    • 4. Pour retirer et replacer le composant, il suffit de faire chauffer les soudures et de retirer le composant rapidement. Ensuite, on utilise la tresse à déssouder pour nettoyer les pistes. On replace ensuite le composant à l'endroit où il doit être, on le maintient en position avec un tournevis par exemple et on ressoude d'un coté avec l'étain encore présent sur la piste afin de le bloquer sur sa position. On ajoute ensuite un peu d'étain sur les côtés du composant et on vérifie que le court circuit a disparu.
    • 5 Cas spécial, j'avais ma clock à la masse. Pour la désouder, on ne peut pas retirer de force le composant en le chauffant sur les côtés car la masse est un très bon dissipateur thermique. Si on tire de force dessus on peut très bien arracher la piste en dessous. Il faut donc pour cela mettre de l'étain au niveau de chaque patte du composant pour faciliter la chauffe des soudures sous le composant. On peut ensuite le retirer et procéder à la soudure du composant.

On obtient alors un résultat peut propre mais fonctionnel à modifier dans les prochaines conceptions. A noter qu'il y a une erreur dans les connexions du PCB actuel. Il suffit de un ou deux récepteurs IR pour le robot et il faut les placer sur une pin digitale et non analogique si on veut pouvoir récupérer les codes de la télécommande. J'ai donc du couper une piste et faire un pont entre la pin de sortie du récepteur IR et la pin digitale de l'ATMEGA.

Bootloader et téléversement du programme

j'ai réalisé le bootloader à l'aide d'une ATMEGA328P sur funduino et du schéma suivant :

Schéma d'interfaçage entre l'atmega externe et celle du PCB

Pour la partie téléversement, il faut connecter les pins suivantes :

  • gnd-->gnd
  • V-->5V
  • tx-->rx
  • rx-->tx
  • reset-->reset
Téléversement sur l'ATMEGA du PCB

Pour se faire, le plus simple est de prévoir des pattes pour ces pins sur le PCB pour faciliter les connexions notamment pour le téléversement des données qui nécessite de se connecter souvent.

Semaine 13

Lors de cette semaine, je me suis occupé de terminer le robot ainsi que la connexion entre le PCB et le gyroscope. Le programme sans régulation a fonctionné sur le PCB. Néanmoins, avant de le faire fonctionner il semblait ne pas démarrer lorsque le PCB était alimenté par la pile. En utilisant l'alimentation de la funduino par contre, on remarque que le programme fonctionne bien. Avant de changer de batterie, j'ai d'abord regardé si les fils pour l'alimentation étaient encore bons et je les ai donc changés pour vérifier s'il étaient ou oui ou non suffisants pour faire passer le courant nécessaire au système. Après avoir vu que ce n'était pas le cas, j'ai changé la batterie qui était bien en cause ici. De plus, la led me servant de protection pour l'alimentation baissait trop le courant. J'ai donc du la retirer et faire un pont.

Il reste encore à tester le programme avec régulation sur le robot. Pour cette régulation, nous allons nous intéresser à l'axe selon lequel notre robot est orienté. Si l'on va tout droit, on garde la donnée d'angle enregistrée au début du programme et on la compare ensuite constamment à notre position réelle afin que le robot respecte bien la trajectoire prescrite. Pour récupérer cette valeur d'angle on se sert d'un gyroscope MPU6050 qui renvoie les données sous forme de vitesse angulaire et d'accélération. Ici, la valeur qui nous intéresse est la valeur d'angle selon l'axe z (hauteur). Angle.png

  • La commande est donc ajoutée dans le code. On sauvegarde notre valeur d'angle en mise en route du robot grâce au bouton ON/OFF et on modifie cette valeur uniquement lors des appuis bouton gauche/droite. Si l'un de ces deux boutons est pressé, on modifie alors la valeur de commande de + ou - 10°. Par la suite, la valeur de vitesse des moteurs prend en compte la différence entre consigne et valeur réelle pour ajuster la répartition de puissance des moteurs. Si l'angle observé est plus faible que l'angle de consigne, on décélère la roue gauche et on accélère la roue droite. Dans le cas inverse, on fait l'inverse.
  • Pour ce qui est du gyroscope, les données sont reçues et stockées dans un buffer FIFO.

Le code modifié (sans la partie traitement des données du MPU) est le suivant :

 if (irrecv.decode(&results)) {
   unsigned int value = results.value;
   switch(value) {

on prend ici la valeur actuelle de l'angle theta0

   case ONOFF :
   if (isON == 0){
    isON = 1;
    ServoG.write(VmotG); //
    ServoD.write(VmotD); 
    direc=ypr[0]*180.0/M_PI;
   }
   else {
     isON = 0;
     VmotG=90;
     VmotD=90;
     ServoG.write(VmotG); //
     ServoD.write(VmotD); 
   }
   break;

On va ici modifier nos valeurs de consigne

   case codeD :
     if(isON==1){
     direc+=10;
     } 
   
   break;
   case codeG :
     if(isON==1){
     direc-=10;
     }
   
   break;
   case accel :
   if (VmotG<=170 && isON==1){
     VmotG = VmotG+10;
     VmotD = VmotD-10;
     ServoG.write(VmotG);
     ServoD.write(VmotD);
     }
   
   break;
     case decel :
     if (VmotG>=10 && isON==1){
       VmotG = VmotG-10;
       VmotD = VmotD+10;
       ServoG.write(VmotG);
       ServoD.write(VmotD);
       }
     
  break;
  }     
  Serial.println(value,HEX); 
  irrecv.resume(); 
 }

on applique ici les modifications de trajectoire en fonction de l'angle actuel et de la consigne. On ajoute un coefficient de telle sorte que la valeur appliquée au servomoteur soit comprise entre 0 et 180 degrés. Ce coefficient est équivalent à un gain proportionnel d'un PID et a pour valeur 1/36.

 if(isON==1){
  ServoG.write(VmotG + (direc-ypr[0]*180.0/M_PI)/36);
  ServoD.write(VmotD + (direc-ypr[0]*180.0/M_PI)/36);
  Serial.println(VmotD);
  Serial.println(VmotG); 
 }


Pour ce qui est de la partie traitement des données envoyées par le gyroscope, le principe est simple : Le gyroscope communique par interruption avec l'ATMEGA, il envoie un bus de données de 42 bytes à chaque interruptions. On vérifie tout d'abord que le message est complet puis on le stock dans un buffer FIFO (first in first out) qui stocke les données en attente de traitement par l'ATMEGA. Le programme n'est pas trop important donc chaque boucle est rapide à s’exécuter de sorte que le retard entre l'acquisition de la donnée et la lecture de cette même donnée est assez faible. Dans le cas contraire, on pourrait observer un retard dans la régulation du robot. L'intérêt d'avoir un buffer de capacité assez faible est que l'on va limiter ce retard en stockant la valeur envoyée par le gyroscope seulement si le buffer n'est pas plein. Cela va nous faire perdre des données mais limiter le retard entre acquisition et lecture. Ce genre de problème est moins visible en régulation de position qu'en balancement car le système en balancement est plus instable que le système sans balancement(à l'arrêt, le pendule inversé est en position d'équilibre instable alors que sans le système de balancement, le système est à un point d'équilibre stable grâce à la roue folle et la cale.). Si l'instabilité est plus importante, la qualité des données capteurs est elle aussi plus importante tout comme son actualisation. Le code est présent en annexe dans le fichier arduino "avec régulation"

  • On peut voir sur cette vidéo que le robot est bien fonctionnel et régule bien en position : Média:Test angle.mp4

Correctifs de soutenance

Je vais ici essayer de mieux répondre aux questions posés lors de la soutenance.

  • 1. Le robot est sur deux étages alors que nous sommes censés réduire son centre de gravité car au départ de la conception je prévoyais d'utiliser les capteurs de souris sous le robot en plus du gyroscope ce qui aurait bien abaissé le centre de gravité. Le PCB est situé en haut car son poids reste faible et le gyroscope présent sur le PCB aura des valeurs plus précises lors de l'auto balancement car en hauteur les variations de valeurs de vitesse angulaire ainsi que d'accélération sont plus facilement observables. De plus, avoir deux étages permet de se rapprocher des équations d'un pendule inversé ce qui permet d'avoir un modèle du système que l'on peut réguler par la suite en s'appuyant sur ces mêmes équations. Comme l'auto balancement ainsi que les capteurs de souris n'ont pas été utilisés, la conception est donc moins optimisée pour le prototype actuel.
  • 2. Si l'on arrive à sauvegarder les valeurs du gyroscope en boucle ouverte ainsi que les valeurs de vitesse angulaires envoyées aux moteurs, il possible lorsque l'on ne régule pas le robot c'est à dire lorsque le système est en boucle ouverte, d'utiliser la toolbox de matlab "System identification" qui récupère les valeurs d'entrée du système ainsi que ses valeurs de sortie pour déterminer une valeur approchée des composantes du système selon un modèle mathématique préalablement sélectionné.
  • 3. Le choix de ne pas utiliser les capteurs de souris plus faciles à mettre en place et plus fiables que le gyroscope est dû au fait de l'une des évolutions possibles du système c'est à dire son auto balancement. Les souris n'apportent pas d'information sur l'orientation du robot à l'instar du gyroscope. Les souris auraient donc étaient utilisées dans le but d'affiner la valeur d'orientation du robot en position en les recoupant aux valeurs obtenues par le gyroscope.

Références


Documents rendus

Rapport : Fichier:Rapport de projet IMA4bid.pdf

Diapo de soutenance : Fichier:PresentationIMA4bis.pdf

Fichier Altium du robot : Fichier:Fichier Altium.zip

Code du robot : Fichier:Fichier Arduino.zip

Vidéo de présentation du projet 720p

Vidéo basse qualité : Media:Video_de_presentationP3.mp4

=Documents Rendus=