Un badge simple est simple, mais c’est le vôtre

Fabriquer des badges de conférence, officiels ou non, est devenu une forme d’art. Cela peut devenir assez sérieux. #badgevie.

Mais les amateurs de DEFCON ne sont pas les seuls à créer des badges personnalisés et sophistiqués. Les jambons avaient souvent des badges d’indicatif remontant aussi loin que je me souvienne. La plupart étaient faits de plastique gravé, mais, à un moment donné, il est devenu courant de mettre quelque chose comme une LED clignotante sur le dessus de la tour d’antenne gravée ou peut-être quelque chose de clignotant en code Morse.

En revenant à cette époque plus simple, je voulais voir si je pouvais créer mon propre badge à partir de modules facilement accessibles. Est-ce que cela peut être facile ? Découvrons-le. En cours de route, nous parlerons de la programmation multicœur, des sections critiques, des espaces de noms et du brouillage d’images dans du code C++. Je vais également vous montrer comment détourner le préprocesseur C pour créer un petit langage de script afin de faciliter la configuration du badge.

Ligne inférieure à l’avant

La photo montre le badge Pico. Il possède un processeur RP2040 mais pas un véritable Raspberry Pi Pico. Le clone Waveshare RP2040-Plus dispose d’un connecteur de batterie et d’un chargeur. Il dispose également d’un bouton de réinitialisation, et celui-ci dispose de 16 Mo de flash, mais vous n’en avez pas besoin de beaucoup. L’écran LCD est également un produit Waveshare. (Cela a fonctionné. J’ai acheté tout cela et je ne connais même personne chez Waveshare.) La seule autre chose dont vous avez besoin est un câble USB C et une batterie avec un connecteur MX 1.25 avec le polarité correcte. Matériel terminé ! C’est l’heure du logiciel.

Pour le logiciel, vous disposez de nombreuses options. La documentation Waveshare vous montre comment piloter l’affichage à l’aide du code C standard et de Micropython. J’ai décidé d’emprunter une voie différente et de m’en tenir aux outils Arduino. [Earlephilhower] propose un fantastique package de support de carte pour le RP2040. Je l’utilise ces derniers temps avec d’excellents résultats. Il contient de nombreuses fonctionnalités intéressantes, notamment une prise en charge simple du multicœur et bien plus encore.

Le badge est plus ou moins un diaporama. Vous pouvez afficher des images et écrire du texte sur un arrière-plan uni ou sur une image. Chaque diapositive apparaît pendant une durée définie bien que, dans certaines limites, vous puissiez l’accélérer ou la ralentir. Vous pouvez voir une démo rapide dans la vidéo ci-dessous.

Le badge peut vous renvoyer vers sa propre page GitHub

Évidemment, si vous souhaitez le personnaliser, vous pouvez prends mon code et changez-le. Mais cela signifie que vous devez en comprendre un peu plus. Qui a le temps pour ça ? Au lieu de cela, le code peut prendre un fichier de script qui, éventuellement, se transforme en code C, mais vous n’avez pas besoin de savoir grand-chose sur les composants internes du badge.

Par exemple, supposons que vous souhaitiez montrer un joyeux tournevis avec votre nom écrit dessus. Le script ressemble à ceci :

Sbwimg(wrencher,GREEN,BLACK)
Stext(TCENTER,TCENTER,"-AL-")

Il existe des commandes pour dessiner des images couleur et monochromes, remplir l’écran de couleurs et imprimer en utilisant différentes polices et couleurs.

Les boutons répondent presque instantanément car ils sont gérés par le deuxième cœur du RP2040. C’est probablement exagéré, mais c’est presque facile à faire. Les quatre boutons sur le côté gauche vous permettent de sélectionner quelques scènes ou boucles, de modifier la durée du diaporama et de mettre le spectacle en pause.

Le joystick de haut en bas vous permet de contrôler plus précisément le timing, tandis que les boutons gauche et droit passent à différentes parties du diaporama. Appuyer sur le joystick pour allumer ou éteindre l’écran. Pour personnaliser les boutons, vous avez besoin d’un peu de code C personnalisé, mais vous n’avez pas besoin d’une compréhension approfondie du matériel ou du logiciel.

Les détails

Le logiciel ne comporte que quatre parties principales : l’affichage, l’interface des boutons, les services du script et le traitement réel du langage de script. Tout cela est simple une fois que vous les explorez.

