Modification d’une bibliothèque Adafruit CircuitPython pour prendre en charge le Pimoroni 11×7 LED Matrix Breakout sur le Raspberry Pi Pico

Modification d'une bibliothèque Adafruit CircuitPython pour prendre en charge le Pimoroni 11x7 LED Matrix Breakout sur le Raspberry Pi Pico

En ce moment, j’essaie de combiner plusieurs produits différents – capteurs, écrans – dans un projet pour le Raspberry Pi Pico. L’un d’eux est le Matrice Breakout Garden 11 × 7 de Pimoroni. J’ai choisi d’utiliser CircuitPython car il y a un parcelle des bibliothèques disponibles auprès d’Adafruit. L’un de ceux disponibles est le IS31FL3731 bibliothèque qui prend en charge une variété de produits (utilisez le lien pour voir lesquels) mais pas celui dont j’avais besoin. J’ai décidé de voir à quel point il était difficile d’y ajouter la prise en charge de la matrice 11 × 7. Voici ce que j’ai fait pour faire exactement cela.

Fichiers MPY

La première chose que j’ai réalisé était que le fichiers de bibliothèque fournis par Adafruit sont pré-construits en tant que fichiers .mpy – Python compilé. Donc, j’aurais besoin de comprendre comment construire à partir du fichier source Python .py en .mpy. Heureusement, étant les gens gentils qu’ils sont, Adafruit fournit le fichier de code source afin qu’il soit modifiable. Alors… Comment puis-je tout construire?

Sous-système Windows pour Linux

J’utilise Windows en ce moment (pour le meilleur ou pour le pire) donc il y a des obstacles à franchir! j’ai trouvé ce fil sur un forum qui contenait quelques conseils et mentionnait quelque chose appelé WSL – le sous-système Windows pour Linux – qui vous donne une invite de terminal Linux et vous permet de faire les choses d’une manière «Linux-y».

Adafruit fournit des instructions pour installer le WSL ici (que je ne dupliquerai pas, mais il suffit de dire que vous utilisez les fonctionnalités Windows pour l’ajouter, puis installez l’application Ubuntu via le Windows Store). Une fois que j’ai installé cela et configuré un nom d’utilisateur pour moi-même, j’ai vu un écran de terminal Ubuntu typique.

Ensuite, j’ai dû installer des outils de construction dans le WSL. De nouveau, Adafruit fournit des instructions pour l’installation de ces. La «viande» de ceci est la suivante (j’ai ajouté l’installation de pip3 car elle n’était pas là):

sudo apt update
# Try running `make` at the command line. If it's not installed, do:
# sudo apt install build-essential
sudo apt install git
sudo apt install gettext
sudo apt install python3-pip
pip3 install huffman

Chaîne d’outils ARM gcc

J’avais également besoin de la «chaîne d’outils ARM gcc» (que je pense est les bits et les morceaux nécessaires pour compiler pour un processeur ARM). Je vais utiliser le dernier firmware CircuitPython (qui plane autour de la v6.2 beta-3) donc j’avais besoin la version 10-2020-q4-major. Maintenant, j’aurais probablement dû utiliser curl ou wget pour obtenir le fichier directement dans WSL, mais je ne l’ai pas fait, il a donc été téléchargé dans mon dossier Téléchargements Windows.

Cependant … le WSL monte mon lecteur C dans / mnt, donc j’ai d’abord déplacé le fichier sur le lecteur C, puis copié le fichier dans la zone Linux en utilisant:

mkdir ~/bin
cp /mnt/c/<filename> ~/bin/

Cela a créé un dossier bin dans mon dossier personnel, puis copié dedans. Pour décompresser le fichier, j’ai fait ceci:

cd ~/bin
tar xvf <filename>

J’avais maintenant besoin d’ajouter le chemin à mon fichier ~ / .bash_profile.

C’est plus facile à dire qu’à faire si vous n’êtes pas habitué à Linux. J’espère que vous l’êtes parce que vous lisez un blog Raspberry Pi! Si ce n’est pas le cas, jetez un œil à l’utilisation de l’éditeur Nano car je ne veux pas entrer dans cela ici.

