IMA4 2017/2018 P66 : Différence entre versions

De Wiki de Projets IMA
(Récupération des données des encodeurs)
 
(139 révisions intermédiaires par 3 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
 +
<include nopre noesc src="/home/pedago/pimasc/include/video-CoupeRobotique-iframe.html" />
 
__TOC__
 
__TOC__
 
<br style="clear: both;"/>
 
<br style="clear: both;"/>
Ligne 102 : Ligne 103 :
 
====Connaissance de l'environnement====
 
====Connaissance de l'environnement====
  
* '''2 × HEDM-550X.''' Encodeur rotatif pour l'asservissemnt.
+
* '''2 × HEDS-5500 C06.''' Encodeur rotatif pour l'asservissemnt.
  
 
* '''Capteur MinIMU-9 v3.''' Centrale intertielle utilisée en complément pour l'asservissement.
 
* '''Capteur MinIMU-9 v3.''' Centrale intertielle utilisée en complément pour l'asservissement.
Ligne 146 : Ligne 147 :
 
== Liste des tâches à effectuer ==
 
== Liste des tâches à effectuer ==
 
=== Optionnel ===
 
=== Optionnel ===
* Filtre de Kalman <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
+
* Filtre de Kalman <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
* Enlever le flag -D de avrdude <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
 
* Concevoir contrôleur moteur avec transistor de puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* Concevoir contrôleur moteur avec transistor de puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
* ⇑Buildroot 2018.02 <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
 
* Buildroot en AArch64 <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* Buildroot en AArch64 <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* Couche niveau 3 pour correction d'erreur <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="color: #333">(Geoffrey)</span>
 
* Couche niveau 3 pour correction d'erreur <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="color: #333">(Geoffrey)</span>
* Multi-ADC <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey)</span>
 
 
* Alléger noyau Linux (encore) <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* Alléger noyau Linux (encore) <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* Wi-Fi direct ? <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* Wi-Fi direct ? <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
* Faire les calculs en point fixe / entiers <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
+
* Utiliser la numérotation BCM de WiringPi <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
* Retrograder la priorité de l'UART0 <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
+
* réaliser PCB pour le FPGA avec les pins dédiés aux différens controles + des borniers pour le reste <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span>
 +
=== À faire ===
 +
=== En cours ===
 +
=== À rédiger ===
 +
=== Terminé ===
 +
* Expliquer Geoffrey IMU <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
 +
* Gérer les signaux <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* PPPoE <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* i2c sur Rpb maitre escalve <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey)</span>
 +
* ↑115200 Baud <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="color: #333">(Geoffrey)</span>
 +
* Mettre en place la liaison série Arduino ↔ FPGA <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 +
* Synchronisation de temps <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Controleur moteur via FPGA <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Contrôle des controlleurs moteurs <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Geoffrey)</span>
 +
* tester contrôleur moteur TLE 5206-2 e <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury, Geoffrey)</span>
 
* pilotage en courant des moteurs : recherches bibliographiques <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* pilotage en courant des moteurs : recherches bibliographiques <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
=== À faire ===
+
* ajouter photos wiki <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="background: black; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Mécanique</span> <span style="color: #333">(Amaury)</span>
* concevoir schematic LMt18200T <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
+
* ⇑Buildroot 2018.02 <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Référence du controleur moteur = pin de sortie du FPGA <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Geoffrey)</span>
 +
* tester contrôleur moteur LM 18200T <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury, Geoffrey)</span>
 +
* Ré-assembler le robot <span style="background: black; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Mécanique</span> <span style="color: #333">(Amaury)</span>
 +
* Analyse interference capteurs <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="color: #333">(Amaury)</span>
 +
* dessouder controleur moteur 5206 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: black; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Mécanique</span> <span style="color: #333">(Amaury)</span>
 +
* analyse interférence capteurs : recherche bibliographiques <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
 +
* Liste de matériel <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Amaury, Geoffrey)</span>
 +
* Afficheur & Boutons <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span>
 +
* IMU sur FPGA: voir si c'est judicieux <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury, Geoffrey)</span>
 +
* Hard reset LCD <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Rattrapage session Arduino <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 +
* GDB server <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Diagnostics <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* PID <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Angle indeterminé <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Journaux <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* router controleur moteur avec Lm 18200t sur eagle <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 +
* Rate limiter <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* alimentation 12v max pour bioloid : prévoir résistance si besoin de changer <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 +
* alimentation rpb 4.9 actuellement prévoir résistance pour monter à 5.5V si besoin de changer <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 +
* rédaction correction V2 Mr Flamen <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Amaury)</span>
 +
* re vérifier datasheet puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Geoffrey)</span>
 +
* réparation TLE5206 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* commande composant complément pour 5206 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* commande composant complément pour 5206 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
* router controleur moteur avec Lm 18200t sur eagle <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* tester contrôleur moteur TLE 5206-2 e <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey, Amaury)</span>
 
* tester contrôleur moteur LM 18200T <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="color: #333">(Geoffrey, Amaury)</span>
 
* PID Arduino <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* PID polaire <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* Analyse interference capteurs <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
 
* Afficheur & Boutons <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span>
 
 
* faire mail Mr Flamen pour composants complémentaires <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* faire mail Mr Flamen pour composants complémentaires <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
* IMU sous free RTOS <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
 
* Gérer les signaux <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* Calibration en position <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* re vérifier datasheet puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Geoffrey)</span>
 
* Analyser comportement HCSR04 quand pas d'echo <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span>
 
* PWM sans IDE Arduino <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
=== En cours ===
 
* Expliquer Geoffrey IMU <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
 
 
* commande matériel électronique de puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* commande matériel électronique de puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* acheter composant carte de puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* acheter composant carte de puissance <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
* Programme chef <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* analyse interférence capteurs : recherche bibliographiques <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
 
=== À rédiger ===
 
* IMU sur FPGA: voir si c'est judicieux <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey, Amaury)</span>
 
* Repenser la récupération des données des codeuses <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey)</span>
 
* Mettre en place la liaison série Arduino ↔ FPGA <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* Filtre capteurs <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey)</span>
 
 
* Améliorer le module communication <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="color: #333">(Geoffrey)</span>
 
* Améliorer le module communication <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="color: #333">(Geoffrey)</span>
=== Terminé ===
 
* Liste de matériel <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey, Amaury)</span>
 
* Rattrapage session Arduino <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* rédaction correction V2 Mr Flamen <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Amaury)</span>
 
 
* Mettre en place la liaison série Arduino ↔ Raspberry Pi <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* Mettre en place la liaison série Arduino ↔ Raspberry Pi <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* Différencier stop/brake <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* Différencier stop/brake <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
Ligne 205 : Ligne 214 :
 
* Choix techniques <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey)</span>
 
* Choix techniques <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey)</span>
 
* changer bornier 5206 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* changer bornier 5206 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
* Tester l'IMU <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey, Amaury)</span>
+
* Tester l'IMU <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury, Geoffrey)</span>
 
* concevoir V0 contrôleur moteur avec TLE 5206-2 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* concevoir V0 contrôleur moteur avec TLE 5206-2 <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="color: #333">(Amaury)</span>
 
* IMU test faisabilite sur IDE arduino <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
 
* IMU test faisabilite sur IDE arduino <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Amaury)</span>
Ligne 218 : Ligne 227 :
 
* Rectifier le modèle de FPGA <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey)</span>
 
* Rectifier le modèle de FPGA <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey)</span>
 
* Faire fonctionner Wi-Fi <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* Faire fonctionner Wi-Fi <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Repenser la récupération des données des codeuses <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey)</span>
 +
* Filtre capteurs <span style="background: purple; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">FPGA</span> <span style="background: cyan; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Capteurs</span> <span style="color: #333">(Geoffrey)</span>
 
* commande matériel contrôleur moteur <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Amaury)</span>
 
* commande matériel contrôleur moteur <span style="background: red; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Electronique</span> <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Amaury)</span>
 
* Base freeRTOS <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
 
* Base freeRTOS <span style="background: blue; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Arduino</span> <span style="color: #333">(Geoffrey)</span>
Ligne 223 : Ligne 234 :
 
* Travail prologue à documenter <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey)</span>
 
* Travail prologue à documenter <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey)</span>
 
* OS Raspberry Pi <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 
* OS Raspberry Pi <span style="background: green; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Raspberry Pi</span> <span style="color: #333">(Geoffrey)</span>
 +
* Le bon modèle des codeuses <span style="background: yellow; border-radius: 3px; color: white; text-shadow: 0 0 1px black; padding: 0 3px;">Wiki</span> <span style="color: #333">(Geoffrey)</span>
  
 
==Calendrier prévisionnel==
 
==Calendrier prévisionnel==
Ligne 231 : Ligne 243 :
  
 
{| class="wikitable"
 
{| class="wikitable"
!Tâche !! Prlg.<br/>30/10 !! Prlg.<br/>6/11 !! Prlg.<br/>13/11 !! Prlg.<br/>20/11 !! Prlg.<br/>8/1 !! S1<br/>15/1 !! S2<br/>22/1 !! S3<br/>29/1 !! S4<br/>5/2 !! S5<br/>12/2 !! S6<br/>19/2 !! Vacs.<br/>26/2 !! Total
+
!Tâche !! Prlg.<br/>30/10 !! Prlg.<br/>6/11 !! Prlg.<br/>13/11 !! Prlg.<br/>20/11 !! Prlg.<br/>8/1 !! S1<br/>15/1 !! S2<br/>22/1 !! S3<br/>29/1 !! S4<br/>5/2 !! S5<br/>12/2 !! S6<br/>19/2 !! Vacs.<br/>26/2 !! S7<br/>5/3 !! S8<br/>12/3 !! S9<br/>19/3 !! S10<br/>26/3 !! S11<br/>2/4 !! S12<br/>9/4 !! S13<br/>16/4 !! Vacs.<br/>23/4 !! Vacs.<br/>30/4 !! CdF<br/>7/5 !! Fin<br/>14/5 !! Total
 
|-
 
|-
 
| Analyse et préparation
 
| Analyse et préparation
Ligne 238 : Ligne 250 :
 
|
 
|
 
| 8
 
| 8
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 
|
 
|
 
|
 
|
Ligne 253 : Ligne 276 :
 
| 1
 
| 1
 
| 0.5
 
| 0.5
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 
|
 
|
 
|
 
|
Ligne 275 : Ligne 309 :
 
| 1.5
 
| 1.5
 
| 3
 
| 3
| 3
+
| 6
| <strong>21.5</strong>
+
| 1.5
 +
| 1
 +
| 2
 +
| 4
 +
| 2
 +
| 4
 +
| 4
 +
|
 +
|
 +
|
 +
| 8
 +
| <strong>51</strong>
 
|-
 
|-
 
| Système Raspberry Pi
 
| Système Raspberry Pi
Ligne 291 : Ligne 336 :
 
|
 
|
 
|
 
|
| <strong>10</strong>
+
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 3
 +
|
 +
|
 +
|
 +
| <strong>13</strong>
 
|-
 
|-
| Routage contrôleur moteur
+
| Élaboration contrôleur moteur
 
| 3
 
| 3
 
|
 
|
Ligne 306 : Ligne 362 :
 
|
 
|
 
|
 
|
| <strong>18</strong>
+
| 4
 +
| 11
 +
| 3
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| <strong>36</strong>
 
|-
 
|-
| Routage carte de puissance
+
| Élaboration carte de puissance
 
|
 
|
 
|
 
|
Ligne 321 : Ligne 388 :
 
| 4
 
| 4
 
|
 
|
| <strong>12</strong>
+
|
 +
| 4
 +
|
 +
| 2
 +
|
 +
|
 +
|
 +
| 3
 +
| 4
 +
|
 +
|
 +
| <strong>25</strong>
 
|-
 
|-
 
| Autre
 
| Autre
Ligne 331 : Ligne 409 :
 
|
 
|
 
| 0.5
 
| 0.5
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 
|
 
|
 
|
 
|
Ligne 338 : Ligne 427 :
 
| <strong>0.5</strong>
 
| <strong>0.5</strong>
 
|-
 
|-
| Analyse et implémentation des capteurs
+
| Essai d'exploitation de l'IMU
 
 
 
|
 
|
 
|
 
|
Ligne 352 : Ligne 440 :
 
| 1
 
| 1
 
|
 
|
| <strong>7.5</strong>
+
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 2
 +
| 2
 +
|
 +
|
 +
| <strong>11.5</strong>
 
|-
 
|-
 
| Nettoyage & Consolidation
 
| Nettoyage & Consolidation
Ligne 366 : Ligne 465 :
 
|
 
|
 
|
 
|
 +
| 3
 
|
 
|
| <strong>3</strong>
+
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 2
 +
|
 +
| 1
 +
| <strong>9</strong>
 
|-
 
|-
 
| Communication entre les appareils
 
| Communication entre les appareils
Ligne 381 : Ligne 491 :
 
| 22
 
| 22
 
| 8
 
| 8
| 17
+
| 16
| <strong>47</strong>
+
|
 +
|
 +
|
 +
|
 +
| 0.5
 +
| 1
 +
|
 +
| 0.5
 +
|
 +
|
 +
|
 +
| <strong>48</strong>
 
|-
 
|-
 
| Analyse et implémentation des capteurs
 
| Analyse et implémentation des capteurs
Ligne 397 : Ligne 518 :
 
| 1.5
 
| 1.5
 
|
 
|
| <strong>1.5</strong>
+
|
 +
|
 +
|
 +
|
 +
| 3
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| <strong>4.5</strong>
 +
|-
 +
| Vérification de l'implémentation
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 4
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| <strong>4</strong>
 +
|-
 +
| Simulation
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 6.5
 +
| 4.5
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| <strong>11</strong>
 +
|-
 +
| Rédaction rapport
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 1
 +
| 5
 +
| 5
 +
| 7
 +
| 17
 +
| <strong>35</strong>
 +
|-
 +
| Assemblage et cablage du robot
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 1
 +
|
 +
| 2
 +
|
 +
|
 +
| 1
 +
|
 +
| 2
 +
|
 +
|
 +
|
 +
| 6
 +
| 3
 +
| 7
 +
|
 +
| <strong>22</strong>
 +
|-
 +
| Contrôle en position
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 2
 +
| 2
 +
|
 +
|
 +
| 6
 +
| 5
 +
| 5
 +
|
 +
| <strong>20</strong>
 +
|-
 +
| Contrôle utilisateur
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| 15
 +
| 8
 +
|
 +
|
 +
| <strong>23</strong>
 
|-
 
|-
 
| <strong>Total</strong>
 
| <strong>Total</strong>
Ligne 408 : Ligne 696 :
 
| <strong>13.5</strong>
 
| <strong>13.5</strong>
 
| <strong>8</strong>
 
| <strong>8</strong>
| <strong>12.5</strong>
+
| <strong>13.5</strong>
 
| <strong>31.5</strong>
 
| <strong>31.5</strong>
| <strong>17.5</strong>
+
| <strong>19.5</strong>
| <strong>20</strong>
+
| <strong>25</strong>
| <strong>138</strong>
+
| <strong>9.5</strong>
 +
| <strong>23.5</strong>
 +
| <strong>9.5</strong>
 +
| <strong>10</strong>
 +
| <strong>7.5</strong>
 +
| <strong>5</strong>
 +
| <strong>5</strong>
 +
| <strong>40.5</strong>
 +
| <strong>29</strong>
 +
| <strong>19</strong>
 +
| <strong>26</strong>
 +
| <strong>330.5</strong>
 
|}
 
|}
 
==Prologue==
 
 
===Codeuses, Arduino & FPGA===
 
 
Pour connaitre la rotation des roues du moteur pour l'asservissement, on utilise des codeuses de référence HEDM-550X.
 
Chacune de ces codeuses disposent de deux sorties tout ou rien, nommées A et B, dont la sortie en fonction de la rotation de roue évoluent comme ci-contre.
 
 
[[Fichier:IMA17-18P66-Codeuse.png|thumb|right|500px]]
 
 
Pour un tour de roue, il y aura 1024 périodes du signal.
 
On peut donc connaitre la rotation de la roue en comptant le nombre de fronts montant d'une des sorties, à condition que la roue tourne dans un sens.
 
On peut s'affranchir de cette condition et connaitre le sens de rotation de la roue, en regardant l'état de B lors d'un front montant.
 
Pour utiliser pleinement les capacités que nous propose les codeuses, on considèrera les différents fronts de chaque entrée, soit 4 fronts par périodes.
 
 
Faisons un rapide calcul.
 
Les roues de nos moteurs font 4 cm de diamètre, et rouleront à un maximum de 10 km/h, soit un maximum de 11 tours par seconde, ce qui représente un maximum de 45270 fronts par seconde (pour une roue), ou une définition de 0,06 mm.
 
 
Cela représenterait une interruption toutes les 22 µs, ce qui fait beaucoup pour un Arduino.
 
C'était ce que nous avions essayé lors de l'édition précédente de la coupe, en ne comptant que les fronts montants d'une seule sortie, le sens étant récupéré d'après l'ordre donné au moteur, et la seconde roue a été considérée mécaniquement symétrique à celle comptée.
 
Autant vous dire que ni les performances de l'Arduino ni la précision de la mesure n'étaient au rendez-vous.
 
 
L'utilisation d'un FPGA en réponse à ce problème est donc totalement justifiée, ce dernier fonctionnant à 100 MHz, il peut largement gérer tous les fronts de la codeuse.
 
 
[https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/fpga/hedm.vhd Code VHDL utilisé pour les codeuse]
 
 
===Workflow utilisé pour la programmation par FPGA===
 
 
'''Paragraphe ajouté rétro-activement puisqu'utile pour la suite.'''
 
 
Le FPGA que nous utilisons est un Xilinx Spartan 3A. ''A priori'', ces types de FPGA ne sont programmables qu'en utilisant les environnement de développement integrés Xilinx ISE et Xilinx Vivado. N'étant pas de grands fan des environnements de développement integrés (et de tout ce qui s'utilise avec une interface graphique en général), nous avons préféré utiliser [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/fpga/Makefile un fichier Makefile] qui appelle les outils internes de Xilinx ISE afin de générer le fichier .bit qui sera téléversé sur le FPGA.
 
 
Un des avantages de cette technique est qu'elle permet une organisation beaucoup plus concise de notre dépôt. En effet, toute la configuration est stockée dans [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/fpga/project.cfg un seul fichier] et non dans une hiérarchie complexe de fichiers XML comme le générerait un projet Xilinx ISE. Les fichiers générés (et donc à ne pas inclure dans le dépôt) sont tous inclus dans un même dossier facile à exclure du système de contrôle de version. En guise de bonus, la synthétisation d'un design est 50% plus rapide qu'en utilisant l'IDE (nous n'avons pas su l'expliquer). Enfin et surtout, on pourra intégrer la synthétisation dans les scripts de mises à jour du robot sans peine.
 
 
Le désavantage de cette technique est qu'il devient plus difficile d'utiliser les outils plus poussés de l'IDE, tel que la génération d'IP cores ou la simulation. Pour le premier ce n'est pas trop un problème car notre programme ne sera pas très complexe (et que certains IP core ne fonctionnerait pas dans notre cas vu l'exotisme de notre FPGA). Pour le deuxième, on utilisera par la suite un système de simulation différent et à notre goût plus performant.
 
  
 
==Semaine 1==
 
==Semaine 1==
Ligne 488 : Ligne 752 :
 
Le '''TLE 5206-2''' est bien plus simple de fonctionnement et offre moins de services que le LM18200T, il permet donc également une simplicité de routage et de modularité mais il ne permet de piloter qu'un seul moteur.
 
Le '''TLE 5206-2''' est bien plus simple de fonctionnement et offre moins de services que le LM18200T, il permet donc également une simplicité de routage et de modularité mais il ne permet de piloter qu'un seul moteur.
  