La bibliothèque graphique que j’ai utilisée est la bibliothèque Arduino GFX. Cette bibliothèque est impressionnante car elle gère de nombreux types d’affichage différents. Vous devez définir un bus pour indiquer à la bibliothèque comment communiquer avec l’écran. Dans ce cas, il s’agit de SPI sur des broches spécifiques. Ensuite, la bibliothèque elle-même est séparée du canal de communication. Vous pouvez facilement utiliser l’écran comme périphérique de sortie de texte ou périphérique de sortie graphique. Il prend même en charge les polices u8g2.

Boutons et multicœur

Au début, je vérifiais simplement chaque commutateur dans le cadre du traitement de boucle standard. Pourquoi pas? Mais il y a un problème. La nature même du badge signifie que la plupart du temps, le processeur exécute un délai entre les « diapositives ». Pendant ce temps, les clés n’étaient pas scannées. Vous pouvez bien sûr diviser le délai en petites parties simplement pour vérifier les touches entre les deux.

Cependant, le RP2040 possède deux cœurs parfaitement fins, et l’un d’eux reste normalement endormi. Par défaut, votre programme s’exécute sur le core 0 avec le port série USB. Alors pourquoi ne pas utiliser ce noyau supplémentaire ? Mais programmer avec plusieurs cœurs doit être difficile, n’est-ce pas ?

En fait non. Si vous voulez que deux choses se produisent simultanément, il vous suffit de définir setup1() et loop1() dans votre programme (voir core1.cpp). C’est comme l’Arduino standard setup et loop, mais il réveillera le noyau 1 et fonctionnera dessus. C’est aussi simple que cela.

Le problème, bien sûr, se pose lorsque vous souhaitez communiquer entre les cœurs. Le package de support RP2040 dispose d’une forme de communication interprocessus de type FIFO, mais pour ce travail simple, j’ai opté pour quelque chose de plus simple.

Les deux cœurs partagent une variable : button. Core 0 lit cette variable et la remet à zéro. Le noyau 1 marque les bits de la variable qui correspondent aux pressions actives sur les boutons. Il ne réinitialise jamais les bits, donc le code principal verra une pression sur un bouton à chaque fois qu’il le verra, même si le bouton a déjà été relâché.

Le code Core 1 contient également des dispositions permettant d’anticiper les commutateurs et de ne signaler qu’un seul événement au thread principal par pression sur un bouton. L’astuce n’est pas que les deux processeurs lisent et écrivent cette variable simultanément. Dans un système d’exploitation classique, vous auriez l’idée d’une section critique. Dans ce cas, j’utilise l’appel API pour geler « l’autre » noyau pendant la brève période nécessaire pour lire ou écrire la variable des boutons. Par exemple:

rp2040.idleOtherCore();
boutons |= xbtn; // insère ceux qui sont définis ; le client les réinitialisera
rp2040.resumeOtherCore();

Je ne voulais pas trop retarder l’utilisation des clés, alors le scaledelay la routine (dans badge.cpp) divise le délai en tranches de 100 millisecondes. Bien sûr, cela signifie que les retards ont une résolution pratique de 100 millisecondes, mais ce n’est pas grave pour cette application. Après chaque délai de 0,1 seconde, la boucle vérifie toute pression sur une touche et si elle est trouvée, la boucle se termine.

Le Core 1 retarde de 5 millisecondes dans sa boucle principale. Cela donne à l’autre noyau une chance de fonctionner et signifie que les boutons n’ont pas besoin d’être appuyés longuement pour fonctionner. Aller plus court a peu de valeur, et vous pourriez probablement aller un peu plus longtemps, ce qui pourrait économiser sur la durée de vie de la batterie.

Services de scripts

Je souhaitais fournir des services au script afin que vous puissiez personnaliser le badge sans trop d’effort. Il existe une fonction de rappel (customize) qui, s’il est fourni, peut effectuer des opérations telles que mettre le diaporama en pause ou le mettre en boucle à différents points.

Dans un premier temps, j’ai mis ces fonctions dans une classe statique. De cette façon, vous deviez y faire référence explicitement à partir de la fonction de personnalisation. Si votre code avait une fonction appelée pausepar exemple, cela n’avait pas d’importance car il fallait appeler BADGE::pause pour bénéficier du service pause.

