KiCAD et FreeCAD convergent pour fournir un environnement cohérent de conception électronique et mécanique assistée par ordinateur. Ces deux outils rendent leurs fonctions accessibles depuis Python, langage permettant d’automatiser un certain nombre de tâches répétitives et donc fastidieuses. Nous proposons de rédiger quelques greffons (plugins) pour distribuer des vias [1] le long de lignes de transmissions radiofréquences (KiCAD), puis automatiser la réalisation du boîtier contenant un circuit imprimé avec les ouvertures pour ses connecteurs (FreeCAD).
Convié par le réseau des électroniciens du Centre National de la Recherche Scientifique (CNRS) à présenter les solutions libres de conception électronique et mécanique de circuits imprimés, notre intervention se conclut par une série de questions portant sur des comparaisons avec certaines fonctionnalités des alternatives propriétaires, et en particulier dans le cas de la conception de circuits imprimés radiofréquences. Dans ce contexte, il est classique de distribuer une forte densité de vias [1] entre un plan de masse en face inférieure pour entourer les pistes en face supérieure transportant des signaux radiofréquences et minimiser les risques de couplages par rayonnement, en imposant des liaisons de faible impédance vers le potentiel de référence qu’est la masse. Si une fonctionnalité n’existe pas, KiCAD fournit la capacité à combler cette lacune par l’ajout de fonctionnalités au travers de greffons (plugins). Comme à peu près tous les logiciels libres actuels (KiCAD, FreeCAD, GNU Radio, QGis...), l’API est exportée vers Python pour permettre de compléter les fonctionnalités manquantes par des plugins.
Nous allons donc explorer l’interaction avec le circuit imprimé (printed circuit board – PCB) de KiCAD pour automatiser les tâches répétitives, ce que tout développeur abhorre, et exposer cette fonctionnalité comme greffon afin de partager avec autrui les algorithmes de modification de circuits routés. Dans la continuité de ces efforts, nous aborderons l’automatisation des tâches dans FreeCAD pour la conception automatique du boîtier autour du circuit imprimé : l’ensemble des fonctions accessibles par les icônes est ici aussi exporté sous forme de fonctions Python, qui permettront de rationaliser les étapes de conception de la boîte à partir des contours du circuit imprimé.
Avant de nous lancer dans la programmation, mentionnons en introduction que les fichiers stockés par KiCAD sont en ASCII et limpides à lire :
Ils sont donc simples à éditer avec son outil favori (sed) pour, par exemple, modifier les largeurs de toutes les pistes ou la couche sur laquelle elles se trouvent.
1. Interaction avec Python : prototypage d’un greffon
KiCAD propose une console Python pour se familiariser avec son interface. La plus grande difficulté rencontrée pour prendre en main cette API a été de trier les informations obsolètes obtenues sur le Web [2] pour en extraire le principe sous-jacent et le mettre en œuvre avec la version actuelle de KiCAD 5.
Ainsi, si nous désirons insérer un texte dans un circuit routé après avoir exécuté un apt-get install python3-wxgtk4.0 pour permettre d’accéder à la console Python de KiCAD (PCBNew > Tools > Scripting Console), rien n’est plus simple puisque, depuis PCB New qui permet d’éditer son circuit routé, nous fournissons les commandes :
Ceci permet d'atteindre le résultat de la figure 1, à savoir ajouter un via ou du texte aux coordonnées fournies en nanomètres (10-6 mm) sur le circuit imprimé. Nous avons choisi d’adresser les couches par leur numéro puisque http://docs.kicad-pcb.org/doxygen/layers__id__colors__and__visibility_8h.html indique que les identifiants des couches supérieures et inférieures sont F_Cu = PCBNEW_LAYER_ID_START,B_Cu = PCBNEW_LAYER_ID_START + 31.
Si au lieu d’entrer directement les commandes dans la console, nous désirons les éditer dans notre éditeur de texte favori pour rédiger un script demo_jmf.py chargé dans la console, alors la première instanciation s’obtiendra par import demo_jmf pour ensuite être mise à jour, après avoir chargé les méthodes adéquates par import importlib et importlib.reload(demo_jmf).
La fonctionnalité proposée ci-dessus ne présente évidemment strictement aucun intérêt, sinon de permettre d’appréhender la co-simulation et le routage d’antennes planaires [3] au travers de fichiers communs de configuration.
Router des lignes de transmissions radiofréquences en les décorant par des vias à la masse pour les isoler les unes des autres se nomme via fence. Cette fonctionnalité, qui distribue des vias connectés à la masse le long de pistes propageant des signaux radiofréquences, est classiquement disponible dans les logiciels propriétaires d’analyse de systèmes radiofréquences tels qu’Altium (https://techdocs.altium.com//display/ADOH/Via+Shielding et https://www.altium.com/documentation/altium-designer/via-stitching-and-via-shielding-ad) ou Cadence (https://resources.pcb.cadence.com/blog/the-case-for-stitching-vias-on-your-pcb-2). Nous n’avons pas identifié de telle fonctionnalité dans KiCAD, et avons dû admettre lors des questions en fin de présentation une déficience du logiciel libre face à l’offre propriétaire. Qu’à cela ne tienne, si une fonctionnalité manque dans un logiciel libre, notre devoir est de l’ajouter.
2. Rédaction du greffon
Soit un utilisateur qui a routé une trace et qui désire l’identifier comme une ligne de transmission radiofréquence en l’entourant de vias à la masse. Que faut-il faire pour atteindre ce résultat, et le fournir comme greffon KiCAD utilisable depuis l’interface utilisateur ? Il va nous falloir manipuler des traces, insérer des vias (nous venons de voir comment faire) après avoir calculé les coordonnées le long de la trace, et encapsuler ce programme dans le formalisme d’un greffon. Pour ce faire, nous nous inspirerons de [4], mais surtout [5] qui explicite les interfaces à déclarer. La principale difficulté rencontrée pour passer d’un script fonctionnel dans la console Python de KiCAD à un greffon tient aux indentations : exécuter le greffon sous Python 3 par python3 -m mon_script.py permet au moins de déverminer les erreurs de syntaxe et d’indentation.
Nous commençons par mettre en place l’environnement de travail en chargeant les classes et le circuit en cours d’édition, ainsi que quelques constantes que sont la distance entre les vias adjacents dL et la distance dr des vias à la piste que nous désirons décorer (figure 2) :
Nous désirons connecter les vias à la masse et nous recherchons donc le numéro dans la liste des couches de la masse supposée être nommée GND :
Munis de cette information, nous commençons la rédaction de la classe afin de la rendre compatible avec les méthodes attendues d’un greffon :
Commençons à appréhender le sujet à résoudre en parcourant la liste des pistes (for track in pcb.GetTracks():) et traiter celles qui sont sélectionnées (track.IsSelected()) :
Pour chaque trace sélectionnée, nous calculons le nombre n de vias qu’il faudra placer, et distribuons ces vias uniformément le long du segment en suivant l’équation de droite correspondante, en prenant soin de traiter séparément le cas des lignes verticales, pour lesquelles le coefficient directeur a de la droite est infini :
Une fois les coordonnées du via identifiées, celui-ci est ajouté comme nous l’avons vu auparavant entre les couches supérieures et inférieures et en assignant le via à la masse par newvia.SetNetCode(gndcode) :
Nous laissons le lecteur reproduire ce mécanisme pour le via qui se trouve de l’autre côté de la piste ou traiter le cas des pistes verticales, qui réutilisent les mêmes commandes avec des coordonnées (xp, yp) calculées un peu différemment (la solution se trouve sur le dépôt GitHub cité en fin de conclusion). Après ajout de chaque via, nous incrémentons la position x = x + dL * math.cos(theta).
Une fois les vias ajoutés le long de la ligne de transmission, nous mettons à jour le dessin du circuit imprimé pcbnew.Refresh().
Le greffon est initialisé par TransmissionLine().register() qui conclut le fichier que nous constatons être finalement de structure fort simple. Les fonctionnalités basiques du greffon sont fonctionnelles (figure 3), malgré quelques défauts qui mériteraient d'être corrigés pour le rendre réellement utilisable, en particulier le recouvrement de via dans les angles. On pourra aussi noter dès maintenant que les traces arrondies sont promises pour la prochaine mouture de KiCAD de la fin d’année, et qu’il faudra trouver un algorithme plus intelligent que la subdivision des segments en sous-segments équidistants. Nous verrons en conclusion que la relève est déjà prise.
En prenant soin de placer le script Python dans le répertoire /usr/share/kicad/scripting/plugins, nous éviterons même de devoir chercher le script dans la liste des outils, et pourrons nous contenter de cliquer sur une icône ajoutée au menu des actions sur la barre en haut de l’interface graphique (figure 3, indications rouges).
3. Greffon pour FreeCAD
Nous venons de finir de concevoir un circuit et maintenant, il faut le mettre en boîte pour le protéger de son environnement. La symbiose entre KiCAD et FreeCAD permet de facilement appréhender la conception du boîtier à partir du circuit imprimé, et automatiser la procédure par des programmes Python. FreeCAD, et notamment la version 0.18.4 que nous utilisons, exposant son API (et celle d’OpenCASCADE sur lequel il s’appuie [6]), ce que nous venons d’apprendre sur les greffons KiCAD est presque directement applicable à FreeCAD. Voyons comment importer le circuit (et ses connecteurs) de KiCAD dans FreeCAD, et automatiser la conception de la boîte, quelle que soit la forme du circuit imprimé. Seule contrainte, nous devons penser dans KiCAD (figure 3, indications vertes) à inclure une couche de détourage Edge.Cuts qui est de toute façon nécessaire si nous exportons un fichier Gerber pour réaliser le circuit imprimé en gravure anglaise (fraisage des pistes).
Un greffon FreeCAD externe a été rédigé (en Python) pour importer directement un fichier KiCAD (https://github.com/easyw/kicadStepUpMod) qui s’installe par Tools > Addon Manager > Workbenches > kicadStepUpMod. Alors que jusqu’alors il fallait exporter un fichier VRML ou Step de KiCAD pour l’importer dans FreeCAD, il est désormais possible de directement importer le fichier PCB en cliquant sur Load KiCAD PCB Board and Parts (troisième icône) qui en pratique fait appel à la fonction onLoadBoard. Nous chargeons le circuit imprimé et, si les modèles de connecteurs sont disponibles, les fichiers Step associés. Notre objectif est de nous appuyer sur ce greffon pour automatiser la création d’une boîte permettant d’encapsuler le circuit imprimé, tout en laissant traverser les connecteurs.
Nous constatons au chargement du circuit imprimé qu’un Sketch est associé au circuit imprimé : c’est la forme du circuit tel que déterminé par la couche Edge.Cuts. Nous en profitons pour utiliser le « 2D Offset » du Part Workbench qui effectue l’homothétie d’une courbe. Nous allons recourir deux fois à cette opération, une première fois pour laisser un peu de jeu entre le circuit imprimé et la face interne du mur, puis une seconde fois pour définir l’épaisseur de la boîte. Lors du passage de la courbe 2D à 3D par extrusion (Part Workbench > Extrude a Selected Sketch), nous voulons que la surface externe soit un peu plus basse que la surface interne pour définir l’épaisseur du fond du boîtier : la courbe extérieure obtenue par la double homothétie de la forme du circuit imprimé est abaissée de 1 mm. Une fois les deux courbes extrudées, il reste à soustraire le volume intérieur du volume extérieur pour obtenir une boîte. Cette séquence d’opérations s’automatise par le script Python suivant, qui suppose que le circuit imprimé a été chargé et a donné lieu à la création de la variable PCB_Sketch_387.
Tout comme pour KiCAD, ce script peut soit s’exécuter dans la console Python (View > Panels > Python Console) ou se charger depuis cette même console en sauvant le script dans un fichier (import boite si le nom du fichier est boite.py). La principale difficulté dans cet exercice est de pallier l’absence quasi totale de documentation par la lecture des sources sur le dépôt GitHub du greffon, mais il s’agit sinon de programmation FreeCAD on ne peut plus standard, avec la manipulation des divers champs de position des objets et leur assemblage par opérations booléennes (figure 4), tel que discuté en détail dans [7].
Plus intéressant, la gestion des connecteurs. Nous ne savons pas a priori combien il y a de connecteurs ni où ils se trouvent. Nous proposons la démarche suivante : sachant que les connecteurs sont les seuls éléments dépassant du capot, nous plaçons exprès ce dernier au-dessus de la boîte où il n’intersecte que les connecteurs et aucun composant ou circuit imprimé. Nous itérons sur tous les connecteurs supposés être des objets FreeCAD importés en même temps que le circuit imprimé (attribut Part::Feature) : pour chaque connecteur, nous cherchons l’intersection avec le capot, effectuons une homothétie de cette courbe d’intersection pour laisser un peu de jeu entre le capot et le connecteur et finalement, effectuons la soustraction de l’ouverture du connecteur avec le capot.
Ces opérations se résument tout d’abord par la création du capot, ici à une altitude arbitraire de 10 mm :
Ensuite, nous itérons sur les connecteurs pour trouer le capot aux bons endroits. Étant donné que seul un motif peut être fourni comme argument d’une opération booléenne, nous mémorisons l’état du capot dans une liste t qui s’incrémente à chaque nouvelle opération :
Pour que le cylindre représentant le connecteur puisse être soustrait du capot, il faut absolument qu’il s’agisse d’un volume (et non d’une surface comme nous l'obtiendrions si nous oubliions l’attribut trouplein.Solid = True).
Le résultat est acceptable (figure 5), même si un petit épaulement permettrait de maintenir le capot en place : nous laissons cette optimisation comme exercice au lecteur.
Il ne reste plus qu’à réaliser la boîte – ici en impression additive sur une imprimante UltiMaker 2+ – et constater le parfait alignement des ouvertures avec les connecteurs (figure 6).
Conclusion
La beauté du logiciel libre est de pouvoir contribuer aux lacunes des outils proposés, pour combler des points de détails qui n’auraient pas été abordés par les développeurs principaux du logiciel. Au travers des greffons (plugins), il est possible d’ajouter des fonctionnalités périphériques sans être obligé de rentrer dans le cœur du code principal du logiciel. Nous avons illustré ce concept pour KiCAD, logiciel de conception de circuits imprimés, dont les développeurs n’ont pas nécessairement abordé toutes les attentes de la conception de circuit radiofréquences, ainsi que pour FreeCAD, logiciel de conception mécanique. Alors que nous étions en train de combler cette lacune, une alternative plus stable et complète est apparue sur le Web sous la forme des greffons RF-tools-KiCAD disponibles sur https://github.com/easyw/RF-tools-KiCAD et annoncés sur https://hackaday.com/2019/11/19/kicad-action-plugins/.
Tous les codes associés au greffon KiCAD décrit dans cet article sont disponibles sur https://github.com/jmfriedt/kicad_transmissionline.
Remerciements
É. Carry (FEMTO-ST, Besançon) a réalisé l’impression de la boîte et relu le manuscrit. Cette étude a été motivée par le séminaire organisé par le réseau des électroniciens du CNRS à Strasbourg fin 2019.
Références & Notes
[1] Un via est un trou métallisé permettant d'établir une liaison électrique entre deux couches d'un circuit imprimé.
[2] https://kicad.mmccoo.com/kicad-scripting-table-of-contents/ (pour KiCAD 4).
[3] J.-M FRIEDT, É. CARRY et O. TESTAULT, « Petites antennes réalisées par impression additive : de la conception à la visualisation des diagrammes de rayonnement (en vrai et en virtuel) », Hackable n°31, pp.80-96, oct.-nov. 2019 : https://connect.ed-diamond.com/Hackable/HK-031/Petites-antennes-realisees-par-impression-additive-de-la-conception-a-la-visualisation-des-diagrammes-de-rayonnement-en-vrai-et-en-virtuel
[4] KiCAD Pcbnew script to generate teardrops : https://github.com/svofski/kicad-teardrops
[5] Python Plugin Development for Pcbnew : http://docs.kicad-pcb.org/doxygen/md_Documentation_development_pcbnew-plugins.html
[6] Y. VAN HAVRE et B. COLLETTE, « Open-source design ecosystems around FreeCAD », FOSDEM 2020 : https://fosdem.org/2020/schedule/event/freecad/
[7] J.-M FRIEDT, « Dessiner des carrés avec des ronds : simulation d’un ordinateur mécanique en scriptant sous FreeCAD », Hackable (à paraître)