Notre choix s'arrête donc sur la conception dans un premier temps du contrôleur avec les '''TLE 5206-2''' avec deux PCB isolés (un par moteur), puis on utilisera un '''LM18200T''' qui pilotera les deux moteurs à lui tout seul en tant que solution alternative.
+
Notre choix s'arrête donc sur la conception dans un premier temps du contrôleur avec les '''TLE 5206-2''' avec deux PCB isolés (un par moteur), puis on utilisera un '''LM18200T''' qui pilotera les moteurs en tant que solution alternative mais sur un seul PCB.
  
 
===FreeRTOS pour Arduino===
 
===FreeRTOS pour Arduino===
Ligne 504 : Ligne 768 :
 
[[Fichier:IMA4SC17-18-P66-Graph-size.png|200px|thumb|right|Répartition de la taille du système d'exploitation]]
 
[[Fichier:IMA4SC17-18-P66-Graph-size.png|200px|thumb|right|Répartition de la taille du système d'exploitation]]
  
Nous allons donc utiliser un système d'exploitation alternatif conçu uniquement les fonctionnalités dont nous avons besoin. Notons que le cahier des charges nous impose de pouvoir utiliser le Wi-Fi et de pouvoir mettre à jour le système des autres cartes, et on souhaitera pour cela utiliser des outils pré-existants. On n'utilisera donc pas un système type FreeRTOS. Notre choix se portera sur [https://buildroot.org/ Buildroot] qui est un utilitaire qui permet de construire des images de système d'exploitation sur base de noyaux Linux en sélectionnant les options et programmes via [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/raspberrypi/configs/cdfprincipal_defconfig un simple fichier de configuration]. Le système nous propose aussi de créer nos propres programmes et s'occupe lui-même de la cross-compilation, ce que l'on utilisera pour le(s) programme(s) régissant la logique du robot. La compilation des programmes étant faite sur une machine hôte (et non sur la machine cible, ici le Raspberry Pi), cela nous permet de réduire les temps de compilation. Cela sera particulièrement utile lors des phases de test du robot.
+
Nous allons donc utiliser un système d'exploitation alternatif conçu uniquement les fonctionnalités dont nous avons besoin. Notons que le cahier des charges nous impose de pouvoir utiliser le Wi-Fi et de pouvoir mettre à jour le système des autres cartes, et on souhaitera pour cela utiliser des outils pré-existants. On n'utilisera donc pas un système type FreeRTOS. Notre choix se portera sur [https://buildroot.org/ Buildroot] qui est un utilitaire qui permet de construire des images de système d'exploitation sur base de noyaux Linux en sélectionnant les options et programmes via [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/raspberrypi/configs/cdfprincipal_defconfig un simple fichier de configuration]. Le système nous propose aussi de créer nos propres programmes et s'occupe lui-même de la cross-compilation, ce que l'on utilisera pour le(s) programme(s) régissant la logique du robot. La compilation des programmes étant faite sur une machine hôte (et non sur la machine cible, ici le Raspberry Pi), cela nous permet de réduire les temps de compilation. Cela sera particulièrement utile lors des phases de test du robot.
  
 
Après ~45 minutes de compilation, une image d'une soixantaine de Mio contenant notre système d'exploitation est générée. Le système démarre en une poignée de seconde, et en idle ne consomme qu'une dizaine de Mio de RAM et il n'y a que très peu d'activité sur le CPU. Toutes le reste des ressources sont alors disponibles pour notre utilisation<!-- Spoiler : On en utilisera même pas 10% -->. Seul bémol, devoir reflasher la carte à chaque modification du système (le programme étant inclus) est assez lourd<!-- RIP La carte microSD de Robotech 2018-2018 -->. On décrira une solution à ce problème dans une prochaine section.
 
Après ~45 minutes de compilation, une image d'une soixantaine de Mio contenant notre système d'exploitation est générée. Le système démarre en une poignée de seconde, et en idle ne consomme qu'une dizaine de Mio de RAM et il n'y a que très peu d'activité sur le CPU. Toutes le reste des ressources sont alors disponibles pour notre utilisation<!-- Spoiler : On en utilisera même pas 10% -->. Seul bémol, devoir reflasher la carte à chaque modification du système (le programme étant inclus) est assez lourd<!-- RIP La carte microSD de Robotech 2018-2018 -->. On décrira une solution à ce problème dans une prochaine section.
Ligne 516 : Ligne 780 :
  
 
[[Fichier:IMA4-1718-P66-debugPin.png|300px|thumb|right|]]
 
[[Fichier:IMA4-1718-P66-debugPin.png|300px|thumb|right|]]
Cependant, pour assurer que le Raspberry Pi se lance en un minimum de temps lors de la compétition, on s'assurera de charger uniquement ce qui est nécessaire. Les outils de debug, la connexion Wi-Fi ne seront activées que lorsque deux broches du Raspberry Pi sont court-circuitées. La vérification sera faite à la dernière étape de lancement à l'aide [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/chef/src/testpin.c du binaire '''testpin'''], qui prend comme argument deux [http://wiringpi.com/pins/ numéros de pins selon la bibliothèque Wiring Pi].
+
Cependant, pour assurer que le Raspberry Pi se lance en un minimum de temps lors de la compétition, on s'assurera de charger uniquement ce qui est nécessaire. Les outils de debug, la connexion Wi-Fi ne seront activées que lorsque deux broches du Raspberry Pi sont court-circuitées. La vérification sera faite à la dernière étape de lancement à l'aide [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/chef/src/testpin.c du binaire '''testpin'''], qui prend comme argument deux [http://wiringpi.com/pins/ numéros de pins selon la bibliothèque Wiring Pi].
 
<!-- Ce paragraphe a pour unique but de me rappeler de quelle broche il faut que j'utilise -->
 
<!-- Ce paragraphe a pour unique but de me rappeler de quelle broche il faut que j'utilise -->
  
Ligne 528 : Ligne 792 :
 
Sur un système d'exploitation classique, il suffit généralement de brancher un dongle Wi-Fi pour faire en sorte qu'il fonctionne<!-- exceptés pour certains constructeurs à problème...-->. Pour fonctionner, un dongle Wi-Fi (comme beaucoup d'autre périphériques) a besoin d'un firmware, c'est à dire un petit bout de code qui est chargé sur le matériel depuis par le noyau afin qu'il puisse fonctionner. Or, dans notre système d'exploitation à la carte, celui pour notre dongle Wi-Fi n'est pas installé par défaut, il a donc fallu le faire compiler. Ensuite à l’exécution<!-- aka runtime -->, il faut charger le module correspondant au dongle via un `modprobe`, car il n'est pas chargé automatiquement par le système lors de l'insertion (cela nécessiterait un démon supplémentaire<!-- un truc comme udev si je raconte pas de bêtises mais j'en suis pas sûr-->). À partir de là, l'interface `wlan0` est fonctionelle et on peut potentiellement se connecter à un réseau Wi-Fi.
 
Sur un système d'exploitation classique, il suffit généralement de brancher un dongle Wi-Fi pour faire en sorte qu'il fonctionne<!-- exceptés pour certains constructeurs à problème...-->. Pour fonctionner, un dongle Wi-Fi (comme beaucoup d'autre périphériques) a besoin d'un firmware, c'est à dire un petit bout de code qui est chargé sur le matériel depuis par le noyau afin qu'il puisse fonctionner. Or, dans notre système d'exploitation à la carte, celui pour notre dongle Wi-Fi n'est pas installé par défaut, il a donc fallu le faire compiler. Ensuite à l’exécution<!-- aka runtime -->, il faut charger le module correspondant au dongle via un `modprobe`, car il n'est pas chargé automatiquement par le système lors de l'insertion (cela nécessiterait un démon supplémentaire<!-- un truc comme udev si je raconte pas de bêtises mais j'en suis pas sûr-->). À partir de là, l'interface `wlan0` est fonctionelle et on peut potentiellement se connecter à un réseau Wi-Fi.
  
Donc ''a priori'', si on crée un fichier `/etc/network/interfaces` comme nous avons vu [https://rex.plil.fr/Enseignement/Reseau/TP.Reseau.IMA2a4/reseau004.html#toc12 en TP de réseau]  et qu'on lance un `ifup wlan0` cela devrait fonctionner non ? Pas tout à fait. Il s'avère que la commande `ifup` inclue dans notre système (fournie par la boîte à outils [https://www.busybox.net/ BusyBox]) n'est pas aussi complète que celle dans l'OS Raspbian utilisé en TP et ne gère pas les instructions `wpa-*` du fichiers `interfaces`. Pour parer à cela, [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/raspberrypi/board/robotech/cdfprincipal/rootfs_overlay/etc/extra.d/S40wifi il suffit d'appeler `wpa-supplicant` directement], qui est le programme qui s'occupe (même sur Raspbian) de l'authentification au réseau Wi-Fi. On peut ensuite utiliser `ifup` pour la configuration IP.
+
Donc ''a priori'', si on crée un fichier `/etc/network/interfaces` comme nous avons vu [https://rex.plil.fr/Enseignement/Reseau/TP.Reseau.IMA2a4/reseau004.html#toc12 en TP de réseau]  et qu'on lance un `ifup wlan0` cela devrait fonctionner non ? Pas tout à fait. Il s'avère que la commande `ifup` inclue dans notre système (fournie par la boîte à outils [https://www.busybox.net/ BusyBox]) n'est pas aussi complète que celle dans l'OS Raspbian utilisé en TP et ne gère pas les instructions `wpa-*` du fichiers `interfaces`. Pour parer à cela, [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/raspberrypi/board/robotech/cdfprincipal/rootfs_overlay/etc/extra.d/S40wifi il suffit d'appeler `wpa-supplicant` directement], qui est le programme qui s'occupe (même sur Raspbian) de l'authentification au réseau Wi-Fi. On peut ensuite utiliser `ifup` pour la configuration IP.
  
 
Après un rapide test de ping, on installe (enfin plus précisément on dit à Buildroot de compiler dans l'image, puisque le système n'a pas de gestionnaire de paquets) [https://matt.ucc.asn.au/dropbear/dropbear.html un serveur SSH] sur la machine, et on met en place un petit système afin que les la clef privée et l'empreinte de la clef du client soient sur le Raspberry Pi afin de se connecter simplement et rapidement à la machine.
 
Après un rapide test de ping, on installe (enfin plus précisément on dit à Buildroot de compiler dans l'image, puisque le système n'a pas de gestionnaire de paquets) [https://matt.ucc.asn.au/dropbear/dropbear.html un serveur SSH] sur la machine, et on met en place un petit système afin que les la clef privée et l'empreinte de la clef du client soient sur le Raspberry Pi afin de se connecter simplement et rapidement à la machine.
Ligne 598 : Ligne 862 :
  
 
====Mise à jour de l'OS du Raspberry Pi====
 
====Mise à jour de l'OS du Raspberry Pi====
Nous avons vu que pour mettre à jour le système d'exploitation du Raspberry Pi, ré-écrire la carte SD en entier n'est ni pratique, ni rapide, ni bon pour la durabilité de la carte. On a donc établi -conformément à ce qui était demandé dans le cahier des charges- un moyen de le mettre à jour par liaison sans file. On a déjà un moyen de se connecter en SSH au Raspberry Pi par Wi-Fi, on transférera donc par ce canal les fichiers générés par buildroot avant mise en image, vers la racine de la carte. On utilisera pour cela `rsync`. Cela rajoute un programme en plus sur l'OS, mais cela permet de ne pas ré-envoyer les fichiers qui n'ont pas changé. Ce n'est pas une solution très élégante, mais elle est redoutablement fonctionelle. Il suffit alors de taper [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/raspberrypi/Makefile#L75 `make upgrade-filesystem`] pour lancer l'opération.
+
Nous avons vu que pour mettre à jour le système d'exploitation du Raspberry Pi, ré-écrire la carte SD en entier n'est ni pratique, ni rapide, ni bon pour la durabilité de la carte. On a donc établi -conformément à ce qui était demandé dans le cahier des charges- un moyen de le mettre à jour par liaison sans file. On a déjà un moyen de se connecter en SSH au Raspberry Pi par Wi-Fi, on transférera donc par ce canal les fichiers générés par buildroot avant mise en image, vers la racine de la carte. On utilisera pour cela `rsync`. Cela rajoute un programme en plus sur l'OS, mais cela permet de ne pas ré-envoyer les fichiers qui n'ont pas changé. Ce n'est pas une solution très élégante, mais elle est redoutablement fonctionelle. Il suffit alors de taper [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/raspberrypi/Makefile#L75 `make upgrade-filesystem`] pour lancer l'opération.
  
 
====Mise à jour de l'Arduino====
 
====Mise à jour de l'Arduino====
Le programme utilisé pour téléverser un programme sur un Arduino s'appelle avrdude, et par chance il est dans les programmes proposés par buildroot. Il suffit simplement de l'activer dans [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/raspberrypi/configs/cdfprincipal_defconfig#L79 la configuration de buildroot] et d'ajouter une entrée `upgrade-arduino` dans [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/raspberrypi/Makefile#L82 le Makefile] qui se chargera de l'envoi vers le Raspberry Pi et de l'invocation de la commande de téléversement.
+
Le programme utilisé pour téléverser un programme sur un Arduino s'appelle avrdude, et par chance il est dans les programmes proposés par buildroot. Il suffit simplement de l'activer dans [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/raspberrypi/configs/cdfprincipal_defconfig#L79 la configuration de buildroot] et d'ajouter une entrée `upgrade-arduino` dans [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/raspberrypi/Makefile#L82 le Makefile] qui se chargera de l'envoi vers le Raspberry Pi et de l'invocation de la commande de téléversement.
  
 
====Mise à jour du FPGA====
 
====Mise à jour du FPGA====
On procèdera de la même manière pour téléverser un programme sur le FPGA. Cependant, [https://www.micro-nova.com/mercury le FPGA utilisé] étant assez peu connu, il n'existe pas de programme directement dans buildroot capable d'effectuer le téléversement. De plus, le programme fourni par le constructeur pour le téléversement est sous forme d'interface graphique <!--en plus de tourner sous mono ce qui rend le machin super lourd-->ce qui n'est pas adapté pour notre cas. Heureusement, la source du programme est ouverte, et quelqu'un l'a réécrit sous forme [https://github.com/cr1901/mercpcl de programme en ligne de commande]. Il ne reste qu'à créer [https://archives.plil.fr/gbontoux/cdf2018-principal/tree/master/raspberrypi/package/cr1901/mercpcl un package pour buildroot] et le tour est joué.
+
On procèdera de la même manière pour téléverser un programme sur le FPGA. Cependant, [https://www.micro-nova.com/mercury le FPGA utilisé] étant assez peu connu, il n'existe pas de programme directement dans buildroot capable d'effectuer le téléversement. De plus, le programme fourni par le constructeur pour le téléversement est sous forme d'interface graphique <!--en plus de tourner sous mono ce qui rend le machin super lourd-->ce qui n'est pas adapté pour notre cas. Heureusement, la source du programme est ouverte, et quelqu'un l'a réécrit sous forme [https://github.com/cr1901/mercpcl de programme en ligne de commande]. Il ne reste qu'à créer [https://archives.plil.fr/gbontoux/cdf2018-principal/tree/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/raspberrypi/package/cr1901/mercpcl un package pour buildroot] et le tour est joué.
  
 
==Semaine 5==
 
==Semaine 5==
Ligne 727 : Ligne 991 :
 
[[Fichier:IMA4SC1718-Communication.svg|400px]]
 
[[Fichier:IMA4SC1718-Communication.svg|400px]]
  
Pour les liaisons séries, on utilisera en couche applicative notre propre format de trame. Chaque trame commencera par un octet indiquant le type d'information à être envoyé. Elle peut être ensuite suivie par des données, dont la taille et la consitution est définie par le type d'information. Chaque information pouvant être transmise, et la structure de données à envoyer est définie dans des fichiers .h, un pour la communication [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/arduino/AFsignals.h Arduino↔FPGA] et un pour la communication [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/arduino/ACsignals.h Arduino↔Raspberry Pi] (dans ces fichiers le Raspberry Pi est aussi appelé Chef, pour le nom du programme).
+
Pour les liaisons séries, on utilisera en couche applicative notre propre format de trame. Chaque trame commencera par un octet indiquant le type d'information à être envoyé. Elle peut être ensuite suivie par des données, dont la taille et la consitution est définie par le type d'information. Chaque information pouvant être transmise, et la structure de données à envoyer est définie dans des fichiers .h, un pour la communication [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/arduino/AFsignals.h Arduino↔FPGA] et un pour la communication [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/arduino/ACsignals.h Arduino↔Raspberry Pi] (dans ces fichiers le Raspberry Pi est aussi appelé Chef, pour le nom du programme).
  
 
Certaines informations seront envoyée à l'initiative de l'appareil possédant l'information ('''D'''irect), tels que les ordres du Raspberry Pi à l'Aruino. D'autres, seront envoyés à l'initiative de l'appareil ayant besoin de l'information ('''I'''ndirect), tels que les valeurs des codeuses qui changent bien plus souvent que l'Ardnuio ne saura les traiter. Les dernières, seront envoyés dès que certaines valeurs dépassent un certain seuil ('''T'''rigger), seuil fixé par l'appareil reçevant l'information, telles que les valeurs des capteurs de distance. Tout cela permet de garder uniquement les informations utiles, afin de réduire au maximum la congestion du réseau et le traitement par les appareils.
 
Certaines informations seront envoyée à l'initiative de l'appareil possédant l'information ('''D'''irect), tels que les ordres du Raspberry Pi à l'Aruino. D'autres, seront envoyés à l'initiative de l'appareil ayant besoin de l'information ('''I'''ndirect), tels que les valeurs des codeuses qui changent bien plus souvent que l'Ardnuio ne saura les traiter. Les dernières, seront envoyés dès que certaines valeurs dépassent un certain seuil ('''T'''rigger), seuil fixé par l'appareil reçevant l'information, telles que les valeurs des capteurs de distance. Tout cela permet de garder uniquement les informations utiles, afin de réduire au maximum la congestion du réseau et le traitement par les appareils.
Ligne 735 : Ligne 999 :
 
Jusque là en cours, pour envoyer ou reçevoir des octets sur l'Arduino, on utilisait une boucle qui attendait que les bits ''RXCn'' et ''UDREn'' du regsitres ''UCSRnA'' soit mis à 1, affin d'attendre qu'un octet soit reçu ou prêt à être envoyé respectivement. Le problème de cette méthode, est qu'elle utilise excessivement le CPU et empêche de faire quelque chose d'autre en même temps. Avec le système RTOS, on peut faire plusieurs choses à la fois, mais il faut attendre que la tâche de cette boucle soit élue pour pouvoir traiter l'envoi / la réception de données.
 
Jusque là en cours, pour envoyer ou reçevoir des octets sur l'Arduino, on utilisait une boucle qui attendait que les bits ''RXCn'' et ''UDREn'' du regsitres ''UCSRnA'' soit mis à 1, affin d'attendre qu'un octet soit reçu ou prêt à être envoyé respectivement. Le problème de cette méthode, est qu'elle utilise excessivement le CPU et empêche de faire quelque chose d'autre en même temps. Avec le système RTOS, on peut faire plusieurs choses à la fois, mais il faut attendre que la tâche de cette boucle soit élue pour pouvoir traiter l'envoi / la réception de données.
  
Heureusement, l'Atmega2560 dispose d'interruptions sur le port série. Il suffit d'[https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/arduino/AC.c#L94 activer le bit ''RXCIEn'' dans le registre ''UCSRnB''] pour qu'à chaque réception d'octet sur le port série, l'[https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/arduino/AC.c#L39 interruption ''USARTn_RX_vect''] se déclenche. Dans notre cas, cette interruption [https://www.freertos.org/ulTaskNotifyTake.html réveille] une tâche FreeRTOS à l'aide d'[https://www.freertos.org/vTaskNotifyGiveFromISR.html une notification], tâche qui va s'occuper récupérer et traîter les données juste reçues, et se ré-endort jusqu'à la prochaine réception.
+
Heureusement, l'Atmega2560 dispose d'interruptions sur le port série. Il suffit d'[https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/arduino/AC.c#L94 activer le bit ''RXCIEn'' dans le registre ''UCSRnB''] pour qu'à chaque réception d'octet sur le port série, l'[https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/arduino/AC.c#L39 interruption ''USARTn_RX_vect''] se déclenche. Dans notre cas, cette interruption [https://www.freertos.org/ulTaskNotifyTake.html réveille] une tâche FreeRTOS à l'aide d'[https://www.freertos.org/vTaskNotifyGiveFromISR.html une notification], tâche qui va s'occuper récupérer et traîter les données juste reçues, et se ré-endort jusqu'à la prochaine réception.
  
 
On pourrait directement traîter les données dans l'interruption, mais cette méthode a plusieurs avantages. En effet la durée de l'interruption est minime, permet d'utiliser le système de priorités des tâches (alors que l'interruption a une priorité absolue) et évite d'empêcher l'arrivée d'autres interruptions. D'autre part, la tâche peut-être interrompue à n'importe quel endroit, elle est donc un moyen simple de stocker à quel endroit de la reception on en est.
 
On pourrait directement traîter les données dans l'interruption, mais cette méthode a plusieurs avantages. En effet la durée de l'interruption est minime, permet d'utiliser le système de priorités des tâches (alors que l'interruption a une priorité absolue) et évite d'empêcher l'arrivée d'autres interruptions. D'autre part, la tâche peut-être interrompue à n'importe quel endroit, elle est donc un moyen simple de stocker à quel endroit de la reception on en est.
Ligne 741 : Ligne 1 005 :
 
Pour la transmission, deux choix s'offrent à nous : l'utilisation de l'interruption ''USARTn_TX_vect'' ou de l'interruption ''USARTn_UDRE_vect''. La première est déclenchée quand un caractère vient de finir sa transmission. On peut alors utiliser cette interruption pour envoyer le prochain caractère dans la file d'attente. Cependant, si on utilise la même méthode que pour la réception, entre le moment où la transmission d'un caractère est terminée et celui où la transmission d'un nouveau caractère est initiée, il va falloir que la tâche faisant l'envoi soit élue. On peut en revanche utiliser le cache matériel de l'Atmega2560, qui permet de stocker deux caractères, et nous permet donc d'envoyer une suite ininterrompue de caractères, et ainsi envoyer les messages plus rapidement. Il faut pour cela utiliser l'autre interruption, ''USARTn_UDRE_vect'' qui se déclenche quand il est possible d'écrire dans le cache.
 
Pour la transmission, deux choix s'offrent à nous : l'utilisation de l'interruption ''USARTn_TX_vect'' ou de l'interruption ''USARTn_UDRE_vect''. La première est déclenchée quand un caractère vient de finir sa transmission. On peut alors utiliser cette interruption pour envoyer le prochain caractère dans la file d'attente. Cependant, si on utilise la même méthode que pour la réception, entre le moment où la transmission d'un caractère est terminée et celui où la transmission d'un nouveau caractère est initiée, il va falloir que la tâche faisant l'envoi soit élue. On peut en revanche utiliser le cache matériel de l'Atmega2560, qui permet de stocker deux caractères, et nous permet donc d'envoyer une suite ininterrompue de caractères, et ainsi envoyer les messages plus rapidement. Il faut pour cela utiliser l'autre interruption, ''USARTn_UDRE_vect'' qui se déclenche quand il est possible d'écrire dans le cache.
  
Cependant, cette interruption s'utilise différemment des deux précédentes. En effet, là où les interruptions se déclenchent à un changement d'état (e.g. reception d'un octet), ''USARTn_UDRE_vect'' se déclenche continuellement quand le cache de la liaison série est écrivable. D'une part, il faut donc désactiver l'interruption quand il n'y a rien à transmettre. D'autre part, il faut donc écrire dans le cache à l'interieur de l'interruption. On définiera donc [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/arduino/AC.h#L22 un pointeur global vers les données à écrire et leur taille] qui sera écrit depuis la tâche voulant envoyer des informations et lue par 'interruption. Une fois l'envoi terminé, l'interruption se désactivera d'elle même et réveillera la tâche ayant initié l'envoi. Cette méthode nous permet d'utiliser au maximum de sa capacité la liaison série tout en encombrant un minimum le processeur de l'Arduino.
+
Cependant, cette interruption s'utilise différemment des deux précédentes. En effet, là où les interruptions se déclenchent à un changement d'état (e.g. reception d'un octet), ''USARTn_UDRE_vect'' se déclenche continuellement quand le cache de la liaison série est écrivable. D'une part, il faut donc désactiver l'interruption quand il n'y a rien à transmettre. D'autre part, il faut donc écrire dans le cache à l'interieur de l'interruption. On définiera donc [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/arduino/AC.h#L22 un pointeur global vers les données à écrire et leur taille] qui sera écrit depuis la tâche voulant envoyer des informations et lue par 'interruption. Une fois l'envoi terminé, l'interruption se désactivera d'elle même et réveillera la tâche ayant initié l'envoi. Cette méthode nous permet d'utiliser au maximum de sa capacité la liaison série tout en encombrant un minimum le processeur de l'Arduino.
  
 
===Répartitions des messages reçus===
 
===Répartitions des messages reçus===
  
Que ce soit du côté de l'Arduino ou du Raspberry Pi, la réception d'octets sur la liaison série est gérée par une seule tâche (ou thread sur le Raspberry Pi). Cependant, pour éviter de complexifier trop cette tâche et de la rendre indépendante des types de messages reçus, on utilisera un système d'observateurs. N'importe quelle partie du programme peut demander à [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/chef/src/debug.c#L43 ajouter un observateur sur un certain type de message]. L'observateur, étant une fonction, est éxecutée lors de la réception dudit type de message. Cette fonction peut alors [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/chef/src/debug.c#L37 récupérer les données du message] pour les stocker à l'endroit voulu, et dire à une autre tâche de faire quelque chose avec ces données.
+
Que ce soit du côté de l'Arduino ou du Raspberry Pi, la réception d'octets sur la liaison série est gérée par une seule tâche (ou thread sur le Raspberry Pi). Cependant, pour éviter de complexifier trop cette tâche et de la rendre indépendante des types de messages reçus, on utilisera un système d'observateurs. N'importe quelle partie du programme peut demander à [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/chef/src/debug.c#L43 ajouter un observateur sur un certain type de message]. L'observateur, étant une fonction, est éxecutée lors de la réception dudit type de message. Cette fonction peut alors [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/chef/src/debug.c#L37 récupérer les données du message] pour les stocker à l'endroit voulu, et dire à une autre tâche de faire quelque chose avec ces données.
  
Pour faire cela, la tâche de réception garde [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/chef/src/CA.h#L20 un tableau d'observateurs] indexés par le type de message auquel il est accroché. Quand le début d'un message est reçu, la tâche [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/chef/src/CA.c#L80 regarde dans le tableau] si un observateur a été associé au type de message, si oui éxecute la fonction (dans la même tâche, afin que cette fonction puisse lire le reste du message) et si non affiche une erreur.
+
Pour faire cela, la tâche de réception garde [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/chef/src/CA.h#L20 un tableau d'observateurs] indexés par le type de message auquel il est accroché. Quand le début d'un message est reçu, la tâche [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/chef/src/CA.c#L80 regarde dans le tableau] si un observateur a été associé au type de message, si oui éxecute la fonction (dans la même tâche, afin que cette fonction puisse lire le reste du message) et si non affiche une erreur.
  
 
===Récupération de session===
 
===Récupération de session===
Ligne 770 : Ligne 1 034 :
  
 
Il faut faire cependant attention aux différences existantes entre la simulation et la synthétisation. En effet la simulation est beaucoup plus permissive ce qui permet notamment de simplifier l'écriture de testbenchs. Cependant, certains comportements sont inconnus voire ignorés par le synthétiseur. Par exemple, dans un process il est possible de définir des listes de sensiblité, qui font en sorte que le process ne soit executé uniquement si une des valeurs des éléments de cette liste est changée. Cependant sur le vrai FPGA, cette liste de sensibilité est totalement ignorée et le process est éxecuté à chaque front d'horloge, ce qui peut causer de grandes différences entre la simulation et la réalité. Il faut donc garder en tête ces différences lors de la simulation.
 
Il faut faire cependant attention aux différences existantes entre la simulation et la synthétisation. En effet la simulation est beaucoup plus permissive ce qui permet notamment de simplifier l'écriture de testbenchs. Cependant, certains comportements sont inconnus voire ignorés par le synthétiseur. Par exemple, dans un process il est possible de définir des listes de sensiblité, qui font en sorte que le process ne soit executé uniquement si une des valeurs des éléments de cette liste est changée. Cependant sur le vrai FPGA, cette liste de sensibilité est totalement ignorée et le process est éxecuté à chaque front d'horloge, ce qui peut causer de grandes différences entre la simulation et la réalité. Il faut donc garder en tête ces différences lors de la simulation.
 +
 +
 +
===Recherche sur le capteur à ultrason HCR04===
 +
 +
Ce composant est un grand classique de la robotique et pourtant on trouve assez peu d'informations précises sur son fonctionnement et ses limites.
 +
 +
====étude du capteur====
 +
on note qu'il fonctionne à 40Hz soit potentiellement un résultat toutes les 25ms. Les différentes datasheet consultées préconisent une acquisition toutes les 60ms.
 +
 +
 +
[[Fichier:P66_ultrasoundD.PNG|500px|thumb|right|Datagramme du capteur ]]
 +
 +
Notre objectif dans cette analyse était principalement de chercher une technique pour s'assurer que le signal provient bien de notre capteur et pas d'un capteur adverse ou d'un autre appareil présent lors de la compétition.
 +
 +
Comme on peut le voir sur ce datagramme il ne sait pas faire la différence entre son écho ou l'envoi d'un autre capteur, cela pourra poser un problème lors de la compétition.
 +
 +
====Solutions envisageables====
 +
Une solution envisageable peut-être d'intégrer dans le code une logique qui vérifie une certaine redondance de l'information (le delta du capteur étant très inférieur à celui du déplacement des robots) pour s'assurer qu'il s'agit bien de l'écho de notre capteur. On peut également le placer à la limite haute réglementaire qui n'est pas souvent privilégiées par les concurrents.
 +
 +
Une autre solution peut consister à remplacer le capteur ultrason par d'autres types de capteurs. On peut envisager d'utiliser le VL53L0X qui mesure le time of flight (comme le HSR04 au final) mais avec une lumière infrarouge. Il offre sur le papier un capteur sensible de 3cm à 2m avec une précision de 1mm à  plus ou moins 10% dans le pire cas. Pour notre usage il n'offre pas d'avantages immenses vu que la précision n'est pas notre critère cependant en utilisant une autre technologie cela pourrait éviter des conflits avec les capteurs adverses.
 +
[https://www.pololu.com/product/2490 VL53L0X]
 +
 +
Nous utiliserons la première solution, pour des raisons financières et également parce que c'est une technique qui a fait ses preuves lors des années précédentes. Cependant elle sera soumise dans le rapport final pour les années futures.
 +
 +
 +
====Fréquence d'échantillonage====
 +
Il est recommandé dans la datasheet du composant d'échantilloner au minimum toutes les 60 ms, afin d'éviter les intérférences avec les ondes des précédentes mesures (en 60ms le son a la temps de parcourir 10m, distance à partir de laquelle on considère qu'il est complètement atténué). Notre robot possèdera au plus 4 capteurs à ultrasons, est-on obligé de lire les valeurs des capteurs un par un, réduisant la fréquence d'échantillonage à 4 Hz ? La réponse est non. En effet nos capteurs sont positionnés dans des distances opposées, et si les 4 envoient une onde en même temps, la première onde reçue sera renvoyée par l'obstacle le plus proche du capteur la reçevant. On peut donc conserver une fréquence d'échantillonage de 16 Hz.
  
 
==Vacances==
 
==Vacances==
 +
 +
===Vue d'ensemble du FPGA===
 +
Cette semaine nous allons beaucoup parler du FPGA. Pour mieux comprendre la suite, il peut être utile de rappeler ce que cette carte est censée faire et comment nous comptons lui faire faire.
 +
 +
Les tâches à réaliser par le FPGA sont les suivantes :
 +
 +
* Récupérer les valeurs des capteurs de deux capteurs distance (un devant et un derrière) (pour l'instant ce sont des capteurs ultrasons de type HC-SR04)
 +
* Filtrer les précédentes valeurs de façons à enlever les valeurs aberrantes liées aux interférences
 +
* Récupérer les valeurs des encodeurs (un à gauche et un à droite)
 +
* Communiquer les valeurs récupérées par liaison série
 +
 +
Basiquement, on écrira un modules VHDL pour chaque tâche, respectivement [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/fpga/hcsr04.vhd hcsr04.vhd], [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/6082662c2d4c0fce006b26a8852ed2e6c8dbbc25/fpga/fir.vhd fir.vhd],
  
 
===Récupération des données des encodeurs===
 
===Récupération des données des encodeurs===
Ligne 780 : Ligne 1 083 :
  
 
On peut d'ailleurs en profiter pour réduire le nombre entier des valeurs des encodeurs à 16 bits, ce qui laisse au robot le temps de parcourir 5 m sans mise à jour de position avant de faire un dépassement.
 
On peut d'ailleurs en profiter pour réduire le nombre entier des valeurs des encodeurs à 16 bits, ce qui laisse au robot le temps de parcourir 5 m sans mise à jour de position avant de faire un dépassement.
 +
 +
===Implémentation du filtre pour les interférences===
 +
'''Note : le travail sur le filtre est basé en partie sur le travail réalisé dans le cadre du tutorat de Circuits Numériques Programmables du S7 par Eloi Zalczer et Geoffrey Preud'homme.'''
 +
 +
Pour filtrer les intérférences et autres valeurs erronées des capteurs de distance, on utilisera un filtre à réponse impulsionnelle finie (ou FIR). L'avantage de ce type de filtres est qu'il est très générique : on peut changer le mode de filtrage (passe-bas, passe-haut...) et ses paramètres (fréquence de coupure...) en changeant les valeurs d'un tableau de coefficients. Plus le nombre N de coefficients est grand, plus Le calcul du signal de sortie se fait simplement en faisant la somme du produit de chaque coefficient par le signal d'entré décalé dans le temps proportionellement à l'indice du coefficient.
 +
 +