Après un moment, cependant, j’ai réalisé qu’il n’y avait aucune valeur réelle à l’avoir dans une classe statique, et qu’un meilleur choix serait d’utiliser un espace de noms. Le customize le code est exactement le même dans les deux cas. Tu appelles toujours BADGE::pause. Cependant, vous appelez maintenant une fonction dans le BADGE espace de noms, pas une fonction statique dans le BADGE classe. Une petite distinction, mais pratique. Par exemple, vous pouvez utiliser pour importer la fonction pause ou même l’intégralité de l’espace de noms si vous le souhaitez.

Dans le code d’origine, j’avais des variables statiques qui étaient « privées » pour le code du service. Ces variables se trouvent désormais dans un espace de noms sans nom. Ceci est très similaire au statique : le code du fichier peut utiliser ce qui y est défini, mais il n’est visible par rien d’autre.

Compilation du script

Le script est simple à mettre en œuvre car j’ai détourné le préprocesseur C. Chaque action de script est un élément dans un tableau de structures. Ensuite, il existe des définitions de préprocesseur C qui configurent ce tableau et chaque élément (voir pico-badge.h). Par exemple, ce script :

Scommencer
Clair (ROUGE)
Stext(3,10, »Bonjour ! »)
Envoyer

S’étend à :

SCRIPT script[]= {
{ CLEAR, NULL, NULL, RED, 0 },
{ TEXT, "Hello!", NULL, 3, 10}
};
unsigned script_size=sizeof(script)/sizeof(script[0])

C’est ça. Le préprocesseur effectue tout le travail de compilation. N’oubliez pas que les choses sont configurées lors de l’initialisation du tableau. Par exemple, le script par défaut utilise tdelay pour maintenir le délai de base entre les diapositives. Une fois le tableau construit, changer tdelay ne fait rien pour toi. Vous devrez modifier l’élément du tableau, ce qui n’est pas très amusant.

Le Stag La macro vous permet de définir une étiquette numérique (comme un numéro de ligne de base) que vous pourrez retrouver ultérieurement. Les nombres ne doivent pas nécessairement être séquentiels : ils servent simplement à identifier une position dans votre script. Certains assistants de script acceptent des balises afin que vous n’ayez pas à compter (et recompter) les éléments du tableau pour faire référence à une partie spécifique du script.

Images

Si vous voulez des images, vous devez les mettre dans des tableaux. Certains sites Web peuvent vous aider pour les images monochromes ou couleur. GIMP peut également exporter vers des fichiers .C ou .H, comme le montre la vidéo ci-dessous.

Si vous commencez avec le code dans script.cpp, vous devriez être en mesure de comprendre comment tout rassembler.

Ce qui reste?

Pas mal pour du matériel standard. Il ne remportera aucun prix lors de votre prochaine conférence, mais vous pouvez facilement le personnaliser et vous l’approprier. Si vous en avez un chez Supercon, retrouvez-moi à la table du défi de soudure et montrez votre construction.

Qu’est-ce que les attaches zippées ne peuvent pas faire ?

Il me reste encore à réaliser un boîtier pour le badge, même si, avec une batterie de 220 mAh coincée entre les cartes, il se débrouille plutôt bien tout seul. J’ai utilisé quelques attaches zippées et de la super colle pour fabriquer un connecteur de fortune pour un cordon. Cela ne me dérangerait pas de mettre en place une option d’affichage de l’horloge, mais vous auriez besoin d’un moyen de régler l’horloge. Un moniteur de charge de batterie serait également bien.

Si vous pouviez trouver un processeur de type Pico avec à la fois le chargeur de batterie et le sans fil, cela ouvrirait certaines possibilités. Une grande partie des capacités de l’appareil, comme les PIO et le port USB, sera également gaspillée. Étant donné que le package Arduino prend en charge LittleFS, vous pouvez lire les fichiers à partir du « disque ». Il devrait probablement aussi pouvoir jouer à Life.

François Zipponi
Je suis François Zipponi, éditorialiste pour le site 10-raisons.fr. J'ai commencé ma carrière de journaliste en 2004, et j'ai travaillé pour plusieurs médias français, dont le Monde et Libération. En 2016, j'ai rejoint 10-raisons.fr, un site innovant proposant des articles sous la forme « 10 raisons de... ». En tant qu'éditorialiste, je me suis engagé à fournir un contenu original et pertinent, abordant des sujets variés tels que la politique, l'économie, les sciences, l'histoire, etc. Je m'efforce de toujours traiter les sujets de façon objective et impartiale. Mes articles sont régulièrement partagés sur les réseaux sociaux et j'interviens dans des conférences et des tables rondes autour des thèmes abordés sur 10-raisons.fr.