Automatic Soldering System Project : Différence entre versions

De Wiki d'activités IMA
m (Le protocole de communication)
 
(29 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
 +
<include nopre noesc src="/home/pedago/pimasc/include/video-PlaceurCMS-iframe.html" />
 
__TOC__
 
__TOC__
 
<br style="clear: both;"/>
 
<br style="clear: both;"/>
Ligne 79 : Ligne 80 :
 
  ! scope="row" | Semaine 53 (28/12)
 
  ! scope="row" | Semaine 53 (28/12)
 
  | Réception espérée du matériel : Montage de la maquette / Prise en main et calibrage des éléments / Tests
 
  | Réception espérée du matériel : Montage de la maquette / Prise en main et calibrage des éléments / Tests
|-
 
! scope="row" | Semaine 01 (04/01)
 
|
 
|-
 
! scope="row" | Semaine 02 (11/01)
 
|
 
|-
 
! scope="row" | Semaine 03 (18/01)
 
|
 
|-
 
! scope="row" | Semaine 04 (25/01)
 
|
 
|-
 
! scope="row" | Semaine 05 (01/02)
 
|
 
|-
 
! scope="row" | Semaine 06 (08/02)
 
|
 
|-
 
! scope="row" | Semaine 07 (15/02)
 
|
 
|-
 
! scope="row" | Semaine 08 (22/02)
 
|
 
 
  |-
 
  |-
 
  |}
 
  |}
Ligne 140 : Ligne 117 :
 
[[Fichier:assp_usinage3.jpg|200px|thumb|left|Marquages sur le support pour la pose de pylônes]]
 
[[Fichier:assp_usinage3.jpg|200px|thumb|left|Marquages sur le support pour la pose de pylônes]]
 
[[Fichier:assp_usinage4.jpg|200px|thumb|right|Etat de la maquette avant la fixation finale]]
 
[[Fichier:assp_usinage4.jpg|200px|thumb|right|Etat de la maquette avant la fixation finale]]
Notre projet comprend une partie extrêmement importante de conception. Sur conseils de M. Astori, nous avons donc décidé d'utiliser une organisation plus particulière. Le principe de cette organisation est de créer des pièces (on parle ici uniquement de leur impression à l'imprimante 3D et de la phase de conception sous Catia) rapidement, avec une faible taux de remplissage (de l'ordre de 30%). Le but de cette méthode est de créer un nombre de pièces plus important, permettant plus facilement rectifications en fonction des remarques que nous tirons du montage.
+
Notre projet comprend une partie extrêmement importante de conception. Sur conseils de M. Astori, nous avons donc décidé d'utiliser une organisation particulière. Le principe de cette organisation est de créer des pièces (on parle ici uniquement de leur impression à l'imprimante 3D et de la phase de conception sous Catia) rapidement, avec une faible taux de remplissage (de l'ordre de 20 à 30%). Le but de cette méthode est de créer un nombre de pièces plus important, permettant plus facilement rectifications en fonction des remarques que nous tirons du montage.
  
 
===La partie usinage===
 
===La partie usinage===
Nous avons commencé par acheter une support contreplaqué en bois. Sur ce support, nous avons disposé quatre pylônes reliés deux à deux par un axe métallique. Nous avons donc découpé à la scie à chantourner plusieurs linteaux de bois pour fabriquer les pylônes. Ensuite, nous avons usiné les pylônes à l'aide d'une perceuse à colonne pour leur permettre de recevoir l'axe métallique.
+
Nous avons commencé par acheter une support contre-plaqué en bois. Sur ce support, nous avons disposé quatre pylônes reliés deux à deux par un axe métallique. Nous avons donc découpé à la scie à chantourner plusieurs linteaux de bois pour fabriquer les pylônes. Ensuite, nous avons usiné les pylônes à l'aide d'une perceuse à colonne pour leur permettre de recevoir l'axe métallique.
  
Ensuite, nous avons eu la surprise de recevoir des poulies non percées. Nous avons donc du les percer. Nous avons percé les deux premières à l'aide de la perceuse à colonne. Le désavantage de cet outil est son imprécision sur la largeur de perçage. De plus, il n'était pas possible d'y ajouter un mécanisme permettant son maintien au moteur. Par conséquent, nous avons eu la chance d'être aidé par l'atelier mécanique. Ainsi, nous avons usiné les deux dernières poulies à l'aide d'un tour conventionnel (sous la supervision du responsable de l'atelier mécanique). Nous avons ensuite, toujours avec l'aide de M.Yoan Dhont, percé les deux poulies selon un axe perpendiculaire au précédent et créé un filetage pour permettre l'insertion d'une vis sans tête pour assurer la fixation au moteur.
+
Ensuite, nous avons eu la surprise de recevoir des poulies non percées. Nous avons donc les percer. Nous avons percé les deux premières à l'aide de la perceuse à colonne. Le désavantage de cet outil est son imprécision sur la largeur de perçage. De plus, il n'était pas possible d'y ajouter un mécanisme permettant son maintien au moteur. Fort heureusement, nous avons eu la chance d'être aidés par l'atelier mécanique. Ainsi, nous avons usiné les deux dernières poulies à l'aide d'un tour conventionnel (sous la supervision du responsable de l'atelier mécanique). Nous avons ensuite, toujours avec l'aide de M.Yohann Dhondt, percé les deux poulies selon un axe perpendiculaire au précédent et créé un filetage pour permettre l'insertion d'une vis sans tête pour assurer la fixation au moteur.
  
Pour des raisons pratiques et esthétiques, nous avons demandé à la menuiserie de Polytech Lille de corriger nos pylônes pour assurer leur perpendicularité. Cette correction a été effectuée par M. David [TODO] et M. JP [TODO] à l'aide d'une scie à bande. Par la suite, nous avons marqué le support pour faciliter le perçage et l'ajustement des pylônes. Une fois les marquages, nous avons percé le support et les pylônes pour assurer une bonne fixation.
+
Pour des raisons pratiques et esthétiques, nous avons demandé à la menuiserie de Polytech Lille de corriger nos pylônes pour assurer leur perpendicularité. Cette correction a été effectuée par M. Perraux et M. Parent à l'aide d'une scie à bande. Par la suite, nous avons marqué le support pour faciliter le perçage et l'ajustement des pylônes. Une fois les marquages, nous avons percé le support et les pylônes pour assurer une bonne fixation.
  
===La partie impression===
+
Cependant, nous avons été contraints de mettre en place de nouveaux pylônes qui, pour des questions d’organisation, n’ont pas pu être rectifiés par le service menuiserie. Nous avons donc essayé de les découper au mieux en prenant en compte leur torsion.
 +
 
 +
===La partie impression 3D===
 +
====Pièces "guide axe" mobiles====
 
[[Fichier:assp_impression1.png|200px|thumb|left|Version 1 et 2 du guide axe avec moteur]]
 
[[Fichier:assp_impression1.png|200px|thumb|left|Version 1 et 2 du guide axe avec moteur]]
 
[[Fichier:assp_impression2.png|180px|thumb|right|Guide axe antagoniste (sans moteur)]]
 