[[Image:FIR Filter.svg|250px|thumb|left|Schéma fonctionnel d'un FIR]]
 +
 +
Les opérations réalisées sont donc de simples retard, additions et multiplications (à l'opposé du filtre à réponse impulsionelle infinie), qui sont des opérations très simple pour le FPGA. Cepedant, les facteurs du filtre sont des décimaux inférieurs à 1, ce que traite difficilement un FPGA. Pour pallier à ce problème, on utilisera la propriété linéaire du filtre : on multipliera les facteurs par un nombre N afin qu'ils signifient quelque chose en tant qu'entier, puis on divisera le résultat par N. Afin de pouvoir effectuer la division simplement sur le FPGA, on prendra une puissnce de 2 comme valeur de N : la division se simplifie alors par un décalage de bits par la droite.
 +
 +
[[Image:IMA4SC1718-P66-FIRPipeline.png|350px|thumb|right|Résumé de l'utilisation du FPGA contenant un filtre à 128 coefficients. À gauche: méthode « immédiate ». À droite méthode « pipeline »]]
 +
 +
L'implémentation réalisée précédemment calcule la sortie du filtre en un seul front d'horloge. Cette méthode a un avantage : elle est très rapide car prend avantage des ressources du FPGA : chaque multiplication est réalisée en parallèle et chacune utilise une partie des ressources du FPGA (i.e. les tables de correspondances (LUT) et les bascules (flip-flop)). Mais c'est aussi un inconvénient, car ces ressources ne peuvent pas être réutilisées pour quelque chose d'autre. Dans notre cas, la sortie du filtre n'a pas besoin d'être calculée en un coup d'horloge (20 ns), on préfèrera utiliser un fonctionnement dit en « pipeline ». Cela consiste à répartir une partie des calculs sur différents coups d'horloge. Dans notre cas, on effectuera une multiplication et une addition par coup d'horloge. Beaucoup moins de ressources du FPGA seront utilisées, car elles seront utilisées plusieurs fois pour le calcul de plusieurs coefficients (cf capture ci-contre).
 +
 +
On peut remarquer que la méthode « pipeline » utilise un des multiplieurs 18 bits × 18 bits du FPGA. Or, ils n'étaient pas utilisés dans la méthode « immédiate ». On peut supposer ceci : étant donné que les coefficients du filtre étaient fixes, chaque multiplication effectuée possèdait un membre fixe. Les blocs de multiplication ont pu donc être optimisés (par exemple une multiplication par un coefficient de valeur '1' peut être remplacée par une identité).
 +
 +
=== Module de communication ===
 +
 +
Ce module permet de connecté les différentes valeurs qui peuvent être lues / écrites depuis / vers les autres modules avec le module de la liaison série. Il s'occupe alors de traiter les données arrivant sur la liaison série, modifier valeurs à envoyer sur les autres modules si besoin, et de renvoyer un message sur la liaison série si nécessaire.
 +
 +
À l'arrivée d'un premier octet (qui est dans notre cas le code du message), des signaux sont modifiés pour indiquer la taille du message et ce qu'il faut faire une fois totalement reçu. Le reste du message est lu puis est stocké dans un buffer. Une fois totalement reçu, une routine redirigeant les informations contenues dans le buffer dans les signaux connectés aux autres modules est executée. Éventuellement, un message à envoyer est stocké dans une queue d'envoi. Lorsque cette queue n'est pas vide, le premier élément de la queue est lu, les informations correspondantes sont stockées dans un buffer d'envoi, et le message est envoyé octet par octet. Une fois terminé, l'opération est recommencée jusqu'à ce que cette queue soit vide.
 +
 +
Une première version de ce module a été écrite, elle utilisait beaucoup de variables de process. Cela faisait en sorte que chaque traitement était réalisé au maximum en un coup d'horloge. Cependant, la vitesse de communication de la liaison série (même à 115200 baud/s) est 400 fois plus lente que les coups d'horloge. Il n'est pas nécessaire d'utiliser des variables dont la modification est immédiate. Le module a donc été réécrit à base de signaux, et 4 coups d'horloge sont à attendre entre la finalisation de la reception d'un message et l'initation de l'envoi de la réponse (reception du caractère, redirection des informations et ajout à la pile, dépilage et écriture du buffer, envoi du caractère). Cela a deux avantages : il réduit la complexité du programme en réduisant le nombre de LUT et de liens, et permet une fréquence de travail plus élevée, ce qui permet ainsi à notre code de fonctionne sur des FPGA dont la fréquence d'horloge est plus basse.
 +
 +
=== Corrections après usinage carte 5206===
 +
Suite à l'usinage nous avons constaté que le plan de masse n'avais pas été correctement interprété par le logiciel, il s'avère que cette toute première étape avait été mal faite. En effet le polygone permettant de créer la masse comportait un segment supplémentaire qui probablement à causé une mauvaise interprétation du logiciel.
 +
Cependant grâce au sauvetage de Mr Flamen, nous pouvons tout de même utiliser la carte afin de réaliser un premier test lors de la semaine de rentrée.
 +
 +
===Finalisation avec le "client" des besoins en terme de puissance===
 +
A la suite d'une dernière réunion nous avons tranché les besoins et les composants de puissances ont donc pu être commandés.
 +
 +
==Semaine 7==
 +
 +
===I2C et IMU===
 +
 +
Après avoir étudié les données que nous fourni l'IMU, étudions d'un peu plus près la communication entre l'IMU et l'Arduino, qui avait été faite par abstraction jusqu'à aujourd'hui. La communication se fait via le protocole I2C.
 +
Une communication I2C fonctionne à l'aide de 2 pins, SCL et SDA. La pin SCL fourni une clock à l'IMU pour que celui-ci puisse envoyer ses datas via SDA.
 +
 +
La communication peut se faire à plusieurs vitesses différentes, la commutation des bits se fait sur un intervalle de durée déterminé par le tableau ci-dessous.
 +
 +
{| class="wikitable centre"
 +
|-
 +
! scope=row; align=center | Mode
 +
! scope=row; align=center | t<sub>LOWmin</sub>
 +
! scope=row; align=center | t<sub>HIGHmin</sub>
 +
|-
 +
| align="center" | Standard
 +
| align="center" | 4,7 μs
 +
| align="center" | 4 μs
 +
|-
 +
| align="center" | Fast
 +
| align="center" | 1,3 μs
 +
| align="center" | 0,6 μs
 +
|-
 +
| align="center" | Fast plus
 +
| align="center" | 0,5 μs
 +
| align="center" | 0,26 μs
 +
|}
 +
 +
On remarque que les délais sont assez courts. De plus, l'Arduino ne possède pas d'accélérateur matériel pour ce genre de communication. On en déduit donc que le code d'exemple que nous avons utilisé jusqu'ici gère la communication I2C par le programme, et monopolise le CPU pour avoir un timing conforme.
 +
 +
Or, le problème est que notre Arduino est multi-tâches. A première vue FreeRTOS ne nous autorise pas un contrôle aussi précis d'une tâche, et même si c'était le cas les performances seraient probablement fortement dégradées. On abandonne donc l'idée d'utiliser l'IMU depuis l'Arduino.
 +
 +
===Retour sur nos pas===
 +
 +
Une confusion avait été faite lors de l'élaboration du système d'inter-communication des périphériques. En effet, on pensait que l'IMU communiquait en SPI au lieu de I2C, protocole de communication pour lequel l'Arduino possède un accélérateur matériel. On va donc devoir repenser ce système.
 +
 +
La solution la plus simple pour passer outre ce problème serait d'utiliser le FPGA pour recevoir les communications I2C et les re-transmettre par la liaison série. Cependant, considérons les choses suivantes :
 +
 +
* Le Raspberry Pi possède un accélérateur matériel pour les liaisons I2C
 +
* Le Raspberry Pi possède aussi des broches de sortie tout ou rien et deux sorties PWM, de quoi contrôler les moteurs
 +
* L'Arduino prend beaucoup de temps à effectuer les calculs en point flottant (environ 7 ms pour simplement calculer la position à partir des informations des codeuses), alors que le Raspberry Pi est beaucoup plus rapide
 +
 +
Il serait beaucoup plus judicieux d'effectuer les calculs de position et d'asservissement directement sur le Raspberry Pi, et s'affranchir complètement de l'Arduino. Et c'est d'ailleurs ce que nous allons faire à partir de maintenant.
 +
 +
Pourquoi ne pas être parti sur cette méthode depuis le départ alors ? La raison principale est qu'il était initialement prévu de réaliser l'asservissement sur le FPGA, et ne faire des calculs de positions qu'à chaque nouvel ordre (soit relativement peu fréquemment). En voyant la possibilité de faire de la fusion de données (pour pouvoir connaitre la position à partir de deux sources, les codeuses et la centrale inertielle), trop compliquée à réaliser sur un FPGA à notre niveau, on a simplement remonté le traitement d'un étage sans se poser de question. Ce qui était une erreur, parce que les calculs en points flottant (qu'on devra utiliser de toute manière si l'on ne veut pas rentrer dans de la théorie mathématique trop poussée pour utiliser des nombres entiers) sur l'Arduino ont une performance très faible. On le savait, mais une autre erreur a été de penser que la latence rajoutée du fait des lents calculs était négligeable par rapport à la latence du Raspberry Pi liée au système d'exploitation. Après avoir vérifié en pratique, il se trouve que c'est même l'inverse.<!-- Après tout, quel est l'intérêt d'utiliser un système d'exploitation minimal si c'est pour ne pas en profiter des bénéfices ? -->
 +
 +
L'Arduino n'a donc plus aucun rôle à jouer dans le déplacement du robot. Mais le travail réalisé sur la communication Raspberry Pi <-> Arduino et sur la carte de puissance n'est pas perdu puisqu'il y aura toujours un Arduino sur le robot pour réaliser les actions nécessaires pour le client mais hors du contexte du projet. De plus une partie sera réutilisée pour la communication Raspberry Pi <-> FPGA.
 +
 +
Voici donc ci-dessous le système de communication repensé. A noter qu'une confusion avait été aussi faite précédemment sur le système de communication de l'écran LCD, qui est lui aussi en I2C et non en SPI. Cependant cela ne pose pas de problème car le protocole I2C supporte le mode maître-esclave et que l'écran ne sera pas mis à jour très régulièrement.
 +
 +
[[Fichier:IMA4SC1718-Communication2.svg|400px]]
 +
 +
==Semaine 8==
 +
 +
===Carte de puissance 24V===
 +
 +
Nous avons pu tester notre composant de puissance 24V, nous avons ainsi pu noter que :
 +
le composant est capable de délivrer un 24V continu on note un décrochage à 8,5V et une tension d'accrochage à 9V.
 +
Certaines fonctionnalités des pins Sense et du ON/OFF ont été vérifiée à l'aide d'un potentiomètre mais nous n'en aurons pas l'usage. Cependant pour respecter le choix du client nous garderons toutes les pins disponibles pour assurer la modularité du composant à long terme.
 +
Plusieurs modifications doivent donc être ajoutées au design du PCB.
 +
 +
 +
===Carte de puissance 10V-5V===
 +
 +
[[Image:P66-excelResistor.PNG|350px|thumb|right|Simulateur de décision des résistances, accessible [[https://docs.google.com/spreadsheets/d/12o-t0-J8r7Gmm0sNj0GpuK4PqRz_7LqPpdcwkLS9ias/edit?usp=sharing ici]]]]
 +
 +
Le downconverter de la carte de puissance utilise une résistance pour ajuster la tension de sortie, à partir de la tension d'entrée de la batterie.
 +
Afin de la choisir simplement (et parce qu'un ingénieur qui doit faire au moins deux fois la même chose se doit de l'automatiser), nous avons créé un tableur permettant de connaître :
 +
* la résistance selon la tension de sortie
 +
* la tension selon la résistance
 +
* le taux de variation entre les deux tests précédents (pour savoir si l'approximation réalisée est correcte)
 +
 +
===Routage LMT18200===
 +
 +
[[Image:P66 Top.png|300px|thumb|left|Vue du dessus]]
 +
[[Image:Bot.png|300px|thumb|right|Vue du dessous]]
 +
 +
 +
Pour ce contrôleur moteur nous sommes partis sur une autre approche, l'idée est de réaliser un PCB  permettant le contrôle des deux moteurs directement et utilisant les différents enseignements acquis lors de la conception du PCB destiné au TLE5206.
 +
 +
Pour ce PCB nos objectifs sont dont les suivants :
 +
* Un seul PCB pour contrôler les deux moteurs
 +
* Utilisation de toutes les fonctionnalités offertes pas le LMT (brake, current sense, bootstrap...)
 +
* Optimisation du PCB en terme de place
 +
* Travail sur du double face
 +
* Applications des bonnes pratiques appris durant le routage du TLE5206
 +
 +
Ci-contre se trouve la première version du routage réalisé cette semaine.
 +
 +
<br style="clear: both;" />
 +
 +
==Semaine 9==
 +
 +
=== Finalisation du routage ===
 +
Nous avons modifié le DRC (Design Rule Check) afin de permettre des soudures plus simples. Pour cela nous avons changé la taille de la fraise qui grave le contour des pistes en prenant un diamètre supérieur. Cela permet d'éviter les ponts de soudures et dans l'absolu (même si ici le problème ne se pose pas vu les fréquences utilisées). Cela nous évite également d'avoir des diaphonies en cas de pistes trop proches ou collées entre elles.
 +
 +
 +
Nous avons donc finalisé les 4 PCB :
 +
* La carte de puissance pour les moteurs
 +
* La carte de puissance pour le Raspberry Pi et les autres tâches du robot
 +
* Le contrôleur moteur à base de TLE5206
 +
* Le contrôleur moteur à base de LMT18200
 +
 +
Ce dernier sera en complément usiné en Chine, afin de permettre sa réutilisation pour plusieurs années.
 +
 +
=== Simulation ===
 +
 +
Afin de simplifier la détermination de valeurs pour le régulateur PID servant pour l'asservissement, et de valider l'algorithme de calcul de position et de génération de consigne, une simulation a été initiée sous le logiciel Matlab-Simulink. C'est l'occasion de présenter les différents algorithmes prévus.
 +
 +
==== Calcul de la position ====
 +
 +
[[Fichier:IMA41718P66-CalculPos.png|300px|thumb|right|Visualisation graphique du calcul de position]]
 +
 +
On souhaite (pour un calcul de consigne simple) repérer à tout moment notre robot dans un repère cartésien à l'aide de coordonnées '''x''' et '''y''', ainsi que son orientation via un angle '''o''' par rapport au vecteur directeur des abscisses.
 +
 +
Dans un premier temps, nous récupèrerons la position du robot uniquement grâce aux valeurs des encodeurs. Le FPGA communique au Raspberry Pi la différence de rotation des encodeurs de chaque roue (que l'on nommera deltaGauche et deltaDroite) depuis la dernière lecture. [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/master/chef/src/position.c#L101 On calcule] grâce à de simple calculs de trigonométrie la différence d'angle et de distance qu'a effectué le robot, puis on applique cette différences aux coordonnées existantes.
 +
 +
==== Calcul de la consigne ====
 +
 +
[[Fichier:IMA41718P66-Simu.png|300px|thumb|left|Schema bloc de l'algorithme de choix de la consigne]]
 +
 +
On considère une consigne comme un point de destination (x, y, o) (ou simplement (x, y) si l'angle d'arrivée n'est pas important). On peut alors calculer deux erreurs : l'erreur de distacee et l'erreur en angle.
 +
 +
L'erreur en angle peut prendre deux valeurs différentes. La première est la différence entre l'angle actuel du robot, est l'angle nécessaire que doit adopter le robot pour s'orienter dans la direction du point. C'est la valeur qui est prise quand le robot est loin du point de destination. La deuxième valeur, le cas échéant, est l'angle nécessaire que doit adopter le robot pour s'orienter dans l'angle d'arrivée. On fera en sorte de recadrer la différence dans l'intervalle ]-π, π] afin d'éviter de faire des tours complets inutiles.
 +
 +
L'erreur en distance peut prendre deux valeurs différentes. La première est la distance entre le point actuel du robot et le point de destination du robot. C'est la valeur qui est prise lorsque le robot est orienté vers le point de destination mais n'est pas encore arrivé. La deuxième valeur, le cas échéant, est 0.
 +
 +
De cette manière, à chaque nouvelle consigne le robot évolue de la façon suivante :
 +
 +
* Il s'oriente vers le point de destination
 +
* Il s'avance vers la destination
 +
* Il s'oriente dans l'angle désiré (si présent)
 +
 +
==== Asservissement ====
 +
 +
On se contentera d'utiliser un PID sur chaque roue. La consigne étant recalulée à chaque instant, on peut se le permettre. Si la consigne n'était que calculée une fois, une évolution disparate des deux roues aurait compromis la direction et donc l'arrivée sur le point voulu (même si la distance parcourue par chaque roue aurait été correcte). C'était la technique utilisée par Robotech l'an dernier, et nous avons pu constater de son fonctionnement approximatif.
 +
 +
==== Bilan ====
 +
 +
La simulation permet de vérifier (dans une moindre mesure) les deux algorithmes, et aura permis d'éviter plusieurs erreurs s'il avait été testé en réel directement (les moteurs n'auraient probablement pas apprécié, et les murs non plus), mais le test en conditions réelles doit être réalisé pour vraiment valider ces algorithmes.
 +
 +
==Semaine 10==
 +
 +
 +
===Routage===
 +
Nous avons envoyé à l'usinage les cartes après les derniers ajustements réalisés pendant le weekend.
 +
 +
===préparation du robot===
 +
Le robot est remonté pour permettre une démonstrations rapide lors de la séance de mercredi.
 +
La carte de puissance de l'année dernière a été remise en place avec de nouveaux borniers pour ceux abîmés. Le convertisseur 9V est mort mais nous le savions depuis longtemps.
 +
 +
Problèmes rencontrés et solutions appliquées:
 +
*Un des deux contrôleur moteur qui avait pourtant passé le test lors des soudures s'avèrent défectueux. Une étincelle est apparue au niveau d'un des condensateur qui sera changé. Des tests doivent être refait à basse tension mais la mise en sécurité de l'alimentation et l'échauffement du condensateur ont disparu, il faut à présent vérifier que le pont en H n'a pas été endommagé.
 +
*Tout le câblage a été remplacé avec du câble neuf et bien dimensionné pour les courants passant dedans. De plus nous avons appris lors de nos discussions avec Mr Flamen que l'étamage d'un fil peut engendrer de forts échauffements or un de nos câble était étamé ce qui explique peut être la défaillance du convertisseur 9V de l'année précédente (même si cela est très peu probable car nous n'avons pas ni très fortes tensions ni de très forts courants).
 +
 +
=== Export Gerber pour usinage de PCB à l'extérieur===
 +
Afin de réaliser l'export en gerber de notre PCB nous avons utilisé le fichier CAM suivant[[https://projets-ima.plil.fr/mediawiki/images/e/e1/Elecrow_Gerber_Generater_DrillAlign.zip]] préconisé par electrow.
 +
 +
===Préparation du test de la simulation===
 +
 +
Suite aux échanges que nous avons eu avec M. Boé et M. Redon nous avons compris l'importance de la réalisation d'un test grandeur nature de notre système. Pour le moment nous avons développé un simulateur permettant de tester l'algorithme de déplacement du robot afin de ne pas risquer de l'abîmer lors des tests et pour des gains de temps (on simule en quelques secondes un comportement de quelques minutes).
 +
Toujours est-il que nous n'avons encore jamais vérifié que ce simulateur est bel et bien un simulateur de notre robot. Nous allons donc mettre en place le protocole suivant dans les plus brefs délais :
 +
 +
* test n°1 : Déplacements basique
 +
Situation : robot équilibré
 +
Déplacements : le robot va aller tout droit sur 1m, 2m et 3m.
 +
Mesures : nous mesurerons la dérive droite et gauche après chacun des déplacements ainsi que la fiabilité de la distance parcourue (arrêt trop tardif ou trop précoce)
 +
 +
* test n°2 : Déplacements déséquilibrés à droite
 +
Situation : robot déséquilibré sur sa droite par des poids équivalent à environ 30% du poids du robot actuel
 +
Déplacements : identiques au test 1
 +
Mesures : identiques au test 1
 +
 +
* test n°3 : Déplacements déséquilibrés à gauche
 +
Identique au test 2 mais à gauche
 +
 +
Afin de mesurer les dérives nous placerons un repère droit au sol à l'aide de scotch rouge ou vert centré sur la roue mobile placé au centre du robot.
 +
Nous mesurerons ensuite la distance qui sépare le centre de la roue mobile au scotch à la fin du trajet cela nous indiquera la dérive à l'aide de trigonométrie basique, comme l'illustre le schéma ci-dessous en connaissant AC et AB nous pourrons en déduire Gamma.
 +
 +
[[Fichier:Triangle-trigo.png|200px|thumb|left|]]
 +
 +
<br style="clear: both;" />
 +
 +
==Semaine 11==
 +
 +
===Debugue du TLE5206 ===
 +
 +
Après avoir changé le câblage, les condensateurs et vérifié les pistes du circuits nous en sommes venus à la conclusion que pour une obscure raison les pont en H étaient défaillant. Nous allons donc les dessouder et les remplacer par ceux de rechange.
 +
On peut peut-être conclure que ces ponts en H aux rapports prix/fonctionnalités si intéressants sur le papier ne le sont peut-être pas tant que cela dans la réalité.
 +
Nous sommes d'autant plus heureux d'avoir anticipé avec la conception des autres contrôleurs LMT18200, beaucoup plus fiable normalement.
 +
 +
Nous avons donc pris la décision de ne pas l'utiliser sur les parties vitales du robot lors de la Coupe de France au profit des LMT18200 jugés plus fiables.
 +
 +
===Discussion sur l'agencement du robot ===
 +
Nous avons discuté avec le responsable mécanique de la coupe de France de l'agencement du robot avec les nouvelles cartes plus modulable.
 +
Nous avons envisagés 3 méthodes :
 +
* à l'horizontale avec la construction de plusieurs étages
 +
* à la verticale sur un seul étage ou sur plusieurs avec les cartes les unes derrières les autres
 +
* en carré avec toutes les cartes à la verticale se faisant face.
 +
Certaines parties du robot n'ayant pas encore été complètement conçu nous ne pouvons pas trancher cette question très épineuse surtout en considérant les multiples problèmes que nous avons eu avec les gestions de câbles lors des phases de test. (voir ci-après)
 +
 +
 +
 +
[[Image:P66Bornier-a-vis-3-voies.png|300px|thumb|right|Bornier à vis 3 voies clipsable]]
 +
 +
 +
===Gestion des câbles: déporter la contrainte===
 +
 +
Lors de nos tests nous avons eu beaucoup de difficultés pour maintenir les différents PCB en place sans obtenir de faux contacts ou des câbles débranchées. En faisant part de ce problème avec Mr Boé, il nous a expliqué que la meilleur technique consiste à déplacer la contrainte mécanique en dehors des borniers en utilisant des colliers de serrages attachées à la structure du robot.
 +
Nous avons également décidé de changer certaines borniers pour des plus résistants et surtout emboîtable, de cette façon nous pourrons pour certains PCB visser dans un premier temps les câbles puis placer les pcb à l'intérieur du robot et enfin seulement attacher ces borniers, la majorité des difficultés étant rencontrées à l'installation.
 +
 +
===Pilotage en courant ===
 +
 +
Nous nous sommes posés la question du pilotage en courant de nos moteurs. En effet il pourrait être intéressant de les contrôler en courant ne serait-ce que pour réguler le fait qu'il n'y ait pas de surcharge ou pour lisser les accélérations, décélérations... Ou simplement parce que c'est intéressant.
 +
 +
La méthode la plus simple pour piloter facilement en courant nos moteurs consisterait à placer une résistance en sortie de celui-ci et d'utiliser la loi d'ohm pour déduire de la tension mesuré le courant. Cette tension pouvant aisément être lue par le convertisseur CAN d'un arduino. Attention toutefois à bien choisir la valeur de la résistance pour ne pas envoyer une trop grande tension dans l'arduino.
 +
Une autre méthode pourrait être d'acheter des capteurs de courants qui ne sont pas si onéreux. De cette façon on peut asservir le moteur en courant bien que le seul moyen reste l'envoi d'une tension découpée de l'alimentation à l'aide d'un contrôleur moteur.
 +
 +
Cet aspect restera uniquement théorique malheureusement par manque de temps et surtout d'intérêt pratique immédiat pour la poursuite du projet.
 +
 +
===Contrôle des contrôleurs moteurs===
 +
 +
[[Fichier:IMA41718P66-LMD.png|400px|thumb|right|Table de vérité du LMT18200]]
 +
 +
Chaque contrôleur moteur possède plusieurs entrées, soit analogique (dans laquelle une PWM est fournie), soit numérique (tout ou rien). Les premières servent généralement à indiquer la tension à appliquer aux moteurs, les deuxièmes servent généralement à indiquer le sens de rotation, ou de sélectionner le mode frein ou roue libre.
 +
 +
Nous avons donc créé des fonctions permettant le contrôle des moteurs (fonctions avancer, freiner, reculer...) en appliquant les bonnes entrées sur les contrôleurs moteurs reliés aux broches du Raspberry Pi (cf table ci-contre). On remarque que le Raspberry Pi contient uniquement deux sorties PWM matérielles dédoublées, ce qui est suffisant dans notre cas mais aurait été un facteur limitant dans le cas du TLE5206 possèdant deux entrées PWM par contrôleurs.
 +
 +
Pour contrôler les broches du Raspberry Pi, on utilise la bibliothèque wiringPi, qui s'occupe de mettre les broches dans le bon mode (chaque GPIO peut être mis dans un mode différent offrant une fonctionalité différente) et d'effectuer les appels systèmes nécessaires pour mettre à jour la valeur des broches.
 +
 +
Le contrôle des moteurs est désormais fonctionnel, à une exception près : malgré que les valeurs des PWM soient correctes quand mesurées à l'aide d'un multimètre, les moteurs roulent à puissance maximale ou ne roulent pas, ce qui n'est pas le cas quand on les contrôle avec un Arduino. C'est un problème à investiguer.
 +
 +
==Semaine 12==
 +
 +
=== Récupération des PCB de puissance et corrections d'erreurs ===
 +
 +
A la récupération des PCB nous avons pu constater une erreur apparemment classique de la conception. Lors du choix des composants nous avons placé des borniers en les mesurant en millimètres, or le logiciel était paramétré en mil ou en pouces lors de l'export. Nous avons donc obtenu les PCB avec un décalage de 1 millimètre soit un décalage suffisant pour nous empêcher de placer nos borniers.
 +
 +
Nous sommes donc retournés dans les bibliothèques de composants pour modifier l'espacement et renvoyé à l'impression un seul des 3 PCB pour s'assurer que les corrections sont adaptées.
 +
 +
 +
Cette semaine une partie du temps est consacrée à la soudure de tout ces PCB et également celui usiné en Chine : le fameux LMT18200.
 +
 +
=== câble : gestion de la contrainte mécanique ===
 +
 +
Nous avons continué de traiter ce problème en travaillant avec le responsable mécanique du robot pour envisager les intégrations possibles évoquées la semaine précédente.
 +
 +
 +
=== anticipation modification cartes d'alimentation à découpage ===
 +
 +
Actuellement toutes les cartes sont fonctionnelles et délivre exactement :
 +
4,89V
 +
9,2V
 +
24V
 +
 +
Cela nous permet d'alimenter tout ce dont nous avons besoin en respectant les tensions acceptées sur les différents appareils. En effet la plupart des alimentations secteurs (surtout celles de mauvaises qualités) ne délivrent pas parfaitement 5V et les instruments sont donc souvent tolérants à des tensions comprises entre 5 et 10% entre la tension nominale.
 +
Cependant le Easpberry Pi model B+ est très capricieux sur sa tension d'alimentation et il peut facilement "décrocher" ce qui entraîne des reset aléatoirement durant son fonctionnement d'après nos recherches et des tests réalisés à l'aide d'une alimentation réglable.
 +
 +
Afin de se tenir prêt à toute éventualité nous avons mis de côté des potentiomètres, ceux-ci vont nous permettre de placer en parallèle à notre résistance déjà soudés une résistance d'ajustement. Nous avons des potentiomètres qui possèdent un petit écrou qui peut-être serré de façon à bloquer la résistance. A l'aide de ce système en cas de difficulté lors de la Coupe de France nous pourrons réajuster le système très rapidement.
 +
 +
=Interruption pédagogique=
 +
 +
==Première semaine==
 +
 +
Durant cette période nous partagerons notre temps entre gestion avec les autres membres travaillant sur le robot (essentiellement pour éviter les incompatibilités de conception entre notre travail et le leur) et progression/tests de notre projet IMA4.
 +
 +
=== test de la simulation en réel ===
 +
Suite à la discussion avec nos encadrants nous avions compris l'importance de la réalisation de tests du simulateur qui a été réalisé au cours des semaines précédentes. Cela n'a jamais été aussi vrai vu que lors des tout premiers essais le robot ne s'est pas comporté comme prévu.
 +
Nous avons eu un comportement erratique sans comprendre d'où il pouvait provenir.
 +
Nous allons donc passer en revue toute les sources de problèmes pour les éliminer une à une, à savoir : câblage défectueux, lecture des codeuses par le FPGA, communication FPGA- Raspberry, asservissement, défaut matériel (contrôleur moteur, codeuse, mécanique), alimentation.
 +
 +
 +
=== Résolution du contrôle des moteurs ===
 +
Nous avions vu précédemment que les moteurs tels que contrôlés depuis le Raspberry Pi allaient dans le bon sens mais considérient l'entrée PWM analogique comme une entrée tout ou rien : soit les moteurs tournent à plein régime, soit ils ne tournent pas du tout. Le problème ne se produisant pas lors de nos tests sur Arduino, nous avons essayé de déporter le contrôle des moteurs sur le FPGA, pour voir si cela changeait quelque chose, en vain.
 +
 +
Après quelques recherches plus approfondies, nous nous sommes rendu compte que la capa à l'entrée du contrôleur moteur servait à lisser le signal d'entrée PWM, et la façon dont nous l'avons choisie ne permet d'utiliser des PWM dont la fréquence est au maximum 500 kHz. L'Arduino fonctionne correctement car sa fréquence de génération de PWM est de plusieurs kHz, mais pas le Raspberry étant de base à 19,2 MHz, et pas non plus le FPGA, dont nous avons réalisé la PWM pour une fréquence cible de 700 kHz.
 +
 +
En réduisant la fréquence cible des PWM du FPGA, nous avons pu contrôler les moteurs en toute fluidité. On a remarqué par la suite que la fréquence de génération de PWM du Raspberry Pi est configurable, et peut être changée pour des valeurs tolérées par notre contrôleur moteur, cependant pour des raisons d'optimisation de câblage nous préférereons conserver l'utilisation du FPGA.
 +
 +
=== tle5206 suite et fin ===
 +
 +
Les contrôleurs moteurs TLE5206 se sont révélés très décevant en tests, ils ont rapidement été défaillants n'assurant aucune constance dans leurs fonctionnements même lors des tests avec une alimentation de laboratoire et en respectant les schémas typiques proposés dans la datasheet. Vu la nécessité de fiabilité extrême dont nous avons besoin il n'est pas possible de compteur sur eux.
 +
 +
 +
 +
=== Point rapide sur la soudure : le RoHs ===
 +
Il avait été soulevé la question des températures tolérées par les différents composants à la soudure, en effet on le sait les microcontroleurs par exemple ne sont jamais soudés à même le système car bien trop sensible aux températures élevées. Dans nos datasheet nous avions pu voir une indication de température à propos des "wave solder temperature" autour de 250°  mais aucune concernant une soudure "classique".
 +
Dans les petites lignes nous avons cependant vu que le composant répondait à la norme Rohs ("Restriction of Hazardous Substances") qui indique pour les soudures les alliages autorisés ou non et surtout nous indique les températures de soudures pour chaque cas. De cette façon nous avons vu qu'il n'y avait pas de souci à se faire de ce côté là.
 +
 +
 +
=== Augmentation de la vitesse de la liaison série ===
 +
Jusque là le Raspberry Pi et le FPGA communiquaient à une vitesse de 9600 Baud, valeur utilisée par défaut durant nos tests. Sauf que dans ce cas, l'envoi des données des encodeurs et la récéption de la consigne pour les contrôleurs moteurs (échange de 5 + 4 = 9 octets) prend déjà 7,5 ms. Nous avons donc aumenté le débit à 115200 Baud ce qui s'est passé sans encombre et réduit l'aller-retour de ces données sur liaison série à un négligeable 0,625 ms.
 +
 +
=== Contrôleur moteur différence entre un PCB double face et un PCB industriel ===
 +
 +
==== Carte industriel analyse ====
 +
Lors de nos essais à Polytech de contrôleur moteur nous avions laissé passer une patte normalement relié à la masse au travers d'une piste, cela n'avait pas posé de problème, nous avons juste soudé le composant d'un seul côté et non pas en traversant et le problème était réglé.
 +
Cependant lors de l'usinage industriel nous n'avions pas imaginé une certaine différence : l'intérieur des trous est étamé. Cela signifie que lorsque l'on usine un trou pour composant celui ci est relié entre les pistes de chaque côté! Dans le cas de notre PCB cela n'a pas eu de conséquence pour son fonctionnement global. C'est un point tout de même intéressant à prendre en compte à l'avenir.
 +
 +
==== Solutions et opportunités ====
 +
 +
Toutefois cette situation nous permet d'envisager une solution très élégante pour le robot.
 +
Le problème principal sur notre projet réside au final dans le volume disponible pour la disposition de tout nos éléments au sein du robot, c'est cette contrainte, très forte, qui a conduit à de nombreux choix sur le robot.
 +
Suite à la constatation précédentes nous devons donc souder 2 cartes pour contrôler les moteurs en utilisant les PCB usinés à l'extérieur. Cela nous offre donc des PCB beaucoup plus petit et nous pouvons donc exploiter un espace pour le moment inutilisé : l'étage des moteurs!
 +
A cet étage se trouve les moteurs, les codeuses et les engrenages allant à la roue, tout ces éléments occupent environ 80% de l'étage et il n'avait donc jamais été envisagé de l'utiliser jusqu'à présent.
 +
Mais avec nos nouveaux PCB nous le pouvons à présent et c'est un gain énorme pour le robot et ses étages supérieurs. Cela devrait même nous permettre de ne pas avoir besoin d'intégrer de 3ème étage, entreprise complexe au vue du barillet très massif qui gêne cette proposition.
 +
 +
 +
=== LM18200T ===
 +
 +
Le LM18200T a été soudé et est parfaitement fonctionnel sur le robot. Fidèle à sa réputation il permet un contrôle rapide et précis des moteurs sans faille constatée pour le moment.
 +
Nous nous sommes mêmes amusés à le pousser dans ses retranchements en bloquant les moteurs à 12V ou en le laissant fonctionner durant plus de 15min pour mesurer si l'échauffement nécessitait un dissipateur passif ou actif. La température est resté raisonnable lors de ces tests donc nous n'en inclurons pas.
 +
 +
=== Alimentation 5v-10V ===
 +
 +
Le PCB permettant la conversion du 14V de la batterie en deux tensions utilisables 5V et 10V utilisables pour respectivement le raspberry et le moteur du barillet ainsi que d'une éventuel arduino Mega est fonctionnel. Il a été testé sur alimentation réglable afin de visualiser les écarts en cas de variation de tensions. En effet les batteries Lipo n'offrent pas une tension très stable, en charge complète on peut observer 15.3V et en décharge descendre en dessous de 14.4 V! Dans ces conditions notre cartes à toujours maintenus une tension équivalente ce qui est très positif.
 +
Nous avions ici fait le pari d'un PCB très petit au détriment éventuellement de certains composants extérieurs de feedback ou de filtres en comptant sur le fait que les possibles fluctuations pouvant s'opérer seraient tolérer par nos composants, ce qui est parfaitement le cas.
 +
 +
=== Construction du robot ===
 +
Les étages du robot précédent ont été démonté.
 +
Afin de limiter les court circuit un revêtement en caoutchouc a été placé sur tout l'étage principal.
 +
Après relecture du cahier des charges nous avons utilisé une règle étalon avec toutes les mesures (hauteur maximal du robot, de sa balise, hauteurs des différents éléments de jeux influençant le design du robot etc.) ainsi qu'une corde pour vérifier rapidement le périmètre du robot.
 +
La partie haute du robot accueillant la balise a été surélevée de plusieurs centimètres, une platforme a été intégré, cela a eu deux effets : de la place disponibles en dessous pour permettre la disposition de cartes, un support bien pratique pour fixer les Lipo qui prennent une place très conséquente.
 +
 +
=== Garder le Raspberry Pi à l'heure ===
 +
 +
On a pu remarquer que l'heure du Raspberry Pi était toujours remise au premier janvier 1970 à minuit. Cela est dû au fait que ce composant ne comporte pas d'horloge interne avec une batterie séparée, et de ce fait l'heure est remise à 0 à chaque coupure électrique. Pourquoi cette date ? C'est lié au fait que les systèmes UNIX manipulent le plus souvent le temps comme un nombre de secondes écoulé après cette date arbitraire appélée Epoch.
 +
 +
On peut cependant mettre le Raspberry Pi à l'heure en lui faisant se connecter à un serveur de temps par l'intérmédiaire du protocole NTP, cependant cela n'est pas possible sans connexion internet, le robot sera donc à l'heure uniquement lorsqu'il sera démarré en mode debug. Certains systèmes d'exploitation pour Raspberry Pi sauvegardent en mémoire la dernière date connue et la restaurent lors du démarage du système à défaut de trouver un serveur de temps, mais ce n'est pas le cas dans la configuration actuelle de Buildroot, qui préfère remettre la date à 0.
 +
 +
Une date correcte a deux influences dans notre utilisation :
 +
 +
* La mise à jour des fichiers du système d'exploitation dépend des dates de ceux-ci. Si le fichier possède une date proche de l'epoch, il sera écrasé même si le contenu est en réalité plus récent ou identique. Il faut donc faire attention à cela
 +
* Les fichiers de journaux que nous générons portent le nom d'une date pour les organiser chronologiquement. Cependant, cela serait efficace dans le cas où l'horloge système était uniquement croissante... On préfèrera utiliser un numéro incrémentant pour ces noms de fichier.
 +
 +
=== Disposition des cartes et éléments vitaux sur le robot ===
 +
 +
Nous avons a disposer les éléments suivants :
 +
1 Lipo placé dans un sac de protection Lipo Safe
 +
1 carte de puissance 24V
 +
1 carte de puissance 5V/10V
 +
2 cartes de contrôleurs moteurs
 +
1 Raspberry pi
 +
1 PCB pour le contrôle d'un moteur Bioloid
 +
1 Arduino Mega ( en discussion avec les autres équipes travaillant sur le robot pour voir à incorporer cette partie dans la raspberry)
 +
 +
 +
Pour cette étape nous avons rajouté un étage sur le robot, cela a pu être fait car le reste des actionneurs étaient choisis et installées et nous savions donc la place qu'il nous restait de disponible.
 +
 +
=== Capteurs de distance : détermination d'un filtre ===
 +
 +
Les capteurs de distance sont primordiales, ils nous permettront lors de la coupe de France de calibrer le robot automatiquement et surtout d'éviter les potentiels robots adverses (voir même notre robot secondaire si il existe).
 +
Le problème que nous avons déja évoqués est qu'ils sont fortement bruités en environnement "sain" (le fabricarium quand personne ne s'y trouve), lors de la coupe de france l'environnement sera bien pire.
 +
 +
Voici une représentation graphique de ce que renvoi un capteur HSr04 : [[Fichier:P66 bruit.png|200px|thumb|center|]]
 +
 +
 +
Réalisations :
 +
Enregistrements des valeurs renvoyés par le capteur dans un fichier texte au format csv : Pour réaliser cela nous échantillonnons notre capteur à 200Hz en renvoyant sur le port série les valeurs. Puis nous avons utilisé putty qui est capable de façon très simple de lire un port série et d'enregistrer les valeurs dans un fichier texte. Après une petite remise en forme des données à coup de sed nous obtenons le graphique présenté plus haut.
 +
 +
Afin de pouvoir tester différents filtres passe bas nous sommes passés par matlab, en bref nous avons :
 +
Chargé le fichier csv dans une matrice
 +
Réaliser une FFT sur cette matrice  [[Fichier:P66 fft.png|200px|thumb|center|]]
 +
 +
Remis en forme les valeurs pour pouvoir les afficher et ainsi obtenir ce graphe :
 +
Testé différents filtre comme montré ci dessous :
 +
à 5Hz : [[Fichier:P66_5hz.png|200px|thumb|center|]]
 +
 +
à 1Hz : [[Fichier:p661hz.png|200px|thumb|center|]]
 +
 +
à 10Hz : [[Fichier:P6610Hz.png|200px|thumb|center|]]
 +
 +
Pour conclure c'est le filtre 10Hz qui l'emporte, il permet un retard négligeable compte tenu de notre constante de temps mécanique (le robot ne se déplacera pas à plus de 8 km/h en moyenne) [[Fichier:P66graph.png|200px|thumb|center|]]
 +
 +
 +
Ce filtre sera intégré sur le FPGA.
 +
 +
=== Point d'attention lié à l'alimentation du robot avec les batteries===
 +
Nous avons remarqué quelque chose quelque peu surprenant mais bel et bien non négligeable. Lorsque la batterie baisse en charge, autour de 40% soit 15.1V-15V, la batterie ne délivre plus assez de courant pour alimenter l'ensemble du robot bien que nos tensions au sein du robot restent stable (donc aucune coupure des ordinateurs de bords et moteur alimenté en 24V). La carte de puissance remplit donc bien son rôle mais le courant ne suit plus. 
 +
Ce problème nous a causé plusieurs fois des soucis car il n'est pas évident à déceler le système fonctionnant toujours mais au ralenti pour les moteurs, nous avons donc souvent suspecter des problèmes d'ordre informatique lié à la commande.
 +
 +
=== Gestion des signaux ===
 +
Il n'est pas rare que l'un de nos tests tourne au vinaigre, et que le robot se mette dans un état dangereux pour lui (foncer dans un mur ou appliquer une tension trop faible pour les moteurs). Dans ce cas, il est prérférable dans une certaine mesure d'arrêter le programme depuis l'ordinateur de contrôle plutôt que d'utiliser le bouton d'arrêt d'urgence qui éteint complètement le Raspberry Pi entraînant la perte des dernières informations de journaux souvent cruciales dans la détermination de ce qui a pu causer le dysfonctionnement. Cependant, la gestion des contrôleurs moteurs ayant été déporté sur le FPGA, l'envoi d'un signal SIGINT (via les touches Ctrl+C) au programme n'a aucune influence sur le FPGA qui continue à envoyer les mêmes contrôles aux moteurs. Il est alors nécessaire de taper manuellement la commande '''s''' sur la liaison de contrôle afin d'arrêter les moteurs et les actionneurs.
 +
 +
Nous avons donc décidé d'implémenter une simple gestion de signaux telle que vue en cours : en cas d'interruption le programme courant est arrêté et les instructions d'arrêt sont envoyées. C'est une modification simple mais pourtant très pratique. Attention certains programmes de tests ne l'implémentent pas, il faut donc faire attention.
 +
 +
=== Journalisation ===
 +
 +
[[Fichier:IMA41718P66-DebugCSV.png|200px|thumb|left|Extrait d'un journal]]
 +
 +
==== Collecte des journaux ====
 +
 +
 +
Afin de pouvoir analyser les parcours et réaliser des tests, une routine de journalisation est disponible pour chaque programme de test sur le robot, accessible en incluant "debug.h". Elle doit d'abord etre initialisée avant l'initialisation des autres modules à l'aide de la fonction 'configureDebug'. Les autres modules sont ensuite libre d'appeler la fonciton '''void registerDebugVar(char* name, enum debugArgTypes type, void* var)''' qui prend un nom, un type, et un pointeur vers la donnée à journaliser. Une fois l'initialisation de chaque module terminée, il est nécessaire d'appeler la fonction '''void startDebug()''' qui s'occupera de lancer une routine éxécutée en continu s'occupant de récupérer les valeurs indiquées par les pointeurs passsés en paramètre et de les stocker dans un fichier CSV.
 +
 +
[[Fichier:IMA41718P66-Visualisaiton.png|200px|thumb|right|Visualisation d'un journal]]
 +
 +
==== Utilisation des journaux ====
 +
 +
Il est ensuite possible de récupérer les journaux avec la commande 'make getlogs' une fois connecté. Ils sont stockés dans le dossier 'logs', on peut les afficher directement.
 +
Mais il est plus pratique de voir une représentation graphique des données. Pour cela nous avons recyclé le script de simulations (qui n'a pas été continué, faute de complexité d'élaborer une modélisation réaliste du système) afin qu'il puisse afficher les graphes de ces journaux.
 +
 +
=== Contrôle par Ethernet ===
 +
Après le Wi-Fi integré du Raspberry Pi, c'est au tour de notre dongle Wi-Fi de nous lâcher. En attendant d'en trouver un autre, et parce que les câbles de liaison série que nous possèdons sont assez courts et assez peu pratique pour transférer des fichiers (bien que possible avec le protocole xmodem), nous avons établi un moyen de se connecter au robot via câble Ethernet. Mais plutôt que de le connecter à un commutateur, on préfèrera le connecter directement à un ordinateur à l'aide d'une liaison point à point.
 +
 +
Pour cela rien de bien compliqué, il suffit du côté du Raspberry Pi de modifier le fichier /etc/network/interfaces afin d'appliquer à l'interface eth0 une adresse pour le Raspberry Pi et une addresse pour l'ordinateur (qui sont fixées), et de faire la même chose côté ordinateur, avec la commande 'ip address add dev <interface> <adresse PC>/20 peer <adresse Raspberry Pi>' (géré automatiquement par la commande 'make sshconf CON_MODE=eth -B').
 +
 +
Il n'y a pas besoin de câble croisé dans ce cas, pour peu que la carte réseau de l'ordinateur soit suffisament récente.
 +
 +
==Seconde semaine==
 +
 +
Cette semaine a été consacré à l'amélioration du système d'asservissement du robot, l'électronique de puissance et le câblage étant finalisé (il faut toutefois régulièrement lutter contre les branchements chaotique des bénévoles travaillant sur les actionneurs et devant se connecter aux cartes ou aux ordinateurs.
 +
 +
=== Asservissement en position===
 +
Les algorithmes testés précédemment en simulation ont été implémentsé, et ont pu être validé par des tests.
 +
 +
Un changement majeur vis à vis de la simulation a été la place du régulateur PID. En effet, initialement prévu sur les consignes données aux roues, il a été déplacé sur les erreurs en position et en angle. De cette manière, on peut régler la proportion entre la consigne en angle et celle en distance, ce qui nous permet d'améliorer les phases où le robot avance vers sa destination : il doit constamment rectifier sa trajectoire en même temps qu'il avance, mais pas de trop, sous peine que le robot oscille autour de sa trajectoire, et finisse par tourner autour du point de destination sans s'en rapprocher.
 +
 +
On obtient certains problèmes cependant, un gain trop faible (en distance ou en angle) engendre une erreur statique faisant en sorte que le robot n'atteigne jamais sa position.  En effet, autour d'une tension trop faible, les moteurs ne sont pas capables de fournir assez de couple pour déplacer le robot : il y a donc une vitesse minimum pour le robot. Pour corriger ça on peut augmenter le gain afin que le robot aie plus d'élan sur son arrivée, mais dans son départ il demande une grande tension (parfois passant de 0 à 24 V en quelques millisecondes) ce qui n'est ni bon pour les moteurs, ni pour le glissement, ni pour l'accélération trop brutale pour les composants du robot.
 +
De plus, sur des tests en statique sur alimentation réglable, le courant demandé dépassait la limite que pouvait fournir l'alimentation, éteignant ainsi tout le système.
 +
 +
==== Facteur intégral ====
 +
 +
Usuellement, une erreur statique est corrigée par l'augmentation du coefficient intégral du PID, mais cela induit forcément un dépassement de la consigne. En effet, le coefficient intégral ajoute à la consigne une portion du total d'erreur cumulé tout au long de l'asservissement, et ne cesse d'augmenter jusqu'à ce qu'un dépassement suffisant ait eu lieu. Sauf que dans notre cas, un dépassement de consigne engendre un demi-tour du robot pour y revenir, ce qui n'est pas tellement pertinent étant donné qu'il sait pourtant bien reculer. Nous avons essayé de gérer ce cas, en vain.
 +
 +
==== Rate limiter ====
 +
Pour pallier aux problèmes d'accélération trop brutale, nous avons choisi d'implémenter un rate limiter, qui est simplement un procédé mathématique qui s'assure que la dérivée d'une fonction ne dépasse pas une certaine valeur. Dans notre cas, cela permet de limiter l'accélération du robot à une certaine valeur. Cela répond correctement au problème, mais en introduit un autre, en effet pendant la phase d'accélération, l'accélération de la consigne étant au dessus de celle autorisée par le rate limiter, ce qui fait que la tension des deux moteurs augmente à la même vitesse, et la correction de l'angle est donc perdue par le rate limiter.
 +
 +
==== Bilan ====
 +
 +
On se retrouve donc avec trois solutions pas très viables : avoir une grande erreur statique en asservissement, avoir accélération brutale pour les grandes consignes, ou avoir un robot incapable de suivre une ligne droite. Aucune solution n'a cependant été trouvée cette semaine.
 +
 +
[[Fichier:IMA41718P66-AffBoutons.jpg|200px|thumb|left|Afficheur et boutons]]
 +
 +
=== Interface Homme-Machine ===
 +
 +
Afin d'afficher des informations pour le debug de sélectionner des paramètres lors des phases de fonctionnement du robot, un afficheur et des boutons étaient nécessaires. Nous disposions d'un afficheur LCD 16 caractères × 2 lignes contrôlable par une liaison I2C et d'un grand nombre de boutons et d'interrupteurs. Le nombre de paramètres à modifier et de données à afficher n'étant pas très grand, nous avons opté pour un système à base d'écrans. Chaque paramètre modifiable (ex: parcours du robot) et chaque action réalisable (ex : remettre la position à 0) possède son propre écran. On peut passer d'un écran à l'autre à l'aide d'un bouton (le jaune en l'occurence), et changer le paramètre / lancer l'action à l'aide d'un autre bouton (rouge). Cette méthode nous limite donc à des paramètres booléens ou sous forme de liste, mais c'est largement suffisant pour nos besoins. Les informations de debug sont assez nombreuses pour la taille de l'écran, on préferera utiliser les journaux.
 +
 +
 +
L'implémentation des boutons a été réalisée simplement en reliant une broche du bouton à une du Raspberry Pi et l'autre broche du bouton à la masse (la carcasse du robot pouvant servir de masse commune, cela permet de réduire le nombre de fils). Il a ensuite suffit de configurer la broche de l'Arduino en pull-up et de fournir [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/fe3ae8efe9f3ed470307d04078a19360bedf1715/chef/src/buttons.c un objet C] permettant au reste du programme de les utiliser. L'implémentation de l'écran a été réalisé en paramètrant [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/0eb11d9fc6790c0a66de024b3ee03e8699c4995d/raspberrypi/board/robotech/cdfprincipal/post-image.sh le fichier /boot/config.txt du Raspberry Pi pour qu'il active la liaison I2C], en [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/0eb11d9fc6790c0a66de024b3ee03e8699c4995d/raspberrypi/board/robotech/cdfprincipal/rootfs_overlay/etc/init.d/S30hardware activant les modules nécessaires], en créant [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/fe3ae8efe9f3ed470307d04078a19360bedf1715/chef/src/i2c.c un objet C pour simplifier la communication I2C] (utilisant notamment des verrous pour éviter les conflits), et enfin un [https://archives.plil.fr/gbontoux/cdf2018-principal/blob/fe3ae8efe9f3ed470307d04078a19360bedf1715/chef/src/lcd.c objet C pour contrôler l'afficheur LCD].
 +
 +
[[Image:IMA4SC1718P66-IHM.jpg|300px|thumb|right|Ébauche du schéma fonctionnel de l'IHM]]
 +
 +
 +
Le code de l'afficheur LCD a été principalement repris de codes d'exemple pour Arduino. En effet nous n'avons pas étudié en profondeur le fonctionnement de cet écran car ne souhaitions pas utiliser les fonctionalités avancée de l'écran, et si celui-ci venait à devenir défaillant, possédant uniquement des types différents d'afficheur cette étude et le code produit serait devenu obsolète. Cependant, on a remarqué que l'écran se mettait de temps en temps en défaut, affichant des caractères japonais. Ce problème est probablement dû aux modes de l'afficheur (envoi de données sur 8 ou 4 bits) se décalant. En guise de solution créative au problème, nous avons connecté la masse de l'afficheur sur une broche de sortie du Raspberry Pi, permettant de remettre à zéro l'afficheur à volonté (notamment pour les moments critiques).
 +
 +
Enfin, afin de pouvoir contrôler le robot à distance, l'affichage de l'écran a été dédoublé pour être aussi affiché sur la sortie standard lorsque le programme est éxecuté en mode attaché, et les deux boutons peuvent être aussi appuyés en tapant 1 ou 2 dans l'entrée standard. Cela permet un contrôle à distance, certes basique mais amplement suffisant pour nos besoins.
 +
 +
=== Outils de débug ===
 +
Lors de la programmation quelques erreurs de segmentations sont survenues. Hors, la machine n'embarquant pas (par choix) les outils de debug tels que GDB, et le problème n'étant pas reproductible sur un autre PC (le programme étant trop dépendant de son environnement). Embarquer l'intégralité des outils de débogage sur la machine serait assez lourd, cependant il est possible d'embarquer un programme appelé '''gdb-server''' permettant d'exposer sur une connexion TCP les informations nécessaires pour le déboguage, et on peut ensuite connecter un instace de gdb sur n'importe quel PC connecté au robot pour débuguer à distance. Il suffit simplement de lui indiquer l'adresse du robot et les fichiers comprenant les symboles de debug, qui ne sont pas envoyés sur le Raspberry Pi car ce n'est pas nécessaire mais sont stockés sur l'ordinateur ayant réalisé la compilation (la composante debug a été séparée de la composante programme des éxecutables à l'aide de l'utilitaire 'strip'). À l'accoutumée, il est possible d'accéder automatiquement à cette fonctionalité avec la commande préparée 'make debug'.
 +
 +
 +
=== Auto-diagnostics ===
 +
La façon dont le robot a été cablé étant assez sensible, il a été choisi de réaliser un programme d'auto-diagnostics afin de vérifier que tout fonctionne bien. Le programme -selectionnable même quand le robot n'est pas connecté à un ordinateur depuis l'interface homme-machine embarquée, vérifie que tous les composants sont bien connectés, puis essaye de leur envoyer un ordre, et si possible, vérifie que l'ordre a bien été éxécute (exemple : une tension est appliquée quelques secondes sur un moteur, on vérifie que le déplacement a bien été propagé dans les encodeurs). En cas d'échec d'un diagnostic, son nom reste affiché sur l'écran. Sans echec, il ne dure que quelques secondes.
 +
 +
==Coupe de France de Robotique==
 +
 +
===préparatif===
 +
Nous avons choisi et inventorié tout le matériel emmené "au cas-où", en ce qui concerne le projet il s'agissait essentiellement de cartes de secours et de composants de secours pour le contrôleur moteur, élément le plus susceptible de défaillir lors de la compétition.
 +
 +
=== Sur place===
 +
Toujours en ce qui concerne le projet nous n'avons pas eu de difficultés majeurs hormis une soudure qui a sauté lors du transport mais qui a été décelé lors des tests préliminaire à l'arrivée.
 +
A chaque déplacement du matériel il est conseillé de faire un rapide test de continuité au multimètre puis un essai sous alimentation réglable en courant limité, c'est là que nous avons décelé le problème.
 +
 +
=== un isolant pas si isolant===
 +
Pour isoler nos circuits imprimés du reste de la carcasse métallique nous avons utilisé un caoutchouc déjà disponible dans le matériel de Robotech.
 +
Or nous avons découvert que celui-ci n'était pas isolant! Il semble d'après nos recherches que ce caoutchouc soit complété avec du carbone ce qui le rend conducteur, nous avons mesuré une résistance de 300 kΩ sur un échantillon de 10 cm².
 +
Cette erreur heureusement ne nous a pas causé de dégradation par chance. Toutefois cet imprévu à demander d'improviser une nouvelle isolation, forcément un peu moins propre, à base de bois et de carton.
 +
 +
=== Correction de l'asservissement ===
 +
 +
Après discussions avec d'autres équipes sur l'asservissement que nous avions élaboré, certains conseils nous ont été donnés.
 +
 +
Le rate limiter, bien qu'une bonne idée sur le principe, induit un délai pur dans le process, ce qui est un véritable poison pour l'asservissement. Pour pallier au problème d'accélération trop brutale, il est généralement choisi un asservissement en vitesse et non en position. Pour cela on peut créer un signal de consigne suivant une rampe, mais cela nécessite un nombre non-négligeable de calculs d'intégrales. Étant donné la contrainte de temps, une solution créative a été trouvé pour simuler ce fonctionnement de limiter l'erreur en position et en angle à une certaine valeur, afin de virtuellement limiter la cible à un cone devant le robot. De cette manière l'accélération est limitée, et la correction de la trajectoire peut toujours avoir lieu grâce à une marge sur la tension maximale applicable au robot (que vous avons fixé à 4 V dans notre cas).
 +
 +
De cette manière l'erreur intégrale est calculée sur la consigne réduite, et est donc limitée. Il reste toujours à implémenter la possibilité au robot de reculer dans le cas d'un dépassement. L'erreur commise jusqu'à lors était de laisser activée la correction en angle lors de l'approche du point de destination. En effet dans ce cas le robot pase (inévitablement) un tout petit peu à coté du point, et la correction en angle fait en sorte que le robot soit face au point à tout moment, il ne dépasse jamais donc vraiement le point. En désactivant cette correction à l'approche du point de destination (elle n'est de toutes façons qu'utile loin du point de destination), le robot peut sereinement dépasser le point, puis reculer pour arriver à la valeur voulue. On peut donc désormais augmenter les gains sans problème, et donc profiter d'une plus grande vitesse et d'une meilleure correction d'angle sans en avoir les inconvénients.
 +
 +
Jusqu'à lors, on considérait qu'un ordre était terminé dès que le robot arrivait dans un rayon autour du point de consigne. Deux erreurs sont possible avec ce mode de fonctionnement :
 +
 +
* Le robot n'a pas assez d'élan et bloque un peu avant le rayon
 +
* Le robot a trop d'élan et la consigne suivante est déclenchée alors que la vitesse du robot n'est pas nulle, provoquant des glissements.
 +
 +
Pour pallier à ce problème, on considère que le robot a terminé sa consigne quand sa vitesse est en dessous d'un seuil très bas, et que la tension appliquée aux roues est inférieure au seuil en dessous duquel le robot ne peut démarrer. Cette double vérification permet d'éviter le passage à la consigne suivante dans les cas suivants :
 +
 +
* La tension est nulle car très proche du point de destination mais le robot continue à avancer par intertie
 +
* La vitesse est nulle car elle est en inversion, mais la tension n'est pas nulle car pas encore à la consigne
 +
 +
Avec ces conditions supplémentaires, on peut donc sans problème augmenter le rayon pour lequel le robot en considéré sur le point de destination.
 +
 +
==== Bilan ====
 +
 +
On dispose désormais d'un asservissement tout à fait correct. Cependant l'erreur entre la position connue par le robot et la position réelle n'est pas négligeable après quelques mouvements, en effet les glissements sont de mise.
 +
 +
=== Homologation ===
 +
Lors de la compétition les robots doivent passer devant les arbitres qui vérifient que le robot respectent les différents points précisés dans le cahier des charges. Tout d'abord on a une vérification statique où le robot est mesuré et inspecté puis une vérification dynamique où le robot est placé en situation sur le terrain pour vérifier son bon fonctionnement et surtout qu'il ne peut pas être un danger pour le robot adverse.
 +
 +
==== Statique ====
 +
L'homologation s'est très bien déroulé, les aspects du projet qui ont été évalués n'ont pas posés de problème :
 +
- sécurité et contrôle des batteries
 +
- présence d'un bouton d'arrêt d'urgence permettant de mettre en sécurité le robot et son environnement
 +
- respect des dimensions du robot
 +
 +
==== Dynamique ====
 +
 +
L'homologation dynamique a elle été un peu plus délicate notamment parce que l'arbitre a considéré qu'il existait trop d'angle mort dans notre système de détection d'obstacle. Après un simple réajustement des capteurs le problème était résolu.
 +
L'asservissement un peu capricieux sur le terrain officiel nous a également causé certains problèmes mais encore une fois après ajustements le robot a été homologué.
 +
 +
=== Comparatif avec les autres robots===
 +
Lors de la compétition nous avons l'occasion d'échangé avec de nombreuses équipes sur les choix techniques fait sur leur robot. Il en ressort plusieurs éléments intéressants :
 +
* très peu d'équipe réalisent eux mêmes leurs circuits imprimés, des cartes toutes faites sont achetés puis mise ensemble voir pour certaines équipes l'ensemble de l'électronique est rassemblé sur une seule et même carte professionnel éludant complètement cette difficulté dans la conception du robot.
 +
* Le langage privilégié par les étudiants restent le C mais on constate par rapport à l'année dernière une croissance des langages haut niveau voir très haut niveaux avec certains robots programmés intégralement en Labview par exemple!
 +
* Le choix des capteurs, nous avons utilisé l'existant car Robotech est souvent difficile à convaincre pour l'achat de nouveau matériel quand il en existe déjà du fonctionnel. Nos capteurs bas de gamme et assez anciens sont très loin de ceux d'adversaires qui comportent souvent beaucoup plus d'informatique embarqué que les notre. C'est une piste à souligner pour les années futurs, cela nous aurait probablement faciliter la tâche pour réaliser l'auto-calibrage du robot qui s'est révélé assez incertain malgré l'implémentation de notre filtre sur FPGA pour filtrer les données.
 +
Un capteur pouvant être un bon candidat pour une montée en gamme serait le SRF10 (20€ environ) qui reste un capteur ultrason donc à large cône (environ 30°) ce qui limite le nombre nécessaire sur le robot pour couvrir tout le périmètre de déplacement. De plus grâce à sa communication en I2C il permet un accès facile et une moins grande utilisation des GPIO de la Raspberry ou de l'arduino.
 +
Pour réaliser un auto-calibrage de qualité il faudrait utiliser un capteur dédié de préférence laser sera toujours plus précis qu'un capteur ultrason.
 +
 +
==Dernière semaine et conclusion==
 +
Lors de cette dernière semaine nous avons tourné une vidéo présentant le travail accomplit et dans quel but. Nous remercions d'ailleurs le Laurent Engels pour sa patience et son professionnalisme.
 +
 +
Nous avons également finalisé la rédaction du rapport.
  
 
=Documents Rendus=
 
=Documents Rendus=
  
 +
== Rapport ==
 +
[[Media:IMA41718P66-Rapport.pdf]]
 +
 +
== Code et PCB ==
 +
[https://archives.plil.fr/gbontoux/cdf2018-principal/tree/master Source]
 +
 +
Répartition :
 +
 +
* pcb : Fichiers utilisés pour l'impression des contrôleurs moteurs et des cartes de puissance
 +
* arduino : Partie Robotech, hors-projet
 +
* fpga : Code pour le FPGA et outils de simulation
 +
* raspberrypi : Code pour le système d'exploitation du Raspberry Pi. Contient le Makefile racine.
 +
* simu : code permettant de générer les graphes issu des journaux
 +
* chef : programme principal du Raspberry Pi (gérant le contrôle en position)
 +
 +
Au cours de l'évolution du projet, des grosses parties de codes ont été supplantées par d'autres pour diverses raisons. Elles n'en sont pour le moins pas ininteressantes, voici donc leur lien dans l'historique.
 +
 +
'''Gestion de l'asservissement en position sur Arduino à l'aide de FreeRTOS :'''
 +
 +
[https://archives.plil.fr/gbontoux/cdf2018-principal/tree/a6179781e094d5fbd672501721e080e39db4437d/arduino]
 +
 +
 +
'''Utilisation de la liaison série pour la communication Raspberry Pi ↔ Arduino :'''
 +
 +
Au cours de la compétition un défaut matériel et un manque de pièces de rechange de câble de liaison série ↔ USB nous a forcé à la réimplémenter à l'aide d'une liaison I²C. Cependant cette implémentation rapide est beaucoup moins performante et moins bien réalisée.
 +
 +
[https://archives.plil.fr/gbontoux/cdf2018-principal/tree/a6179781e094d5fbd672501721e080e39db4437d/arduino Module de communication du FPGA]
 +
[https://archives.plil.fr/gbontoux/cdf2018-principal/blob/f730d7b2b11a9252609379956d55a427b03af412/fpga/communication_tb.vhd Banc de test du module de communication du FPGA]
 +
[https://archives.plil.fr/gbontoux/cdf2018-principal/blob/f730d7b2b11a9252609379956d55a427b03af412/fpga/Principal.vhd Module principal du FPGA]
 +
 +
La gestion de la liaison série côté Raspberry Pi est similaire à celle utilisée avec l'Arduino.
  
 
=Bibliographie=
 
=Bibliographie=
 +
Datasheet :
 +
moteurs :
 +
[[Média:P66_Moteurs_principal.zip]]

Version actuelle datée du 15 juin 2018 à 21:57


Vidéo HD

Sommaire


Présentation générale

IMA4-1718-P68-illu.png

Description

La coupe de France de robotique est un événement où des équipes doivent créer un robot autonome afin de réaliser un maximum de tâches données au préalable dans un cahier des charges. Pour ce projet, nous nous concentrerons sur la réalisation de sa base mobile lui permettant de se déplacer ainsi que son “cerveau” qui lui permettra de le contrôler.

Objectifs

Analyse du projet

Positionnement par rapport à l'existant

On se limitera pour cette comparaison aux robots qui visent le même but que le nôtre (à terme) : marquer des points pour les matchs de la coupe de France de robotique. En effet, la robotique est omniprésente dans nos vies maintenant, et il y a un nombre incalculable de bases mobiles existantes, avec différentes caractéristiques : avec des moteurs pas à pas, asservies, rapides, puissantes, capables de se déplacer sur différents terrains… Et ne parlons pas des systèmes de contrôles.

Il y a approximativement 200 participants à l'événement, et donc presque autant de systèmes similaires au notre développés ou en train d’être développés. Cependant leur détails de conceptions sont jalousement gardés par les équipes. On fera donc notre études sur les robots de l’année dernière. On prendra le robot fait par Robotech Lille et celui fait par une autre équipe finaliste, Robotech Legends.

Analyse du premier concurrent

Le robot de l'année dernière en situation

Pour progresser il faut apprendre de ses erreurs. C’est pourquoi regarder en quoi le robot de l’année dernière n’a pas été un franc succès nous paraît judicieux pour pouvoir faire quelques chose de plus performant cette année.

L’erreur qui nous avait été fatale l’année dernière était le manque de qualité du contrôleur moteur. Réalisé avec la graveuse numérique de Polytech et non verni, son ancienneté aura eu raison de lui. De plus, on peut constater quelques défauts d’optimisation : le driver L298 sur la carte peut supporter le contrôle de deux moteurs mais n’en contrôle qu’un seul à la fois. La fonction de freinage est rendue inaccessible par le design de la carte. La solution que nous proposons est simple : créer une nouvelle carte, qui sera vernie pour pouvoir tenir plusieurs coupes.

La carte de puissance avait été réalisée de la même façon, et était beaucoup plus grande que nécessaire. Elle risque de d’avoir le même sort que son congénère. La solution que nous proposons est la même que précédemment, refaire une nouvelle carte plus optimisée et vernie.

L’asservissement en position du robot était aussi dérisoire (heureusement, nous n’avions pas eu à l’utiliser). Seule un encodeur sur deux était utilisé, et seule une des deux sorties de l’encodeur était considérée. De plus le fonctionnement de l’Arduino récupérant les données pouvait parfois faire en sorte qu’un front pouvait être négligé. Pour pallier à ça, on utilisera un FPGA, qui permettra de faire tourner autant de processus en simultané que l’on désire sans qu’ils n’interfèrent entre eux.

De plus, l’utilisation seule des encodeurs n’autorise pas les dérapages (même légers). Pour pallier à ça, on utilisera une centrale inertielle comme seconde source pour récupérer la position du robot.

Enfin, un souci assez récurrent que l’on a rencontré est la difficulté à modifier un programme dans un des processeurs du robot. Il fallait pour cela rapprocher son ordinateur du robot, déplacer la carte de son logement, et la brancher (en prenant le risque de déloger un autre composant au passage). Pour améliorer le processus, on fera en sorte que le Raspberry Pi puisse être mis à jour via une communication sans fil et puisse mettre à jour les autres cartes (Arduino, FPGA) à son tour. Cela permettra d’éviter de perdre du temps à rebrancher des composants.

On remarquera que le choix du matériel n’étais pas tellement un problème l’année dernière, ce dernier se situant plutôt de la manière dont il a été utilisé. C’est pourquoi on peut se permettre d’améliorer sans pour autant trop changer ce qui nous est disponible au départ.

Analyse du second concurrent

Regardons désormais ce qui se fait chez le voisin. Nous avons choisi cette équipe parce qu’elle nous a parlé des méthodes qu’elle a utilisé tout en faisant un bon score.

Cette équipe utilisait un moteur pas à pas afin d’éviter d’avoir à utiliser des encodeurs. Cependant, le caractère discret de la rotation du moteur rajoute un phénomène de glissement, qu’il est difficilement possible de calculer. Pour réduire ce phénomène, nous utilisons des moteurs à courant continu, et nous récupérons leur rotation à l’aide d’encodeurs. Un régulateur PID permet alors de réduire les variations de vitesse trop brusques.

Ils avaient un système de LEDs pour pouvoir savoir où en était le robot dans son programme, et ainsi faciliter le débogage des programmes. Pour reprendre ce principe et l’améliorer, on enregistrera toutes les informations que le système puisse obtenir, et on les transmet par liaison sans fil pour un débogage encore plus simple.

Enfin, ils utilisaient des microcontrôleurs STMicroelectronics pour tout le contrôle du robot. Bien que ces cartes soient très puissantes, elles embarquent un système d’exploitation multi-tâches. Cela simplifie énormément l’étape de programmation, cependant le multi-tâche rajoute de la latence pour les entrées sorties, et perd donc en précision. À la place, nous utiliserons trois puces (deux micro-contrôleurs et un FPGA) plus ou moins complexes parfaitement adaptées à leur tâche. On pourra aussi se vanter d’avoir un robot totalement open-source. Ces puces seront chargées avec le strict minimum pour répondre aux contraintes du cahier des charges, ni plus, ni moins.

Certes, certaines de ces “améliorations” ne sont pas nécessaires pour l’accomplissement du cahier des charges et/ou du défi. Les autres méthodes que nous n’utilisons pas peuvent être “suffisantes”, preuve en est, cette équipe est arrivée en finale alors que d’autres équipes avec des techniques similaires aux nôtres sont arrivées bien plus bas. Mais où est le challenge si on se contente du fait que ça fonctionne ?

Scénario d'usage du produit ou du concept envisagé

Notre robot (vue d'artiste)

Le scénario d’usage voulu serait de jouer et de remporter un match de la coupe de robotique. Cependant, cela ne pourra être atteint sans un travail hors contexte de ce projet, donc voici un scénario type utilisant toutes les éléments que nous aurons eu à réaliser pour ce projet.

Lorsque l’on appuie sur un bouton du robot, il doit se déplacer en suivant un trajet prédéfini ou aléatoire sur un terrain plat. Ce terrain peut être composé de différentes matières. Il possède des mur et des obstacles, si ces derniers se trouvent sur le trajet du robot, ce dernier émet un signal (sonore ou lumineux) et change de trajectoire. Il doit à terme revenir à sa position exacte de départ, avec une faible dérive même en étant passé sur sur des surfaces différentes. Des robots utilisant des capteurs similaires à ceux utilisés par le robot peuvent être disposés sur le parcours, ils doivent être évités mais ne pas faire de faux positifs liés aux interférences. L’utilisateur peut alors se connecter au robot via une communication sans fil et récupérer les journaux de fonctionnement du robot pendant son parcours.

Réponse à la question difficile

Nous n'avons pas eu de questions difficiles lors de la séance de présentation.

Préparation du projet

Cahier des charges

Le robot (du moins la partie du robot sur laquelle nous travaillons) devra répondre aux contraintes suivantes :

  • Se déplace en suivant un parcours. Sur une piste de 2m×3m en PVC (type bâche adhésive décorative pour sol).
  • Est capable de savoir où il est. On s'autorise une dérive de 1mm pour 5m de déplacements. Ces 5 mètres correspondent à la distance que parcourra le robot durant un match. Une précision de 1mm est nécessaire pour réaliser les actions.
  • Évite les obstacles à l’avant et à l’arrière. Le parcours à réaliser est statique, cependant une protection basique contre les imprévus (autres robots) est nécessaire.
  • Résiste aux interférences causées par d’autres capteurs de distance de même type. Il y aura d’autres robots présents sur la piste, et certains d’entre eux pourront utiliser les mêmes capteurs que nous utilisons. Il faudra donc faire en sorte que les interférences ne perturbent en rien le bon fonctionnement de notre robot.
  • Est facilement débugguable. Après la réalisation du robot dans le cadre du projet, il passera dans une longue phase de test pour s'assurer du bon fonctionnement des actions qu'il est censé réaliser. Afin de faciliter et accélerer cette phase, on aimerait plusieurs choses du système de contrôle du robot. Il devra démarrer rapidement, utiliser le minimum de ressources nécessaires, et pouvoir être mis à jour et débuggué via une communication sans fil.
  • Pouvoir interagir avec l'utilisateur. Une fois sur le chemin de compétition, le robot n'aura plus l'aide d'un ordinateur pour pouvoir communiquer avec l'utilisateur. L'utilisateur doit toutefois pouvoir effectuer des tâches simples (saisir la zone de départ, l'équipe, la stratégie...) et contrôler l'état du robot (batterie, calibrage...).
  • Est conforme au cahier des charges de la Coupe de France de Robotique 2018 en tant que robot principal. Disponible ici, il fixe entre autres des conditions sur les dimensions du robot et sur le type de matériel qu'il peut embarquer.
  • Réutilise le matériel disponible. La création depuis zéro d’un tel robot est largement hors-budget pour un projet IMA4. On utilisera au maximum le matériel mis à disposition par Robotech pour minimiser les dépenses.
  • Dispose une alimentation 9 V. Sera utilisé pour les actions du robot hors projet.

Choix techniques : matériel et logiciel

Matériel

Alimentation

  • Batterie Lipo 4S. Dans son sac inifugé.
  • Carte de puissance. Dimensionnée en fonction des éléments et imprimée à Polytech.

Déplacement

  • Support mécanique & Roues. Utilisées pour l'édition de l'année précédente.
  • 2 × Faulhaber MOTOR 3557K024CS. Moteur à courant continu.
  • Contrôleur moteur. Dimensionnée pour nos besoins et imprimée à Polytech.

Connaissance de l'environnement

  • 2 × HEDS-5500 C06. Encodeur rotatif pour l'asservissemnt.
  • Capteur MinIMU-9 v3. Centrale intertielle utilisée en complément pour l'asservissement.
  • X × Capteurs ultrasons / infrarouges. Pour détecter les robots environnants.

Contrôle

La commande et le controle du robot sera géré par 3 puces différentes :

  • MicroNova Mercury FPGA Development Board. Ce FPGA sera utilisé pour les tâches nécessitant une faible puissance de calcul mais un parrallélisme un une très grande réactivité. Entre autre, il récupèrera les valeurs des codeuses des moteurs et s'occupera des l'asservissement des roues à l'aide d'un régulateur PID.
  • Arduino MEGA 2560. Utilisé pour les tâches nécessitant une bonne réactivité mais une puissance de calcul un peu plus élevés. Il s'occupera de s'assurer du bon déroulement de l'action en cours (avancer, pivoter...). Il gèrera notamment les différents capteurs d'obstacles.
  • Raspberry Pi 3. Utilisé pour les tâches n'ayant pas besoin d'une grande réactivité mais d'une grande puissance puissance de calcul. Il s'occupera de garder l'état du robot dans sa mission et de décider de ses prochaines actions. Il sera aussi utilisé pour toutes les actions de débug, sauvegarde et mise à jour des autres puces.

Interface humain-machine

  • Écran LCD SPI. Pour afficher des informations à l'utilisateur.
  • X × Boutons. Pour laisser l'utilisateur choisir des paramètres.

Logiciel

Systèmes d'exploitation

  • Buildroot. Système d'exploitation à configurer et compiler pour le Raspberry Pi. Complètement customisable et permet donc une grande legerté et flexibilité pour les tâches requises.
  • FreeRTOS. Système d'exploitation temps réel pour l'Arduino Mega 2560. Choisi pour simplifier les choses étant donné qu'on l'a déjà vu en TP de temps-réel.

Asservissement

  • Régulateur PID. Asservissement encodeur → moteur à courant continu (direct).
  • Filtre de Kalman / Fusion de données. Asservissement encodeur + IMU → informations sur l'emplacement du robot sur le terrain.


Conception cartes électroniques

  • Eagle
  • Altium

Liste des tâches à effectuer

Optionnel

  • Filtre de Kalman Raspberry Pi (Geoffrey)
  • Concevoir contrôleur moteur avec transistor de puissance Electronique (Amaury)
  • Buildroot en AArch64 Raspberry Pi (Geoffrey)
  • Couche niveau 3 pour correction d'erreur Arduino Raspberry Pi FPGA (Geoffrey)
  • Alléger noyau Linux (encore) Raspberry Pi (Geoffrey)
  • Wi-Fi direct ? Raspberry Pi (Geoffrey)
  • Utiliser la numérotation BCM de WiringPi Raspberry Pi (Geoffrey)
  • réaliser PCB pour le FPGA avec les pins dédiés aux différens controles + des borniers pour le reste Electronique

À faire

En cours

À rédiger

Terminé

  • Expliquer Geoffrey IMU Capteurs (Amaury)
  • Gérer les signaux Raspberry Pi (Geoffrey)
  • PPPoE Raspberry Pi (Geoffrey)
  • i2c sur Rpb maitre escalve Raspberry Pi Capteurs (Geoffrey)
  • ↑115200 Baud Raspberry Pi FPGA (Geoffrey)
  • Mettre en place la liaison série Arduino ↔ FPGA FPGA Arduino (Geoffrey)
  • Synchronisation de temps Raspberry Pi (Geoffrey)
  • Controleur moteur via FPGA FPGA Raspberry Pi (Geoffrey)
  • Contrôle des controlleurs moteurs Raspberry Pi Electronique (Geoffrey)
  • tester contrôleur moteur TLE 5206-2 e Electronique (Amaury, Geoffrey)
  • pilotage en courant des moteurs : recherches bibliographiques Wiki Electronique (Amaury)
  • ajouter photos wiki Wiki Raspberry Pi Electronique Arduino Capteurs Mécanique (Amaury)
  • ⇑Buildroot 2018.02 Raspberry Pi (Geoffrey)
  • Référence du controleur moteur = pin de sortie du FPGA FPGA Electronique (Geoffrey)
  • tester contrôleur moteur LM 18200T Electronique (Amaury, Geoffrey)
  • Ré-assembler le robot Mécanique (Amaury)
  • Analyse interference capteurs Capteurs FPGA (Amaury)
  • dessouder controleur moteur 5206 Electronique Mécanique (Amaury)
  • analyse interférence capteurs : recherche bibliographiques Wiki Capteurs (Amaury)
  • Liste de matériel Wiki (Amaury, Geoffrey)
  • Afficheur & Boutons Raspberry Pi
  • IMU sur FPGA: voir si c'est judicieux FPGA Arduino Capteurs (Amaury, Geoffrey)
  • Hard reset LCD Raspberry Pi (Geoffrey)
  • Rattrapage session Arduino Raspberry Pi Arduino (Geoffrey)
  • GDB server Raspberry Pi (Geoffrey)
  • Diagnostics Raspberry Pi (Geoffrey)
  • PID Raspberry Pi (Geoffrey)
  • Angle indeterminé Raspberry Pi (Geoffrey)
  • Journaux Raspberry Pi (Geoffrey)
  • router controleur moteur avec Lm 18200t sur eagle Electronique (Amaury)
  • Rate limiter Raspberry Pi (Geoffrey)
  • alimentation 12v max pour bioloid : prévoir résistance si besoin de changer Raspberry Pi Electronique (Amaury)
  • alimentation rpb 4.9 actuellement prévoir résistance pour monter à 5.5V si besoin de changer Raspberry Pi Electronique (Amaury)
  • rédaction correction V2 Mr Flamen Electronique Wiki (Amaury)
  • re vérifier datasheet puissance Electronique (Geoffrey)
  • réparation TLE5206 Electronique (Amaury)
  • commande composant complément pour 5206 Electronique (Amaury)
  • faire mail Mr Flamen pour composants complémentaires Electronique (Amaury)
  • commande matériel électronique de puissance Electronique (Amaury)
  • acheter composant carte de puissance Electronique (Amaury)
  • Améliorer le module communication FPGA (Geoffrey)
  • Mettre en place la liaison série Arduino ↔ Raspberry Pi Raspberry Pi Arduino (Geoffrey)
  • Différencier stop/brake Raspberry Pi Arduino (Geoffrey)
  • Upload Pi → FPGA Raspberry Pi FPGA (Geoffrey)
  • Établir protocole communication entre appareils Wiki FPGA Raspberry Pi Arduino (Geoffrey)
  • Dépot git FPGA Arduino Raspberry Pi (Geoffrey)
  • concevoir composants carte de puissance - V0 Electronique (Amaury)
  • concevoir schematic carte de puissance Electronique (Amaury)
  • concevoir carte de puissance Electronique (Amaury)
  • Upload Pi → Arduino Raspberry Pi Arduino (Geoffrey)
  • dimensionner tout les besoin carte de puissance Electronique (Amaury)
  • modification V2-> V3 tle5206 Electronique (Amaury)
  • vérifier typon capa 100uF --> dimension étrange Electronique (Amaury)
  • Choix techniques Wiki (Geoffrey)
  • changer bornier 5206 Electronique (Amaury)
  • Tester l'IMU Capteurs (Amaury, Geoffrey)
  • concevoir V0 contrôleur moteur avec TLE 5206-2 Electronique (Amaury)
  • IMU test faisabilite sur IDE arduino Arduino Capteurs (Amaury)
  • IMU documentation Wiki Electronique Arduino (Amaury)
  • Script pour générer la feuille d'heure Wiki (Geoffrey)
  • Codeuses FPGA Capteurs (Geoffrey)
  • Faire fonctionner la liaison série Raspberry Pi (Geoffrey)
  • Tenter sauvetage module Wi-Fi Raspberry Pi Raspberry Pi Electronique (Amaury)
  • Rajouter des illustrations Wiki (Geoffrey)
  • Tester FPGA Robotech FPGA (Geoffrey)
  • tester moteur pour propulsion des balles --> caractérisation technique indispensable pour la carte de puissance Electronique (Amaury)
  • Rectifier le modèle de FPGA Wiki (Geoffrey)
  • Faire fonctionner Wi-Fi Raspberry Pi (Geoffrey)
  • Repenser la récupération des données des codeuses FPGA Arduino Capteurs (Geoffrey)
  • Filtre capteurs FPGA Capteurs (Geoffrey)
  • commande matériel contrôleur moteur Electronique Arduino (Amaury)
  • Base freeRTOS Arduino (Geoffrey)
  • prendre en compte recommandations Mr Flamen sur V0 Electronique (Amaury)
  • Travail prologue à documenter Wiki (Geoffrey)
  • OS Raspberry Pi Raspberry Pi (Geoffrey)
  • Le bon modèle des codeuses Wiki (Geoffrey)

Calendrier prévisionnel

Difficile d'établir un calendrier prévisionnel quand notre méthode de travail se résume à « prendre un élément dans la liste des tâches à faire qui nous plaît, le faire, répéter ». Heureusement, notre client n'est pas trop pointilleux là dessus.

Réalisation du Projet

Feuille d'heures

Tâche Prlg.
30/10
Prlg.
6/11
Prlg.
13/11
Prlg.
20/11
Prlg.
8/1
S1
15/1
S2
22/1
S3
29/1
S4
5/2
S5
12/2
S6
19/2
Vacs.
26/2
S7
5/3
S8
12/3
S9
19/3
S10
26/3
S11
2/4
S12
9/4
S13
16/4
Vacs.
23/4
Vacs.
30/4
CdF
7/5
Fin
14/5
Total
Analyse et préparation 2 8 10
Prise en main FPGA et tests 5.5 1 0.5 7
Rédaction wiki 2 2.5 5 4.5 1.5 3 6 1.5 1 2 4 2 4 4 8 51
Système Raspberry Pi 3 7 3 13
Élaboration contrôleur moteur 3 9 3 1 2 4 11 3 36
Élaboration carte de puissance 0.5 0.5 0.5 0.5 6 4 4 2 3 4 25
Autre 0.5 0.5
Essai d'exploitation de l'IMU 2 2.5 2 1 2 2 11.5
Nettoyage & Consolidation 3 3 2 1 9
Communication entre les appareils 22 8 16 0.5 1 0.5 48
Analyse et implémentation des capteurs 1.5 3 4.5
Vérification de l'implémentation 4 4
Simulation 6.5 4.5 11
Rédaction rapport 1 5 5 7 17 35
Assemblage et cablage du robot 1 2 1 2 6 3 7 22
Contrôle en position 2 2 6 5 5 20
Contrôle utilisateur 15 8 23
Total 5 5.5 1 8.5 0.5 14.5 13.5 8 13.5 31.5 19.5 25 9.5 23.5 9.5 10 7.5 5 5 40.5 29 19 26 330.5

Semaine 1

Dimensionnement de la carte de puissance

Nous utiliserons comme source d'énergie une batterie Lithium-Polymère (ou LiPo) 4s délivrant une tension de 14.8V.

Note rétro-active : Certaines valeurs et remarques lors de cette analyse initiales sont erronnées, elles ont été corrigées en semaine 4.

Voici l'ensemble des consommateurs constituants le robot :

  • Arduino MEGA : consommant 500mA avec une tension d'alimentation recommandé de 7 à 12V ou par USB de 5V mais cette option est peu recommandée car elle peut entraîner des manques de stabilité dans le fonctionnement du micro-contrôleur et dans la qualité du 5V donnée par les broches.
  • Raspberry Pi 3 : consommant 2.5A avec une tension d'alimentation de 5V.
  • Moteur déplacement: consommant 3A chacun au maximum de leur utilisation nominale cependant ils s'avèrent surdimensionnés pour notre usage. Empiriquement leur utilisation étaient plutôt de l'ordre de 1.5 A maximum. La tension nominale est de 24V nous pouvons donc les alimenter en 12V tout en maintenant une bonne qualité de pilotage. Cependant on choisira de garder l'alimentation du contrôleur moteur en 24V afin de laisser pour les années à venir le choix aux futurs équipes.
  • FPGA Spartan 6 : Consommant au grand maximum 1A à une tension d'alimentation de 5V.
  • Moteur pour les actions du robot. Les actions a proprement parler n'ont pas encore toutes été parfaitement déterminées par notre client. On y reviendra donc plus tard.

Dimensionnement du contrôleur moteur avec pont en H intégré

Voici les caractéristiques demandées par le contrôleur moteur :

  • alimentation au moins en 12V minimum et 24V maximum
  • sortie en 24 V maximum avec 3A de courant par moteur (donc x2)
  • dimensions réduites
  • capacité à être réparé/remplacé facilement lors de la Coupe de France
  • optionnel: protection intégré contre les retours de courants et les courts circuits

Lors de nos recherches nous avons trouvés les 4 commposants suivants répondants à première vue à nos besoins :

Le L298 offre un courant de 4 A maximum donc il ne permet pas de contrôler les deux moteurs en même temps il est donc d'office éliminé.

Le LM 18200T et le LM 18201T offrent un courant de 6 A en pilotant deux moteurs, ils ne sont pas très différents l'un de l'autre à part un prix plus élevé pour le LM 18201T alors qu'il ne possède pas de capteur de courant. De toute façon nous n'avons pas prévu d'utiliser cette fonctionnalité. Le LM18200T permet lui un pilotage plus précis des moteurs avec des capteurs de courants et de températures intégrés mais la densité des pins rend plus complexes le routage et les réparations rapides.

Le TLE 5206-2 est bien plus simple de fonctionnement et offre moins de services que le LM18200T, il permet donc également une simplicité de routage et de modularité mais il ne permet de piloter qu'un seul moteur.

Notre choix s'arrête donc sur la conception dans un premier temps du contrôleur avec les TLE 5206-2 avec deux PCB isolés (un par moteur), puis on utilisera un LM18200T qui pilotera les moteurs en tant que solution alternative mais sur un seul PCB.

FreeRTOS pour Arduino

L'Arduino du robot doit gérer plusieurs tâches à la fois, telles que : la gestion de l'asservissement, des capteurs, l'envoi des données de déboguage... Pour cela, l'utilisation d'un ordonnanceur est inévitable. On aura probablement besoin de sémaphores pour (entre autres) la gestion des ports série et des variables communes aux taches (celles concernant la position du robot notamment).

Nous avons choisi d'utiliser le système d'exploitation temps réel FreeRTOS pour deux raisons. La première est qu'il est très léger, et n'embarque pas plus que ce dont nous avons besoin. La deuxième est que c'est le système que nous avons utilisé dans les TP de l'enseignement Temps Réel, nous avons donc déjà un peu d'experience dans le domaine. La configuration de FreeRTOS pour un hôte Linux et une cible Arduino Mega 2560 nous a été fourni par M. Forget.

Buildroot pour Raspberry Pi

Le Raspberry Pi est le composant qui décide et envoie les ordres de déplacement à l'Arduino et au FPGA. Même s'il n'a pas besoin d'autant de réactivité que ses confrères, il est souhaitable que dès qu'il reçoit l'information que l'ordre précédent a été réalisé (et ses conditions de réalisation), il calcule et et envoie l'ordre suivant dès que possible.

Le problème d'un système d'exploitation de bureau est qu'il y a un certains nombre de services pour simplifier la vie de l'utilisateur tels que l'indexation des fichiers, la découverte réseau, le pare-feu, la vérification des mises à jour... Nous pouvons difficilement contrôler ces tâches, et si notre robot a besoin de la puissance de calcul de la carte quand le système réalise ces tâches plus ou moins inutiles dans notre cas, le temps de réponse pourrait augmenter. Sur une application comme la notre où le temps est compté, cela peut avoir une influence (elle est très probablement minime dans notre cas, mais on choisira de ne pas la négliger).

Répartition de la taille du système d'exploitation

Nous allons donc utiliser un système d'exploitation alternatif conçu uniquement les fonctionnalités dont nous avons besoin. Notons que le cahier des charges nous impose de pouvoir utiliser le Wi-Fi et de pouvoir mettre à jour le système des autres cartes, et on souhaitera pour cela utiliser des outils pré-existants. On n'utilisera donc pas un système type FreeRTOS. Notre choix se portera sur Buildroot qui est un utilitaire qui permet de construire des images de système d'exploitation sur base de noyaux Linux en sélectionnant les options et programmes via un simple fichier de configuration. Le système nous propose aussi de créer nos propres programmes et s'occupe lui-même de la cross-compilation, ce que l'on utilisera pour le(s) programme(s) régissant la logique du robot. La compilation des programmes étant faite sur une machine hôte (et non sur la machine cible, ici le Raspberry Pi), cela nous permet de réduire les temps de compilation. Cela sera particulièrement utile lors des phases de test du robot.

Après ~45 minutes de compilation, une image d'une soixantaine de Mio contenant notre système d'exploitation est générée. Le système démarre en une poignée de seconde, et en idle ne consomme qu'une dizaine de Mio de RAM et il n'y a que très peu d'activité sur le CPU. Toutes le reste des ressources sont alors disponibles pour notre utilisation. Seul bémol, devoir reflasher la carte à chaque modification du système (le programme étant inclus) est assez lourd. On décrira une solution à ce problème dans une prochaine section.

Semaine 2

Mode production / Mode debug

Lorsque le robot sera assemblé, il pourra être fastidieux de brancher un câble à l'interieur pour pouvoir mettre à jour les différentes cartes possèdant une mémoire (Raspberry Pi, Arduino et FPGA). D'autre part, après notre projet terminé, le robot sera transferé à Robotech qui s'occupera d'ajouter des actionneurs pour mener à bien sa tâche pour la compétition, et qui testera le robot. Il va donc falloir mettre à jour les programmes un nombre important de fois.

C'est pour cela qu'a été instauré la contrainte de pouvoir mettre à jour la mémoire des cartes via une communication sans fil. Nous avons choisi d'utiliser une communication Wi-Fi, car elle est simple à mettre en place, et elle permet d'utiliser le protocole SSH qui nous semble le plus simple à configurer pour déboguer. La simplicité est ici de mise, ce n'est pas une section critique du fonctionnement du robot donc si la méthode utilisé pour le déboguage n'est pas la plus performante, ce n'est pas un problème. De plus, l'utilisation d'un protocole très connu et bien testé nous évitera les complications.

IMA4-1718-P66-debugPin.png

Cependant, pour assurer que le Raspberry Pi se lance en un minimum de temps lors de la compétition, on s'assurera de charger uniquement ce qui est nécessaire. Les outils de debug, la connexion Wi-Fi ne seront activées que lorsque deux broches du Raspberry Pi sont court-circuitées. La vérification sera faite à la dernière étape de lancement à l'aide du binaire testpin, qui prend comme argument deux numéros de pins selon la bibliothèque Wiring Pi.

Raspberry Pi 3 : Réparation de la puce Wi-Fi interne

Nous avons constaté durant la semaine précédente que le wifi ne fonctionnait plus. Après avoir éliminé une possible source software nous avons voulu vérifier qu'aucun court-circuit n'était présent sur la carte, elle a donc été nettoyé avec du flux en C201. Le problème a persisté. Par curiosité nous avons mesuré la tension d'alimentation de la puce wifi, elle est de 1.34 V. Or la datasheet du constructeur nous a indiqué que la tension d'alimentation de cette puce doit être comprise entre 3 et 5V. Il semble donc que le problème se trouve au niveau de la carte de puissance. Le Raspberry Pi n'étant pas open hardware (et la possibilité d'une réparation assez faible, vu la taille et la protection des pistes), nous avons arrêté là nos investigations et installé un dongle wifi USB.

Raspberry Pi 3 : Mise en fonctionnement du Wi-Fi

Sur un système d'exploitation classique, il suffit généralement de brancher un dongle Wi-Fi pour faire en sorte qu'il fonctionne. Pour fonctionner, un dongle Wi-Fi (comme beaucoup d'autre périphériques) a besoin d'un firmware, c'est à dire un petit bout de code qui est chargé sur le matériel depuis par le noyau afin qu'il puisse fonctionner. Or, dans notre système d'exploitation à la carte, celui pour notre dongle Wi-Fi n'est pas installé par défaut, il a donc fallu le faire compiler. Ensuite à l’exécution, il faut charger le module correspondant au dongle via un `modprobe`, car il n'est pas chargé automatiquement par le système lors de l'insertion (cela nécessiterait un démon supplémentaire). À partir de là, l'interface `wlan0` est fonctionelle et on peut potentiellement se connecter à un réseau Wi-Fi.

Donc a priori, si on crée un fichier `/etc/network/interfaces` comme nous avons vu en TP de réseau et qu'on lance un `ifup wlan0` cela devrait fonctionner non ? Pas tout à fait. Il s'avère que la commande `ifup` inclue dans notre système (fournie par la boîte à outils BusyBox) n'est pas aussi complète que celle dans l'OS Raspbian utilisé en TP et ne gère pas les instructions `wpa-*` du fichiers `interfaces`. Pour parer à cela, il suffit d'appeler `wpa-supplicant` directement, qui est le programme qui s'occupe (même sur Raspbian) de l'authentification au réseau Wi-Fi. On peut ensuite utiliser `ifup` pour la configuration IP.

Après un rapide test de ping, on installe (enfin plus précisément on dit à Buildroot de compiler dans l'image, puisque le système n'a pas de gestionnaire de paquets) un serveur SSH sur la machine, et on met en place un petit système afin que les la clef privée et l'empreinte de la clef du client soient sur le Raspberry Pi afin de se connecter simplement et rapidement à la machine.

Conception de la carte de contrôleur moteur avec le composant TLE5206

Schematic du contrôleur moteur à base de TLE5206
Routage du contrôleur moteur à base de TLE5206

L'intérêt de ce contrôleur est qu'il très bon marché (4€/pièce), et il permet de contrôler un moteur jusque 5A avec un pic de courant de 6A et une tension d'alimentation allant jusque 40V.

Cependant il disposes de quelques limites :

  • Le pic de courant accepté n'est que de 100ms, ce qui peut être court si nous voulons avoir un déplacement agressif lors de la compétition.
  • Il possède assez peu de protections. En regardant la datasheet on voit que beaucoup court-circuits éventuels ne sont pas couvert par le système de protection, ni par l'indication de flag. La non-détection d'un court circuit au niveau du moteur pourrait lui entrainer des dommages. Étant l'élément le plus cher du robot, notre client nous a demandé d'apporter un soin particulier à ce composant, d'où cette préoccupation.

La conception de la carte a été faite sur Eagle après avoir suivi plusieurs cours en ligne pour se former au logiciel.

Pour nous assurer de la bonne qualité de notre carte, nous avons demandé à M. Flamen un retour sur la qualité de la conception. Voici les premiers éléments à améliorer :

  • Les pistes sont trop étroites. Il est nous est conseillé d'utiliser l'application Electrodroid pour les choisirs.
  • Il faut éviter les angles aigus.
  • Il faut mettre les composants de puissance en bordure de PCB pour permettre l'installation d'un dissipateur.

Semaine 4

Conception de la carte de contrôleur moteur avec le composant TLE5206

Exemple d'un mauvais routage n'optimisant pas l'espace avec des pistes parallèles

Un deuxième retour nous a été effectué par M. Flamen.

Compatibilité Électro-Magnétique : Les angles à 90° sont à éviter mais pas forcément à proscrire, surtout si l'on ne fonctionne pas en haute fréquence (ce qui est notre cas). Les angles inférieurs à 45° et ceux supérieurs à 135° sont à éviter autant que ceux à 90°. Il faut également essayer de garder le même angle entre des broches parallèles afin d'optimiser l'espace et les fraises. En effet en cas d'angle très aigus (comme ceux formés par une connexion en arc de cercle avec une ligne droite) la jonction entre les deux forment un angle très aigus que la fraiseuse va devoir usiner avec des fraises très spécifiques coûtant souvent plus cher que la machine. De plus il s'agit d'une bonne pratique à garder si l'usinage des cartes est chimique car il peut favoriser une collection d'acide entraînant des grignotages sur la carte pouvant altérer son fonctionnement.

Texte sur la carte : L'ajout d'annotations gravées sur le circuit directement est fondamentale, il permet d'éviter les erreurs de branchements et permet de garder un contrôle des versions sur les PCB. Il faut l'ajouter au format tdocu dans l'onglet Computer-Aided Manufacturing afin de graver les lettres et non le contour des lettres. De cette façon on économise en temps de conception et on éviter de trop user les fraises.

Design Rule Check : Il faut modifier la valeur copper dimension à 4mm afin de suivre les spécifications de la graveuse numérique. Cette valeur représente l'espace entre la découpe du contour du PCB et l'espace sans cuivre qu'on laisse autour.

Divers :

  • Il faut faire attention avec le plan de masse à ne pas laisser des zones trop étroite, cela pourrait engendrer des échauffements.
  • Il faut faire attention aux trous de fixation : il faut prendre en compte la tête de la vis. Pour se simplifier la tâche on utilisera Drill 3, qui la prend en compte sur le PCB contrairement à Hole qui se contente de faire un trou.

Après quelques ajustements mineurs par la suite, la carte a été envoyé en impression.

Centrale inertielle

Illustration des 3 composantes
Visualisation d'une séquence de Yaw

Le problème avec les encodeurs de moteurs est qu'ils ne sont pas sensibles à d'éventuels dérapages des roues sur la piste. Dans la mesure où nous souhaitons de fortes accélérations, nous ne pouvons néglier ces pertes. C'est pourquoi nous allons utiliser une centrale intertielle, ou Inertial Measurement Unit (IMU), qui est un PCB embarquant avec lui un gyroscope, un accéléromètre et une boussole. Bien que la précision du capteur soit bonne que les encodeurs, elle permettra de détecter des incohérences liées aux dérapages et les corriger.

Notre IMU, une MinIMU-9 v3 embarque le gyroscope L3GD20H et un accéléromètre/magnétomètre LSM303D.

Nous avons fait des tests préliminaires A l'aide de la documentation fournie par Pololu nous nous sommes assurés du câblage et avons pu nous renseigner sur la communication I2C et les différentes possibilités de l'IMU.

L'IMU peut nous donner les paramètres suivants : le yaw, le pitch et le roll.

Sur l'enregistre de gauche on voit que pour un passage brutal d'angle de la position verticale à horizontale on obtient un pic négatif important (50% de la variation réelle). Cependant il reste très bref (quelques millisecondes).

Un pic similaire a pu être observé sur les autres axes.

Il ne semble pas que celui ci soit un obstacle à la fonctionnalité recherchée mais il est à prendre en compte dans la conception du programme d'asservissement afin d'éviter des corrections excessives en cas de rotation brutale.

Mise à jour du/par Raspberry Pi

Mise à jour de l'OS du Raspberry Pi

Nous avons vu que pour mettre à jour le système d'exploitation du Raspberry Pi, ré-écrire la carte SD en entier n'est ni pratique, ni rapide, ni bon pour la durabilité de la carte. On a donc établi -conformément à ce qui était demandé dans le cahier des charges- un moyen de le mettre à jour par liaison sans file. On a déjà un moyen de se connecter en SSH au Raspberry Pi par Wi-Fi, on transférera donc par ce canal les fichiers générés par buildroot avant mise en image, vers la racine de la carte. On utilisera pour cela `rsync`. Cela rajoute un programme en plus sur l'OS, mais cela permet de ne pas ré-envoyer les fichiers qui n'ont pas changé. Ce n'est pas une solution très élégante, mais elle est redoutablement fonctionelle. Il suffit alors de taper `make upgrade-filesystem` pour lancer l'opération.

Mise à jour de l'Arduino

Le programme utilisé pour téléverser un programme sur un Arduino s'appelle avrdude, et par chance il est dans les programmes proposés par buildroot. Il suffit simplement de l'activer dans la configuration de buildroot et d'ajouter une entrée `upgrade-arduino` dans le Makefile qui se chargera de l'envoi vers le Raspberry Pi et de l'invocation de la commande de téléversement.

Mise à jour du FPGA

On procèdera de la même manière pour téléverser un programme sur le FPGA. Cependant, le FPGA utilisé étant assez peu connu, il n'existe pas de programme directement dans buildroot capable d'effectuer le téléversement. De plus, le programme fourni par le constructeur pour le téléversement est sous forme d'interface graphique ce qui n'est pas adapté pour notre cas. Heureusement, la source du programme est ouverte, et quelqu'un l'a réécrit sous forme de programme en ligne de commande. Il ne reste qu'à créer un package pour buildroot et le tour est joué.

Semaine 5

Carte de puissance

Après de nombreuses discussions auprès du client (à savoir les différentes équipes travaillant sur le robot principal) il semble que les besoins en diverses tensions et courant sont à présent fixés, nous avons donc :

Bilan de puissance
Quantité Consommateur Alimentation Courant maximum
1 Arduino MEGA 9-12V 500mA
1 Raspberry Pi 3 5V 1A
2 Moteur Faulhaber 24V 4,2 A bridé à 2,5A environ
1 FPGA MicroNova Mercury 5V 275mA (nominal 60mA)
1 Dynamixel AX-12 (demmande client) 9-10V 900mA (à vérifier)
2 QH4 4347 (demmande client)  ?  ?


Nous avons donc besoin de sources de tension suivantes :

  • 5V délivrant 1,275A maximum
  • 9V délivrant 1,4A maximum
  • 24V délirant 5A maximum

Il reste une inconnue pour le moment, l'alimentation du moteur QH4 4347.

Il nous reste à présent le choix des composants, 3 possibilités s'offrent à nous :

  • Acheter des convertisseurs clés en mains [1] de ce type. Ils proposent souvent un prix imbattable mais sont rarements fiable presque dangereux.
  • Acheter des composants à souder sur des sites réuputés de ce type. Le prix est plus élevé mais nous avons un composants bien plus fiable et où les échauffements sont très réduits offrant une efficacité imbattable. De plus on a le plaisir de concevoir le PCB qui l’accueillera.
  • Créer nous même le convertisseur en descendant encore d'un niveau. Cependant cela demande de nombreuses heures de conceptions et de tests tout en ayant un prix pas si compétitif face à l'option 1 et 2 et aucune garantie quant à l'efficacité du produit final.
Carte d'alimentation des moteurs
Carte d'alimentation des parties non motorisées

Si l'on s'appuie sur l'expériences des dernières années nous pouvons prospecter la deuxième option : Pour le 5 et le 9V nous pouvons : [2]. Pour le 24V : [3]. Il s'agit de la même famille de composants qui permettent de choisir la tension de sortie à l'aide de quelques composants extérieurs offrant une modularité à cette carte pour les années suivantes. Soit un total de plus de 70€, une solution couteuse mais de qualité.

Pour trancher cette décision nous en avons discuté avec un professeur d'électronique de puissance, M. Delarue.

Il nous a conseillé de favoriser l'option 2 qui reste la meilleure option « en terme de fiabilité, de rendement, d'encombrement, de prix, ... ».

Les composants proposés précédemment sont cepednat des step-down, ils ne peuvent pas produire des tensions supérieures à la tension d'alimentation. On ne pourra donc pas créer de tension à 24V.

Pour le booster qui alimentera nos deux moteurs nous avons vérifié la datasheet du moteur. Il n'y a pas d'indications sur le pic de courant au démarrage du moteur, nous nous baserons donc sur les composants qui ont résisté lors des compétitions précédentes pour que ceux choisis correspondent au minimum aux mêmes caractéristiques techniques.

Pour alimenter nos moteurs nous utiliserons ce composant en 2 exemplaires (1 par contrôleur moteur et donc par moteur).


Nous avons donc routé une première version de deux cartes d'alimentation, une pour les moteurs et une pour le reste (images ci-dessus). Elles sont encore améliorables, il est notamment question d'éventuellement placer un bornier sur les pins inutilisés afin de permettre un éventuel usage plus tard.


Communication entre les appareils

Le Raspberry Pi, l'Arduino et le FPGA doivent pouvoir communiquer ensemble afin de remplir leur rôle. Pour établir un système de communication adapté à leur besoins, établissons la liste (grossière) des informations qui doivent être envoyées d'un appareil à l'autre.

Raspberry Pi → Arduino

  • Ordre d'arrêt
  • Ordre de nouvelle destination
  • Réinitialisation des informations de position

Arduino → Raspberry Pi

  • Arrivée à destination
  • Informations d'état pour le débug

Arduino → FPGA

  • Réinitialisation de la valeur des encodeurs

FPGA → Arduino

  • Valeur des encodeurs
  • Valeur des capteurs de distance

Informons nous sur les différents modes de communication natif des différents appareils :

  • Le Rapsberry Pi possède des accélérateurs matériels pour communiquer en I2C, en SPI et en UART. De plus, une liaison série supplémentaire avec un Arduino est aisément possible à l'aide d'un câble USB.
  • L'Arduino Mega 2560 possède 4 liaisons UART matérielles, et une liaison SPI matérielle.
  • Le FPGA peut utiliser n'importe quel protocole de communication sans effort.

Passons en revue les autres systèmes de communication que nous seront amenés à utiliser et pour lesquels il n'y a peut-être pas de solution alternative.

  • Sur le Raspberry Pi, on aimerait garder la liaison UART matérielle étant un moyen très peu prones aux erreurs d'accéder à un shell du Raspberry Pi. De plus, le port SPI sera utilisé pour l'écran LCD qui servira pour l'interface humain-machine.
  • Sur l'Arduino, la liaison SPI sera utilisée pour communiquer avec la centrale intertielle. La liaison série n°0 est aussi utilisée pour la mise à jour du programme de l'Arduino par USB, il faudra donc éviter de brancher quelque chose dessus.

Cependant ces deux contraintes n'en sont pas réellement, puisque le protocole SPI autorise le branchement de tous les périphériques sur le même réseau de par son schéma maître-esclave. En conséquence, chaque élément possède un temps de parole limité, ce qui peut être problématique dans notre cas d'usage. En effet, il serait facheux que le FPGA doive attendre pour transmettre des informations concernant une collision imminente alors que le réseau est occupé à transférer des données de debug. De plus, les périphériques esclaves ne peuvent communiquer entre eux, tout doit passer par le maître qui devra jouer le rôle de messager au besoin.

Pour ces raisons, et aussi pour des raisons de simplicité, on connectera chaque appareil deux à deux à l'aide d'une liaison série. On obtient un schéma de communication suivant :

IMA4SC1718-Communication.svg

Pour les liaisons séries, on utilisera en couche applicative notre propre format de trame. Chaque trame commencera par un octet indiquant le type d'information à être envoyé. Elle peut être ensuite suivie par des données, dont la taille et la consitution est définie par le type d'information. Chaque information pouvant être transmise, et la structure de données à envoyer est définie dans des fichiers .h, un pour la communication Arduino↔FPGA et un pour la communication Arduino↔Raspberry Pi (dans ces fichiers le Raspberry Pi est aussi appelé Chef, pour le nom du programme).

Certaines informations seront envoyée à l'initiative de l'appareil possédant l'information (Direct), tels que les ordres du Raspberry Pi à l'Aruino. D'autres, seront envoyés à l'initiative de l'appareil ayant besoin de l'information (Indirect), tels que les valeurs des codeuses qui changent bien plus souvent que l'Ardnuio ne saura les traiter. Les dernières, seront envoyés dès que certaines valeurs dépassent un certain seuil (Trigger), seuil fixé par l'appareil reçevant l'information, telles que les valeurs des capteurs de distance. Tout cela permet de garder uniquement les informations utiles, afin de réduire au maximum la congestion du réseau et le traitement par les appareils.

Communication série par interruptions sur Arduino

Jusque là en cours, pour envoyer ou reçevoir des octets sur l'Arduino, on utilisait une boucle qui attendait que les bits RXCn et UDREn du regsitres UCSRnA soit mis à 1, affin d'attendre qu'un octet soit reçu ou prêt à être envoyé respectivement. Le problème de cette méthode, est qu'elle utilise excessivement le CPU et empêche de faire quelque chose d'autre en même temps. Avec le système RTOS, on peut faire plusieurs choses à la fois, mais il faut attendre que la tâche de cette boucle soit élue pour pouvoir traiter l'envoi / la réception de données.

Heureusement, l'Atmega2560 dispose d'interruptions sur le port série. Il suffit d'activer le bit RXCIEn dans le registre UCSRnB pour qu'à chaque réception d'octet sur le port série, l'interruption USARTn_RX_vect se déclenche. Dans notre cas, cette interruption réveille une tâche FreeRTOS à l'aide d'une notification, tâche qui va s'occuper récupérer et traîter les données juste reçues, et se ré-endort jusqu'à la prochaine réception.

On pourrait directement traîter les données dans l'interruption, mais cette méthode a plusieurs avantages. En effet la durée de l'interruption est minime, permet d'utiliser le système de priorités des tâches (alors que l'interruption a une priorité absolue) et évite d'empêcher l'arrivée d'autres interruptions. D'autre part, la tâche peut-être interrompue à n'importe quel endroit, elle est donc un moyen simple de stocker à quel endroit de la reception on en est.

Pour la transmission, deux choix s'offrent à nous : l'utilisation de l'interruption USARTn_TX_vect ou de l'interruption USARTn_UDRE_vect. La première est déclenchée quand un caractère vient de finir sa transmission. On peut alors utiliser cette interruption pour envoyer le prochain caractère dans la file d'attente. Cependant, si on utilise la même méthode que pour la réception, entre le moment où la transmission d'un caractère est terminée et celui où la transmission d'un nouveau caractère est initiée, il va falloir que la tâche faisant l'envoi soit élue. On peut en revanche utiliser le cache matériel de l'Atmega2560, qui permet de stocker deux caractères, et nous permet donc d'envoyer une suite ininterrompue de caractères, et ainsi envoyer les messages plus rapidement. Il faut pour cela utiliser l'autre interruption, USARTn_UDRE_vect qui se déclenche quand il est possible d'écrire dans le cache.

Cependant, cette interruption s'utilise différemment des deux précédentes. En effet, là où les interruptions se déclenchent à un changement d'état (e.g. reception d'un octet), USARTn_UDRE_vect se déclenche continuellement quand le cache de la liaison série est écrivable. D'une part, il faut donc désactiver l'interruption quand il n'y a rien à transmettre. D'autre part, il faut donc écrire dans le cache à l'interieur de l'interruption. On définiera donc un pointeur global vers les données à écrire et leur taille qui sera écrit depuis la tâche voulant envoyer des informations et lue par 'interruption. Une fois l'envoi terminé, l'interruption se désactivera d'elle même et réveillera la tâche ayant initié l'envoi. Cette méthode nous permet d'utiliser au maximum de sa capacité la liaison série tout en encombrant un minimum le processeur de l'Arduino.

Répartitions des messages reçus

Que ce soit du côté de l'Arduino ou du Raspberry Pi, la réception d'octets sur la liaison série est gérée par une seule tâche (ou thread sur le Raspberry Pi). Cependant, pour éviter de complexifier trop cette tâche et de la rendre indépendante des types de messages reçus, on utilisera un système d'observateurs. N'importe quelle partie du programme peut demander à ajouter un observateur sur un certain type de message. L'observateur, étant une fonction, est éxecutée lors de la réception dudit type de message. Cette fonction peut alors récupérer les données du message pour les stocker à l'endroit voulu, et dire à une autre tâche de faire quelque chose avec ces données.

Pour faire cela, la tâche de réception garde un tableau d'observateurs indexés par le type de message auquel il est accroché. Quand le début d'un message est reçu, la tâche regarde dans le tableau si un observateur a été associé au type de message, si oui éxecute la fonction (dans la même tâche, afin que cette fonction puisse lire le reste du message) et si non affiche une erreur.

Récupération de session

Chaque appareil (FPGA, Arduino et Raspberry Pi) est censé pouvoir fonctionner indépendament. Par exemple, si l'on pousse le robot alors que le programme chef du Raspberry Pi est inactif, on veut quand même enregistrer le déplacement afin d'éviter de devoir re-calibrer la position du robot par rapport à son environnement. Ce n'est pas inclus dans le cahier des charges, mais c'est une fonctionalité simple à réaliser vu la réalisation choisie. On pourra donc travailler facilement sur le programme principal (c'est à dire le redémarrer et le modifier) sans que ce dernier n'ait à sauvegarder la dernière position du robot puis la relire.

Cependant, que se passe-t-il si le programme du Raspberry Pi est interrompu alors que l'Arduino est en train d'attendre des informations ? Vraisemblablement, les premiers messages envoyés par le Raspberry Pi seront considerés comme des données de message et seront donc ignorés en tant que message, et par la suite un décalage s'ensuivra. Pour éviter cela, on instaure un nouveau message, le ping. Quand le Raspberry Pi envoi un message de ce type (sur 1 octet), l'Arduino doit lui renvoyer un message du même type et ne rien faire d'autre. Lors du démarrage du programme du Raspberry Pi, ce dernier envoi plein de requêtes ping à la suite, jusqu'à ce que ce que l'Arduino lui renvoie son message. De cette manière tout message en cours de réception côté Arduino sera rempli et les deux appareils seront de nouveau synchronisés. Il faut juste prendre gare à envoyer un message d'arrêt des actionneurs du robot dès la première réponse reçue, car le message en cours de réception contient alors des données invalides qu'il faut annuler.

Semaine 6

Simulation du FPGA

Tests unitaires avec un échec pour le module de communication du FPGA

Écrire un programme pour FPGA est un processus plus compliqué que l'écriture d'un programme pour ordinateur. En effet, dans le premier, il n'y a pas possiblité d'utiliser de débuggueurs pour observer le contenu des variables, ou de moyen simple d'afficher des messages à l'écran. De plus, le processus de synthétisation est plutôt long, et lorsque le FPGA est utilisé avec d'autres périphériques il n'est pas toujours facile de les avoir sous la main pour tester.

Heureusement, il est possible de simuler les programmes de FPGA à l'aide de simulateurs. La génération d'une simulation est généralement beaucoup plus rapide que la synthétisation d'un design, et permet d'observer les signaux internes des composants. L'outil Isim, proposé par Xilinx -le constructeur du FPGA que nous utilisons-, est l'un de ces simulateurs, mais il n'est pas très flexible et s'utilise difficilement sans projet de l'IDE Xilinx, que nous n'utilisons pas pour des raisons évoquées dans le prologue. Nous allons plutôt utiliser deux outils libres, GHDL et GTKWave.

Affichage des signaux pour le module de communication du FPGA

La simulation d'un process commence par l'élaboration d'un testbench, qui est un fichier VHDL qui embarquera comme composant le module à tester, et génèrera des signaux sur les entrées du module à différents instants de la simulation. On peut alors vérifier que les sorties du modules soient conformes à ce qui est attendu : on réalise de la sorte des tests unitaires (cf capture de terminal à gauche). On peut aussi afficher avec GTKWave l'évolution des signaux en fonction du temps afin de débuguer plus finement le programme (cf capture d'écran à droite). Bien entendu, tout le processus de simulation (à part l'élaboration du testbench) a été intégré dans un makefile, afin de pouvoir rafraichir la simulation d'un seul relancement de commande. On retrouvera des fichiers XXX_tb.vhd contenant le testbench pour le module XXX ; des fichiers build/XXX.ghw contenant l'évolution des signaux dans la simulation ; et des fichiers XXX.gtkw contenant les informations d'affichage desdits signaux dans le logiciel (ordre, couleur, type de données...).

Il faut faire cependant attention aux différences existantes entre la simulation et la synthétisation. En effet la simulation est beaucoup plus permissive ce qui permet notamment de simplifier l'écriture de testbenchs. Cependant, certains comportements sont inconnus voire ignorés par le synthétiseur. Par exemple, dans un process il est possible de définir des listes de sensiblité, qui font en sorte que le process ne soit executé uniquement si une des valeurs des éléments de cette liste est changée. Cependant sur le vrai FPGA, cette liste de sensibilité est totalement ignorée et le process est éxecuté à chaque front d'horloge, ce qui peut causer de grandes différences entre la simulation et la réalité. Il faut donc garder en tête ces différences lors de la simulation.


Recherche sur le capteur à ultrason HCR04

Ce composant est un grand classique de la robotique et pourtant on trouve assez peu d'informations précises sur son fonctionnement et ses limites.

étude du capteur

on note qu'il fonctionne à 40Hz soit potentiellement un résultat toutes les 25ms. Les différentes datasheet consultées préconisent une acquisition toutes les 60ms.


Datagramme du capteur

Notre objectif dans cette analyse était principalement de chercher une technique pour s'assurer que le signal provient bien de notre capteur et pas d'un capteur adverse ou d'un autre appareil présent lors de la compétition.

Comme on peut le voir sur ce datagramme il ne sait pas faire la différence entre son écho ou l'envoi d'un autre capteur, cela pourra poser un problème lors de la compétition.

Solutions envisageables

Une solution envisageable peut-être d'intégrer dans le code une logique qui vérifie une certaine redondance de l'information (le delta du capteur étant très inférieur à celui du déplacement des robots) pour s'assurer qu'il s'agit bien de l'écho de notre capteur. On peut également le placer à la limite haute réglementaire qui n'est pas souvent privilégiées par les concurrents.

Une autre solution peut consister à remplacer le capteur ultrason par d'autres types de capteurs. On peut envisager d'utiliser le VL53L0X qui mesure le time of flight (comme le HSR04 au final) mais avec une lumière infrarouge. Il offre sur le papier un capteur sensible de 3cm à 2m avec une précision de 1mm à plus ou moins 10% dans le pire cas. Pour notre usage il n'offre pas d'avantages immenses vu que la précision n'est pas notre critère cependant en utilisant une autre technologie cela pourrait éviter des conflits avec les capteurs adverses. VL53L0X

Nous utiliserons la première solution, pour des raisons financières et également parce que c'est une technique qui a fait ses preuves lors des années précédentes. Cependant elle sera soumise dans le rapport final pour les années futures.


Fréquence d'échantillonage

Il est recommandé dans la datasheet du composant d'échantilloner au minimum toutes les 60 ms, afin d'éviter les intérférences avec les ondes des précédentes mesures (en 60ms le son a la temps de parcourir 10m, distance à partir de laquelle on considère qu'il est complètement atténué). Notre robot possèdera au plus 4 capteurs à ultrasons, est-on obligé de lire les valeurs des capteurs un par un, réduisant la fréquence d'échantillonage à 4 Hz ? La réponse est non. En effet nos capteurs sont positionnés dans des distances opposées, et si les 4 envoient une onde en même temps, la première onde reçue sera renvoyée par l'obstacle le plus proche du capteur la reçevant. On peut donc conserver une fréquence d'échantillonage de 16 Hz.

Vacances

Vue d'ensemble du FPGA

Cette semaine nous allons beaucoup parler du FPGA. Pour mieux comprendre la suite, il peut être utile de rappeler ce que cette carte est censée faire et comment nous comptons lui faire faire.

Les tâches à réaliser par le FPGA sont les suivantes :

  • Récupérer les valeurs des capteurs de deux capteurs distance (un devant et un derrière) (pour l'instant ce sont des capteurs ultrasons de type HC-SR04)
  • Filtrer les précédentes valeurs de façons à enlever les valeurs aberrantes liées aux interférences
  • Récupérer les valeurs des encodeurs (un à gauche et un à droite)
  • Communiquer les valeurs récupérées par liaison série

Basiquement, on écrira un modules VHDL pour chaque tâche, respectivement hcsr04.vhd, fir.vhd,

Récupération des données des encodeurs

Au départ on pensait stocker les valeurs des encodeurs (générées par le FPGA) sur un entier signé de 32 bits, et ce dernier serait envoyé à l'Arduino à chaque fois que ce dernier en a besoin pour actualiser la position du robot. Cependant, on s'est rendu compte que l'Arduino n'a besoin que de la différence entre la précédente valeur et la valeur actuelle pour calculer le déplacement en position. Nous avons donc fait en sorte d'envoyer directement la différence, en remettant à 0 les valeurs à chaque lecture par l'Arduino. Cela se fait par l'entrée zero des modules VHDL des encodeurs, forçant leur valeur à 0, qui est donc mise à '1' pendant un cycle d'horloge.

Mais que se passe-t-il si la valeur des encodeurs change pendant une lecture  ? L'utilisation d'un signal VHDL pour stocker les valeurs ne permet pas d'être modifiée deux fois en un cycle d'horloge (une pour remettre à 0 et une pour incrémenter/décrémenter la valeur), on perdrait donc un peu de données. On utilisera plutôt une variable VHDL. À l'instar d'un signal, elle permet de stocker des données (ici un entier) mais au lieu d'être relative au module elle est relative au processus mais permet d'être écrite plusieurs fois dans le même cycle d'horloge : on ne perd donc pas de données. La probabilité d'une perte de donnée est faible (0,073% de chance pour chaque lecture de valeur à 10 km/h) et l'erreur aussi faible (0,077 mm pour chaque perte), et ce problème aurait certainement pu être négligé par rapport aux dérapages de la roue.

On peut d'ailleurs en profiter pour réduire le nombre entier des valeurs des encodeurs à 16 bits, ce qui laisse au robot le temps de parcourir 5 m sans mise à jour de position avant de faire un dépassement.

Implémentation du filtre pour les interférences

Note : le travail sur le filtre est basé en partie sur le travail réalisé dans le cadre du tutorat de Circuits Numériques Programmables du S7 par Eloi Zalczer et Geoffrey Preud'homme.

Pour filtrer les intérférences et autres valeurs erronées des capteurs de distance, on utilisera un filtre à réponse impulsionnelle finie (ou FIR). L'avantage de ce type de filtres est qu'il est très générique : on peut changer le mode de filtrage (passe-bas, passe-haut...) et ses paramètres (fréquence de coupure...) en changeant les valeurs d'un tableau de coefficients. Plus le nombre N de coefficients est grand, plus Le calcul du signal de sortie se fait simplement en faisant la somme du produit de chaque coefficient par le signal d'entré décalé dans le temps proportionellement à l'indice du coefficient.

Schéma fonctionnel d'un FIR

Les opérations réalisées sont donc de simples retard, additions et multiplications (à l'opposé du filtre à réponse impulsionelle infinie), qui sont des opérations très simple pour le FPGA. Cepedant, les facteurs du filtre sont des décimaux inférieurs à 1, ce que traite difficilement un FPGA. Pour pallier à ce problème, on utilisera la propriété linéaire du filtre : on multipliera les facteurs par un nombre N afin qu'ils signifient quelque chose en tant qu'entier, puis on divisera le résultat par N. Afin de pouvoir effectuer la division simplement sur le FPGA, on prendra une puissnce de 2 comme valeur de N : la division se simplifie alors par un décalage de bits par la droite.

Résumé de l'utilisation du FPGA contenant un filtre à 128 coefficients. À gauche: méthode « immédiate ». À droite méthode « pipeline »

L'implémentation réalisée précédemment calcule la sortie du filtre en un seul front d'horloge. Cette méthode a un avantage : elle est très rapide car prend avantage des ressources du FPGA : chaque multiplication est réalisée en parallèle et chacune utilise une partie des ressources du FPGA (i.e. les tables de correspondances (LUT) et les bascules (flip-flop)). Mais c'est aussi un inconvénient, car ces ressources ne peuvent pas être réutilisées pour quelque chose d'autre. Dans notre cas, la sortie du filtre n'a pas besoin d'être calculée en un coup d'horloge (20 ns), on préfèrera utiliser un fonctionnement dit en « pipeline ». Cela consiste à répartir une partie des calculs sur différents coups d'horloge. Dans notre cas, on effectuera une multiplication et une addition par coup d'horloge. Beaucoup moins de ressources du FPGA seront utilisées, car elles seront utilisées plusieurs fois pour le calcul de plusieurs coefficients (cf capture ci-contre).

On peut remarquer que la méthode « pipeline » utilise un des multiplieurs 18 bits × 18 bits du FPGA. Or, ils n'étaient pas utilisés dans la méthode « immédiate ». On peut supposer ceci : étant donné que les coefficients du filtre étaient fixes, chaque multiplication effectuée possèdait un membre fixe. Les blocs de multiplication ont pu donc être optimisés (par exemple une multiplication par un coefficient de valeur '1' peut être remplacée par une identité).

Module de communication

Ce module permet de connecté les différentes valeurs qui peuvent être lues / écrites depuis / vers les autres modules avec le module de la liaison série. Il s'occupe alors de traiter les données arrivant sur la liaison série, modifier valeurs à envoyer sur les autres modules si besoin, et de renvoyer un message sur la liaison série si nécessaire.

À l'arrivée d'un premier octet (qui est dans notre cas le code du message), des signaux sont modifiés pour indiquer la taille du message et ce qu'il faut faire une fois totalement reçu. Le reste du message est lu puis est stocké dans un buffer. Une fois totalement reçu, une routine redirigeant les informations contenues dans le buffer dans les signaux connectés aux autres modules est executée. Éventuellement, un message à envoyer est stocké dans une queue d'envoi. Lorsque cette queue n'est pas vide, le premier élément de la queue est lu, les informations correspondantes sont stockées dans un buffer d'envoi, et le message est envoyé octet par octet. Une fois terminé, l'opération est recommencée jusqu'à ce que cette queue soit vide.

Une première version de ce module a été écrite, elle utilisait beaucoup de variables de process. Cela faisait en sorte que chaque traitement était réalisé au maximum en un coup d'horloge. Cependant, la vitesse de communication de la liaison série (même à 115200 baud/s) est 400 fois plus lente que les coups d'horloge. Il n'est pas nécessaire d'utiliser des variables dont la modification est immédiate. Le module a donc été réécrit à base de signaux, et 4 coups d'horloge sont à attendre entre la finalisation de la reception d'un message et l'initation de l'envoi de la réponse (reception du caractère, redirection des informations et ajout à la pile, dépilage et écriture du buffer, envoi du caractère). Cela a deux avantages : il réduit la complexité du programme en réduisant le nombre de LUT et de liens, et permet une fréquence de travail plus élevée, ce qui permet ainsi à notre code de fonctionne sur des FPGA dont la fréquence d'horloge est plus basse.

Corrections après usinage carte 5206

Suite à l'usinage nous avons constaté que le plan de masse n'avais pas été correctement interprété par le logiciel, il s'avère que cette toute première étape avait été mal faite. En effet le polygone permettant de créer la masse comportait un segment supplémentaire qui probablement à causé une mauvaise interprétation du logiciel. Cependant grâce au sauvetage de Mr Flamen, nous pouvons tout de même utiliser la carte afin de réaliser un premier test lors de la semaine de rentrée.

Finalisation avec le "client" des besoins en terme de puissance

A la suite d'une dernière réunion nous avons tranché les besoins et les composants de puissances ont donc pu être commandés.

Semaine 7

I2C et IMU

Après avoir étudié les données que nous fourni l'IMU, étudions d'un peu plus près la communication entre l'IMU et l'Arduino, qui avait été faite par abstraction jusqu'à aujourd'hui. La communication se fait via le protocole I2C. Une communication I2C fonctionne à l'aide de 2 pins, SCL et SDA. La pin SCL fourni une clock à l'IMU pour que celui-ci puisse envoyer ses datas via SDA.

La communication peut se faire à plusieurs vitesses différentes, la commutation des bits se fait sur un intervalle de durée déterminé par le tableau ci-dessous.

Mode tLOWmin tHIGHmin
Standard 4,7 μs 4 μs
Fast 1,3 μs 0,6 μs
Fast plus 0,5 μs 0,26 μs

On remarque que les délais sont assez courts. De plus, l'Arduino ne possède pas d'accélérateur matériel pour ce genre de communication. On en déduit donc que le code d'exemple que nous avons utilisé jusqu'ici gère la communication I2C par le programme, et monopolise le CPU pour avoir un timing conforme.

Or, le problème est que notre Arduino est multi-tâches. A première vue FreeRTOS ne nous autorise pas un contrôle aussi précis d'une tâche, et même si c'était le cas les performances seraient probablement fortement dégradées. On abandonne donc l'idée d'utiliser l'IMU depuis l'Arduino.

Retour sur nos pas

Une confusion avait été faite lors de l'élaboration du système d'inter-communication des périphériques. En effet, on pensait que l'IMU communiquait en SPI au lieu de I2C, protocole de communication pour lequel l'Arduino possède un accélérateur matériel. On va donc devoir repenser ce système.

La solution la plus simple pour passer outre ce problème serait d'utiliser le FPGA pour recevoir les communications I2C et les re-transmettre par la liaison série. Cependant, considérons les choses suivantes :

  • Le Raspberry Pi possède un accélérateur matériel pour les liaisons I2C
  • Le Raspberry Pi possède aussi des broches de sortie tout ou rien et deux sorties PWM, de quoi contrôler les moteurs
  • L'Arduino prend beaucoup de temps à effectuer les calculs en point flottant (environ 7 ms pour simplement calculer la position à partir des informations des codeuses), alors que le Raspberry Pi est beaucoup plus rapide

Il serait beaucoup plus judicieux d'effectuer les calculs de position et d'asservissement directement sur le Raspberry Pi, et s'affranchir complètement de l'Arduino. Et c'est d'ailleurs ce que nous allons faire à partir de maintenant.

Pourquoi ne pas être parti sur cette méthode depuis le départ alors ? La raison principale est qu'il était initialement prévu de réaliser l'asservissement sur le FPGA, et ne faire des calculs de positions qu'à chaque nouvel ordre (soit relativement peu fréquemment). En voyant la possibilité de faire de la fusion de données (pour pouvoir connaitre la position à partir de deux sources, les codeuses et la centrale inertielle), trop compliquée à réaliser sur un FPGA à notre niveau, on a simplement remonté le traitement d'un étage sans se poser de question. Ce qui était une erreur, parce que les calculs en points flottant (qu'on devra utiliser de toute manière si l'on ne veut pas rentrer dans de la théorie mathématique trop poussée pour utiliser des nombres entiers) sur l'Arduino ont une performance très faible. On le savait, mais une autre erreur a été de penser que la latence rajoutée du fait des lents calculs était négligeable par rapport à la latence du Raspberry Pi liée au système d'exploitation. Après avoir vérifié en pratique, il se trouve que c'est même l'inverse.

L'Arduino n'a donc plus aucun rôle à jouer dans le déplacement du robot. Mais le travail réalisé sur la communication Raspberry Pi <-> Arduino et sur la carte de puissance n'est pas perdu puisqu'il y aura toujours un Arduino sur le robot pour réaliser les actions nécessaires pour le client mais hors du contexte du projet. De plus une partie sera réutilisée pour la communication Raspberry Pi <-> FPGA.

Voici donc ci-dessous le système de communication repensé. A noter qu'une confusion avait été aussi faite précédemment sur le système de communication de l'écran LCD, qui est lui aussi en I2C et non en SPI. Cependant cela ne pose pas de problème car le protocole I2C supporte le mode maître-esclave et que l'écran ne sera pas mis à jour très régulièrement.

IMA4SC1718-Communication2.svg

Semaine 8

Carte de puissance 24V

Nous avons pu tester notre composant de puissance 24V, nous avons ainsi pu noter que : le composant est capable de délivrer un 24V continu on note un décrochage à 8,5V et une tension d'accrochage à 9V. Certaines fonctionnalités des pins Sense et du ON/OFF ont été vérifiée à l'aide d'un potentiomètre mais nous n'en aurons pas l'usage. Cependant pour respecter le choix du client nous garderons toutes les pins disponibles pour assurer la modularité du composant à long terme. Plusieurs modifications doivent donc être ajoutées au design du PCB.


Carte de puissance 10V-5V

Simulateur de décision des résistances, accessible [ici]

Le downconverter de la carte de puissance utilise une résistance pour ajuster la tension de sortie, à partir de la tension d'entrée de la batterie. Afin de la choisir simplement (et parce qu'un ingénieur qui doit faire au moins deux fois la même chose se doit de l'automatiser), nous avons créé un tableur permettant de connaître :

  • la résistance selon la tension de sortie
  • la tension selon la résistance
  • le taux de variation entre les deux tests précédents (pour savoir si l'approximation réalisée est correcte)

Routage LMT18200

Vue du dessus
Vue du dessous


Pour ce contrôleur moteur nous sommes partis sur une autre approche, l'idée est de réaliser un PCB permettant le contrôle des deux moteurs directement et utilisant les différents enseignements acquis lors de la conception du PCB destiné au TLE5206.

Pour ce PCB nos objectifs sont dont les suivants :

  • Un seul PCB pour contrôler les deux moteurs
  • Utilisation de toutes les fonctionnalités offertes pas le LMT (brake, current sense, bootstrap...)
  • Optimisation du PCB en terme de place
  • Travail sur du double face
  • Applications des bonnes pratiques appris durant le routage du TLE5206

Ci-contre se trouve la première version du routage réalisé cette semaine.


Semaine 9

Finalisation du routage

Nous avons modifié le DRC (Design Rule Check) afin de permettre des soudures plus simples. Pour cela nous avons changé la taille de la fraise qui grave le contour des pistes en prenant un diamètre supérieur. Cela permet d'éviter les ponts de soudures et dans l'absolu (même si ici le problème ne se pose pas vu les fréquences utilisées). Cela nous évite également d'avoir des diaphonies en cas de pistes trop proches ou collées entre elles.


Nous avons donc finalisé les 4 PCB :

  • La carte de puissance pour les moteurs
  • La carte de puissance pour le Raspberry Pi et les autres tâches du robot
  • Le contrôleur moteur à base de TLE5206
  • Le contrôleur moteur à base de LMT18200

Ce dernier sera en complément usiné en Chine, afin de permettre sa réutilisation pour plusieurs années.

Simulation

Afin de simplifier la détermination de valeurs pour le régulateur PID servant pour l'asservissement, et de valider l'algorithme de calcul de position et de génération de consigne, une simulation a été initiée sous le logiciel Matlab-Simulink. C'est l'occasion de présenter les différents algorithmes prévus.

Calcul de la position

Visualisation graphique du calcul de position

On souhaite (pour un calcul de consigne simple) repérer à tout moment notre robot dans un repère cartésien à l'aide de coordonnées x et y, ainsi que son orientation via un angle o par rapport au vecteur directeur des abscisses.

Dans un premier temps, nous récupèrerons la position du robot uniquement grâce aux valeurs des encodeurs. Le FPGA communique au Raspberry Pi la différence de rotation des encodeurs de chaque roue (que l'on nommera deltaGauche et deltaDroite) depuis la dernière lecture. On calcule grâce à de simple calculs de trigonométrie la différence d'angle et de distance qu'a effectué le robot, puis on applique cette différences aux coordonnées existantes.

Calcul de la consigne

Schema bloc de l'algorithme de choix de la consigne

On considère une consigne comme un point de destination (x, y, o) (ou simplement (x, y) si l'angle d'arrivée n'est pas important). On peut alors calculer deux erreurs : l'erreur de distacee et l'erreur en angle.

L'erreur en angle peut prendre deux valeurs différentes. La première est la différence entre l'angle actuel du robot, est l'angle nécessaire que doit adopter le robot pour s'orienter dans la direction du point. C'est la valeur qui est prise quand le robot est loin du point de destination. La deuxième valeur, le cas échéant, est l'angle nécessaire que doit adopter le robot pour s'orienter dans l'angle d'arrivée. On fera en sorte de recadrer la différence dans l'intervalle ]-π, π] afin d'éviter de faire des tours complets inutiles.

L'erreur en distance peut prendre deux valeurs différentes. La première est la distance entre le point actuel du robot et le point de destination du robot. C'est la valeur qui est prise lorsque le robot est orienté vers le point de destination mais n'est pas encore arrivé. La deuxième valeur, le cas échéant, est 0.

De cette manière, à chaque nouvelle consigne le robot évolue de la façon suivante :

  • Il s'oriente vers le point de destination
  • Il s'avance vers la destination
  • Il s'oriente dans l'angle désiré (si présent)

Asservissement

On se contentera d'utiliser un PID sur chaque roue. La consigne étant recalulée à chaque instant, on peut se le permettre. Si la consigne n'était que calculée une fois, une évolution disparate des deux roues aurait compromis la direction et donc l'arrivée sur le point voulu (même si la distance parcourue par chaque roue aurait été correcte). C'était la technique utilisée par Robotech l'an dernier, et nous avons pu constater de son fonctionnement approximatif.

Bilan

La simulation permet de vérifier (dans une moindre mesure) les deux algorithmes, et aura permis d'éviter plusieurs erreurs s'il avait été testé en réel directement (les moteurs n'auraient probablement pas apprécié, et les murs non plus), mais le test en conditions réelles doit être réalisé pour vraiment valider ces algorithmes.

Semaine 10

Routage

Nous avons envoyé à l'usinage les cartes après les derniers ajustements réalisés pendant le weekend.

préparation du robot

Le robot est remonté pour permettre une démonstrations rapide lors de la séance de mercredi. La carte de puissance de l'année dernière a été remise en place avec de nouveaux borniers pour ceux abîmés. Le convertisseur 9V est mort mais nous le savions depuis longtemps.

Problèmes rencontrés et solutions appliquées:

  • Un des deux contrôleur moteur qui avait pourtant passé le test lors des soudures s'avèrent défectueux. Une étincelle est apparue au niveau d'un des condensateur qui sera changé. Des tests doivent être refait à basse tension mais la mise en sécurité de l'alimentation et l'échauffement du condensateur ont disparu, il faut à présent vérifier que le pont en H n'a pas été endommagé.
  • Tout le câblage a été remplacé avec du câble neuf et bien dimensionné pour les courants passant dedans. De plus nous avons appris lors de nos discussions avec Mr Flamen que l'étamage d'un fil peut engendrer de forts échauffements or un de nos câble était étamé ce qui explique peut être la défaillance du convertisseur 9V de l'année précédente (même si cela est très peu probable car nous n'avons pas ni très fortes tensions ni de très forts courants).

Export Gerber pour usinage de PCB à l'extérieur

Afin de réaliser l'export en gerber de notre PCB nous avons utilisé le fichier CAM suivant[[4]] préconisé par electrow.

Préparation du test de la simulation

Suite aux échanges que nous avons eu avec M. Boé et M. Redon nous avons compris l'importance de la réalisation d'un test grandeur nature de notre système. Pour le moment nous avons développé un simulateur permettant de tester l'algorithme de déplacement du robot afin de ne pas risquer de l'abîmer lors des tests et pour des gains de temps (on simule en quelques secondes un comportement de quelques minutes). Toujours est-il que nous n'avons encore jamais vérifié que ce simulateur est bel et bien un simulateur de notre robot. Nous allons donc mettre en place le protocole suivant dans les plus brefs délais :

  • test n°1 : Déplacements basique

Situation : robot équilibré Déplacements : le robot va aller tout droit sur 1m, 2m et 3m. Mesures : nous mesurerons la dérive droite et gauche après chacun des déplacements ainsi que la fiabilité de la distance parcourue (arrêt trop tardif ou trop précoce)

  • test n°2 : Déplacements déséquilibrés à droite

Situation : robot déséquilibré sur sa droite par des poids équivalent à environ 30% du poids du robot actuel Déplacements : identiques au test 1 Mesures : identiques au test 1

  • test n°3 : Déplacements déséquilibrés à gauche

Identique au test 2 mais à gauche

Afin de mesurer les dérives nous placerons un repère droit au sol à l'aide de scotch rouge ou vert centré sur la roue mobile placé au centre du robot. Nous mesurerons ensuite la distance qui sépare le centre de la roue mobile au scotch à la fin du trajet cela nous indiquera la dérive à l'aide de trigonométrie basique, comme l'illustre le schéma ci-dessous en connaissant AC et AB nous pourrons en déduire Gamma.

Triangle-trigo.png


Semaine 11

Debugue du TLE5206

Après avoir changé le câblage, les condensateurs et vérifié les pistes du circuits nous en sommes venus à la conclusion que pour une obscure raison les pont en H étaient défaillant. Nous allons donc les dessouder et les remplacer par ceux de rechange. On peut peut-être conclure que ces ponts en H aux rapports prix/fonctionnalités si intéressants sur le papier ne le sont peut-être pas tant que cela dans la réalité. Nous sommes d'autant plus heureux d'avoir anticipé avec la conception des autres contrôleurs LMT18200, beaucoup plus fiable normalement.

Nous avons donc pris la décision de ne pas l'utiliser sur les parties vitales du robot lors de la Coupe de France au profit des LMT18200 jugés plus fiables.

Discussion sur l'agencement du robot

Nous avons discuté avec le responsable mécanique de la coupe de France de l'agencement du robot avec les nouvelles cartes plus modulable. Nous avons envisagés 3 méthodes :

  • à l'horizontale avec la construction de plusieurs étages
  • à la verticale sur un seul étage ou sur plusieurs avec les cartes les unes derrières les autres
  • en carré avec toutes les cartes à la verticale se faisant face.

Certaines parties du robot n'ayant pas encore été complètement conçu nous ne pouvons pas trancher cette question très épineuse surtout en considérant les multiples problèmes que nous avons eu avec les gestions de câbles lors des phases de test. (voir ci-après)


Bornier à vis 3 voies clipsable


Gestion des câbles: déporter la contrainte

Lors de nos tests nous avons eu beaucoup de difficultés pour maintenir les différents PCB en place sans obtenir de faux contacts ou des câbles débranchées. En faisant part de ce problème avec Mr Boé, il nous a expliqué que la meilleur technique consiste à déplacer la contrainte mécanique en dehors des borniers en utilisant des colliers de serrages attachées à la structure du robot. Nous avons également décidé de changer certaines borniers pour des plus résistants et surtout emboîtable, de cette façon nous pourrons pour certains PCB visser dans un premier temps les câbles puis placer les pcb à l'intérieur du robot et enfin seulement attacher ces borniers, la majorité des difficultés étant rencontrées à l'installation.

Pilotage en courant

Nous nous sommes posés la question du pilotage en courant de nos moteurs. En effet il pourrait être intéressant de les contrôler en courant ne serait-ce que pour réguler le fait qu'il n'y ait pas de surcharge ou pour lisser les accélérations, décélérations... Ou simplement parce que c'est intéressant.

La méthode la plus simple pour piloter facilement en courant nos moteurs consisterait à placer une résistance en sortie de celui-ci et d'utiliser la loi d'ohm pour déduire de la tension mesuré le courant. Cette tension pouvant aisément être lue par le convertisseur CAN d'un arduino. Attention toutefois à bien choisir la valeur de la résistance pour ne pas envoyer une trop grande tension dans l'arduino. Une autre méthode pourrait être d'acheter des capteurs de courants qui ne sont pas si onéreux. De cette façon on peut asservir le moteur en courant bien que le seul moyen reste l'envoi d'une tension découpée de l'alimentation à l'aide d'un contrôleur moteur.

Cet aspect restera uniquement théorique malheureusement par manque de temps et surtout d'intérêt pratique immédiat pour la poursuite du projet.

Contrôle des contrôleurs moteurs

Table de vérité du LMT18200

Chaque contrôleur moteur possède plusieurs entrées, soit analogique (dans laquelle une PWM est fournie), soit numérique (tout ou rien). Les premières servent généralement à indiquer la tension à appliquer aux moteurs, les deuxièmes servent généralement à indiquer le sens de rotation, ou de sélectionner le mode frein ou roue libre.

Nous avons donc créé des fonctions permettant le contrôle des moteurs (fonctions avancer, freiner, reculer...) en appliquant les bonnes entrées sur les contrôleurs moteurs reliés aux broches du Raspberry Pi (cf table ci-contre). On remarque que le Raspberry Pi contient uniquement deux sorties PWM matérielles dédoublées, ce qui est suffisant dans notre cas mais aurait été un facteur limitant dans le cas du TLE5206 possèdant deux entrées PWM par contrôleurs.

Pour contrôler les broches du Raspberry Pi, on utilise la bibliothèque wiringPi, qui s'occupe de mettre les broches dans le bon mode (chaque GPIO peut être mis dans un mode différent offrant une fonctionalité différente) et d'effectuer les appels systèmes nécessaires pour mettre à jour la valeur des broches.

Le contrôle des moteurs est désormais fonctionnel, à une exception près : malgré que les valeurs des PWM soient correctes quand mesurées à l'aide d'un multimètre, les moteurs roulent à puissance maximale ou ne roulent pas, ce qui n'est pas le cas quand on les contrôle avec un Arduino. C'est un problème à investiguer.

Semaine 12

Récupération des PCB de puissance et corrections d'erreurs

A la récupération des PCB nous avons pu constater une erreur apparemment classique de la conception. Lors du choix des composants nous avons placé des borniers en les mesurant en millimètres, or le logiciel était paramétré en mil ou en pouces lors de l'export. Nous avons donc obtenu les PCB avec un décalage de 1 millimètre soit un décalage suffisant pour nous empêcher de placer nos borniers.

Nous sommes donc retournés dans les bibliothèques de composants pour modifier l'espacement et renvoyé à l'impression un seul des 3 PCB pour s'assurer que les corrections sont adaptées.


Cette semaine une partie du temps est consacrée à la soudure de tout ces PCB et également celui usiné en Chine : le fameux LMT18200.

câble : gestion de la contrainte mécanique

Nous avons continué de traiter ce problème en travaillant avec le responsable mécanique du robot pour envisager les intégrations possibles évoquées la semaine précédente.


anticipation modification cartes d'alimentation à découpage

Actuellement toutes les cartes sont fonctionnelles et délivre exactement : 4,89V 9,2V 24V

Cela nous permet d'alimenter tout ce dont nous avons besoin en respectant les tensions acceptées sur les différents appareils. En effet la plupart des alimentations secteurs (surtout celles de mauvaises qualités) ne délivrent pas parfaitement 5V et les instruments sont donc souvent tolérants à des tensions comprises entre 5 et 10% entre la tension nominale. Cependant le Easpberry Pi model B+ est très capricieux sur sa tension d'alimentation et il peut facilement "décrocher" ce qui entraîne des reset aléatoirement durant son fonctionnement d'après nos recherches et des tests réalisés à l'aide d'une alimentation réglable.

Afin de se tenir prêt à toute éventualité nous avons mis de côté des potentiomètres, ceux-ci vont nous permettre de placer en parallèle à notre résistance déjà soudés une résistance d'ajustement. Nous avons des potentiomètres qui possèdent un petit écrou qui peut-être serré de façon à bloquer la résistance. A l'aide de ce système en cas de difficulté lors de la Coupe de France nous pourrons réajuster le système très rapidement.

Interruption pédagogique

Première semaine

Durant cette période nous partagerons notre temps entre gestion avec les autres membres travaillant sur le robot (essentiellement pour éviter les incompatibilités de conception entre notre travail et le leur) et progression/tests de notre projet IMA4.

test de la simulation en réel

Suite à la discussion avec nos encadrants nous avions compris l'importance de la réalisation de tests du simulateur qui a été réalisé au cours des semaines précédentes. Cela n'a jamais été aussi vrai vu que lors des tout premiers essais le robot ne s'est pas comporté comme prévu. Nous avons eu un comportement erratique sans comprendre d'où il pouvait provenir. Nous allons donc passer en revue toute les sources de problèmes pour les éliminer une à une, à savoir : câblage défectueux, lecture des codeuses par le FPGA, communication FPGA- Raspberry, asservissement, défaut matériel (contrôleur moteur, codeuse, mécanique), alimentation.


Résolution du contrôle des moteurs

Nous avions vu précédemment que les moteurs tels que contrôlés depuis le Raspberry Pi allaient dans le bon sens mais considérient l'entrée PWM analogique comme une entrée tout ou rien : soit les moteurs tournent à plein régime, soit ils ne tournent pas du tout. Le problème ne se produisant pas lors de nos tests sur Arduino, nous avons essayé de déporter le contrôle des moteurs sur le FPGA, pour voir si cela changeait quelque chose, en vain.

Après quelques recherches plus approfondies, nous nous sommes rendu compte que la capa à l'entrée du contrôleur moteur servait à lisser le signal d'entrée PWM, et la façon dont nous l'avons choisie ne permet d'utiliser des PWM dont la fréquence est au maximum 500 kHz. L'Arduino fonctionne correctement car sa fréquence de génération de PWM est de plusieurs kHz, mais pas le Raspberry étant de base à 19,2 MHz, et pas non plus le FPGA, dont nous avons réalisé la PWM pour une fréquence cible de 700 kHz.

En réduisant la fréquence cible des PWM du FPGA, nous avons pu contrôler les moteurs en toute fluidité. On a remarqué par la suite que la fréquence de génération de PWM du Raspberry Pi est configurable, et peut être changée pour des valeurs tolérées par notre contrôleur moteur, cependant pour des raisons d'optimisation de câblage nous préférereons conserver l'utilisation du FPGA.

tle5206 suite et fin

Les contrôleurs moteurs TLE5206 se sont révélés très décevant en tests, ils ont rapidement été défaillants n'assurant aucune constance dans leurs fonctionnements même lors des tests avec une alimentation de laboratoire et en respectant les schémas typiques proposés dans la datasheet. Vu la nécessité de fiabilité extrême dont nous avons besoin il n'est pas possible de compteur sur eux.


Point rapide sur la soudure : le RoHs

Il avait été soulevé la question des températures tolérées par les différents composants à la soudure, en effet on le sait les microcontroleurs par exemple ne sont jamais soudés à même le système car bien trop sensible aux températures élevées. Dans nos datasheet nous avions pu voir une indication de température à propos des "wave solder temperature" autour de 250° mais aucune concernant une soudure "classique". Dans les petites lignes nous avons cependant vu que le composant répondait à la norme Rohs ("Restriction of Hazardous Substances") qui indique pour les soudures les alliages autorisés ou non et surtout nous indique les températures de soudures pour chaque cas. De cette façon nous avons vu qu'il n'y avait pas de souci à se faire de ce côté là.


Augmentation de la vitesse de la liaison série

Jusque là le Raspberry Pi et le FPGA communiquaient à une vitesse de 9600 Baud, valeur utilisée par défaut durant nos tests. Sauf que dans ce cas, l'envoi des données des encodeurs et la récéption de la consigne pour les contrôleurs moteurs (échange de 5 + 4 = 9 octets) prend déjà 7,5 ms. Nous avons donc aumenté le débit à 115200 Baud ce qui s'est passé sans encombre et réduit l'aller-retour de ces données sur liaison série à un négligeable 0,625 ms.

Contrôleur moteur différence entre un PCB double face et un PCB industriel

Carte industriel analyse

Lors de nos essais à Polytech de contrôleur moteur nous avions laissé passer une patte normalement relié à la masse au travers d'une piste, cela n'avait pas posé de problème, nous avons juste soudé le composant d'un seul côté et non pas en traversant et le problème était réglé. Cependant lors de l'usinage industriel nous n'avions pas imaginé une certaine différence : l'intérieur des trous est étamé. Cela signifie que lorsque l'on usine un trou pour composant celui ci est relié entre les pistes de chaque côté! Dans le cas de notre PCB cela n'a pas eu de conséquence pour son fonctionnement global. C'est un point tout de même intéressant à prendre en compte à l'avenir.

Solutions et opportunités

Toutefois cette situation nous permet d'envisager une solution très élégante pour le robot. Le problème principal sur notre projet réside au final dans le volume disponible pour la disposition de tout nos éléments au sein du robot, c'est cette contrainte, très forte, qui a conduit à de nombreux choix sur le robot. Suite à la constatation précédentes nous devons donc souder 2 cartes pour contrôler les moteurs en utilisant les PCB usinés à l'extérieur. Cela nous offre donc des PCB beaucoup plus petit et nous pouvons donc exploiter un espace pour le moment inutilisé : l'étage des moteurs! A cet étage se trouve les moteurs, les codeuses et les engrenages allant à la roue, tout ces éléments occupent environ 80% de l'étage et il n'avait donc jamais été envisagé de l'utiliser jusqu'à présent. Mais avec nos nouveaux PCB nous le pouvons à présent et c'est un gain énorme pour le robot et ses étages supérieurs. Cela devrait même nous permettre de ne pas avoir besoin d'intégrer de 3ème étage, entreprise complexe au vue du barillet très massif qui gêne cette proposition.


LM18200T

Le LM18200T a été soudé et est parfaitement fonctionnel sur le robot. Fidèle à sa réputation il permet un contrôle rapide et précis des moteurs sans faille constatée pour le moment. Nous nous sommes mêmes amusés à le pousser dans ses retranchements en bloquant les moteurs à 12V ou en le laissant fonctionner durant plus de 15min pour mesurer si l'échauffement nécessitait un dissipateur passif ou actif. La température est resté raisonnable lors de ces tests donc nous n'en inclurons pas.

Alimentation 5v-10V

Le PCB permettant la conversion du 14V de la batterie en deux tensions utilisables 5V et 10V utilisables pour respectivement le raspberry et le moteur du barillet ainsi que d'une éventuel arduino Mega est fonctionnel. Il a été testé sur alimentation réglable afin de visualiser les écarts en cas de variation de tensions. En effet les batteries Lipo n'offrent pas une tension très stable, en charge complète on peut observer 15.3V et en décharge descendre en dessous de 14.4 V! Dans ces conditions notre cartes à toujours maintenus une tension équivalente ce qui est très positif. Nous avions ici fait le pari d'un PCB très petit au détriment éventuellement de certains composants extérieurs de feedback ou de filtres en comptant sur le fait que les possibles fluctuations pouvant s'opérer seraient tolérer par nos composants, ce qui est parfaitement le cas.

Construction du robot

Les étages du robot précédent ont été démonté. Afin de limiter les court circuit un revêtement en caoutchouc a été placé sur tout l'étage principal. Après relecture du cahier des charges nous avons utilisé une règle étalon avec toutes les mesures (hauteur maximal du robot, de sa balise, hauteurs des différents éléments de jeux influençant le design du robot etc.) ainsi qu'une corde pour vérifier rapidement le périmètre du robot. La partie haute du robot accueillant la balise a été surélevée de plusieurs centimètres, une platforme a été intégré, cela a eu deux effets : de la place disponibles en dessous pour permettre la disposition de cartes, un support bien pratique pour fixer les Lipo qui prennent une place très conséquente.

Garder le Raspberry Pi à l'heure

On a pu remarquer que l'heure du Raspberry Pi était toujours remise au premier janvier 1970 à minuit. Cela est dû au fait que ce composant ne comporte pas d'horloge interne avec une batterie séparée, et de ce fait l'heure est remise à 0 à chaque coupure électrique. Pourquoi cette date ? C'est lié au fait que les systèmes UNIX manipulent le plus souvent le temps comme un nombre de secondes écoulé après cette date arbitraire appélée Epoch.

On peut cependant mettre le Raspberry Pi à l'heure en lui faisant se connecter à un serveur de temps par l'intérmédiaire du protocole NTP, cependant cela n'est pas possible sans connexion internet, le robot sera donc à l'heure uniquement lorsqu'il sera démarré en mode debug. Certains systèmes d'exploitation pour Raspberry Pi sauvegardent en mémoire la dernière date connue et la restaurent lors du démarage du système à défaut de trouver un serveur de temps, mais ce n'est pas le cas dans la configuration actuelle de Buildroot, qui préfère remettre la date à 0.

Une date correcte a deux influences dans notre utilisation :

  • La mise à jour des fichiers du système d'exploitation dépend des dates de ceux-ci. Si le fichier possède une date proche de l'epoch, il sera écrasé même si le contenu est en réalité plus récent ou identique. Il faut donc faire attention à cela
  • Les fichiers de journaux que nous générons portent le nom d'une date pour les organiser chronologiquement. Cependant, cela serait efficace dans le cas où l'horloge système était uniquement croissante... On préfèrera utiliser un numéro incrémentant pour ces noms de fichier.

Disposition des cartes et éléments vitaux sur le robot

Nous avons a disposer les éléments suivants : 1 Lipo placé dans un sac de protection Lipo Safe 1 carte de puissance 24V 1 carte de puissance 5V/10V 2 cartes de contrôleurs moteurs 1 Raspberry pi 1 PCB pour le contrôle d'un moteur Bioloid 1 Arduino Mega ( en discussion avec les autres équipes travaillant sur le robot pour voir à incorporer cette partie dans la raspberry)


Pour cette étape nous avons rajouté un étage sur le robot, cela a pu être fait car le reste des actionneurs étaient choisis et installées et nous savions donc la place qu'il nous restait de disponible.

Capteurs de distance : détermination d'un filtre

Les capteurs de distance sont primordiales, ils nous permettront lors de la coupe de France de calibrer le robot automatiquement et surtout d'éviter les potentiels robots adverses (voir même notre robot secondaire si il existe). Le problème que nous avons déja évoqués est qu'ils sont fortement bruités en environnement "sain" (le fabricarium quand personne ne s'y trouve), lors de la coupe de france l'environnement sera bien pire.

Voici une représentation graphique de ce que renvoi un capteur HSr04 :
P66 bruit.png


Réalisations : Enregistrements des valeurs renvoyés par le capteur dans un fichier texte au format csv : Pour réaliser cela nous échantillonnons notre capteur à 200Hz en renvoyant sur le port série les valeurs. Puis nous avons utilisé putty qui est capable de façon très simple de lire un port série et d'enregistrer les valeurs dans un fichier texte. Après une petite remise en forme des données à coup de sed nous obtenons le graphique présenté plus haut.

Afin de pouvoir tester différents filtres passe bas nous sommes passés par matlab, en bref nous avons : Chargé le fichier csv dans une matrice

Réaliser une FFT sur cette matrice
P66 fft.png

Remis en forme les valeurs pour pouvoir les afficher et ainsi obtenir ce graphe : Testé différents filtre comme montré ci dessous :

à 5Hz :
P66 5hz.png
à 1Hz :
P661hz.png
à 10Hz :
P6610Hz.png
Pour conclure c'est le filtre 10Hz qui l'emporte, il permet un retard négligeable compte tenu de notre constante de temps mécanique (le robot ne se déplacera pas à plus de 8 km/h en moyenne)
P66graph.png


Ce filtre sera intégré sur le FPGA.

Point d'attention lié à l'alimentation du robot avec les batteries

Nous avons remarqué quelque chose quelque peu surprenant mais bel et bien non négligeable. Lorsque la batterie baisse en charge, autour de 40% soit 15.1V-15V, la batterie ne délivre plus assez de courant pour alimenter l'ensemble du robot bien que nos tensions au sein du robot restent stable (donc aucune coupure des ordinateurs de bords et moteur alimenté en 24V). La carte de puissance remplit donc bien son rôle mais le courant ne suit plus. Ce problème nous a causé plusieurs fois des soucis car il n'est pas évident à déceler le système fonctionnant toujours mais au ralenti pour les moteurs, nous avons donc souvent suspecter des problèmes d'ordre informatique lié à la commande.

Gestion des signaux

Il n'est pas rare que l'un de nos tests tourne au vinaigre, et que le robot se mette dans un état dangereux pour lui (foncer dans un mur ou appliquer une tension trop faible pour les moteurs). Dans ce cas, il est prérférable dans une certaine mesure d'arrêter le programme depuis l'ordinateur de contrôle plutôt que d'utiliser le bouton d'arrêt d'urgence qui éteint complètement le Raspberry Pi entraînant la perte des dernières informations de journaux souvent cruciales dans la détermination de ce qui a pu causer le dysfonctionnement. Cependant, la gestion des contrôleurs moteurs ayant été déporté sur le FPGA, l'envoi d'un signal SIGINT (via les touches Ctrl+C) au programme n'a aucune influence sur le FPGA qui continue à envoyer les mêmes contrôles aux moteurs. Il est alors nécessaire de taper manuellement la commande s sur la liaison de contrôle afin d'arrêter les moteurs et les actionneurs.

Nous avons donc décidé d'implémenter une simple gestion de signaux telle que vue en cours : en cas d'interruption le programme courant est arrêté et les instructions d'arrêt sont envoyées. C'est une modification simple mais pourtant très pratique. Attention certains programmes de tests ne l'implémentent pas, il faut donc faire attention.

Journalisation

Extrait d'un journal

Collecte des journaux

Afin de pouvoir analyser les parcours et réaliser des tests, une routine de journalisation est disponible pour chaque programme de test sur le robot, accessible en incluant "debug.h". Elle doit d'abord etre initialisée avant l'initialisation des autres modules à l'aide de la fonction 'configureDebug'. Les autres modules sont ensuite libre d'appeler la fonciton void registerDebugVar(char* name, enum debugArgTypes type, void* var) qui prend un nom, un type, et un pointeur vers la donnée à journaliser. Une fois l'initialisation de chaque module terminée, il est nécessaire d'appeler la fonction void startDebug() qui s'occupera de lancer une routine éxécutée en continu s'occupant de récupérer les valeurs indiquées par les pointeurs passsés en paramètre et de les stocker dans un fichier CSV.

Visualisation d'un journal

Utilisation des journaux

Il est ensuite possible de récupérer les journaux avec la commande 'make getlogs' une fois connecté. Ils sont stockés dans le dossier 'logs', on peut les afficher directement. Mais il est plus pratique de voir une représentation graphique des données. Pour cela nous avons recyclé le script de simulations (qui n'a pas été continué, faute de complexité d'élaborer une modélisation réaliste du système) afin qu'il puisse afficher les graphes de ces journaux.

Contrôle par Ethernet

Après le Wi-Fi integré du Raspberry Pi, c'est au tour de notre dongle Wi-Fi de nous lâcher. En attendant d'en trouver un autre, et parce que les câbles de liaison série que nous possèdons sont assez courts et assez peu pratique pour transférer des fichiers (bien que possible avec le protocole xmodem), nous avons établi un moyen de se connecter au robot via câble Ethernet. Mais plutôt que de le connecter à un commutateur, on préfèrera le connecter directement à un ordinateur à l'aide d'une liaison point à point.

Pour cela rien de bien compliqué, il suffit du côté du Raspberry Pi de modifier le fichier /etc/network/interfaces afin d'appliquer à l'interface eth0 une adresse pour le Raspberry Pi et une addresse pour l'ordinateur (qui sont fixées), et de faire la même chose côté ordinateur, avec la commande 'ip address add dev <interface> <adresse PC>/20 peer <adresse Raspberry Pi>' (géré automatiquement par la commande 'make sshconf CON_MODE=eth -B').

Il n'y a pas besoin de câble croisé dans ce cas, pour peu que la carte réseau de l'ordinateur soit suffisament récente.

Seconde semaine

Cette semaine a été consacré à l'amélioration du système d'asservissement du robot, l'électronique de puissance et le câblage étant finalisé (il faut toutefois régulièrement lutter contre les branchements chaotique des bénévoles travaillant sur les actionneurs et devant se connecter aux cartes ou aux ordinateurs.

Asservissement en position

Les algorithmes testés précédemment en simulation ont été implémentsé, et ont pu être validé par des tests.

Un changement majeur vis à vis de la simulation a été la place du régulateur PID. En effet, initialement prévu sur les consignes données aux roues, il a été déplacé sur les erreurs en position et en angle. De cette manière, on peut régler la proportion entre la consigne en angle et celle en distance, ce qui nous permet d'améliorer les phases où le robot avance vers sa destination : il doit constamment rectifier sa trajectoire en même temps qu'il avance, mais pas de trop, sous peine que le robot oscille autour de sa trajectoire, et finisse par tourner autour du point de destination sans s'en rapprocher.

On obtient certains problèmes cependant, un gain trop faible (en distance ou en angle) engendre une erreur statique faisant en sorte que le robot n'atteigne jamais sa position. En effet, autour d'une tension trop faible, les moteurs ne sont pas capables de fournir assez de couple pour déplacer le robot : il y a donc une vitesse minimum pour le robot. Pour corriger ça on peut augmenter le gain afin que le robot aie plus d'élan sur son arrivée, mais dans son départ il demande une grande tension (parfois passant de 0 à 24 V en quelques millisecondes) ce qui n'est ni bon pour les moteurs, ni pour le glissement, ni pour l'accélération trop brutale pour les composants du robot. De plus, sur des tests en statique sur alimentation réglable, le courant demandé dépassait la limite que pouvait fournir l'alimentation, éteignant ainsi tout le système.

Facteur intégral

Usuellement, une erreur statique est corrigée par l'augmentation du coefficient intégral du PID, mais cela induit forcément un dépassement de la consigne. En effet, le coefficient intégral ajoute à la consigne une portion du total d'erreur cumulé tout au long de l'asservissement, et ne cesse d'augmenter jusqu'à ce qu'un dépassement suffisant ait eu lieu. Sauf que dans notre cas, un dépassement de consigne engendre un demi-tour du robot pour y revenir, ce qui n'est pas tellement pertinent étant donné qu'il sait pourtant bien reculer. Nous avons essayé de gérer ce cas, en vain.

Rate limiter

Pour pallier aux problèmes d'accélération trop brutale, nous avons choisi d'implémenter un rate limiter, qui est simplement un procédé mathématique qui s'assure que la dérivée d'une fonction ne dépasse pas une certaine valeur. Dans notre cas, cela permet de limiter l'accélération du robot à une certaine valeur. Cela répond correctement au problème, mais en introduit un autre, en effet pendant la phase d'accélération, l'accélération de la consigne étant au dessus de celle autorisée par le rate limiter, ce qui fait que la tension des deux moteurs augmente à la même vitesse, et la correction de l'angle est donc perdue par le rate limiter.

Bilan

On se retrouve donc avec trois solutions pas très viables : avoir une grande erreur statique en asservissement, avoir accélération brutale pour les grandes consignes, ou avoir un robot incapable de suivre une ligne droite. Aucune solution n'a cependant été trouvée cette semaine.

Afficheur et boutons

Interface Homme-Machine

Afin d'afficher des informations pour le debug de sélectionner des paramètres lors des phases de fonctionnement du robot, un afficheur et des boutons étaient nécessaires. Nous disposions d'un afficheur LCD 16 caractères × 2 lignes contrôlable par une liaison I2C et d'un grand nombre de boutons et d'interrupteurs. Le nombre de paramètres à modifier et de données à afficher n'étant pas très grand, nous avons opté pour un système à base d'écrans. Chaque paramètre modifiable (ex: parcours du robot) et chaque action réalisable (ex : remettre la position à 0) possède son propre écran. On peut passer d'un écran à l'autre à l'aide d'un bouton (le jaune en l'occurence), et changer le paramètre / lancer l'action à l'aide d'un autre bouton (rouge). Cette méthode nous limite donc à des paramètres booléens ou sous forme de liste, mais c'est largement suffisant pour nos besoins. Les informations de debug sont assez nombreuses pour la taille de l'écran, on préferera utiliser les journaux.


L'implémentation des boutons a été réalisée simplement en reliant une broche du bouton à une du Raspberry Pi et l'autre broche du bouton à la masse (la carcasse du robot pouvant servir de masse commune, cela permet de réduire le nombre de fils). Il a ensuite suffit de configurer la broche de l'Arduino en pull-up et de fournir un objet C permettant au reste du programme de les utiliser. L'implémentation de l'écran a été réalisé en paramètrant le fichier /boot/config.txt du Raspberry Pi pour qu'il active la liaison I2C, en activant les modules nécessaires, en créant un objet C pour simplifier la communication I2C (utilisant notamment des verrous pour éviter les conflits), et enfin un objet C pour contrôler l'afficheur LCD.

Ébauche du schéma fonctionnel de l'IHM


Le code de l'afficheur LCD a été principalement repris de codes d'exemple pour Arduino. En effet nous n'avons pas étudié en profondeur le fonctionnement de cet écran car ne souhaitions pas utiliser les fonctionalités avancée de l'écran, et si celui-ci venait à devenir défaillant, possédant uniquement des types différents d'afficheur cette étude et le code produit serait devenu obsolète. Cependant, on a remarqué que l'écran se mettait de temps en temps en défaut, affichant des caractères japonais. Ce problème est probablement dû aux modes de l'afficheur (envoi de données sur 8 ou 4 bits) se décalant. En guise de solution créative au problème, nous avons connecté la masse de l'afficheur sur une broche de sortie du Raspberry Pi, permettant de remettre à zéro l'afficheur à volonté (notamment pour les moments critiques).

Enfin, afin de pouvoir contrôler le robot à distance, l'affichage de l'écran a été dédoublé pour être aussi affiché sur la sortie standard lorsque le programme est éxecuté en mode attaché, et les deux boutons peuvent être aussi appuyés en tapant 1 ou 2 dans l'entrée standard. Cela permet un contrôle à distance, certes basique mais amplement suffisant pour nos besoins.

Outils de débug

Lors de la programmation quelques erreurs de segmentations sont survenues. Hors, la machine n'embarquant pas (par choix) les outils de debug tels que GDB, et le problème n'étant pas reproductible sur un autre PC (le programme étant trop dépendant de son environnement). Embarquer l'intégralité des outils de débogage sur la machine serait assez lourd, cependant il est possible d'embarquer un programme appelé gdb-server permettant d'exposer sur une connexion TCP les informations nécessaires pour le déboguage, et on peut ensuite connecter un instace de gdb sur n'importe quel PC connecté au robot pour débuguer à distance. Il suffit simplement de lui indiquer l'adresse du robot et les fichiers comprenant les symboles de debug, qui ne sont pas envoyés sur le Raspberry Pi car ce n'est pas nécessaire mais sont stockés sur l'ordinateur ayant réalisé la compilation (la composante debug a été séparée de la composante programme des éxecutables à l'aide de l'utilitaire 'strip'). À l'accoutumée, il est possible d'accéder automatiquement à cette fonctionalité avec la commande préparée 'make debug'.


Auto-diagnostics

La façon dont le robot a été cablé étant assez sensible, il a été choisi de réaliser un programme d'auto-diagnostics afin de vérifier que tout fonctionne bien. Le programme -selectionnable même quand le robot n'est pas connecté à un ordinateur depuis l'interface homme-machine embarquée, vérifie que tous les composants sont bien connectés, puis essaye de leur envoyer un ordre, et si possible, vérifie que l'ordre a bien été éxécute (exemple : une tension est appliquée quelques secondes sur un moteur, on vérifie que le déplacement a bien été propagé dans les encodeurs). En cas d'échec d'un diagnostic, son nom reste affiché sur l'écran. Sans echec, il ne dure que quelques secondes.

Coupe de France de Robotique

préparatif

Nous avons choisi et inventorié tout le matériel emmené "au cas-où", en ce qui concerne le projet il s'agissait essentiellement de cartes de secours et de composants de secours pour le contrôleur moteur, élément le plus susceptible de défaillir lors de la compétition.

Sur place

Toujours en ce qui concerne le projet nous n'avons pas eu de difficultés majeurs hormis une soudure qui a sauté lors du transport mais qui a été décelé lors des tests préliminaire à l'arrivée. A chaque déplacement du matériel il est conseillé de faire un rapide test de continuité au multimètre puis un essai sous alimentation réglable en courant limité, c'est là que nous avons décelé le problème.

un isolant pas si isolant

Pour isoler nos circuits imprimés du reste de la carcasse métallique nous avons utilisé un caoutchouc déjà disponible dans le matériel de Robotech. Or nous avons découvert que celui-ci n'était pas isolant! Il semble d'après nos recherches que ce caoutchouc soit complété avec du carbone ce qui le rend conducteur, nous avons mesuré une résistance de 300 kΩ sur un échantillon de 10 cm². Cette erreur heureusement ne nous a pas causé de dégradation par chance. Toutefois cet imprévu à demander d'improviser une nouvelle isolation, forcément un peu moins propre, à base de bois et de carton.

Correction de l'asservissement

Après discussions avec d'autres équipes sur l'asservissement que nous avions élaboré, certains conseils nous ont été donnés.

Le rate limiter, bien qu'une bonne idée sur le principe, induit un délai pur dans le process, ce qui est un véritable poison pour l'asservissement. Pour pallier au problème d'accélération trop brutale, il est généralement choisi un asservissement en vitesse et non en position. Pour cela on peut créer un signal de consigne suivant une rampe, mais cela nécessite un nombre non-négligeable de calculs d'intégrales. Étant donné la contrainte de temps, une solution créative a été trouvé pour simuler ce fonctionnement de limiter l'erreur en position et en angle à une certaine valeur, afin de virtuellement limiter la cible à un cone devant le robot. De cette manière l'accélération est limitée, et la correction de la trajectoire peut toujours avoir lieu grâce à une marge sur la tension maximale applicable au robot (que vous avons fixé à 4 V dans notre cas).

De cette manière l'erreur intégrale est calculée sur la consigne réduite, et est donc limitée. Il reste toujours à implémenter la possibilité au robot de reculer dans le cas d'un dépassement. L'erreur commise jusqu'à lors était de laisser activée la correction en angle lors de l'approche du point de destination. En effet dans ce cas le robot pase (inévitablement) un tout petit peu à coté du point, et la correction en angle fait en sorte que le robot soit face au point à tout moment, il ne dépasse jamais donc vraiement le point. En désactivant cette correction à l'approche du point de destination (elle n'est de toutes façons qu'utile loin du point de destination), le robot peut sereinement dépasser le point, puis reculer pour arriver à la valeur voulue. On peut donc désormais augmenter les gains sans problème, et donc profiter d'une plus grande vitesse et d'une meilleure correction d'angle sans en avoir les inconvénients.

Jusqu'à lors, on considérait qu'un ordre était terminé dès que le robot arrivait dans un rayon autour du point de consigne. Deux erreurs sont possible avec ce mode de fonctionnement :

  • Le robot n'a pas assez d'élan et bloque un peu avant le rayon
  • Le robot a trop d'élan et la consigne suivante est déclenchée alors que la vitesse du robot n'est pas nulle, provoquant des glissements.

Pour pallier à ce problème, on considère que le robot a terminé sa consigne quand sa vitesse est en dessous d'un seuil très bas, et que la tension appliquée aux roues est inférieure au seuil en dessous duquel le robot ne peut démarrer. Cette double vérification permet d'éviter le passage à la consigne suivante dans les cas suivants :

  • La tension est nulle car très proche du point de destination mais le robot continue à avancer par intertie
  • La vitesse est nulle car elle est en inversion, mais la tension n'est pas nulle car pas encore à la consigne

Avec ces conditions supplémentaires, on peut donc sans problème augmenter le rayon pour lequel le robot en considéré sur le point de destination.

Bilan

On dispose désormais d'un asservissement tout à fait correct. Cependant l'erreur entre la position connue par le robot et la position réelle n'est pas négligeable après quelques mouvements, en effet les glissements sont de mise.

Homologation

Lors de la compétition les robots doivent passer devant les arbitres qui vérifient que le robot respectent les différents points précisés dans le cahier des charges. Tout d'abord on a une vérification statique où le robot est mesuré et inspecté puis une vérification dynamique où le robot est placé en situation sur le terrain pour vérifier son bon fonctionnement et surtout qu'il ne peut pas être un danger pour le robot adverse.

Statique

L'homologation s'est très bien déroulé, les aspects du projet qui ont été évalués n'ont pas posés de problème : - sécurité et contrôle des batteries - présence d'un bouton d'arrêt d'urgence permettant de mettre en sécurité le robot et son environnement - respect des dimensions du robot

Dynamique

L'homologation dynamique a elle été un peu plus délicate notamment parce que l'arbitre a considéré qu'il existait trop d'angle mort dans notre système de détection d'obstacle. Après un simple réajustement des capteurs le problème était résolu. L'asservissement un peu capricieux sur le terrain officiel nous a également causé certains problèmes mais encore une fois après ajustements le robot a été homologué.

Comparatif avec les autres robots

Lors de la compétition nous avons l'occasion d'échangé avec de nombreuses équipes sur les choix techniques fait sur leur robot. Il en ressort plusieurs éléments intéressants :

  • très peu d'équipe réalisent eux mêmes leurs circuits imprimés, des cartes toutes faites sont achetés puis mise ensemble voir pour certaines équipes l'ensemble de l'électronique est rassemblé sur une seule et même carte professionnel éludant complètement cette difficulté dans la conception du robot.
  • Le langage privilégié par les étudiants restent le C mais on constate par rapport à l'année dernière une croissance des langages haut niveau voir très haut niveaux avec certains robots programmés intégralement en Labview par exemple!
  • Le choix des capteurs, nous avons utilisé l'existant car Robotech est souvent difficile à convaincre pour l'achat de nouveau matériel quand il en existe déjà du fonctionnel. Nos capteurs bas de gamme et assez anciens sont très loin de ceux d'adversaires qui comportent souvent beaucoup plus d'informatique embarqué que les notre. C'est une piste à souligner pour les années futurs, cela nous aurait probablement faciliter la tâche pour réaliser l'auto-calibrage du robot qui s'est révélé assez incertain malgré l'implémentation de notre filtre sur FPGA pour filtrer les données.

Un capteur pouvant être un bon candidat pour une montée en gamme serait le SRF10 (20€ environ) qui reste un capteur ultrason donc à large cône (environ 30°) ce qui limite le nombre nécessaire sur le robot pour couvrir tout le périmètre de déplacement. De plus grâce à sa communication en I2C il permet un accès facile et une moins grande utilisation des GPIO de la Raspberry ou de l'arduino. Pour réaliser un auto-calibrage de qualité il faudrait utiliser un capteur dédié de préférence laser sera toujours plus précis qu'un capteur ultrason.

Dernière semaine et conclusion

Lors de cette dernière semaine nous avons tourné une vidéo présentant le travail accomplit et dans quel but. Nous remercions d'ailleurs le Laurent Engels pour sa patience et son professionnalisme.

Nous avons également finalisé la rédaction du rapport.

Documents Rendus

Rapport

Media:IMA41718P66-Rapport.pdf

Code et PCB

Source

Répartition :

  • pcb : Fichiers utilisés pour l'impression des contrôleurs moteurs et des cartes de puissance
  • arduino : Partie Robotech, hors-projet
  • fpga : Code pour le FPGA et outils de simulation
  • raspberrypi : Code pour le système d'exploitation du Raspberry Pi. Contient le Makefile racine.
  • simu : code permettant de générer les graphes issu des journaux
  • chef : programme principal du Raspberry Pi (gérant le contrôle en position)

Au cours de l'évolution du projet, des grosses parties de codes ont été supplantées par d'autres pour diverses raisons. Elles n'en sont pour le moins pas ininteressantes, voici donc leur lien dans l'historique.

Gestion de l'asservissement en position sur Arduino à l'aide de FreeRTOS :

[5]


Utilisation de la liaison série pour la communication Raspberry Pi ↔ Arduino :

Au cours de la compétition un défaut matériel et un manque de pièces de rechange de câble de liaison série ↔ USB nous a forcé à la réimplémenter à l'aide d'une liaison I²C. Cependant cette implémentation rapide est beaucoup moins performante et moins bien réalisée.

Module de communication du FPGA Banc de test du module de communication du FPGA Module principal du FPGA

La gestion de la liaison série côté Raspberry Pi est similaire à celle utilisée avec l'Arduino.

Bibliographie

Datasheet : moteurs : Média:P66_Moteurs_principal.zip