Projet IMA3 P7, 2017/2018, TD1 : Différence entre versions
(→Partie électronique) |
(→Arduino) |
||
(208 révisions intermédiaires par 4 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
− | = '''Projet IMA3-SC 2017-2018''' = | + | = '''Projet IMA3-SC 2017-2018- Replica''' = |
− | '''Pour ce projet, nous déposerons tous nos programmes pour la partie informatique | + | '''Pour ce projet, nous déposerons tous nos programmes et documents pour la partie informatique ainsi que pour la partie électronique sur un dépôt GIT[https://github.com/Arezki1995/3D_Scanner_IMA3].''' <br> |
− | '''Ce dépot | + | '''Ce dépot sera régulièrement mis à jour et il sera partagé avec les encadrants du projet afin de permettre la visualisation du travail réalisé. '''<br> |
− | |||
+ | |||
+ | ==<span style="color:Red">'''Description du système'''</span>== | ||
+ | |||
+ | [[Fichier:scanner1.jpg|vignette|200px|Replica]] | ||
+ | |||
+ | '''Replica''' est un objet connecté capable de réaliser un scan en 3D d'une pièce et de la reproduire sous un format STL imprimable sur une imprimante 3D. La commande du scanner se fait à travers une interface web sur laquelle un utilisateur pourra s'authentifier et choisir les paramètres du scan. Après avoir déposé préalablement la pièce à reproduire sur le support, l'utilisateur peut lancer le scan depuis le site. Le dispositif fait alors des acquisitions de points sur les contours de la pièce. Après l'acquisition,il transforme ce nuage de points en une representation 'maille de triangles' (triangle mesh) sous un format STL. Ce fichier pourra être téléchargé une fois le processus terminé. | ||
== <span style="color:Red">'''Cahier des charges'''</span> == | == <span style="color:Red">'''Cahier des charges'''</span> == | ||
− | + | Ce projet a pour but de :<br> | |
+ | # Acquisition de mesures de distance <br> | ||
+ | # Pilotage des moteurs pas-à-pas<br> | ||
+ | # Transmission des points de mesure depuis l'arduino à la Raspberry en liaison série. <br> | ||
+ | # Reconstruction de la géométrie de l'objet scanné<br> | ||
+ | # Génération d'un fichier STL<br> | ||
+ | # Réalisation de l'interface web et mise en place de la communication<br> | ||
− | + | '''Objectif global''': un système capable de fonctionner pour une catégorie d'objets solides plus ou moins uniformes. | |
− | |||
− | < | + | == <span style="color:Red">'''Séance 1'''</span> == |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ===<span style="color:Green">Préparation de la séance</span>=== | |
− | + | Préalablement à cette séance, nous avions:<br> | |
+ | # formé notre groupe et avons déjà réfléchi a notre idée de projet.<br> | ||
+ | # étudié la faisabilité et les éventuelles difficultés. <br> | ||
+ | # récupéré sur internet des modèles 3D du support d'un projet similaire sur internet que nous avons adapté à notre cas.<br> | ||
+ | # préparé une liste des composants et du matériel nécessaire.<br> | ||
− | ===<span style="color:Green"> | + | ===<span style="color:Green">Partie électronique</span>=== |
− | + | [[Fichier:Calcul.jpg|vignette|100px|Calculs]] | |
− | + | [[Fichier: Circuit conditionneur.jpg|vignette|100px|Schéma du Conditionneur]] | |
+ | Nous avons défini deux sous-objectifs pour cette partie: <br> | ||
− | |||
− | |||
− | |||
− | + | ||
− | + | *'''Le conditionnement du signal du capteur:''' | |
− | + | En effet, le capteur de distance fourni revoie, d'après la datasheet (Ref: 2Y0A21F7Y), un signal | |
+ | variant entre 0.3V et 3.1V. | ||
+ | Pour plus de précision nous allons conditionner ce signal pour que la valeur varie entre 0V et 5V. | ||
+ | Pour réaliser cette transformation, nous utilisons un montage à base d'amplificateurs opérationnels. | ||
+ | Après avoir effectué les calculs des paramètres, nous validons l'approche et entamons la simulation. | ||
− | |||
− | + | <br> | |
− | |||
− | |||
− | |||
− | |||
− | *''' | + | *'''Pilotage des moteurs pas-à-pas :''' <br> |
− | + | Nous avons besoin de piloter deux moteurs pas-à-pas pour reproduire les mouvements du scanner. La rotation du support et le balayage vertical du capteur.<br> | |
− | + | Après l'analyse de la datasheet des moteurs qui nous ont été fournis, nous avons relevé les caractéristiques de courant et de tension ainsi que la configuration du moteur. | |
===<span style="color:Green">Partie informatique</span>=== | ===<span style="color:Green">Partie informatique</span>=== | ||
+ | |||
+ | Durant La première séance nous avons entamé l'installation et la configuration de la raspberry. | ||
===<span style="color:Green">Travail supplémentaire entre les deux séances</span>=== | ===<span style="color:Green">Travail supplémentaire entre les deux séances</span>=== | ||
+ | Lancement des impressions 3D du support du scanner.<br> | ||
+ | [[Fichier:objets3D.jpg|vignette|center|Parties mécaniques imprimées|700px]] | ||
+ | <br> | ||
== <span style="color:Red">'''Séance 2'''</span> == | == <span style="color:Red">'''Séance 2'''</span> == | ||
===<span style="color:Green">Préparation de la séance</span>=== | ===<span style="color:Green">Préparation de la séance</span>=== | ||
+ | Nous avons défini les sous-objectifs suivants à réaliser pendant la séance: | ||
+ | *Calibrage du controleur moteur et mise en marche du moteur | ||
+ | *Conception physique du conditionneur de signal et test | ||
+ | *Configuration de la Rasberry pour fonctionner en hotspot | ||
===<span style="color:Green">Partie électronique</span>=== | ===<span style="color:Green">Partie électronique</span>=== | ||
+ | [[Fichier: 35156912_1771212276270661_4977713602522775552_n.jpg|vignette|upright=0.75|100px|Circuit pour controler le moteur]]<br> | ||
+ | [[Fichier: 34818911_2198525003726573_2836142689970290688_n.jpg|vignette|upright=0.75|100px|Le capteur de distance]]<br> | ||
+ | [[Fichier: 35240488_2198525017059905_6735236150148988928_n.jpg|vignette|upright=0.75|100px|Circuit conditionneur de signal]]<br> | ||
+ | Apres nous avons etudie les traits des '''moteurs''' et du '''controleur moteur''', on a essaye de calibrer le controleur pour n'avoir pas un courant qui peut endommager le moteur. Pour faire ca, nous avons cherche comment limiter le courant avec ce type de controleur. Nous avons trouve la methode suivante: | ||
+ | |||
+ | |||
+ | *calculer la valeur optimale pour le courant de sortie de controleur, en utilisant la formule specifique pour nos composants ( Controleur A4988, Moteur pas-à-pas) | ||
+ | *mettre le courant (en entournant le potentiometre) qui sort du controleur a la valeur que nous avons calcule | ||
+ | *ajouter le moteur, le circuit pour controler le moteur, l'Arduino pour une source de 5V et la source de 12V | ||
+ | *allumer les sources | ||
+ | *verifier si le moteur tourne comme prevu | ||
+ | *sinon, tourner le potentiometre jusqu'a le bon mouvement du moteur, comme s'il n'y a pas assez ou trop de courant, le moteur ne tourne pas facilement | ||
+ | |||
+ | Finalement, nous avons calibre le controleur pour avoir en sortie 0.6A. <br> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | Pour verifier que notre '''circuit conditionneur''' convertit correctement le signal, nous avons ajoute le capteur de distance dans notre montage.<br> | ||
+ | |||
+ | |||
+ | <br> | ||
+ | |||
+ | |||
+ | Sur le logiciel Arduino, nous avons cree un code qui nous donne les valeurs recus par le capteur et nous avons les mettre en temps reels sur un graphe. Dans le video au-desous, on peut voir que la sortie du capteur est entre 0V et 5V, donc que notre circuit fonctionne correctement. | ||
− | + | ||
+ | |||
+ | |||
+ | Nous avons réalisé un test du circuit de conditionnement pour l'acquisition de la distance : | ||
+ | [[Média:video-1528891753.mp4|Video]]<br> | ||
===<span style="color:Green">Travail supplémentaire entre les deux séances</span>=== | ===<span style="color:Green">Travail supplémentaire entre les deux séances</span>=== | ||
+ | [[Fichier: 35237579_1771222849602937_6274818658199928832_n.jpg|vignette|upright=0.75|100px|Test translation verticale]]<br> | ||
+ | Test des moteurs et de la translation verticale. Le système mécanique fonctionne mais le controlleur moteur dont nous disposons présente quelques disfonctionnements notamment l'instabilité du courant de sortie. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <br> | ||
− | == <span style="color:Red">''' | + | ==<span style="color:Red">'''Arduino'''</span>== |
+ | |||
+ | Dans cette partie nous allons vous détailler notre code Arduino : | ||
+ | |||
+ | Le programme attend de recevoir l'information sur la précision (envoyé par l'interface web) du scan puis la validation pour commencer. | ||
+ | En fonction de la précision le programme va faire plus ou moins de capture de point de l'objet par rotation. | ||
+ | Vu que nous avons pas pu avoir de contrôleur moteur fonctionnel, nous faisons une acquisition de points toute les X microsecondes. Avec les contrôleurs nous aurions fait la prise de point tout les X degrés de rotation de l'objet (X sera calculé en fonction de la précision envoyé). | ||
+ | |||
+ | Les points sont ensuite envoyé un a un par liaison série jusqu’à la Raspberry pour être traité. On envoie dans un premier temps les paramètres du scan, c'est a dire la précision et la hauteur de l'objet, puis tout les points renvoyés par le capteur. | ||
+ | |||
+ | |||
+ | Programme Arduino : [[Fichier: Envoie_capteur_V3.ino.zip]]<br> | ||
+ | |||
+ | ==<span style="color:Red">'''Reconstruction 3D'''</span>== | ||
+ | ===<span style="color:Green">'''Capteur vers fichier texte'''</span>=== | ||
+ | |||
+ | Les points arrivent un a un via la liaison série sur la Raspberry, un programme python récupère les deux paramètres puis l'ensemble des points et les ajoutent a la ligne dans un fichier texte. | ||
+ | |||
+ | 20 | ||
+ | 2 | ||
+ | 655 | ||
+ | 640 | ||
+ | 625 | ||
+ | 610 | ||
+ | 620 | ||
+ | 623 | ||
+ | 610 | ||
+ | ... | ||
+ | .. | ||
+ | . | ||
+ | |||
+ | Programme de récupération liaison série : [[Fichier: Recup_fichier.zip]]<br> | ||
+ | |||
+ | |||
+ | C'est ensuite un programme en C qui récupère le fichier texte précédent et pour chaque points calcule les coordonnées cartésienne et stocke le tout dans un autre fichier texte. | ||
+ | |||
+ | 10 | ||
+ | 5.000000 | ||
+ | 0.000000 | ||
+ | 0.000000 | ||
+ | |||
+ | 4.755282 | ||
+ | 1.545085 | ||
+ | 0.000000 | ||
+ | |||
+ | 4.045085 | ||
+ | 2.938926 | ||
+ | 0.000000 | ||
+ | |||
+ | 2.938926 | ||
+ | 4.045085 | ||
+ | 0.000000 | ||
+ | |||
+ | 1.545085 | ||
+ | ... | ||
+ | .. | ||
+ | |||
+ | [[Fichier:Respresentation.png|vignette|upright=0.50|Representation]] | ||
+ | Programme de conversion : [[Fichier: CylindriqueTOcartesien.c.zip]]<br> | ||
+ | |||
+ | ===<span style="color:Green">'''Représentation STL'''</span>=== | ||
+ | |||
+ | Ensuite, on convertie ce fichier texte en Format STL [https://en.wikipedia.org/wiki/STL_(file_format)]:<br> | ||
+ | Pour réussir la conversion, nous avons dû construire en premier lieu une librairie C contenant les types de données ainsi que les fonctions de base nécessaires pour travailler. Dans la représentation STL, le modèle 3D est représenté en utilisant les élements géométriques suivants: Les points (Vertex), Les Vecteurs (Vectors), Les vecteurs normaux (Normal), les faces (Facet), les solides (Solid) et les objets(Object). | ||
+ | |||
+ | *ICI SONT REPRESENTES LES STRUCTURES DE DONNEE DE BASE | ||
+ | typedef struct { | ||
+ | float x; | ||
+ | float y; | ||
+ | float z; | ||
+ | } Vertex; | ||
+ | |||
+ | typedef struct { | ||
+ | float vx; | ||
+ | float vy; | ||
+ | float vz; | ||
+ | } Vector; | ||
+ | |||
+ | typedef struct { | ||
+ | Vector normal; | ||
+ | Vertex v1; | ||
+ | Vertex v2; | ||
+ | Vertex v3; | ||
+ | } Facet; | ||
+ | |||
+ | typedef Facet* Solid; | ||
+ | |||
+ | En ce qui concerne l'élement '''objet''' (Object), ce dernier n'est pas un type de donnée explicite mais juste un contenaire (Wrapper). Il est juste utilisé pour parser à la phase finale le fichier STL en encodage ASCII. | ||
+ | |||
+ | === <span style="color:Green">'''Explication des fonctions de la librairie C créée'''</span> === | ||
+ | |||
+ | *AFFICHAGE CONSOLE | ||
+ | void dispVertex(Vertex ver); | ||
+ | void dispVector(Vector vect); | ||
+ | void dispFacet(Facet facet); | ||
+ | void dispSolid(Solid solid, int NB_facets); | ||
+ | |||
+ | *GENERATION DU FICHIER STL | ||
+ | void generateFile(Solid s, int NB_facets); //FONCTION MERE FAISANT APPEL SEQUENTIELLEMENT AUX FONCTIONS SUIVANTES | ||
+ | void genVertex(Vertex ver, FILE* fp); //ECRIRE UN VERTEX DANS LE FICHIER STL | ||
+ | void genVector(Vector vect, FILE* fp); //ECRIRE UN VECTEUR DANS LE FICHIER STL | ||
+ | void genFacet(Facet facet, FILE* fp); //ECRIRE UNE FACET DANS LE FICHIER STL | ||
+ | void genSolid(Solid solid,int NB_facets, FILE* fp); //ECRIRE UN SOLIDE DANS LE FICHIER STL | ||
+ | |||
+ | *CONSTRUCTEURS D ELEMENTS ALEATOIRES POUR LE TEST DES ALGORITHMES | ||
+ | Vertex likelyRandomVertex(int level,int precision,int circle_pos, int max); //GENERE SEQUENTIELLEMENT LES POINTS DE LA SURFACE D UN CONE | ||
+ | float randomCoordinate(); | ||
+ | Vertex randomVertex(); | ||
+ | Facet randomFacet(); | ||
+ | Solid randomSolid(int NB_facets); //GENERE UN SOLID AVEC UN NOMBRE DONNE DE FACETs | ||
+ | |||
+ | *CONSTRUCTEURS D ELEMENTS DEFINIS | ||
+ | Vertex getVertex(float x,float y, float z); //CREE UN VERTEX A PARTIR DE 3 COORDONEES CARTESIENNES | ||
+ | Vector getVector(Vertex A ,Vertex B); //CREE UN VECTEUR A PARTIR DE 3 VERTEX | ||
+ | Facet getFacet(Vector normal, Vertex ver1,Vertex ver2, Vertex ver3); //CREE UNE FACET A PARTIR DE 3 VERTEX ET UN VECTEUR NORMAL | ||
+ | Facet makeFacet(Vertex ver1, Vertex ver2, Vertex ver3); //CREE UNE FACET A PARTIR DE 3 VERTEX SEULEMENT | ||
+ | Solid allocateSolid(int NB_facets); //ALLOCATION DYNAMIQUE DU SOLIDE | ||
+ | *CALCUL | ||
+ | Vector crossProduct(Vector a,Vector b); //CALCULE LE PRODUIT VECTORIEL POUR CREER UN VECTEUR NORMAL | ||
+ | |||
+ | === <span style="color:Green">'''Test de l'algorithme de reconstruction avec simulation de point d'acquisition'''</span> === | ||
+ | [[Fichier:Vmatrix.jpg|left|vignette|250px|VMatrix]] | ||
+ | [[Fichier:Vmatrix_closed.jpg|right|vignette|250px|VMatrix avec points virtuels]] | ||
+ | |||
+ | |||
+ | La première approche de reconstruction est faite en créant une matrice des vertex collectés (VMatrix). On crée une Facet à partir de chaque trois Vertex voisins. Le principe pour créer un solide fermé est que chaque Facet partage chacun de ses côtés avec d'autres Facets. Ceci implique que les Vertex de la derniere colonne devrons se lier avec ceux de la première comme on peut le voir sur les illustrations. Pour réaliser un solide complètement fermé il est necessaire de rajouter deux points (Vertex) virtuels. L'un devra être placé à l'origine sur l'axe de rotation du dispositif à la première couche de scan (Niv 0) afin de fermer l'objet par le bas. L'autre devra être placé à la dernière couche du scan au même emplacement pour ainsi pouvoir fermer le solide de haut. | ||
+ | <br> | ||
+ | |||
+ | <br> | ||
+ | |||
+ | <br> | ||
+ | |||
+ | [[Fichier:Reconstruction1.png|vignette|200px|Approche de reconstruction]] | ||
+ | |||
+ | Pour allouer dynamiquement la mémoire requise, il fallait calculer le nombre de Facet qui seront créées à partir d'un nombre donné de Vertex qui seront contenu dans la matrice. Nous nous sommes penché alors sur les proprités géométriques de notre approche. En se basant sur la formule des polyhèdres d''''Euleur''' [https://plus.maths.org/content/eulers-polyhedron-formula] nous avons réussi à calculer exactement la taille mémoire à allouer. En prenant en compte, biensur, la résolution radiale maximale du moteur pas-à-pas en Pas/tour comme nombre de points max par niveau de scan. Sans oublier la résolution verticale sachant que notre système mécanique nous offre une translation verticale de 1mm/tour avec intervalle de translation de 15cm. Ceci nous donne donc un résolution verticale de 150 Nivaux. | ||
+ | |||
+ | |||
+ | |||
+ | <br> | ||
+ | <br> | ||
+ | [[Fichier:Test_cone.png |vignette|200px|Résultats de simulation]] | ||
+ | |||
+ | Pour les premiers tests nous avons mis en place des fonctions qui permettent de générer sequentiellement des points d'un solide conique. Nous avons implémenté aussi un moyen de selectionner la résolution du scan avec un paramètre '''precision'''. Nous avons effectué plusieurs test avec et sans bruit sur des résolutions différentes et les résultats sont plutôt concluants. Nous visionons les fichiers généré sur le Logiciel open-source Blender. | ||
+ | |||
+ | |||
+ | |||
+ | <br> | ||
+ | Programme conversion texte vers stl: [[Fichier: TexteTOstl.zip]]<br> | ||
+ | |||
+ | ==<span style="color:Red">'''Interface web'''</span>== | ||
+ | |||
+ | Dans un premier temps l'utilisateur doit se logger pour pouvoir accéder a l'interface de scan : <br> | ||
+ | "En vue de la priorité des autres étapes, nous avons reporté l'aspect dynamique de cette page à plutard" | ||
+ | [[Fichier:login.png|400px|vignette]] | ||
+ | |||
+ | Ensuite il arrive sur la page du scan : | ||
+ | |||
+ | Les boutons qui envoient l'information de la precision sont les suivants : | ||
+ | |||
+ | <button onclick="sendMessage(1); bas">MAX 200pts (1)</button> | ||
+ | <button onclick="sendMessage(2);">INTER1 40pts (5)</button> | ||
+ | <button onclick="sendMessage(3);">MIN 20pts (10)</button> | ||
+ | |||
+ | <br><br><br><br><br><br><br><br> | ||
+ | [[Fichier:Scan_php.png|400px|vignette]] | ||
+ | Notre interface de scan, on choisie la précision parmi les trois proposés puis on lance le scan. | ||
+ | Une fois celui-ci fini on télécharge le fichier stl via un href : | ||
+ | |||
+ | <a href= "../data/objet.stl"> Clique pour telecharger l'objet stl !! </a> | ||
+ | <br><br><br><br><br><br><br><br> | ||
+ | |||
+ | == <span style="color:Red">'''Les tests'''</span> == | ||
+ | |||
+ | [[Fichier: Objet.jpg|left|thumb|200px|Objet scanné]] | ||
+ | <br> | ||
+ | Etant donné que nous n'avons pas de contrôleurs moteur, nous avons choisie un objet uniforme selon l'axe des Z (cf: photo objet scanné). Ainsi on peut scanner toute la forme sans que le capteur monte ou que l'objet tourne. | ||
+ | |||
+ | |||
+ | Après le premier scan ("Rien" c'est a dire sans filtre passe bas), on remarque que la forme générale est belle et bien présente mais qu'il a aussi de nombreuses imperfections. | ||
+ | |||
+ | |||
+ | On suppose que c'est imperfections sont du au capteur qui quelques fois renvoient des valeurs légèrement différente de la réalité. Pour résoudre ce problème nous allons essayer de filtrer la sortie du capteur. | ||
+ | |||
+ | |||
+ | Avec une capacité ("Capacité 100uF") ou des filtres passe-bas avec des valeurs de résistance différentes. D'après les objets 3D obtenu il semble que ce soit le passe-bas (C = 100uF et R = 20K) qui filtre le mieux les parasites. | ||
+ | |||
+ | |||
+ | Avec plus de temps nous aurions put faire plusieurs prises pour chaque points retirer les extrêmes puis faire une moyenne. On aurait obtenue une forme surement plus lisse. | ||
+ | |||
+ | <br><br><br><br><br><br><br> | ||
+ | [[Fichier: Compare1.png|left|thumb|400px|Objet 3D en fonction du filtre appliqué]] | ||
+ | [[Fichier: Compare2.png|center|thumb|380px|Objet 3D en fonction du filtre appliqué]] | ||
+ | |||
+ | |||
+ | <br><br> | ||
+ | |||
+ | == <span style="color:Red">'''Bilan'''</span> == | ||
+ | |||
+ | [[Fichier: Demonstration.png|vignette|350px|Notre meilleur résultat]] | ||
− | |||
− | |||
− | + | <br> | |
+ | En conclusion, nous avons réussi à réaliser un prototype fonctionnel du projet que nous nous étions fixé au départ. Une bonne partie du cahier des charges initial a été respectée néanmoins il reste encore de nombreuses améliorations et corrections à apporter à ce système pour obtenir un scan fidèle à la réalité. Notamment: | ||
− | + | *Nous devrons remplacer le capteur de distance qui présente un fort bruit causant ainsi l'apparition de piques autour de l'objet scanné.<br> | |
+ | *Ajouter un degré de libérté supplémentaire pour pouvoir scanner l'objet dans son intégralité.<br> | ||
+ | *Améliorer l'interface web: Affichage sur page web du fichier STL et ajout d'une barre de progression du scan.<br> | ||
− | + | *Améliorer l'approche de reconstruction de l'objet en 3D pour pouvoir scanner des objets plus complèxes.<br> | |
− | + | Ces améliorations peuvent faire l'objet d'un projet en 4ème Année. |
Version actuelle datée du 21 juin 2018 à 12:02
Sommaire
Projet IMA3-SC 2017-2018- Replica
Pour ce projet, nous déposerons tous nos programmes et documents pour la partie informatique ainsi que pour la partie électronique sur un dépôt GIT[1].
Ce dépot sera régulièrement mis à jour et il sera partagé avec les encadrants du projet afin de permettre la visualisation du travail réalisé.
Description du système
Replica est un objet connecté capable de réaliser un scan en 3D d'une pièce et de la reproduire sous un format STL imprimable sur une imprimante 3D. La commande du scanner se fait à travers une interface web sur laquelle un utilisateur pourra s'authentifier et choisir les paramètres du scan. Après avoir déposé préalablement la pièce à reproduire sur le support, l'utilisateur peut lancer le scan depuis le site. Le dispositif fait alors des acquisitions de points sur les contours de la pièce. Après l'acquisition,il transforme ce nuage de points en une representation 'maille de triangles' (triangle mesh) sous un format STL. Ce fichier pourra être téléchargé une fois le processus terminé.
Cahier des charges
Ce projet a pour but de :
- Acquisition de mesures de distance
- Pilotage des moteurs pas-à-pas
- Transmission des points de mesure depuis l'arduino à la Raspberry en liaison série.
- Reconstruction de la géométrie de l'objet scanné
- Génération d'un fichier STL
- Réalisation de l'interface web et mise en place de la communication
Objectif global: un système capable de fonctionner pour une catégorie d'objets solides plus ou moins uniformes.
Séance 1
Préparation de la séance
Préalablement à cette séance, nous avions:
- formé notre groupe et avons déjà réfléchi a notre idée de projet.
- étudié la faisabilité et les éventuelles difficultés.
- récupéré sur internet des modèles 3D du support d'un projet similaire sur internet que nous avons adapté à notre cas.
- préparé une liste des composants et du matériel nécessaire.
Partie électronique
Nous avons défini deux sous-objectifs pour cette partie:
- Le conditionnement du signal du capteur:
En effet, le capteur de distance fourni revoie, d'après la datasheet (Ref: 2Y0A21F7Y), un signal variant entre 0.3V et 3.1V. Pour plus de précision nous allons conditionner ce signal pour que la valeur varie entre 0V et 5V. Pour réaliser cette transformation, nous utilisons un montage à base d'amplificateurs opérationnels. Après avoir effectué les calculs des paramètres, nous validons l'approche et entamons la simulation.
- Pilotage des moteurs pas-à-pas :
Nous avons besoin de piloter deux moteurs pas-à-pas pour reproduire les mouvements du scanner. La rotation du support et le balayage vertical du capteur.
Après l'analyse de la datasheet des moteurs qui nous ont été fournis, nous avons relevé les caractéristiques de courant et de tension ainsi que la configuration du moteur.
Partie informatique
Durant La première séance nous avons entamé l'installation et la configuration de la raspberry.
Travail supplémentaire entre les deux séances
Lancement des impressions 3D du support du scanner.
Séance 2
Préparation de la séance
Nous avons défini les sous-objectifs suivants à réaliser pendant la séance:
- Calibrage du controleur moteur et mise en marche du moteur
- Conception physique du conditionneur de signal et test
- Configuration de la Rasberry pour fonctionner en hotspot
Partie électronique
Apres nous avons etudie les traits des moteurs et du controleur moteur, on a essaye de calibrer le controleur pour n'avoir pas un courant qui peut endommager le moteur. Pour faire ca, nous avons cherche comment limiter le courant avec ce type de controleur. Nous avons trouve la methode suivante:
- calculer la valeur optimale pour le courant de sortie de controleur, en utilisant la formule specifique pour nos composants ( Controleur A4988, Moteur pas-à-pas)
- mettre le courant (en entournant le potentiometre) qui sort du controleur a la valeur que nous avons calcule
- ajouter le moteur, le circuit pour controler le moteur, l'Arduino pour une source de 5V et la source de 12V
- allumer les sources
- verifier si le moteur tourne comme prevu
- sinon, tourner le potentiometre jusqu'a le bon mouvement du moteur, comme s'il n'y a pas assez ou trop de courant, le moteur ne tourne pas facilement
Finalement, nous avons calibre le controleur pour avoir en sortie 0.6A.
Pour verifier que notre circuit conditionneur convertit correctement le signal, nous avons ajoute le capteur de distance dans notre montage.
Sur le logiciel Arduino, nous avons cree un code qui nous donne les valeurs recus par le capteur et nous avons les mettre en temps reels sur un graphe. Dans le video au-desous, on peut voir que la sortie du capteur est entre 0V et 5V, donc que notre circuit fonctionne correctement.
Nous avons réalisé un test du circuit de conditionnement pour l'acquisition de la distance :
Video
Travail supplémentaire entre les deux séances
Test des moteurs et de la translation verticale. Le système mécanique fonctionne mais le controlleur moteur dont nous disposons présente quelques disfonctionnements notamment l'instabilité du courant de sortie.
Arduino
Dans cette partie nous allons vous détailler notre code Arduino :
Le programme attend de recevoir l'information sur la précision (envoyé par l'interface web) du scan puis la validation pour commencer. En fonction de la précision le programme va faire plus ou moins de capture de point de l'objet par rotation. Vu que nous avons pas pu avoir de contrôleur moteur fonctionnel, nous faisons une acquisition de points toute les X microsecondes. Avec les contrôleurs nous aurions fait la prise de point tout les X degrés de rotation de l'objet (X sera calculé en fonction de la précision envoyé).
Les points sont ensuite envoyé un a un par liaison série jusqu’à la Raspberry pour être traité. On envoie dans un premier temps les paramètres du scan, c'est a dire la précision et la hauteur de l'objet, puis tout les points renvoyés par le capteur.
Programme Arduino : Fichier:Envoie capteur V3.ino.zip
Reconstruction 3D
Capteur vers fichier texte
Les points arrivent un a un via la liaison série sur la Raspberry, un programme python récupère les deux paramètres puis l'ensemble des points et les ajoutent a la ligne dans un fichier texte.
20 2 655 640 625 610 620 623 610 ... .. .
Programme de récupération liaison série : Fichier:Recup fichier.zip
C'est ensuite un programme en C qui récupère le fichier texte précédent et pour chaque points calcule les coordonnées cartésienne et stocke le tout dans un autre fichier texte.
10 5.000000 0.000000 0.000000 4.755282 1.545085 0.000000 4.045085 2.938926 0.000000 2.938926 4.045085 0.000000 1.545085 ... ..
Programme de conversion : Fichier:CylindriqueTOcartesien.c.zip
Représentation STL
Ensuite, on convertie ce fichier texte en Format STL [2]:
Pour réussir la conversion, nous avons dû construire en premier lieu une librairie C contenant les types de données ainsi que les fonctions de base nécessaires pour travailler. Dans la représentation STL, le modèle 3D est représenté en utilisant les élements géométriques suivants: Les points (Vertex), Les Vecteurs (Vectors), Les vecteurs normaux (Normal), les faces (Facet), les solides (Solid) et les objets(Object).
- ICI SONT REPRESENTES LES STRUCTURES DE DONNEE DE BASE
typedef struct { float x; float y; float z; } Vertex; typedef struct { float vx; float vy; float vz; } Vector; typedef struct { Vector normal; Vertex v1; Vertex v2; Vertex v3; } Facet; typedef Facet* Solid;
En ce qui concerne l'élement objet (Object), ce dernier n'est pas un type de donnée explicite mais juste un contenaire (Wrapper). Il est juste utilisé pour parser à la phase finale le fichier STL en encodage ASCII.
Explication des fonctions de la librairie C créée
- AFFICHAGE CONSOLE
void dispVertex(Vertex ver); void dispVector(Vector vect); void dispFacet(Facet facet); void dispSolid(Solid solid, int NB_facets);
- GENERATION DU FICHIER STL
void generateFile(Solid s, int NB_facets); //FONCTION MERE FAISANT APPEL SEQUENTIELLEMENT AUX FONCTIONS SUIVANTES void genVertex(Vertex ver, FILE* fp); //ECRIRE UN VERTEX DANS LE FICHIER STL void genVector(Vector vect, FILE* fp); //ECRIRE UN VECTEUR DANS LE FICHIER STL void genFacet(Facet facet, FILE* fp); //ECRIRE UNE FACET DANS LE FICHIER STL void genSolid(Solid solid,int NB_facets, FILE* fp); //ECRIRE UN SOLIDE DANS LE FICHIER STL
- CONSTRUCTEURS D ELEMENTS ALEATOIRES POUR LE TEST DES ALGORITHMES
Vertex likelyRandomVertex(int level,int precision,int circle_pos, int max); //GENERE SEQUENTIELLEMENT LES POINTS DE LA SURFACE D UN CONE float randomCoordinate(); Vertex randomVertex(); Facet randomFacet(); Solid randomSolid(int NB_facets); //GENERE UN SOLID AVEC UN NOMBRE DONNE DE FACETs
- CONSTRUCTEURS D ELEMENTS DEFINIS
Vertex getVertex(float x,float y, float z); //CREE UN VERTEX A PARTIR DE 3 COORDONEES CARTESIENNES Vector getVector(Vertex A ,Vertex B); //CREE UN VECTEUR A PARTIR DE 3 VERTEX Facet getFacet(Vector normal, Vertex ver1,Vertex ver2, Vertex ver3); //CREE UNE FACET A PARTIR DE 3 VERTEX ET UN VECTEUR NORMAL Facet makeFacet(Vertex ver1, Vertex ver2, Vertex ver3); //CREE UNE FACET A PARTIR DE 3 VERTEX SEULEMENT Solid allocateSolid(int NB_facets); //ALLOCATION DYNAMIQUE DU SOLIDE
- CALCUL
Vector crossProduct(Vector a,Vector b); //CALCULE LE PRODUIT VECTORIEL POUR CREER UN VECTEUR NORMAL
Test de l'algorithme de reconstruction avec simulation de point d'acquisition
La première approche de reconstruction est faite en créant une matrice des vertex collectés (VMatrix). On crée une Facet à partir de chaque trois Vertex voisins. Le principe pour créer un solide fermé est que chaque Facet partage chacun de ses côtés avec d'autres Facets. Ceci implique que les Vertex de la derniere colonne devrons se lier avec ceux de la première comme on peut le voir sur les illustrations. Pour réaliser un solide complètement fermé il est necessaire de rajouter deux points (Vertex) virtuels. L'un devra être placé à l'origine sur l'axe de rotation du dispositif à la première couche de scan (Niv 0) afin de fermer l'objet par le bas. L'autre devra être placé à la dernière couche du scan au même emplacement pour ainsi pouvoir fermer le solide de haut.
Pour allouer dynamiquement la mémoire requise, il fallait calculer le nombre de Facet qui seront créées à partir d'un nombre donné de Vertex qui seront contenu dans la matrice. Nous nous sommes penché alors sur les proprités géométriques de notre approche. En se basant sur la formule des polyhèdres d'Euleur [3] nous avons réussi à calculer exactement la taille mémoire à allouer. En prenant en compte, biensur, la résolution radiale maximale du moteur pas-à-pas en Pas/tour comme nombre de points max par niveau de scan. Sans oublier la résolution verticale sachant que notre système mécanique nous offre une translation verticale de 1mm/tour avec intervalle de translation de 15cm. Ceci nous donne donc un résolution verticale de 150 Nivaux.
Pour les premiers tests nous avons mis en place des fonctions qui permettent de générer sequentiellement des points d'un solide conique. Nous avons implémenté aussi un moyen de selectionner la résolution du scan avec un paramètre precision. Nous avons effectué plusieurs test avec et sans bruit sur des résolutions différentes et les résultats sont plutôt concluants. Nous visionons les fichiers généré sur le Logiciel open-source Blender.
Programme conversion texte vers stl: Fichier:TexteTOstl.zip
Interface web
Dans un premier temps l'utilisateur doit se logger pour pouvoir accéder a l'interface de scan :
"En vue de la priorité des autres étapes, nous avons reporté l'aspect dynamique de cette page à plutard"
Ensuite il arrive sur la page du scan :
Les boutons qui envoient l'information de la precision sont les suivants :
<button onclick="sendMessage(1); bas">MAX 200pts (1)</button> <button onclick="sendMessage(2);">INTER1 40pts (5)</button> <button onclick="sendMessage(3);">MIN 20pts (10)</button>
Notre interface de scan, on choisie la précision parmi les trois proposés puis on lance le scan. Une fois celui-ci fini on télécharge le fichier stl via un href :
<a href= "../data/objet.stl"> Clique pour telecharger l'objet stl !! </a>
Les tests
Etant donné que nous n'avons pas de contrôleurs moteur, nous avons choisie un objet uniforme selon l'axe des Z (cf: photo objet scanné). Ainsi on peut scanner toute la forme sans que le capteur monte ou que l'objet tourne.
Après le premier scan ("Rien" c'est a dire sans filtre passe bas), on remarque que la forme générale est belle et bien présente mais qu'il a aussi de nombreuses imperfections.
On suppose que c'est imperfections sont du au capteur qui quelques fois renvoient des valeurs légèrement différente de la réalité. Pour résoudre ce problème nous allons essayer de filtrer la sortie du capteur.
Avec une capacité ("Capacité 100uF") ou des filtres passe-bas avec des valeurs de résistance différentes. D'après les objets 3D obtenu il semble que ce soit le passe-bas (C = 100uF et R = 20K) qui filtre le mieux les parasites.
Avec plus de temps nous aurions put faire plusieurs prises pour chaque points retirer les extrêmes puis faire une moyenne. On aurait obtenue une forme surement plus lisse.
Bilan
En conclusion, nous avons réussi à réaliser un prototype fonctionnel du projet que nous nous étions fixé au départ. Une bonne partie du cahier des charges initial a été respectée néanmoins il reste encore de nombreuses améliorations et corrections à apporter à ce système pour obtenir un scan fidèle à la réalité. Notamment:
- Nous devrons remplacer le capteur de distance qui présente un fort bruit causant ainsi l'apparition de piques autour de l'objet scanné.
- Ajouter un degré de libérté supplémentaire pour pouvoir scanner l'objet dans son intégralité.
- Améliorer l'interface web: Affichage sur page web du fichier STL et ajout d'une barre de progression du scan.
- Améliorer l'approche de reconstruction de l'objet en 3D pour pouvoir scanner des objets plus complèxes.
Ces améliorations peuvent faire l'objet d'un projet en 4ème Année.