J’ai obtenu le chemin du dossier bin du dossier que je viens de décompresser. Ce sera quelque chose comme…

/home/<user>/bin/gcc-arm-none-eabi-10-2020-q4-major/bin

J’ai copié cela dans mon presse-papiers, puis modifié le fichier ~ / .bash_profile (qui était un nouveau fichier pour moi – assurez-vous d’inclure le point si vous répliquez) et ajouté la ligne suivante (que vous devrez modifier pour correspondre à votre propre chemin).

export PATH=/home/recantha/bin/gcc-arm-none-eabi-10-2020-q4-major/bin:$PATH

Je me suis déconnecté du terminal (CTRL-D le fait normalement), puis j’ai à nouveau ouvert le terminal Ubuntu pour taper:

which arm-none-eabi-gcc

Cela a renvoyé un chemin (par opposition à une ligne vide). Si vous me suivez et que cela renvoie une ligne vide, vous avez fait quelque chose de mal et vous devriez revenir sur vos pas. Vous avez probablement mal exécuté la commande d’exportation dans .bash_profile ou vous ne vous êtes pas déconnecté et reconnecté!

Je me suis assuré que j’étais dans mon répertoire personnel avant d’aller plus loin en tapant:

cd ~

Construire le compilateur

J’avais maintenant besoin de construire le compilateur mpy-cross. Ceci est décrit dans ce tutoriel d’Adafruit. En bref:

git clone https://github.com/adafruit/circuitpython.git
cd circuitpython
git submodule sync --quiet --recursive
git submodule update --init
make -C mpy-cross

je n’a pas construire CircuitPython lui-même car je n’ai pas besoin de compiler mon propre firmware CircuitPython (pour le moment!). La dernière étape (construire mpy-cross) a pris un peu de temps.

Compilation de py en mpy

La prochaine chose à faire était de compiler un fichier .py en .mpy juste pour voir si cela fonctionnait. Pour ce faire, j’avais besoin de connaître le chemin d’accès à l’exécutable mpy-cross. C’était, dans mon cas: ~ / circuitpython / mpy-cross / mpy-cross

J’ai décidé de bifurquer de la bibliothèque Adafruit à mon propre référentiel. De cette façon, si je le voulais, je pourrais alors faire une pull request à Adafruit pour incorporer le nouveau code. Que je fasse cela ou non dépend de mon courage! ? Alors, j’ai cliqué sur le bouton de la fourche et répliqué le code pour mon propre repo.

La prochaine chose à faire était d’obtenir ce référentiel dans l’environnement WSL sur ma machine Windows. J’ai fait cela en:

git clone https://github.com/recantha/Adafruit_CircuitPython_IS31FL3731

Je suis ensuite allé dans le répertoire que j’avais cloné et utilisé mpy-cross pour compiler le fichier Python en .mpy:

cd Adafruit_CircuitPython_IS31FL3731
~/circuitpython/mpy-cross/mpy-cross adafruit_is31fl3731.py

À ma grande surprise, cela a fonctionné sans erreur!

Connexion du Pico à WSL

Maintenant, comment puis-je obtenir ce fichier de bibliothèque sur le Pico. Je pourrais, bien sûr, le copier de la zone Linux dans le lecteur C: et le faire de cette façon, mais il y avait une méthode plus simple.

Tout d’abord, j’ai identifié que mon Pico était monté sur Windows en utilisant E :.

J’ai donc fait ce qui suit pour créer un «point de montage», puis j’ai monté le Pico (le lecteur E) dessus:

sudo mkdir /mnt/e
sudo mount -t drvfs E: /mnt/e
ls /mnt/e

Cette dernière commande devrait lister les fichiers sur le lecteur E: (dont un devrait, si vous avez déjà téléchargé du code sur le Pico, soyez code.py).

Je savais que je devais mettre le fichier mpy dans le dossier lib sur le Pico, alors j’ai fait ceci:

