Projet IMA3 P7, 2017/2018, TD1 : Différence entre versions

De Wiki de Projets IMA
(Travail supplémentaire entre les deux séances)
(Arduino)
 
(132 révisions intermédiaires par 4 utilisateurs non affichées)
Ligne 5 : Ligne 5 :
  
  
===<span style="color:Green">'''Description du système'''</span>===
+
==<span style="color:Red">'''Description du système'''</span>==
INSERER LA PHOTO FINALE
+
 
 +
[[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é.
 
'''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>
 
Ce projet a pour but de :<br>
  1. Acquisition de mesures de distance <br>
+
# Acquisition de mesures de distance <br>
  2. Pilotage des moteurs pas-à-pas<br>
+
# Pilotage des moteurs pas-à-pas<br>
  3. Transmission des points de mesure depuis l'arduino à la Raspberry en liaison série. <br>
+
# Transmission des points de mesure depuis l'arduino à la Raspberry en liaison série. <br>
  4. Reconstruction de la géométrie de l'objet scanné<br>
+
# Reconstruction de la géométrie de l'objet scanné<br>
  5. Génération d'un fichier STL<br>
+
# Génération d'un fichier STL<br>
  6. Réalisation de l'interface web et mise en place de la communication<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.
 
'''Objectif global''': un système capable de fonctionner pour une catégorie d'objets solides plus ou moins uniformes.
Ligne 27 : Ligne 28 :
  
 
Préalablement à cette séance, nous avions:<br>
 
Préalablement à cette séance, nous avions:<br>
1. formé notre groupe et avons déjà réfléchi a notre idée de projet.<br>
+
# formé notre groupe et avons déjà réfléchi a notre idée de projet.<br>
2. étudié la faisabilité et les éventuelles difficultés. <br>
+
# étudié la faisabilité et les éventuelles difficultés. <br>
3. récupéré sur internet des modèles 3D du support d'un projet similaire sur internet que nous avons adapté à notre cas.<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>
4. préparé une liste des composants et du matériel nécessaire.<br>
+
# préparé une liste des composants et du matériel nécessaire.<br>
  
 
===<span style="color:Green">Partie électronique</span>===
 
===<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>
 
Nous avons défini deux sous-objectifs pour cette partie: <br>
  
  
[[Fichier: Circuit conditionneur.jpg|vignette|upright=0.85|Schéma du Conditionneur]]
+
 
 +
 
 +
 +
 
 
*'''Le conditionnement du signal du capteur:'''  
 
*'''Le conditionnement du signal du capteur:'''  
  
En effet, le capteur de distance fourni revoie, d'après la datasheet (Ref: 2Y0A21F7Y), un signal entre 0.3V et 3.1V.<br>
+
En effet, le capteur de distance fourni revoie, d'après la datasheet (Ref: 2Y0A21F7Y), un signal
Pour plus de précision nous allons conditionner ce signal pour que la valeur soit comprise entre 0V et 5V (valeur max lue par les sorties analogiques de l'arduino).
+
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>
  
<br><br>
 
<br>
 
<br>
 
  
  
Ligne 59 : Ligne 66 :
 
===<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>
 
Lancement des impressions 3D du support du scanner.<br>
[[Fichier:objets3D.jpg|vignette|upright|1000px]]<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> ==
Ligne 70 : Ligne 79 :
  
 
===<span style="color:Green">Partie électronique</span>===
 
===<span style="color:Green">Partie électronique</span>===
[[Fichier: 35156912_1771212276270661_4977713602522775552_n.jpg|center|upright=0.75|300px|Circuit pour controler le moteur]]<br>
+
[[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:
 +
 
  
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)
 
*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
 
*mettre le courant (en entournant le potentiometre) qui sort du controleur a la valeur que nous avons calcule
Ligne 82 : Ligne 94 :
 
Finalement, nous avons calibre le controleur pour avoir en sortie 0.6A. <br>
 
Finalement, nous avons calibre le controleur pour avoir en sortie 0.6A. <br>
  
[[Fichier: 34818911_2198525003726573_2836142689970290688_n.jpg|center|upright=0.75|300px|Le capteur de distance]]<br>
 
  
Pour verifier que notre circuit conditionneur convertit correctement le signal, nous avons ajoute le capteur de distance dans notre montage.<br>
 
  
[[Fichier: 35240488_2198525017059905_6735236150148988928_n.jpg|center|upright=0.75|300px|Circuit conditionneur de signal]]<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.
 
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>
 
[[Média:video-1528891753.mp4|Video]]<br>
  
===<span style="color:Green">Partie informatique</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">'''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]]
 +
 
  
===<span style="color:Green">Travail supplémentaire entre les deux séances</span>===
 
[[Fichier: 35237579_1771222849602937_6274818658199928832_n.jpg|center|upright=0.75|300px|Le scanner, forme initiale]]<br>
 
  
== <span style="color:Red">'''Travail supplémentaire'''</span> ==
+
<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:
  
===<span style="color:Green">Partie programmation: arduino</span>===
+
*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>
  
===<span style="color:Green">Reconstruction 3D</span>===
+
*Ajouter un degré de libérté supplémentaire pour pouvoir scanner l'objet dans son intégralité.<br>
  
===<span style="color:Green">Interface web</span>===
+
*Améliorer l'interface web: Affichage sur page web du fichier STL et ajout d'une barre de progression du scan.<br>
  
==  <span style="color:Red">'''Démonstration'''</span> ==
+
*Améliorer l'approche de reconstruction de l'objet en 3D pour pouvoir scanner des objets plus complèxes.<br>
  
  
== <span style="color:Red">'''Bilan'''</span> ==
+
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

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

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 :

  1. Acquisition de mesures de distance
  2. Pilotage des moteurs pas-à-pas
  3. Transmission des points de mesure depuis l'arduino à la Raspberry en liaison série.
  4. Reconstruction de la géométrie de l'objet scanné
  5. Génération d'un fichier STL
  6. 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:

  1. formé notre groupe et avons déjà réfléchi a notre idée de projet.
  2. étudié la faisabilité et les éventuelles difficultés.
  3. récupéré sur internet des modèles 3D du support d'un projet similaire sur internet que nous avons adapté à notre cas.
  4. préparé une liste des composants et du matériel nécessaire.

Partie électronique

Calculs
Schéma du Conditionneur

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.

Parties mécaniques imprimées


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

Circuit pour controler le moteur

Le capteur de distance

Circuit conditionneur de signal

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 translation verticale

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
...
..

Representation

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

VMatrix
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.



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 [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.




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.



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"

Login.png

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> 









Scan php.png

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

Objet scanné


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.








Objet 3D en fonction du filtre appliqué
Objet 3D en fonction du filtre appliqué




Bilan

Notre meilleur résultat



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.