[[Fichier:assp_impression2.png|180px|thumb|right|Guide axe antagoniste (sans moteur)]]
[[Fichier:assp_impression3.png|200px|thumb|left|Guide de poulie et garde moteur]]
+
Nous avons commencé par créer les premières versions des pièces mobiles se fixant sur les barres métalliques, qui permettent le déplacement selon l'axe X, et permettent d'embarquer le moteur pour le déplacement selon Y. Nous les avons créées à l'aide du logiciel Catia. Les cotes imposées sur le schéma sont celles fournies par la documentation et par mesure des axes métalliques au pied à coulisse.
Nous avons commencé par créé un chariot permettant le déplacement selon l'axe X, et permettant d'embarquer le moteur pour le déplacement selon Y. Nous l'avons créé à l'aide du logiciel Catia. Les cotes imposés sur le schéma sont celles fournies par la documentation et par mesure des axes métalliques au pieds à coulisse.
 
  
Après impression, nous nous sommes aperçu que la documentation comprenait une erreur importante sur la taille des moteurs, nous obligeant à réimprimer une deuxième pièce. Nous avons profiter de la deuxième impression pour réduire la surface de contexte entre l'axe X de la pièce et l'axe métallique X.
+
La deuxième pièce est très identique à la première à la différence près qu'elle n'embarque pas de moteur. Elle embarque uniquement une poulie permettant le passage de la courroie de transport en Y. Cette version, bien que fonctionnelle, n'a pas eu (pour le moment) l'amélioration apportée par la deuxième version de la pièce 1 (c'est à dire la réduction de surface de contact).
 +
 
 +
Nous nous sommes aperçu après l'impression que la documentation comprenait une erreur importante sur la taille des moteurs, nous obligeant à réimprimer une deuxième pièce. Nous avons profité de la deuxième impression pour réduire la surface de contact entre l'axe X de la pièce et l'axe métallique X.
 +
 
 +
Après tests sur la maquette, nous avons, malgré tout constaté les problèmes de frottements et de résistance à l’avancement que ces pièces engendrent sur certaines parties de nos axes métalliques. En effet, nos deux axes X ayant un parallélisme imparfait, le choix de notre liaison pivot glissant en bloquant la rotation autour de l’axe n’est pas adapté.
 +
 
 +
Nous avons donc modifié ces pièces en transformant la liaison “tube - cyllindre” par une liaison “roue incurvée - cylindre”, à la manière par exemple d’un rail de roller coaster (montagnes russes). Nous avons également doublé les moteurs sur l’axe X, un entraînement est donc créé sur les deux chariots, permettant une translation selon l’axe X plus fluide et plus homogène.
 +
 
 +
[[Fichier:ASSP_guide_axe_final.jpg|180px|thumb|right|Version finale des guides axes pour l'axe X]]
 +
[[Fichier:ASSP_chariot.jpg|180px|thumb|left|Photo du chariot réalisé]]
 +
 
 +
====Conception du chariot comportant l'outil====
 +
 
 +
Le chariot est la partie la plus complexe de la maquette. Il doit assurer un grand nombre de fonctions. Il embarque un moteur pour la translation en Z, un moteur pour la rotation en Z, un système permettant d’adapter un préhenseur (dans notre cas: une seringue) au système à pression pneumatique et un système permettant de détecter la force appliquée pendant la pose du CMS.
  
La deuxième pièce est très identique à la première à la différence près qu'elle n'embarque pas de moteur. Elle embarque uniquement une poulie permettant le passage de la courroie de transport en Y. Cette version, bien que fonctionnelle, n'a pas eu (pour le moment) l'amélioration apportée par la deuxième version de la pièce 1 (c'est à dire la réduction de surface de contact).
+
Tout d’abord, son mouvement de translation avec l’axe Y est assuré par le même système de poulie que les guides axes. La translation en Z est assurée par un moteur engrènant une vis sans fin. Cette vis lie un solide qui assure alors une liaison glissière. Une pièce imprimée encastrée à ce solide nous permet de lier notre arrivée de pression négative à notre seringue.
  
Les deux dernières pièces sont des pièces de support pour permettre au moteur de l'axe X et à la poulie de l'axe X de se maintenir sur leur pylône respectif. Le support de poulie n'a tenu que deux jours avant de rendre l'âme. Nous avons donc remplacé de façon temporaire son axe par une longue vis à bois. Le support de moteur n'a, lui, pas cassé, mais nécessite d'être imprimer une deuxième fois car la documentation du moteur était incorrecte (encore une fois).
+
Pour permettre une rotation selon l’axe Z, nous avons intégré un logement pour placer un moteur lié à un engrenage. Cet engrenage est destiné à venir faire tourner la pièce centrale (la pièce en rouge sur la photo suivante) à l’aide d’un engrenage interne.
  
Quelques jours avant la pré soutenance, les pièces semblent fonctionnelles. Une amélioration peut être apportée dans un second temps en modifiant les guide d'axe par des poulies (imprimées à l'imprimante 3D) permettant de suivre plus fidèlement l'axe métallique. Ce système sera développé durant les semaines suivants la pré soutenance.
+
Le chariot créé comporte également la solution choisie pour détecter un contact entre l’aiguille et un objet. En effet, nous n’avons pas assez de place pour intégrer des capteurs fin de course sur notre système moteur-glissière assurant la translation en Z. Cependant, ce dont nous avons besoin pour cette fonctionnalité “Détecter le contact entre le composant et la carte afin de ne pas les endommager” est réalisé par un capteur de position linéaire type potentiomètre linéaire. En effet, par un système de ressort intégré dans le chariot, nous pouvons obtenir la petite distance dont la pièce maintenant le moteur-glissière Z s’est déplacée et ainsi, la force exercée sur la carte/composant par l’aiguille.
  
 
+
[[Fichier:ASSP_photo_maquette_finale.JPG|450px|thumb|center|Photo de l'infrastructure mécanique finale et des éléments assemblés]]
  
  
 
==Motorisation et asservissement en position==
 
==Motorisation et asservissement en position==
 
===Besoins et choix des moteurs===
 
===Besoins et choix des moteurs===
Nous avons besoin de déplacer notre chariot comportant l'outil d'aspiration qui manipule les composants selon les 3 axes de l'espace X, Y et Z. Afin d'assurer les translations dans le plan (X,Y), nous nous sommes orienté vers un système moteur-poulie-courroie sur chacun de ces 2 axes. Nous avons besoin d'une précision en position de l'ordre de 0,2mm et n'avons pas un besoin en couple important, ni d'un asservissement en vitesse spécifique.
+
Nous avons besoin de déplacer notre chariot comportant l'outil d'aspiration qui manipule les composants selon les 3 axes de l'espace X, Y et Z. Afin d'assurer les translations dans le plan (X,Y), nous nous sommes orientés vers un système moteur-poulie-courroie sur chacun de ces 2 axes. Nous avons besoin d'une précision en position de l'ordre de 0,2mm et n'avons pas un besoin en couple important, ni d'un asservissement en vitesse spécifique.
  
Nous avons donc choisi d'utiliser des moteurs Pas à Pas, qui offrent les avantages d'être précis en terme de position angulaire, de pouvoir adapter cette précision en les commandant en micro-pas et surtout de pouvoir réaliser l'asservissement en position sans capteurs. En effet, nous nous baserons sur le comptage du nombre de pas que l'on a fait effectuer au moteur, en supposant qu'aucun pas n'est sauté durant le déplacement. En effet, dans notre application la charge a entrainer est suffisamment faible et le déplacement se fera a une vitesse suffisamment basse afin d'assurer cette hypothèse.
+
Nous avons donc choisi d'utiliser des moteurs Pas à Pas, qui offrent les avantages d'être précis en terme de position angulaire, de pouvoir adapter cette précision en les commandant en micro-pas et surtout de pouvoir réaliser l'asservissement en position sans capteurs. En effet, nous nous baserons sur le comptage du nombre de pas que l'on a fait effectuer au moteur, en supposant qu'aucun pas n'est sauté durant le déplacement. En effet, dans notre application la charge a entraîner est suffisamment faible et le déplacement se fera a une vitesse suffisamment lente afin d'assurer cette hypothèse.
  
 
Dans une seconde version, pour être sûr du positionnement et pour palier aux imprécisions (type jeux sur la maquette...) sur la position initiale, la position de la poulie et son diamètre, nous mettrons en place un système d'ajustement via une caméra, où l'utilisateur viendra valider le placement du composant avant dépose sur la carte.
 
Dans une seconde version, pour être sûr du positionnement et pour palier aux imprécisions (type jeux sur la maquette...) sur la position initiale, la position de la poulie et son diamètre, nous mettrons en place un système d'ajustement via une caméra, où l'utilisateur viendra valider le placement du composant avant dépose sur la carte.
Ligne 176 : Ligne 168 :
 
Le déplacement de position est alors déduit ainsi : <math>\Delta X = \mu_{micropas} * \theta_{Pas_{nominal}} * R_{poulie} * \Delta {N_{Pas}}</math>
 
Le déplacement de position est alors déduit ainsi : <math>\Delta X = \mu_{micropas} * \theta_{Pas_{nominal}} * R_{poulie} * \Delta {N_{Pas}}</math>
  
avec <math>\theta_{Pas_{nominal}}</math> le pas angulaire de nos moteurs en radian (ici, 1,8°=0,031415 rad) ,<math>\mu_{micropas}</math> le facteur de micro-pas choisi (typiquement 1/2, 1/4, voire 1/8), <math>R_{poulie}</math> le rayon du moyen de la poulie crantée en mm (ici 7,15mm) et <math>\Delta {N_{Pas}}</math> le nombre de pas demandé (dans un sens ou dans un autre).
+
avec <math>\theta_{Pas_{nominal}}</math> le pas angulaire de nos moteurs en radian (ici, 1,8°=0,031415 rad) ,<math>\mu_{micropas}</math> le facteur de micro-pas choisi (typiquement 1/2, 1/4, voire 1/8), <math>R_{poulie}</math> le rayon primitif de la poulie crantée en mm (ici 7,15mm) et <math>\Delta {N_{Pas}}</math> le nombre de pas demandé (dans un sens ou dans un autre).
  
Pour enfin connaitre la position absolue, il s'agit de connaitre la position initiale du chariot. Ceci sera réalisé avec des capteurs "fin de course", type contacteurs à lamelles.
+
Ceci nous assure donc en théorie, de disposer d’une résolution en déplacement d’une précision de l’ordre de ΔXmin_théorique = 0,028 mm en commandant nos moteurs en 8ème de pas. Ceci est conforme au cahier des charges en terme de précision pour poser du CMS Classe 5, nécessitant une précision de 0,2mm, pour les déplacements en X et en Y.
 +
 
 +
Pour enfin connaître la position absolue, il s'agit de connaître la position initiale du chariot. Ceci est réalisé avec des capteurs "fin de course", type contacteurs à lamelles. En effet, nous effectuons avant le déplacement une “mise à zéro” en terme de position, en commandant le déplacement du chariot jusqu’à atteindre les contacteurs en X = 0 et en Y = 0.
 +
Les capteurs de positions qui sont disposés de part et d’autre de chaque axe (début et fin de course), sont également utilisés en tant que sécurité : si un contact est détecté, les moteurs s’arrêtent, afin de ne pas endommager ces derniers ou la maquette.
  
 
===Commande des moteurs Pas à Pas===
 
===Commande des moteurs Pas à Pas===
Ligne 185 : Ligne 180 :
 
[[Fichier:assp_schema_bipolar_stepper.jpg|300px|thumb|right|Schéma de la séquence d'alimentation complète du moteur bipolaire, en pas complet]]
 
[[Fichier:assp_schema_bipolar_stepper.jpg|300px|thumb|right|Schéma de la séquence d'alimentation complète du moteur bipolaire, en pas complet]]
  
Le principal inconvénient des moteurs Pas à Pas réside dans la commande de ceux-ci. En effet, un moteur Pas à Pas est un moteur particulier sans balai et alimenté par une alimentation continue. Il comporte plusieurs bobines permettant de créer un champ magnétique à l'intérieur et ainsi d'orienter des aimants fixés au rotor dans la direction du champ magnétique crée, ce qui provoque la rotation de l'arbre. On utilise le terme Pas à Pas car le champ magnétique crée à l'intérieur se fait par incréments. Ainsi pour faire tourner l'arbre entièrement, il faut effectuer l'alimentation des bobines pour une position 1, puis position 2, et ainsi de suite, selon la géométrie et la technologie du moteur utilisées.
+
Le principal inconvénient des moteurs Pas à Pas réside dans leur commande. En effet, un moteur Pas à Pas est un moteur particulier sans balai et alimenté par une alimentation continue. Il comporte plusieurs bobines permettant de créer un champ magnétique à l'intérieur et ainsi d'orienter des aimants fixés au rotor dans la direction du champ magnétique créé, ce qui provoque la rotation de l'arbre. On utilise le terme Pas à Pas car le champ magnétique créé à l'intérieur se fait par incréments. Ainsi pour faire tourner l'arbre entièrement, il faut effectuer l'alimentation des bobines pour une position 1, puis position 2, et ainsi de suite, selon la géométrie et la technologie du moteur utilisées.
  
Ainsi, le contrôle de celui ci s'effectue par une séquence d'alimentation spécifique de ses différentes phases. Dans notre cas, nous avons choisi des moteurs bipolaires (de type Hybride, c'est à dire combinant les avantages des technologies "à aimant permanent" et à "réluctance variable"). Le sens de rotation des ces moteurs dépend de l'ordre d'alimentation des 2 bobines, ainsi que du sens du courant.
+
Ainsi, son contrôle s'effectue par une séquence d'alimentation spécifique de ses différentes phases. Dans notre cas, nous avons choisi des moteurs bipolaires (de type Hybride, c'est à dire combinant les avantages des technologies "à aimant permanent" et à "réluctance variable"). Le sens de rotation de ces moteurs dépend de l'ordre d'alimentation des 2 bobines, ainsi que du sens du courant.
  
Ce pilotage peut s'effectuer au moyen d'une électronique de puissance type pont en H, sur laquelle on pilote les séquences de commutation des différentes cellules de commutation (transistor + diode en sens inverse en parallèle). Cependant une telle structure est compliquée à mettre en place au niveau des séquences, n'intègre pas directement de limitation active du courant délivré dans la bobine et surtout n'intègre pas directement de variation de courant afin de contrôler le moteur en micro-pas.
+
Ce pilotage peut s'effectuer au moyen d'une électronique de puissance type pont en H, sur laquelle on pilote les séquences de commutations des différentes cellules de commutation (transistor + diode en sens inverse en parallèle). Cependant une telle structure est compliquée à mettre en place au niveau des séquences, car elle n'intègre pas directement de limitation active du courant délivré dans la bobine et surtout car elle n'intègre pas directement de variation de courant afin de contrôler le moteur en micro-pas.
  
Présentant des prix très faibles (environ 5€) pour l'économie de temps et la simplicité d'utilisation qu'ils représentent, nous avons donc cherché des solutions de drivers adaptés à nos moteurs. Basé sur le circuit A4988 d'Allegro, nous nous sommes tourné vers ce driver pour moteur bipolaire (Pololu A4988 Stepper Motor Driver Carrier). Son principe est simple : il intègre directement cette structure de pont en H et les séquences d'alimentation. Il permet ainsi de faire effectuer au moteur un pas en envoyant une impulsion (front montant) sur sa pin STEP, dans le sens défini par l'état (haut ou bas) de sa pin DIR.
+
Présentant des prix très faibles (environ 5€) pour l'économie de temps et la simplicité d'utilisation qu'ils représentent, nous avons donc cherché des solutions de drivers adaptés à nos moteurs. Basé sur le circuit A4988 d'Allegro, nous nous sommes tournés vers ce driver pour moteur bipolaire (Pololu A4988 Stepper Motor Driver Carrier). Son principe est simple : il intègre directement cette structure de pont en H et les séquences d'alimentation. Il permet ainsi de faire effectuer au moteur un pas en envoyant une impulsion (front montant) sur sa pin STEP, dans le sens de rotation défini par l'état (haut ou bas) de sa pin DIR.
  
 
[[Fichier:assp_driver_pololu_pinout.png|380px|thumb|centre|Schéma du fonctionnement et du branchement du driver]]
 
[[Fichier:assp_driver_pololu_pinout.png|380px|thumb|centre|Schéma du fonctionnement et du branchement du driver]]
Ligne 197 : Ligne 192 :
 
Ce driver réalise également l'interface commande-puissance, il comporte une alimentation séparée pour le circuit logique (5V) et l'alimentation de puissance des moteurs (ici 12V). Il est très important pour éviter la surchauffe et l'endommagement des moteurs de contrôler le courant envoyé dans ses bobines. Nous limitons ainsi activement ce courant grâce au driver au moyen d'un potentiomètre à régler sur ce dernier. Nous avons réglé cette valeur par rapport aux courants nominaux par phase de nos moteurs.
 
Ce driver réalise également l'interface commande-puissance, il comporte une alimentation séparée pour le circuit logique (5V) et l'alimentation de puissance des moteurs (ici 12V). Il est très important pour éviter la surchauffe et l'endommagement des moteurs de contrôler le courant envoyé dans ses bobines. Nous limitons ainsi activement ce courant grâce au driver au moyen d'un potentiomètre à régler sur ce dernier. Nous avons réglé cette valeur par rapport aux courants nominaux par phase de nos moteurs.
  
L'avantage majeur de ce driver est qu'il comporte une solution de fonctionnement en micro-pas directement. Par l'état de ses pins MS1, MS2 et MS3, il nous permet de piloter du pas complet, au 1/16 de pas (maximum). Nous ne piloterons pas jusqu'au 1/16 de pas pour des soucis de stabilité du couple mécanique et pour éviter de sauter des pas, 1/4 voire 1/8 de pas devrait être suffisant. Le choix du micropas maximum sera à déterminer avec les tests sur la machine.
+
L'avantage majeur de ce driver est qu'il comporte une solution de fonctionnement en micro-pas directement. Par l'état de ses pins MS1, MS2 et MS3, il nous permet de piloter du pas complet, au 1/16 de pas (maximum). Nous ne piloterons pas jusqu'au 1/16 de pas pour des soucis de stabilité du couple mécanique et pour éviter de sauter des pas, 1/4 voire 1/8 de pas devrait être suffisant. Et en effet, au gré des différents tests, le pilotage en 8ème de pas a montré un fonctionnement correct et stable.
  
 
Ainsi, nous pilotons toutes ces différentes entrées par le biais d'un Arduino Mega. Plus tard, cet Arduino Mega servira d'interface entre la consigne de position envoyée depuis l'application PC et les moteurs.
 
Ainsi, nous pilotons toutes ces différentes entrées par le biais d'un Arduino Mega. Plus tard, cet Arduino Mega servira d'interface entre la consigne de position envoyée depuis l'application PC et les moteurs.
  
[[Fichier:|200px|thumb|right|Photo de la partie commande des moteurs]]
+
==Création de l'outil de manipulation par aspiration==
  
==Création de l'outil de manipulation par aspiration==
+
[[Fichier:ASSP_schema_pneumatique.png|220px|thumb|right|Schéma du fonctionnement du circuit pneumatique]]
  
 
L'outil qui viendra attraper et déposer les composants sera composé d'une aiguille fine qui les maintiendra par aspiration. Le système sera donc composé d'une pompe à vide, type pompe d'aquariophilie, peu couteuse, car l'aspiration nécessaire pour maintenir un composant est vraiment très faible. Ce genre de pompe se commande en tout ou rien au moyen d'un interrupteur manuel. Afin de ne pas alterner cycles d'allumage de la pompe pour éviter de l'endommager et surtout d'attendre le temps d'établissement du débit à chaque fois, lors des phases aspiration-dépose, nous utiliserons un distributeur pneumatique qui viendra envoyer ou non la dépression dans le tuyau d'air.
 
L'outil qui viendra attraper et déposer les composants sera composé d'une aiguille fine qui les maintiendra par aspiration. Le système sera donc composé d'une pompe à vide, type pompe d'aquariophilie, peu couteuse, car l'aspiration nécessaire pour maintenir un composant est vraiment très faible. Ce genre de pompe se commande en tout ou rien au moyen d'un interrupteur manuel. Afin de ne pas alterner cycles d'allumage de la pompe pour éviter de l'endommager et surtout d'attendre le temps d'établissement du débit à chaque fois, lors des phases aspiration-dépose, nous utiliserons un distributeur pneumatique qui viendra envoyer ou non la dépression dans le tuyau d'air.
  
Une partie majeure du travail va consister en la conception de la pièce mécanique, le chariot, qui intégrera les moteurs pour effectuer la translation et la rotation autour de Z, un capteur piézoélectrique qui permettra la détection du contact entre le composant et la carte et qui intégrera un espace prévu à cet effet pour maintenir le tuyau et l'aiguille. Ce chariot sera adaptable au reste du châssis et comportera une partie qui le fixe à la courroie.
+
Niveau matériel pour cette partie, nous avons pour le moment réuni le distributeur, les tuyaux et l'aiguille. Nous devrions recevoir la pompe sous peu de temps.
 +
 
 +
Après réception, nous avons constaté l’inconvénient de ce genre de pompe : son arrivée d’air (coté aspiration donc) n’est pas accessible et connectable. Il s’agit en effet d’une large membrane souple et perméable, en matière type “feutre”. Nous nous sommes donc procuré un tube à effet Venturi, qui “transforme” une pression entrante positive (“souffle”) en une pression sortante négative (“aspiration”).
 +
 
 +
 
 +
De par sa conception et par le principe physique mis en oeuvre, le tube à effet Venturi nécessite une pression et un débit suffisamment élevés, que notre pompe d’aquariophilie ne nous offre pas. Cependant, après discussion avec Thierry Flamen, la salle du service EEI possèdera dans un futur proche un raccordement en air comprimé. Ainsi, pour une utilisation au service EEI, il suffira de connecter notre câble d’arrivée d’air à ce raccordement. Dans l’attente des travaux, un compresseur à air peut tout à fait être utilisé.
 +
 
 +
Afin de commander ou non l’aspiration dans l’aiguille, nous utilisons un distributeur électro-pneumatique. Le distributeur devant être alimenté avec une tension de 24V, nous utilisons un optocoupleur en guise d’interrupteur commandé, piloté au moyen d’une sortie d’un Arduino.
 +
 
 +
==Commande et lecture des éléments du système via Arduino==
 +
===Description des fonctions réalisées par l'Arduino Mega===
 +
Afin de relier les divers éléments du système à l’application pour l’utilisateur, nous utilisons un Arduino Mega. En effet, ce dernier est utilisé pour jouer le rôle d’interface entre les ordres donnés par l’application PC et le contrôle des actionneurs / lecture des capteurs.
 +
   
 +
Voici les tâches dont se charge l’Arduino en terme de sorties :
 +
 
 +
*Contrôler la commande d’aspiration des composants
 +
*Permettre d’envoyer les ordres aux drivers qui commandent les 5 moteurs, à savoir :
 +
**2 moteurs pour la translation selon l’axe X
 +
**1 moteur pour la translation selon l’axe Y
 +
**1 moteur-glissière pour la translation selon l’axe Z
 +
**1 moteur pour la rotation autour de Z
 +
 
 +
Pour chacun des drivers, 6 sorties logiques sont à commander :
 +
1 bit pour l’activation du moteur (Enable),
 +
1 bit pour le choix du sens de rotation (Dir),
 +
1 bit pour exécuter les pas (Step) et  
 +
3 bits de sélection du micro-pas (MS1, MS2, MS3)
 +
 
 +
Voici les tâches dont se charge l’Arduino en terme d’entrées :
 +
 
 +
*Lecture de l’état des 6 capteurs fin de courses (contacteurs à lamelles, appuyés ou bien non appuyés) disposés pour X1_Min, X2_Min, Y_Min, X1_Max, X2_Max et Y_Max.
 +
*Conversion et lecture de la tension analogique, image de la position du potentiomètre linéaire, représentant la force appliquée sur l’aiguille selon l’axe Z
 +
 
 +
L’Arduino permet ainsi à l’application d’effectuer les fonctions d’écriture (surnommées ‘set’) qui se chargent de :
 +
 
 +
*donner une consigne de nombre de pas  au moteur sélectionné, par rapport à une position d’origine
 +
*choisir le facteur de micro-pas sur le moteur sélectionné (pas complet, ½ pas, ¼ de pas, ⅛ de pas ou 1/16 de pas)
 +
*commander l’optocoupleur relié au distributeur pneumatique pour l’allumage ou l’extinction de l’aspiration dans l’aiguille
 +
*choisir la limite maximale de force que l’aiguille peut appliquer sur l’axe Z. Ceci est réalisé en définissant une limite de position du potentiomètre au delà de laquelle nous arrêtons de commander le moteur Z
 +
*choisir la vitesse du moteur sélectionné, en définissant le temps en ms que nous attendons entre deux pas
 +
*verrouiller ou déverrouiller en position le moteur sélectionné, en envoyant ou pas le courant dans les bobines des moteurs, provoquant un couple de maintien ou non
  
Niveau matériel pour cette partie, nous avons pour le moment réuni le distributeur, les tuyaux et l'aiguille. Nous devrions recevoir la pompe sous peu de temps.
+
Pour que l’application PC puisse connaître les paramètres programmés sur l’Arduino et l’état des capteurs, l’Arduino permet aussi d’effectuer les fonctions de lecture (que nous avons surnommées ‘get’) et qui communique :
 +
 
 +
*l’état de de verrouillage en position des moteurs
 +
*la position d’un moteur sélectionné par rapport à l’origine
 +
*le facteur de micro-pas du moteur sélectionné
 +
*l’état de la consigne d’allumage de l’aspiration
 +
*la limite maximale de force que l’aiguille peut appliquer sur l’axe Z choisie
 +
*l’état des capteurs fin de course
 +
*la valeur convertie par l’ADC de la tension sur le potentiomètre
 +
*la vitesse des moteurs
 +
*la version du logiciel utilisé sur l’Arduino Mega
 +
 
 +
Dans le fonctionnement interne de l’Arduino, il s’assure pour chaque requête de déplacement que l’action demandée est réalisable. Le programme vérifie en effet que les contacteurs ne sont pas enclenchés tout au long du déplacement pour X et Y, ou que le potentiomètre n’a pas dépassé la valeur maximale qui a été fixée. Dans le cas contraire, l’action sur les moteurs est stoppée et l’Arduino communique un code d’erreur. Un code d’erreur est aussi communiqué en cas de jeu de paramètres demandés incorrect lors d’un appel à chaque fonction.
 +
 
 +
Par ailleurs, les codes du programme C implémenté sur l’Arduino sont disponibles sur GitHub à [https://github.com/henyxia/ASSP_Mega cette adresse] et sur [https://github.com/henyxia/ASSP_Mega le GitLab de Polytech Lille]
 +
 
 +
===Protocole de communication entre le logiciel et l'Arduino===
 +
Nous avons été amenés à concevoir un protocole de communication pour assurer l’exécution des ordres et la coopération entre l’application et l’Arduino. Ils communiquent via le port série et nous avons optimisé le protocole pour le rendre le plus compact possible afin de limiter le nombre de communications.
 +
 
 +
[[Fichier:ASSP_mega_task_flowchart.png|200px|thumb|right|Principe de fonctionnement du programme sur l'Arduino]]
 +
 
 +
Nous disposons de 2 types de fonctions : les fonctions d’écriture (‘set’) et les fonctions de lecture (‘get’). Les fonctions “d’actions” (‘set’) retournent un code de retour à la fin de chaque action, disant si elle s’est terminée correctement ou si une erreur est survenue, comme le déclenchement d’un contact ou la saisie d’un paramètre incorrect. Les fonctions de lecture (‘get’) retournent quant à elles l’information demandée.
  
==Conception du logiciel==
+
====Les trames de base====
===Définition du cadre===
 
Un des buts de ce projet est de concevoir une application permettant de contrôler les différents éléments du projet. Pour cela nous, l'application doit être capable de lire des fichiers standards de création de carte électronique (aussi appelés fichiers Gerber). De plus, nous souhaitions que l'application puisse être utilisé sur n'importe quelle plateforme. Pour cela, nous avons choisi de la développer sous [http://www.qt.io/ Qt]. L’environnement de travail Qt nous permet d'utiliser des objets permettant l'accès à n'importe quel type de matériel sans se soucier de la plateforme de destination. Pour la communication avec les éléments de commande (comme les moteurs) nous avons choisi de n'envoyer des ordres qu'à travers l'Arduino Mega.
 
===La communication entre le logiciel et l'Arduino Mega===
 
==Création d'un système sûr pour Arduino Mega==
 
L'application de bureau que nous avons créé va, comme expliqué précédemment, communiqué avec un Arduino Mega. Cet Arduino s'occupera de la commande de la partie du puissance du reste du système. Ces fonctions sont:
 
* Commander des moteurs sur les axes X, Y et Z
 
* Commander de la rotation selon Z
 
* Contrôler de la pompe
 
* Définir les paramètres avancés des moteurs (vitesse, précision des micropas)
 
* S'assurer de ne pas commander un ordre endommageant la machine
 
===Le protocole de communication===
 
[[Fichier:ASSP_mega_task_flowchart.png|200px|thumb|right]]Pour permettre de réaliser ces fonctions, l'application communique à travers le port série avec l'Arduino Mega. Le protocole utilisé est rendant le plus compact possible pour limiter le nombre de communications.
 
L'Arduino Mega ne fonctionne que par tâches (comme décris sur le schéma à droite). La seule possibilité pour l'Arduino de ne pas être dans cette exécution de tâches est d'être interrompu par un contact à lamelle souple (que nous considérons comme prioritaire). Dans ce cas, l'Arduino reste bloqué dans la fonction appelé par l'interruption jusqu'à temps que l'utilisateur valide manuellement la déverrouillage (ce qui permet d'éviter que le système ne puisse s’abîmer).
 
====Liste des fonctions====
 
 
  {| class="wikitable"
 
  {| class="wikitable"
  |+ Liste des fonctions appelées depuis le PC (PC->Mega)
+
  |+ Commande d'initialisation d'une tâche (PC->Mega)
 
  |-
 
  |-
 
  ! scope="row" | Bits
 
  ! scope="row" | Bits
Ligne 244 : Ligne 286 :
 
  |}
 
  |}
 
  {| class="wikitable"
 
  {| class="wikitable"
  |+ Liste des fonctions
+
|+ Commande de réponse d'une tâche (Mega->PC)
 +
|-
 +
! scope="row" | Bits
 +
|7
 +
|6
 +
|5
 +
|4
 +
|3
 +
|2
 +
|1
 +
|0
 +
|-
 +
! scope="row" | Data
 +
| colspan="4" | Donnée dépendant de la fonction
 +
| colspan="4" | Code de retour
 +
|}
 +
<strong>Si le code de retour est différent de 0, les trames de retour 2 et 3 ne sont pas envoyées</strong>
 +
{| class="wikitable"
 +
|+ Liste des codes de retour
 +
! scope="col" colspan="5" | Code retourné
 +
! scope="col" rowspan="2" | Nom dans le header
 +
! scope="col" rowspan="2" | Action à prendre
 +
! scope="col" rowspan="2" | Description du code
 +
|-
 +
! scope="col" | b3
 +
! scope="col" | b2
 +
! scope="col" | b1
 +
! scope="col" | b0
 +
! scope="col" | Hex
 +
|-
 +
| 0
 +
| 0
 +
| 0
 +
| 0
 +
| 0x00
 +
| CMD_OK
 +
| Aucune
 +
| La commande s'est exécutée correctement
 +
|-
 +
| 0
 +
| 0
 +
| 0
 +
| 1
 +
| 0x01
 +
| CMD_NOT_KNOWN
 +
| Report immédiat
 +
| La commande demandée n'est pas connue
 +
|-
 +
| 0
 +
| 0
 +
| 1
 +
| 0
 +
| 0x02
 +
| CMD_DEST_UNREACHABLE
 +
| Report immédiat
 +
| L'appel à la commande setDest a le paramètre <i>dest</i> trop grand sur le moteur choisi
 +
|-
 +
| 0
 +
| 0
 +
| 1
 +
| 1
 +
| 0x03
 +
| CMD_LOCK_MIN_X1
 +
| Report immédiat ou aucun
 +
| Le chariot a déclenché le contact à lamelle souple sur l'axe X 1 à son minimum
 +
|-
 +
| 0
 +
| 1
 +
| 0
 +
| 0
 +
| 0x04
 +
| CMD_LOCK_MAX_X1
 +
| Report immédiat ou aucun
 +
| Le chariot a déclenché le contact à lamelle souple sur l'axe X 1 à son maximum
 +
|-
 +
| 0
 +
| 0
 +
| 1
 +
| 1
 +
| 0x05
 +
| CMD_LOCK_MIN_X2
 +
| Report immédiat ou aucun
 +
| Le chariot a déclenché le contact à lamelle souple sur l'axe X 2 à son minimum
 +
|-
 +
| 0
 +
| 1
 +
| 1
 +
| 0
 +
| 0x06
 +
| CMD_LOCK_MAX_X2
 +
| Report immédiat ou aucun
 +
| Le chariot a déclenché le contact à lamelle souple sur l'axe X 2 à son maximum
 +
|-
 +
| 0
 +
| 1
 +
| 1
 +
| 1
 +
| 0x07
 +
| CMD_LOCK_MIN_Y
 +
| Report immédiat ou aucun
 +
| Le chariot a déclenché le contact à lamelle souple sur l'axe Y à son minimum
 +
|-
 +
| 1
 +
| 0
 +
| 0
 +
| 0
 +
| 0x08
 +
| CMD_LOCK_MAX_Y
 +
| Report immédiat ou aucun
 +
| Le chariot a déclenché le contact à lamelle souple sur l'axe Y à son maximum
 +
|-
 +
| 1
 +
| 0
 +
| 0
 +
| 1
 +
| 0x09
 +
| CMD_LOCK_Z
 +
| Report immédiat ou aucun
 +
| L'aiguille a touché un objet et a dépassé la force maximum à appliquer dessus
 +
|-
 +
| 1
 +
| 0
 +
| 1
 +
| 0
 +
| 0x0A
 +
| WAIT_FOR_NEXT_FRAME
 +
| Report immédiat ou aucun
 +
| La fonction appelée a été comprise, l'Arduino est en attente de la trame suivante.
 +
|-
 +
| 1
 +
| 0
 +
| 1
 +
| 1
 +
| 0x0B
 +
| WAIT_FOR_IT_1
 +
| Aucun
 +
| La réponse est partielle, il manque encore une trame.
 +
|-
 +
| 1
 +
| 1
 +
| 0
 +
| 0
 +
| 0x0C
 +
| WAIT_FOR_IT_2
 +
| Aucun
 +
| La réponse est partielle, il manque encore deux trames.
 +
|}
 +
 
 +
====Liste des fonctions d'écriture====
 +
{| class="wikitable"
 +
  |+ Liste des fonctions  
 
  ! scope="col" colspan="5" | Fonction appelée
 
  ! scope="col" colspan="5" | Fonction appelée
 
  ! scope="col" rowspan="2" | Nom de la fonction
 
  ! scope="col" rowspan="2" | Nom de la fonction
Ligne 261 : Ligne 453 :
 
  | 0
 
  | 0
 
  | 0
 
  | 0
  | 0
+
  | 0x00
 
  | setDest
 
  | setDest
 
  | selectedMotor[2bits]
 
  | selectedMotor[2bits]
Ligne 271 : Ligne 463 :
 
  | 0
 
  | 0
 
  | 1
 
  | 1
  | 1
+
  | 0x01
 
  | setMS
 
  | setMS
 
  | selectedMotor[2bits]
 
  | selectedMotor[2bits]
Ligne 281 : Ligne 473 :
 
  | 1
 
  | 1
 
  | 0
 
  | 0
  | 2
+
  | 0x02
 
  | setPump
 
  | setPump
 
  | onOff[1bit]
 
  | onOff[1bit]
Ligne 291 : Ligne 483 :
 
  | 1
 
  | 1
 
  | 1
 
  | 1
  | 3
+
  | 0x03
 
  | setADC
 
  | setADC
 
  | adcLevel[10bits]
 
  | adcLevel[10bits]
 
  | &empty;
 
  | &empty;
 
  | Donne la consigne d'allumage de la valeur maximale lisible par l'ADC
 
  | Donne la consigne d'allumage de la valeur maximale lisible par l'ADC
 +
|-
 +
| 0
 +
| 1
 +
| 0
 +
| 1
 +
| 0x05
 +
| setSpeed
 +
| selectedMotor[2bits]
 +
| delayStep[8bits]
 +
| Donne le temps en ms à attendre entre 2 pas (<=> la vitesse du moteur)
 +
|-
 +
| 0
 +
| 1
 +
| 1
 +
| 0
 +
| 0x06
 +
| setMotLocked
 +
| lockedOnOff[1bit], selectedMotor[2bits]
 +
| &empty;
 +
| Verrouille ou déverrouille en position le moteur sélectionné (<=> couple de maintien ou non)
 +
|}
 +
{| class="wikitable"
 +
|+ Détails sur la construction des fonctions d'écriture
 +
! scope="col" rowspan="2" | Fonction appelée
 +
! scope="col" colspan="4" | Trame 1
 +
! scope="col" colspan="8" | Trame 2
 +
! scope="col" colspan="8" | Trame 3
 +
|-
 +
! scope="col" | b7
 +
! scope="col" | b6
 +
! scope="col" | b5
 +
! scope="col" | b4
 +
! scope="col" | b7
 +
! scope="col" | b6
 +
! scope="col" | b5
 +
! scope="col" | b4
 +
! scope="col" | b3
 +
! scope="col" | b2
 +
! scope="col" | b1
 +
! scope="col" | b0
 +
! scope="col" | b7
 +
! scope="col" | b6
 +
! scope="col" | b5
 +
! scope="col" | b4
 +
! scope="col" | b3
 +
! scope="col" | b2
 +
! scope="col" | b1
 +
! scope="col" | b0
 +
|-
 +
| setDest
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | selectedMotor[1:0]
 +
| colspan="8" align="center" | destination[15:8]
 +
| colspan="8" align="center" | destination[7:0]
 +
|-
 +
| setMS
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | selectedMotor[1:0]
 +
| colspan="5" align="center" | &empty;
 +
| colspan="3" align="center" | microStep[2:0]
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| setPump
 +
| colspan="3" align="center" | &empty;
 +
| align="center" | onOff
 +
| colspan="16" align="center" | &empty;
 +
|-
 +
| setADC
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | adcLevel[9:8]
 +
| colspan="8" align="center" | adcLevel[7:0]
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| setSpeed
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | selectedMotor[1:0]
 +
| colspan="8" align="center" | delayStep[7:0]
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| setMotLocked
 +
| colspan="1" align="center" | &empty;
 +
| align="center" | onOff
 +
| colspan="2" align="center" | selectedMotor[1:0]
 +
| colspan="16" align="center" | &empty;
 +
|}
 +
 +
====Liste des fonctions de lecture====
 +
{| class="wikitable"
 +
|+ Liste des fonctions
 +
! scope="col" colspan="5" | Fonction appelée
 +
! scope="col" rowspan="2" | Nom de la fonction
 +
! scope="col" rowspan="2" | Paramètre 1
 +
! scope="col" rowspan="2" | Description fonction
 +
|-
 +
! scope="col" | b3
 +
! scope="col" | b2
 +
! scope="col" | b1
 +
! scope="col" | b0
 +
! scope="col" | Hex
 +
|-
 +
| 0
 +
| 1
 +
| 1
 +
| 1
 +
| 0x07
 +
| getMotLocked
 +
| &empty;
 +
| Retourne l'état du verrouillage en position de tous les moteurs
 +
|-
 +
| 1
 +
| 0
 +
| 0
 +
| 0
 +
| 0x08
 +
| getDest
 +
| selectedMotor[2bits]
 +
| Retourne la position d'un moteur donné en seizième de pas par rapport à l'origine
 +
|-
 +
| 1
 +
| 0
 +
| 0
 +
| 1
 +
| 0x09
 +
| getMS
 +
| &empty;
 +
| Retourne la consigne du nombre de micropas par tour pour tous les moteurs
 +
|-
 +
| 1
 +
| 0
 +
| 1
 +
| 0
 +
| 0x0A
 +
| getPump
 +
| &empty;
 +
| Retourne la consigne d'allumage actuelle de la pompe à vide
 +
|-
 +
| 1
 +
| 0
 +
| 1
 +
| 1
 +
| 0x0B
 +
| getADC
 +
| &empty;
 +
| Retourne la consigne d'allumage de la valeur maximale lisible par l'ADC
 +
|-
 +
| 1
 +
| 1
 +
| 0
 +
| 0
 +
| 0x0C
 +
| getContact
 +
| &empty;
 +
| Retourne l'état des contacteurs à lamelles (appuyés ou non)
 +
|-
 +
| 1
 +
| 1
 +
| 0
 +
| 1
 +
| 0x0D
 +
| getADCvalue
 +
| selectedPin[2bits]
 +
| Retourne la valeur convertie par l'ADC de la pin analogique sélectionnée
 +
|-
 +
| 1
 +
| 1
 +
| 1
 +
| 0
 +
| 0x0E
 +
| getSpeed
 +
| selectedMotor[2bits]
 +
| Retourne le délai entre 2 pas choisis pour le moteur sélectionné
 +
|-
 +
| 1
 +
| 1
 +
| 1
 +
| 1
 +
| 0x0F
 +
| getVersion
 +
| &empty;
 +
| Retourne la version du logiciel utilisée sur l'Arduino Mega (Actuelle: 0.1)
 +
|}
 +
{| class="wikitable"
 +
|+ Détails de la construction des trames de lecture
 +
! scope="col" rowspan="3" | Fonction appelée
 +
! scope="col" colspan="4" | Appel (PC->Mega)
 +
! scope="col" colspan="24" | Retour (Mega->PC)
 +
|-
 +
! scope="col" colspan="4" | Trame 1
 +
! scope="col" colspan="4" | Trame 1
 +
! scope="col" colspan="8" | Trame 2
 +
! scope="col" colspan="8" | Trame 3
 +
|-
 +
! scope="col" | b7
 +
! scope="col" | b6
 +
! scope="col" | b5
 +
! scope="col" | b4
 +
! scope="col" | b7
 +
! scope="col" | b6
 +
! scope="col" | b5
 +
! scope="col" | b4
 +
! scope="col" | b7
 +
! scope="col" | b6
 +
! scope="col" | b5
 +
! scope="col" | b4
 +
! scope="col" | b3
 +
! scope="col" | b2
 +
! scope="col" | b1
 +
! scope="col" | b0
 +
! scope="col" | b7
 +
! scope="col" | b6
 +
! scope="col" | b5
 +
! scope="col" | b4
 +
! scope="col" | b3
 +
! scope="col" | b2
 +
! scope="col" | b1
 +
! scope="col" | b0
 +
|-
 +
| getMotorLocked
 +
| colspan="4" align="center" | &empty;
 +
| lockedRotZ
 +
| lockedZ
 +
| lockedY
 +
| lockedX
 +
| colspan="8" align="center" | &empty;
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| getDest
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | selectedMotor[1:0]
 +
| colspan="4" align="center" | &empty;
 +
| colspan="8" align="center" | dest[15:8]
 +
| colspan="8" align="center" | dest[7:0]
 +
|-
 +
| getMS
 +
| colspan="4" align="center" | &empty;
 +
| msY[0]
 +
| colspan="3" align="center" | msX[2:0]
 +
| colspan="3" align="center" | msR[2:0]
 +
| colspan="3" align="center" | msZ[2:0]
 +
| colspan="2" align="center" | msY[2:1]
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| getPump
 +
| colspan="3" align="center" | &empty;
 +
| onOff
 +
| colspan="4" align="center" | &empty;
 +
| colspan="8" align="center" | &empty;
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| getADC
 +
| colspan="4" align="center" | &empty;
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | adcLevel[9:8]
 +
| colspan="8" align="center" | adcLevel[7:0]
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| getContact
 +
| colspan="4" align="center" | &empty;
 +
| isMinX1
 +
| isMaxX1
 +
| isMinX2
 +
| isMaxX2
 +
| colspan="6" align="center" | &empty;
 +
| isMinY
 +
| isMaxY
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| getADCvalue
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | selectedPin[1:0]
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | adcValue[9:8]
 +
| colspan="8" align="center" | adcValue[7:0]
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| getSpeed
 +
| colspan="2" align="center" | &empty;
 +
| colspan="2" align="center" | selectedMotor[1:0]
 +
| colspan="4" align="center" | &empty;
 +
| colspan="8" align="center" | delayStep[7:0]
 +
| colspan="8" align="center" | &empty;
 +
|-
 +
| getVersion
 +
| colspan="4" align="center" | &empty;
 +
| colspan="4" align="center" | minorVersion[3:0]
 +
| colspan="8" align="center" | majorVersion[7:0]
 +
| colspan="8" align="center" | &empty;
 
  |}
 
  |}
 +
 +
==Conception du logiciel d'interfaçage utilisateur==
 +
===Définition du cadre===
 +
Un des buts de ce projet est de concevoir une application permettant de contrôler les différents éléments du projet. Pour cela nous, l'application doit être capable de lire des fichiers standards de création de carte électronique (aussi appelés fichiers Gerber). De plus, nous souhaitions que l'application puisse être utilisé sur n'importe quelle plateforme. Pour cela, nous avons choisi de la développer sous [http://www.qt.io/ Qt]. L’environnement de travail Qt nous permet d'utiliser des objets permettant l'accès à n'importe quel type de matériel sans se soucier de la plateforme de destination. Pour la communication avec les éléments de commande (comme les moteurs) nous avons choisi de n'envoyer des ordres qu'à travers l'Arduino Mega.
 +
 +
Comme l’intégralité de notre travail est placé sous le drapeau de l’open source, nous avons souhaité permettre à n’importe qui de pouvoir compiler notre application sur son ordinateur, et cela quelque soit son système d’exploitation. Pour permettre la réalisation de cet objectif, nous avons choisi un framework parmis ceux permettant cette inter-opérabilité. Son code source est d’ailleurs disponible sur GitHug à [http://github.com/henyxia/ASSP l’adresse suivante]
 +
 +
Les collections d’objets et de librairies (aussi appelés framework) multi-OS se comptent sur les doigts de la main et ont tous leurs avantages et leurs inconvénients. Parmis les plus connus (wxWidgets, GTK+, FLTK, FOX, …), nous avons choisi de prendre Qt. Ce framework a l’avantage d’intégrer des interfaces multiplateformes pour le port série et la Webcam.
 +
 +
Nous noterons quand même le coté négatif de ce choix: le développement de la partie du port série a pris plus de temps que prévu. En effet, la gestion du buffer pour le port série est assez mal expliquée et semble être peu indépendante du système d’exploitation. Pour palier à ce problème, nous avons choisi d’utiliser un protocole de communication octet à octet avec accusé d’émission et de réception.
 +
 +
===Création d'une interface intuitive===
 +
Pour permettre à un utilisateur lambda de pouvoir utiliser notre interface, nous avons essayé de la rendre la plus intuitive possible. Pour cela, nous avons décomposé en trois zones distinctes les différentes informations. La première partie comporte une fenêtre OpenGL permettant la génération du rendu des fichiers GERBERs ouverts. Le deuxième volet est une fenêtre permettant le retour d’erreur et l’affichage d’informations sur l’état de l’application ou de la communication. Enfin, la troisième permet de visualiser en temps réel les variables de l’Arduino MEGA et d’ordonner des consignes.
 +
 +
==Fin du projet==
 +
Au terme d’un semestre consacré majoritairement au développement de ce projet de fin d’étude, nous sommes réellement heureux et fiers des avancées qui ont été accomplies. Les difficultés rencontrées étaient souvent de natures différentes du fait de la multidisciplinarité de ce projet. Cependant, une quantité importante de travail, ainsi qu’un suivi de la part de nos encadrants nous ont permis d’atteindre la majorité de nos objectifs.
 +
 +
Bien que ce projet avait pour vocation d’être intégré au terme du semestre, il reste quand même utile pour le pôle EEI. Il pourra en effet être repris comme futur projet en IMA et ainsi achever l'automatisation des tâches, l'ajout d'une vision caméra et l’interface utilisateur.

Version actuelle datée du 24 mars 2016 à 14:37


Vidéo HD


Placeur de composants sur PCB

Présentation du projet

Durant le début de l'été, nous avons eu l'idée de proposer un projet de soudure automatique. Ce projet avait pour but de concevoir un système permettant l'automatisation des soudures sur une carte électronique à composants traversants. Après des échanges avec le responsable des projet de 5éme année, M. Vantroys, nous avons finalement abandonné notre projet au profit d'un autre projet assez proche.

L'idée du nouveau projet est de proposer un système de Pick & Place de composants CMS sur une carte électronique sur laquelle de la crème à braser est préalablement déposée sur les pastilles. Pour mener à bien ce projet, nous avons été épaulé par M. Redon, M. Vantroys et M. Boé. En plus de nos encadrants école, nous avons travaillé en étroite collaboration avec M. Flamen, responsable du service électronique de Polytech Lille ainsi qu'avec M. Astori, enseignant en Conception Mécanique et responsable du FabLab de Polytech Lille. Nous tenons par ailleurs également à remercier chaleureusement Antoine, contributeur actif au Fablab de Polytech Lille, pour son partage d'expérience à propos de la création de son imprimante 3D RepRap, projet similaire au notre.

Définitions des objectifs

  • Prendre un composant
    • Stocker les composants à déposer sur la carte et identifier leur position
    • Maintenir le composant par aspiration
  • Repérer la position et l’orientation de la carte
  • Déplacer le composant
    • Le déplacer en translation selon les axes X, Y et Z
    • L’orienter correctement sur les pastilles (rotation autour de Z)
  • Déposer le composant
    • S’assurer que l’outil d’aspiration n’endommage ni la carte, ni le composant lors de la dépose -> détecter le contact entre le composant et la carte
  • Connaître la position désirée pour la dépose du composant
    • Récupérer les fichiers provenant du logiciel de CAO et les transformer en déplacement de la machine
    • Permettre à l’utilisateur d’avoir une interface visuelle (sur ordinateur) indiquant l’état des éléments de la machine et permettant leur calibrage

Liste des tâches

  • Créer l’infrastructure mécanique de la machine (châssis)
    • Fabrication du châssis
    • Design des pièces mobiles et impression 3D de ces pièces au FabLab (chariot comportant l’outil d’aspiration et “guides tubes” assurant la transformation de la rotation des moteurs en mouvement de translation (glissières) sur des barres métalliques)
    • Assembler l’outil d’aspiration au chariot
  • Concevoir la commande d’aspiration par pompe
  • Organiser la commande des moteurs du système pour l’asservissement en position de la machine
    • Étude et prise en main des drivers pour les moteurs Pas à Pas
  • Réalisation de l’interface commande-puissance
  • Réaliser la conversion des données de position (relatives) de l’emplacement souhaités des composants en mouvements pour la machine
    • Concevoir l’interface de récupération des données du fichier Gerber de l’utilisateur
    • Caractérisation des différents repères (repère de la machine, repère de l’outil et repère de la carte) et établir le lien entres eux
    • Détecter l’origine du repère de la carte au moyen d’une caméra fixe

Planning prévisionnel de répartition du travail

Semaine 39 (21/09) Brainstorming et réunions avec les encadrants de projet afin de définir les objectifs / Étude de faisabilité
Semaine 40 (28/09) Brainstorming et réunions avec les encadrants de projet afin de définir les objectifs / Étude de faisabilité
Semaine 41 (05/10) Dimensionnement des éléments du système et recherche du matériel à commander en tenant compte des contraintes de coût
Semaine 42 (12/10) Achat du matériel pour le châssis de la machine (bois, tiges métalliques...) et pré-assemblage / Conception des pièces mécaniques à imprimer au FabLab
Semaine 43 (19/10) Dans l'attente de la réception du matériel commandé : Conception des pièces mécaniques à imprimer au FabLab / Développement de l'application PC / Étude de l'asservissement en position
Semaine 44 (26/10) Dans l'attente de la réception du matériel commandé : Conception des pièces mécaniques à imprimer au FabLab / Développement de l'application PC / Étude de l'asservissement en position et du repérage caméra
Semaine 45 (02/11) Dans l'attente de la réception du matériel commandé : Conception des pièces mécaniques à imprimer au FabLab / Développement de l'application PC / Étude de la commande des moteurs et du repérage caméra
Semaine 46 (09/11) Dans l'attente de la réception du matériel commandé : Fabrication du châssis - assemblage des pièces / Développement de l'application PC / Étude de l'asservissement en position et du repérage caméra
Semaine 47 (16/11) Dans l'attente de la réception du matériel commandé : Impression 3D des pièces mécaniques / Développement de l'application PC / Étude de l'asservissement en position et du repérage caméra
Semaine 48 (23/11) Dans l'attente de la réception du matériel commandé : Impression 3D des pièces mécaniques / Développement de l'application PC / Étude de l'asservissement en position et du repérage caméra
Semaine 49 (30/11) Réception espérée du matériel : Montage de la maquette / Prise en main et calibrage des éléments / Tests
Semaine 50 (07/12) Réception espérée du matériel : Montage de la maquette / Prise en main et calibrage des éléments / Tests
Semaine 51 (14/12) Réception espérée du matériel : Montage de la maquette / Prise en main et calibrage des éléments / Tests
Semaine 52 (21/12) Réception espérée du matériel : Montage de la maquette / Prise en main et calibrage des éléments / Tests
Semaine 53 (28/12) Réception espérée du matériel : Montage de la maquette / Prise en main et calibrage des éléments / Tests

Retour sur les directives des encadrants

M. Flamen

Exemple de composants CMS

Dans un premier temps, pour mieux définir les objectifs de notre projet, nous avons pris rendez vous avec M. Flamen. M. Flamen est le responsable du service électronique de PolytechLille. Il est le principal intéressé par notre projet car celui-ci (le projet) permettrait de disposer de la chaîne complète de fabrication de cartes électroniques CMS (composants montés en surface).

Cette rencontre avec M. Flamen nous a permis de déterminer certaines précisions, comme:

  • La précision maximale demandé n'excédera pas 0,2 mm (précision de classe 5, qui est celle de la graveuse de carte du service EEI).

Liste de matériel

Matériel disponible

  • Support
    • 3 Tiges de 1 mètre [Reçu le 2015-10-12]
    • 1 Tasseau de 2m70 (découpé pour fabriquer les supports des tiges) [Reçu le 2015-10-12]
    • 1 Planche en bois pour effectuer le support du projet [Reçu le 2015-10-12]
  • Motorisation
    • 2 Moteurs Pas à Pas type NEMA 17 (pour axes X et Y) [1][Reçu le 2015-11-09]
    • 1 Moteur Pas à Pas (pour rotation autour de Z) [2][Reçu le 2015-11-09]
    • 1 Moteur Pas à Pas avec glissière intégrée (pour translation selon Z) [3][Reçu le 2015-11-09]
    • 4 drivers pour moteur Pas à Pas bipolaire [4][Reçu le 2015-11-09]
  • Outil d'aspiration
    • Aiguille manipulant le composant [5][Reçu le 2015-11-09]
    • Tube flexible [6][Reçu le 2015-11-09]
  • Châssis mécanique
    • 2 Courroies crantées [7][Reçu le 2015-11-09]
    • 4 Poulies crantées [8][Reçu le 2015-11-09]
  • 2 Courroies crantées plus grandes [Reçu le 2015-12-27]

Matériel manquant

  • Rien pour le moment

Fabrication de l'infrastructure mécanique

Usinage des pylônes à la perceuse à colonne
Tour conventionnel utilisé pour le perçage
Marquages sur le support pour la pose de pylônes
Etat de la maquette avant la fixation finale

Notre projet comprend une partie extrêmement importante de conception. Sur conseils de M. Astori, nous avons donc décidé d'utiliser une organisation particulière. Le principe de cette organisation est de créer des pièces (on parle ici uniquement de leur impression à l'imprimante 3D et de la phase de conception sous Catia) rapidement, avec une faible taux de remplissage (de l'ordre de 20 à 30%). Le but de cette méthode est de créer un nombre de pièces plus important, permettant plus facilement rectifications en fonction des remarques que nous tirons du montage.

La partie usinage

Nous avons commencé par acheter une support contre-plaqué en bois. Sur ce support, nous avons disposé quatre pylônes reliés deux à deux par un axe métallique. Nous avons donc découpé à la scie à chantourner plusieurs linteaux de bois pour fabriquer les pylônes. Ensuite, nous avons usiné les pylônes à l'aide d'une perceuse à colonne pour leur permettre de recevoir l'axe métallique.

Ensuite, nous avons eu la surprise de recevoir des poulies non percées. Nous avons donc dû les percer. Nous avons percé les deux premières à l'aide de la perceuse à colonne. Le désavantage de cet outil est son imprécision sur la largeur de perçage. De plus, il n'était pas possible d'y ajouter un mécanisme permettant son maintien au moteur. Fort heureusement, nous avons eu la chance d'être aidés par l'atelier mécanique. Ainsi, nous avons usiné les deux dernières poulies à l'aide d'un tour conventionnel (sous la supervision du responsable de l'atelier mécanique). Nous avons ensuite, toujours avec l'aide de M.Yohann Dhondt, percé les deux poulies selon un axe perpendiculaire au précédent et créé un filetage pour permettre l'insertion d'une vis sans tête pour assurer la fixation au moteur.

Pour des raisons pratiques et esthétiques, nous avons demandé à la menuiserie de Polytech Lille de corriger nos pylônes pour assurer leur perpendicularité. Cette correction a été effectuée par M. Perraux et M. Parent à l'aide d'une scie à bande. Par la suite, nous avons marqué le support pour faciliter le perçage et l'ajustement des pylônes. Une fois les marquages, nous avons percé le support et les pylônes pour assurer une bonne fixation.

Cependant, nous avons été contraints de mettre en place de nouveaux pylônes qui, pour des questions d’organisation, n’ont pas pu être rectifiés par le service menuiserie. Nous avons donc essayé de les découper au mieux en prenant en compte leur torsion.

La partie impression 3D

Pièces "guide axe" mobiles

Version 1 et 2 du guide axe avec moteur
Guide axe antagoniste (sans moteur)

Nous avons commencé par créer les premières versions des pièces mobiles se fixant sur les barres métalliques, qui permettent le déplacement selon l'axe X, et permettent d'embarquer le moteur pour le déplacement selon Y. Nous les avons créées à l'aide du logiciel Catia. Les cotes imposées sur le schéma sont celles fournies par la documentation et par mesure des axes métalliques au pied à coulisse.

La deuxième pièce est très identique à la première à la différence près qu'elle n'embarque pas de moteur. Elle embarque uniquement une poulie permettant le passage de la courroie de transport en Y. Cette version, bien que fonctionnelle, n'a pas eu (pour le moment) l'amélioration apportée par la deuxième version de la pièce 1 (c'est à dire la réduction de surface de contact).

Nous nous sommes aperçu après l'impression que la documentation comprenait une erreur importante sur la taille des moteurs, nous obligeant à réimprimer une deuxième pièce. Nous avons profité de la deuxième impression pour réduire la surface de contact entre l'axe X de la pièce et l'axe métallique X.

Après tests sur la maquette, nous avons, malgré tout constaté les problèmes de frottements et de résistance à l’avancement que ces pièces engendrent sur certaines parties de nos axes métalliques. En effet, nos deux axes X ayant un parallélisme imparfait, le choix de notre liaison pivot glissant en bloquant la rotation autour de l’axe n’est pas adapté.

Nous avons donc modifié ces pièces en transformant la liaison “tube - cyllindre” par une liaison “roue incurvée - cylindre”, à la manière par exemple d’un rail de roller coaster (montagnes russes). Nous avons également doublé les moteurs sur l’axe X, un entraînement est donc créé sur les deux chariots, permettant une translation selon l’axe X plus fluide et plus homogène.

Version finale des guides axes pour l'axe X
Photo du chariot réalisé

Conception du chariot comportant l'outil

Le chariot est la partie la plus complexe de la maquette. Il doit assurer un grand nombre de fonctions. Il embarque un moteur pour la translation en Z, un moteur pour la rotation en Z, un système permettant d’adapter un préhenseur (dans notre cas: une seringue) au système à pression pneumatique et un système permettant de détecter la force appliquée pendant la pose du CMS.

Tout d’abord, son mouvement de translation avec l’axe Y est assuré par le même système de poulie que les guides axes. La translation en Z est assurée par un moteur engrènant une vis sans fin. Cette vis lie un solide qui assure alors une liaison glissière. Une pièce imprimée encastrée à ce solide nous permet de lier notre arrivée de pression négative à notre seringue.

Pour permettre une rotation selon l’axe Z, nous avons intégré un logement pour placer un moteur lié à un engrenage. Cet engrenage est destiné à venir faire tourner la pièce centrale (la pièce en rouge sur la photo suivante) à l’aide d’un engrenage interne.

Le chariot créé comporte également la solution choisie pour détecter un contact entre l’aiguille et un objet. En effet, nous n’avons pas assez de place pour intégrer des capteurs fin de course sur notre système moteur-glissière assurant la translation en Z. Cependant, ce dont nous avons besoin pour cette fonctionnalité “Détecter le contact entre le composant et la carte afin de ne pas les endommager” est réalisé par un capteur de position linéaire type potentiomètre linéaire. En effet, par un système de ressort intégré dans le chariot, nous pouvons obtenir la petite distance dont la pièce maintenant le moteur-glissière Z s’est déplacée et ainsi, la force exercée sur la carte/composant par l’aiguille.

Photo de l'infrastructure mécanique finale et des éléments assemblés


Motorisation et asservissement en position

Besoins et choix des moteurs

Nous avons besoin de déplacer notre chariot comportant l'outil d'aspiration qui manipule les composants selon les 3 axes de l'espace X, Y et Z. Afin d'assurer les translations dans le plan (X,Y), nous nous sommes orientés vers un système moteur-poulie-courroie sur chacun de ces 2 axes. Nous avons besoin d'une précision en position de l'ordre de 0,2mm et n'avons pas un besoin en couple important, ni d'un asservissement en vitesse spécifique.

Nous avons donc choisi d'utiliser des moteurs Pas à Pas, qui offrent les avantages d'être précis en terme de position angulaire, de pouvoir adapter cette précision en les commandant en micro-pas et surtout de pouvoir réaliser l'asservissement en position sans capteurs. En effet, nous nous baserons sur le comptage du nombre de pas que l'on a fait effectuer au moteur, en supposant qu'aucun pas n'est sauté durant le déplacement. En effet, dans notre application la charge a entraîner est suffisamment faible et le déplacement se fera a une vitesse suffisamment lente afin d'assurer cette hypothèse.

Dans une seconde version, pour être sûr du positionnement et pour palier aux imprécisions (type jeux sur la maquette...) sur la position initiale, la position de la poulie et son diamètre, nous mettrons en place un système d'ajustement via une caméra, où l'utilisateur viendra valider le placement du composant avant dépose sur la carte.

Le déplacement de position est alors déduit ainsi : \Delta X = \mu_{micropas} * \theta_{Pas_{nominal}} * R_{poulie} * \Delta {N_{Pas}}

avec \theta_{Pas_{nominal}} le pas angulaire de nos moteurs en radian (ici, 1,8°=0,031415 rad) ,\mu_{micropas} le facteur de micro-pas choisi (typiquement 1/2, 1/4, voire 1/8), R_{poulie} le rayon primitif de la poulie crantée en mm (ici 7,15mm) et \Delta {N_{Pas}} le nombre de pas demandé (dans un sens ou dans un autre).

Ceci nous assure donc en théorie, de disposer d’une résolution en déplacement d’une précision de l’ordre de ΔXmin_théorique = 0,028 mm en commandant nos moteurs en 8ème de pas. Ceci est conforme au cahier des charges en terme de précision pour poser du CMS Classe 5, nécessitant une précision de 0,2mm, pour les déplacements en X et en Y.

Pour enfin connaître la position absolue, il s'agit de connaître la position initiale du chariot. Ceci est réalisé avec des capteurs "fin de course", type contacteurs à lamelles. En effet, nous effectuons avant le déplacement une “mise à zéro” en terme de position, en commandant le déplacement du chariot jusqu’à atteindre les contacteurs en X = 0 et en Y = 0. Les capteurs de positions qui sont disposés de part et d’autre de chaque axe (début et fin de course), sont également utilisés en tant que sécurité : si un contact est détecté, les moteurs s’arrêtent, afin de ne pas endommager ces derniers ou la maquette.

Commande des moteurs Pas à Pas

Schéma symbolisant les phases et l'arbre du moteur Pas à Pas bipolaire
Schéma de la séquence d'alimentation complète du moteur bipolaire, en pas complet

Le principal inconvénient des moteurs Pas à Pas réside dans leur commande. En effet, un moteur Pas à Pas est un moteur particulier sans balai et alimenté par une alimentation continue. Il comporte plusieurs bobines permettant de créer un champ magnétique à l'intérieur et ainsi d'orienter des aimants fixés au rotor dans la direction du champ magnétique créé, ce qui provoque la rotation de l'arbre. On utilise le terme Pas à Pas car le champ magnétique créé à l'intérieur se fait par incréments. Ainsi pour faire tourner l'arbre entièrement, il faut effectuer l'alimentation des bobines pour une position 1, puis position 2, et ainsi de suite, selon la géométrie et la technologie du moteur utilisées.

Ainsi, son contrôle s'effectue par une séquence d'alimentation spécifique de ses différentes phases. Dans notre cas, nous avons choisi des moteurs bipolaires (de type Hybride, c'est à dire combinant les avantages des technologies "à aimant permanent" et à "réluctance variable"). Le sens de rotation de ces moteurs dépend de l'ordre d'alimentation des 2 bobines, ainsi que du sens du courant.

Ce pilotage peut s'effectuer au moyen d'une électronique de puissance type pont en H, sur laquelle on pilote les séquences de commutations des différentes cellules de commutation (transistor + diode en sens inverse en parallèle). Cependant une telle structure est compliquée à mettre en place au niveau des séquences, car elle n'intègre pas directement de limitation active du courant délivré dans la bobine et surtout car elle n'intègre pas directement de variation de courant afin de contrôler le moteur en micro-pas.

Présentant des prix très faibles (environ 5€) pour l'économie de temps et la simplicité d'utilisation qu'ils représentent, nous avons donc cherché des solutions de drivers adaptés à nos moteurs. Basé sur le circuit A4988 d'Allegro, nous nous sommes tournés vers ce driver pour moteur bipolaire (Pololu A4988 Stepper Motor Driver Carrier). Son principe est simple : il intègre directement cette structure de pont en H et les séquences d'alimentation. Il permet ainsi de faire effectuer au moteur un pas en envoyant une impulsion (front montant) sur sa pin STEP, dans le sens de rotation défini par l'état (haut ou bas) de sa pin DIR.

Schéma du fonctionnement et du branchement du driver

Ce driver réalise également l'interface commande-puissance, il comporte une alimentation séparée pour le circuit logique (5V) et l'alimentation de puissance des moteurs (ici 12V). Il est très important pour éviter la surchauffe et l'endommagement des moteurs de contrôler le courant envoyé dans ses bobines. Nous limitons ainsi activement ce courant grâce au driver au moyen d'un potentiomètre à régler sur ce dernier. Nous avons réglé cette valeur par rapport aux courants nominaux par phase de nos moteurs.

L'avantage majeur de ce driver est qu'il comporte une solution de fonctionnement en micro-pas directement. Par l'état de ses pins MS1, MS2 et MS3, il nous permet de piloter du pas complet, au 1/16 de pas (maximum). Nous ne piloterons pas jusqu'au 1/16 de pas pour des soucis de stabilité du couple mécanique et pour éviter de sauter des pas, 1/4 voire 1/8 de pas devrait être suffisant. Et en effet, au gré des différents tests, le pilotage en 8ème de pas a montré un fonctionnement correct et stable.

Ainsi, nous pilotons toutes ces différentes entrées par le biais d'un Arduino Mega. Plus tard, cet Arduino Mega servira d'interface entre la consigne de position envoyée depuis l'application PC et les moteurs.

Création de l'outil de manipulation par aspiration

Schéma du fonctionnement du circuit pneumatique

L'outil qui viendra attraper et déposer les composants sera composé d'une aiguille fine qui les maintiendra par aspiration. Le système sera donc composé d'une pompe à vide, type pompe d'aquariophilie, peu couteuse, car l'aspiration nécessaire pour maintenir un composant est vraiment très faible. Ce genre de pompe se commande en tout ou rien au moyen d'un interrupteur manuel. Afin de ne pas alterner cycles d'allumage de la pompe pour éviter de l'endommager et surtout d'attendre le temps d'établissement du débit à chaque fois, lors des phases aspiration-dépose, nous utiliserons un distributeur pneumatique qui viendra envoyer ou non la dépression dans le tuyau d'air.

Niveau matériel pour cette partie, nous avons pour le moment réuni le distributeur, les tuyaux et l'aiguille. Nous devrions recevoir la pompe sous peu de temps.

Après réception, nous avons constaté l’inconvénient de ce genre de pompe : son arrivée d’air (coté aspiration donc) n’est pas accessible et connectable. Il s’agit en effet d’une large membrane souple et perméable, en matière type “feutre”. Nous nous sommes donc procuré un tube à effet Venturi, qui “transforme” une pression entrante positive (“souffle”) en une pression sortante négative (“aspiration”).


De par sa conception et par le principe physique mis en oeuvre, le tube à effet Venturi nécessite une pression et un débit suffisamment élevés, que notre pompe d’aquariophilie ne nous offre pas. Cependant, après discussion avec Thierry Flamen, la salle du service EEI possèdera dans un futur proche un raccordement en air comprimé. Ainsi, pour une utilisation au service EEI, il suffira de connecter notre câble d’arrivée d’air à ce raccordement. Dans l’attente des travaux, un compresseur à air peut tout à fait être utilisé.

Afin de commander ou non l’aspiration dans l’aiguille, nous utilisons un distributeur électro-pneumatique. Le distributeur devant être alimenté avec une tension de 24V, nous utilisons un optocoupleur en guise d’interrupteur commandé, piloté au moyen d’une sortie d’un Arduino.

Commande et lecture des éléments du système via Arduino

Description des fonctions réalisées par l'Arduino Mega

Afin de relier les divers éléments du système à l’application pour l’utilisateur, nous utilisons un Arduino Mega. En effet, ce dernier est utilisé pour jouer le rôle d’interface entre les ordres donnés par l’application PC et le contrôle des actionneurs / lecture des capteurs.

Voici les tâches dont se charge l’Arduino en terme de sorties :

  • Contrôler la commande d’aspiration des composants
  • Permettre d’envoyer les ordres aux drivers qui commandent les 5 moteurs, à savoir :
    • 2 moteurs pour la translation selon l’axe X
    • 1 moteur pour la translation selon l’axe Y
    • 1 moteur-glissière pour la translation selon l’axe Z
    • 1 moteur pour la rotation autour de Z

Pour chacun des drivers, 6 sorties logiques sont à commander : 1 bit pour l’activation du moteur (Enable), 1 bit pour le choix du sens de rotation (Dir), 1 bit pour exécuter les pas (Step) et 3 bits de sélection du micro-pas (MS1, MS2, MS3)

Voici les tâches dont se charge l’Arduino en terme d’entrées :

  • Lecture de l’état des 6 capteurs fin de courses (contacteurs à lamelles, appuyés ou bien non appuyés) disposés pour X1_Min, X2_Min, Y_Min, X1_Max, X2_Max et Y_Max.
  • Conversion et lecture de la tension analogique, image de la position du potentiomètre linéaire, représentant la force appliquée sur l’aiguille selon l’axe Z

L’Arduino permet ainsi à l’application d’effectuer les fonctions d’écriture (surnommées ‘set’) qui se chargent de :

  • donner une consigne de nombre de pas au moteur sélectionné, par rapport à une position d’origine
  • choisir le facteur de micro-pas sur le moteur sélectionné (pas complet, ½ pas, ¼ de pas, ⅛ de pas ou 1/16 de pas)
  • commander l’optocoupleur relié au distributeur pneumatique pour l’allumage ou l’extinction de l’aspiration dans l’aiguille
  • choisir la limite maximale de force que l’aiguille peut appliquer sur l’axe Z. Ceci est réalisé en définissant une limite de position du potentiomètre au delà de laquelle nous arrêtons de commander le moteur Z
  • choisir la vitesse du moteur sélectionné, en définissant le temps en ms que nous attendons entre deux pas
  • verrouiller ou déverrouiller en position le moteur sélectionné, en envoyant ou pas le courant dans les bobines des moteurs, provoquant un couple de maintien ou non

Pour que l’application PC puisse connaître les paramètres programmés sur l’Arduino et l’état des capteurs, l’Arduino permet aussi d’effectuer les fonctions de lecture (que nous avons surnommées ‘get’) et qui communique :

  • l’état de de verrouillage en position des moteurs
  • la position d’un moteur sélectionné par rapport à l’origine
  • le facteur de micro-pas du moteur sélectionné
  • l’état de la consigne d’allumage de l’aspiration
  • la limite maximale de force que l’aiguille peut appliquer sur l’axe Z choisie
  • l’état des capteurs fin de course
  • la valeur convertie par l’ADC de la tension sur le potentiomètre
  • la vitesse des moteurs
  • la version du logiciel utilisé sur l’Arduino Mega

Dans le fonctionnement interne de l’Arduino, il s’assure pour chaque requête de déplacement que l’action demandée est réalisable. Le programme vérifie en effet que les contacteurs ne sont pas enclenchés tout au long du déplacement pour X et Y, ou que le potentiomètre n’a pas dépassé la valeur maximale qui a été fixée. Dans le cas contraire, l’action sur les moteurs est stoppée et l’Arduino communique un code d’erreur. Un code d’erreur est aussi communiqué en cas de jeu de paramètres demandés incorrect lors d’un appel à chaque fonction.

Par ailleurs, les codes du programme C implémenté sur l’Arduino sont disponibles sur GitHub à cette adresse et sur le GitLab de Polytech Lille

Protocole de communication entre le logiciel et l'Arduino

Nous avons été amenés à concevoir un protocole de communication pour assurer l’exécution des ordres et la coopération entre l’application et l’Arduino. Ils communiquent via le port série et nous avons optimisé le protocole pour le rendre le plus compact possible afin de limiter le nombre de communications.

Principe de fonctionnement du programme sur l'Arduino

Nous disposons de 2 types de fonctions : les fonctions d’écriture (‘set’) et les fonctions de lecture (‘get’). Les fonctions “d’actions” (‘set’) retournent un code de retour à la fin de chaque action, disant si elle s’est terminée correctement ou si une erreur est survenue, comme le déclenchement d’un contact ou la saisie d’un paramètre incorrect. Les fonctions de lecture (‘get’) retournent quant à elles l’information demandée.

Les trames de base

Commande d'initialisation d'une tâche (PC->Mega)
Bits 7 6 5 4 3 2 1 0
Data Paramètre Fonction appelée
Commande de réponse d'une tâche (Mega->PC)
Bits 7 6 5 4 3 2 1 0
Data Donnée dépendant de la fonction Code de retour

Si le code de retour est différent de 0, les trames de retour 2 et 3 ne sont pas envoyées

Liste des codes de retour
Code retourné Nom dans le header Action à prendre Description du code
b3 b2 b1 b0 Hex
0 0 0 0 0x00 CMD_OK Aucune La commande s'est exécutée correctement
0 0 0 1 0x01 CMD_NOT_KNOWN Report immédiat La commande demandée n'est pas connue
0 0 1 0 0x02 CMD_DEST_UNREACHABLE Report immédiat L'appel à la commande setDest a le paramètre dest trop grand sur le moteur choisi
0 0 1 1 0x03 CMD_LOCK_MIN_X1 Report immédiat ou aucun Le chariot a déclenché le contact à lamelle souple sur l'axe X 1 à son minimum
0 1 0 0 0x04 CMD_LOCK_MAX_X1 Report immédiat ou aucun Le chariot a déclenché le contact à lamelle souple sur l'axe X 1 à son maximum
0 0 1 1 0x05 CMD_LOCK_MIN_X2 Report immédiat ou aucun Le chariot a déclenché le contact à lamelle souple sur l'axe X 2 à son minimum
0 1 1 0 0x06 CMD_LOCK_MAX_X2 Report immédiat ou aucun Le chariot a déclenché le contact à lamelle souple sur l'axe X 2 à son maximum
0 1 1 1 0x07 CMD_LOCK_MIN_Y Report immédiat ou aucun Le chariot a déclenché le contact à lamelle souple sur l'axe Y à son minimum
1 0 0 0 0x08 CMD_LOCK_MAX_Y Report immédiat ou aucun Le chariot a déclenché le contact à lamelle souple sur l'axe Y à son maximum
1 0 0 1 0x09 CMD_LOCK_Z Report immédiat ou aucun L'aiguille a touché un objet et a dépassé la force maximum à appliquer dessus
1 0 1 0 0x0A WAIT_FOR_NEXT_FRAME Report immédiat ou aucun La fonction appelée a été comprise, l'Arduino est en attente de la trame suivante.
1 0 1 1 0x0B WAIT_FOR_IT_1 Aucun La réponse est partielle, il manque encore une trame.
1 1 0 0 0x0C WAIT_FOR_IT_2 Aucun La réponse est partielle, il manque encore deux trames.

Liste des fonctions d'écriture

Liste des fonctions
Fonction appelée Nom de la fonction Paramètre 1 Paramètre 2 Description fonction
b3 b2 b1 b0 Hex
0 0 0 0 0x00 setDest selectedMotor[2bits] destination[16bits] Donne la consigne de position en seizième de pas par rapport à l'origine
0 0 0 1 0x01 setMS selectedMotor[2bits] microStep[3bits] Donne la consigne du nombre de micropas par tour pour un moteur
0 0 1 0 0x02 setPump onOff[1bit] Donne la consigne d'allumage ou d'extinction de la pompe à vide
0 0 1 1 0x03 setADC adcLevel[10bits] Donne la consigne d'allumage de la valeur maximale lisible par l'ADC
0 1 0 1 0x05 setSpeed selectedMotor[2bits] delayStep[8bits] Donne le temps en ms à attendre entre 2 pas (<=> la vitesse du moteur)
0 1 1 0 0x06 setMotLocked lockedOnOff[1bit], selectedMotor[2bits] Verrouille ou déverrouille en position le moteur sélectionné (<=> couple de maintien ou non)
Détails sur la construction des fonctions d'écriture
Fonction appelée Trame 1 Trame 2 Trame 3
b7 b6 b5 b4 b7 b6 b5 b4 b3 b2 b1 b0 b7 b6 b5 b4 b3 b2 b1 b0
setDest selectedMotor[1:0] destination[15:8] destination[7:0]
setMS selectedMotor[1:0] microStep[2:0]
setPump onOff
setADC adcLevel[9:8] adcLevel[7:0]
setSpeed selectedMotor[1:0] delayStep[7:0]
setMotLocked onOff selectedMotor[1:0]

Liste des fonctions de lecture

Liste des fonctions
Fonction appelée Nom de la fonction Paramètre 1 Description fonction
b3 b2 b1 b0 Hex
0 1 1 1 0x07 getMotLocked Retourne l'état du verrouillage en position de tous les moteurs
1 0 0 0 0x08 getDest selectedMotor[2bits] Retourne la position d'un moteur donné en seizième de pas par rapport à l'origine
1 0 0 1 0x09 getMS Retourne la consigne du nombre de micropas par tour pour tous les moteurs
1 0 1 0 0x0A getPump Retourne la consigne d'allumage actuelle de la pompe à vide
1 0 1 1 0x0B getADC Retourne la consigne d'allumage de la valeur maximale lisible par l'ADC
1 1 0 0 0x0C getContact Retourne l'état des contacteurs à lamelles (appuyés ou non)
1 1 0 1 0x0D getADCvalue selectedPin[2bits] Retourne la valeur convertie par l'ADC de la pin analogique sélectionnée
1 1 1 0 0x0E getSpeed selectedMotor[2bits] Retourne le délai entre 2 pas choisis pour le moteur sélectionné
1 1 1 1 0x0F getVersion Retourne la version du logiciel utilisée sur l'Arduino Mega (Actuelle: 0.1)
Détails de la construction des trames de lecture
Fonction appelée Appel (PC->Mega) Retour (Mega->PC)
Trame 1 Trame 1 Trame 2 Trame 3
b7 b6 b5 b4 b7 b6 b5 b4 b7 b6 b5 b4 b3 b2 b1 b0 b7 b6 b5 b4 b3 b2 b1 b0
getMotorLocked lockedRotZ lockedZ lockedY lockedX
getDest selectedMotor[1:0] dest[15:8] dest[7:0]
getMS msY[0] msX[2:0] msR[2:0] msZ[2:0] msY[2:1]
getPump onOff
getADC adcLevel[9:8] adcLevel[7:0]
getContact isMinX1 isMaxX1 isMinX2 isMaxX2 isMinY isMaxY
getADCvalue selectedPin[1:0] adcValue[9:8] adcValue[7:0]
getSpeed selectedMotor[1:0] delayStep[7:0]
getVersion minorVersion[3:0] majorVersion[7:0]

Conception du logiciel d'interfaçage utilisateur

Définition du cadre

Un des buts de ce projet est de concevoir une application permettant de contrôler les différents éléments du projet. Pour cela nous, l'application doit être capable de lire des fichiers standards de création de carte électronique (aussi appelés fichiers Gerber). De plus, nous souhaitions que l'application puisse être utilisé sur n'importe quelle plateforme. Pour cela, nous avons choisi de la développer sous Qt. L’environnement de travail Qt nous permet d'utiliser des objets permettant l'accès à n'importe quel type de matériel sans se soucier de la plateforme de destination. Pour la communication avec les éléments de commande (comme les moteurs) nous avons choisi de n'envoyer des ordres qu'à travers l'Arduino Mega.

Comme l’intégralité de notre travail est placé sous le drapeau de l’open source, nous avons souhaité permettre à n’importe qui de pouvoir compiler notre application sur son ordinateur, et cela quelque soit son système d’exploitation. Pour permettre la réalisation de cet objectif, nous avons choisi un framework parmis ceux permettant cette inter-opérabilité. Son code source est d’ailleurs disponible sur GitHug à l’adresse suivante

Les collections d’objets et de librairies (aussi appelés framework) multi-OS se comptent sur les doigts de la main et ont tous leurs avantages et leurs inconvénients. Parmis les plus connus (wxWidgets, GTK+, FLTK, FOX, …), nous avons choisi de prendre Qt. Ce framework a l’avantage d’intégrer des interfaces multiplateformes pour le port série et la Webcam.

Nous noterons quand même le coté négatif de ce choix: le développement de la partie du port série a pris plus de temps que prévu. En effet, la gestion du buffer pour le port série est assez mal expliquée et semble être peu indépendante du système d’exploitation. Pour palier à ce problème, nous avons choisi d’utiliser un protocole de communication octet à octet avec accusé d’émission et de réception.

Création d'une interface intuitive

Pour permettre à un utilisateur lambda de pouvoir utiliser notre interface, nous avons essayé de la rendre la plus intuitive possible. Pour cela, nous avons décomposé en trois zones distinctes les différentes informations. La première partie comporte une fenêtre OpenGL permettant la génération du rendu des fichiers GERBERs ouverts. Le deuxième volet est une fenêtre permettant le retour d’erreur et l’affichage d’informations sur l’état de l’application ou de la communication. Enfin, la troisième permet de visualiser en temps réel les variables de l’Arduino MEGA et d’ordonner des consignes.

Fin du projet

Au terme d’un semestre consacré majoritairement au développement de ce projet de fin d’étude, nous sommes réellement heureux et fiers des avancées qui ont été accomplies. Les difficultés rencontrées étaient souvent de natures différentes du fait de la multidisciplinarité de ce projet. Cependant, une quantité importante de travail, ainsi qu’un suivi de la part de nos encadrants nous ont permis d’atteindre la majorité de nos objectifs.

Bien que ce projet avait pour vocation d’être intégré au terme du semestre, il reste quand même utile pour le pôle EEI. Il pourra en effet être repris comme futur projet en IMA et ainsi achever l'automatisation des tâches, l'ajout d'une vision caméra et l’interface utilisateur.