cp ~/Adafruit_CircuitPython_IS31FL3731/adafruit_is31fl3731.mpy /mnt/e/lib/

Exécuter le code

Je n’avais (et je n’ai toujours) aucune idée de la façon d’utiliser WSL comme environnement de programmation pour le Pico, alors je suis retourné à Windows et j’ai exécuté Mu. J’ai téléchargé mon programme sur le Pico qui utilisait la bibliothèque IS31 *. J’ai reçu la même erreur «Opération non prise en charge» que j’ai eue plus tôt, donc tout va bien jusqu’à présent. Maintenant… voyons comment modifier ce code…

Note d’accompagnement

D’accord, donc ce qui s’est réellement passé, c’est que Mu a arrêté de me montrer la REPL. J’ai donc dû télécharger le Mastic logiciel du terminal et connectez-le séparément pour voir la sortie…

Maintenant, revenons à notre programme programmé…

Obtenir une sortie

Alors, que signifie réellement «Opération non prise en charge»? Eh bien, je l’ai deviné en exécutant ce qui suit sur le Pico:

i2c = busio.I2C(scl=board.GP21, sda=board.GP20, frequency=100000)
display = adafruit_is31fl3731.Matrix(i2c)

et obtenir cette erreur autour de la ligne suivante:

File "adafruit_is31fl3731.py", line 102, in _i2c_write_reg

… Que j’essayais d’écrire sur I2C sur quelque chose que je ne pouvais pas. Alors, regardons le code Matrix… Le code Matrix utilise l’adresse I2C 0x74 par défaut. C’est faux. Au dos du module 11 × 7, il est dit:

1615145771 339 Modification dune bibliotheque Adafruit CircuitPython pour prendre en charge le

… 0x75 ou 0x77. Maintenant, je n’ai pas modifié la carte en coupant la trace en haut à droite, nous allons donc supposer que c’est l’adresse 0x75. Ceci est évidemment différent de la valeur par défaut que la bibliothèque utilise, donc l’erreur semble être que j’essaie d’écrire sur une adresse I2C qui n’est pas là. Assez juste. Dans le code de la bibliothèque, il semble que la fonction init () de la classe Matrix accepte un paramètre d’adresse, alors essayons de l’utiliser et voyons ce que nous obtenons …

display = adafruit_is31fl3731.Matrix(i2c, address=0x75)

Je l’ai sauvegardé et cette fois je n’ai reçu aucun message d’erreur. Excellent. Maintenant, je sais que la classe Matrix a une largeur codée en dur de 16 et une hauteur de 9, ce qui est bien sûr différent des dimensions 11 × 7 du module Breakout Garden. Alors on volonté avez des problèmes pour obtenir les pixels au bon endroit, mais ajoutons au code CircuitPython sur le Pico ce qui suit:

display.fill(127)

Cela devrait afficher une couleur unie… Enregistrez-le… Vérifiez le REPL (en utilisant PuTTY, maintenant – voir ci-dessus). Ta-da!

1615145771 146 Modification dune bibliotheque Adafruit CircuitPython pour prendre en charge le

Ça a marché! Excellent. Maintenant, pour essayer de faire défiler du texte…

Malheureusement, le exemples d’Adafruit pour faire défiler le texte et afficher les images, il faut PIL (Python Image Library). J’ai lu quelque part que PIL ne fonctionne pas dans CircuitPython, juste en Python normal. Euh… Ok, laissons ça pour le moment.

J’ai décidé, à la place, d’essayer de faire une boucle sur chaque pixel afin de faire un test. C’est là que connaître un peu le produit Pimoroni et où ils conservent leur code est utile.

En regardant la bibliothèque Pimoroni

La fonction init () de Pimoroni pour leur matrice 11 × 7 est ici. Maintenant, cela est écrit en Python normal, pas en CircuitPython, pas même en MicroPython, j’ai donc essayé de faire un compromis entre leur code et la bibliothèque Adafruit.

