Automatic Soldering System Project
Sommaire
- 1 Placeur de composants sur PCB
- 1.1 Présentation du projet
- 1.2 Fabrication de l'infrastructure mécanique
- 1.3 Motorisation et asservissement en position
- 1.4 Création de l'outil de manipulation par aspiration
- 1.5 Commande et lecture des éléments du système via Arduino
- 1.6 Conception du logiciel d'interfaçage utilisateur
- 1.7 Fin du projet
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
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
- Châssis mécanique
- 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
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
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.
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.
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 :
avec le pas angulaire de nos moteurs en radian (ici, 1,8°=0,031415 rad) , le facteur de micro-pas choisi (typiquement 1/2, 1/4, voire 1/8), le rayon primitif de la poulie crantée en mm (ici 7,15mm) et 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
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.
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
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.
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
Bits | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Data | Paramètre | Fonction appelée |
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
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
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) |
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
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) |
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.