J’ai regardé un peu autour de moi et j’ai trouvé que la bibliothèque CircuitPython existante prend en charge le Scroll pHAT HD. C’est 17 × 7, donc pas loin. J’ai donc commencé avec cette fonction, je l’ai copiée et collée dans la bibliothèque Adafruit, en changeant le nom de la classe en Matrix11x7. J’ai également ajouté une nouvelle fonction __init __ () qui définirait l’adresse 0x75 par défaut.

Maintenant, pour recompiler à nouveau en utilisant myp-cross et télécharger… Tout va bien jusqu’à présent.

J’ai ensuite changé le code CircuitPython sur le Pico pour utiliser Matrix11x7 ():

display = adafruit_is31fl3731.Matrix11x7(i2c)

Cela a fonctionné à nouveau – cela doit signifier qu’il utilise mon nouveau code de bibliothèque modifié! Passionnant!

Obtenir la bonne matrice

J’ai ajouté du code Pico pour afficher les pixels un par un:

for y in range(7):
    for x in range(11):
        display.pixel(x, y, 100)
        time.sleep(0.1)
        display.fill(0)

Qu’est-ce que ce code devrait faire est de mettre un seul pixel sur l’écran, de gauche à droite, de bas en haut et de le faire pour chaque LED sur l’écran. Comme tu peux le voir…

YouTube video

ça n’a pas assez travailler (même si, avoir mal compris les plages au départ, et pour cette vidéo, n’a pas aidé!) donc je savais que je devais faire une traduction dans la bibliothèque. C’est le code avec lequel j’ai dû travailler, d’une classe différente:

def pixel_addr(x, y):
    if x <= 8:
        x = 8 - x
        y = 6 - y
    else:
        x = x - 8
        y = y - 8

    return x * 16 + y

Je savais, rien qu’en le regardant, que ce n’était pas tout à fait correct. J’adore les maths. Honnêtement je fais…

Puis, je me suis demandé: Pimoroni a-t-il déjà fait le dur travail pour moi? Et en effet ils l’avaient fait! Si vous regardez leur bibliothèque Python normale pour cela, vous verrez que leur fonction _pixel_addr () a un mappage et quelques calculs:

mapping = [
    6, 22, 38, 54, 70, 86, 14, 30, 46, 62, 78,
    5, 21, 37, 53, 69, 85, 13, 29, 45, 61, 77,
    4, 20, 36, 52, 68, 84, 12, 28, 44, 60, 76,
    3, 19, 35, 51, 67, 83, 11, 27, 43, 59, 75,
    2, 18, 34, 50, 66, 82, 10, 26, 42, 58, 74,
    1, 17, 33, 49, 65, 81, 9, 25, 41, 57, 73,
    0, 16, 32, 48, 64, 80, 8, 24, 40, 56, 72
]

y = self.height - 1 - y
return mapping[(y * self.width) + x]

C’est la «sauce magique» (ou source! Ha-ha… #tumbleweed) qui fait les calculs qui le font fonctionner. Je l’ai converti en quelque chose qui fonctionnerait dans MicroPython / CircuitPython et…

1615145771 141 Modification dune bibliotheque Adafruit CircuitPython pour prendre en charge le

Ta-da! Une maison à mi-chemin entre le code de Pimoroni et la bibliothèque originale d’Adafruit. J’ai de nouveau exécuté le code et…

YouTube video

Hourra! Un mod de bibliothèque réussi et un téléchargement sur le Pico, suivi d’un test réussi de chaque pixel dans le bon ordre.

Je ferai quelque chose pour faire défiler le texte plus tard – cela suffit pour le moment!

Réflexions finales

J’espère que cela sera d’une certaine utilité pour quelqu’un – je sais que je vais devoir y revenir à un moment donné!

Si je pouvais gérer ça, vous le pouvez aussi! La chaîne d’outils est un peu compliquée sous Windows (je suppose que si je l’avais fait en utilisant un environnement Raspberry Pi / Linux natif, cela aurait été plus simple, mais vous utilisez ce que vous avez!)

J’ai même eu le courage de faire une Pull Request pour la fusionner dans la bibliothèque Adafruit originale!