Publié le 12 juin 2021 - par

Faites rebondir les LED avec le Raspberry Pi Pico (Episode 2)

Il y a quelque temps je vous ai présenté un projet pour faire rebondir des LEDs sur un ruban de WS2812B avec un Raspberry Pi PICO. L’idée c’était d’avoir un projet visuel à présenter à Nantes Maker Campus début juillet. Le projet a avancé et se finalise avec la mise en boîte et les derniers tests.

Faites rebondir les LED avec le Raspberry Pi Pico

Même si ce genre de « petit » projet ne va pas très loin, il met en œuvre pas mal de domaines qu’un maker passionné va aborder à un moment ou à un autre. Pas obligé de tout maîtriser mais au moins avoir les bases pour se débrouiller. Si vous êtes dans un FabLab pensez aux compétences que vous pouvez y solliciter…

Je vais essayer de décrire le cheminement suivi pour que les makers intéressés puissent découvrir la démarche. Après je ne suis pas le « spécialiste » de la gestion de projets mais si ça peut aider à démarrer… Si un gestionnaire / Chef de projet veut me corriger, il est le bienvenu dans les commentaires.

Le cahier des charges

Tout projet commence ici : si on ne sait pas ce qu’on veut faire…. On ne le fera pas, ou alors on va avoir un projet qui part dans tous les sens. Bien entendu le cahier des charges peut évoluer (dans un sens d’amélioration ou dans un sens de simplification) en fonction des connaissances acquises ou à acquérir, du matériel disponible, des dates de livraison etc…

Suite aux premiers essais, j’ai défini le cahier des charges suivant :

  • Un Raspberry Pi Pico programmé en MicroPython
  • Un ruban de LEDs RGB 2m de long, 144 LEDs par mètre
  • Alimentation de l’ensemble par alimentation 5V/10A
  • Possibilité de connecter le port USB du PICO simultanément
  • Lancement automatique du programme (plus simple sur un stand)
  • Paramétrage par DIP Switch
      • Possibilité de passer en mode démo (arc en ciel)
      • Possibilité de régler le sens de défilement des LEDS (UP/DOWN)
      • Possibilité de régler la taille du bloc (8 ou 12 LEDs)
      • Possibilité de régler la luminosité (40% ou 90%)

Accessoirement et comme j’ai des convertisseurs DC/DC en stock, j’ai décidé d’alimenter le Raspberry Pi PICO avec une alim bien à lui. Je ne sais pas si c’est 100% obligatoire, mais j’espère éviter les éventuels  plantages provoqués par la commutation des LEDs. Et puis au prix que ça côute… comme on dit, « ça mange pas de pain« .

Concevoir un boîtier

L’habillage commence par ça, quelques idées jetées sur la papier. Je réfléchis toujours en griffonnant  des feuilles, en recommençant, gommant…

Un bout de schéma électrique aussi, quelques cotes relevées sur les docs techniques ou mesurées au pied à coulisse..
Pour un programme seul on ne fera pas de boîtier, mais s’il y a une interface homme-machine (un écran pour dialoguer avec le programme) je commence par cette partie en dessinant l’écran principal, les sous-écrans, comme les menus et les sous-menus. Cette approche aide pour séparer l’affichage du programme et avance les choses pour créer des fonctions / sous-fonctions dans le programme.

Quels logiciels utiliser ?

Il n’y a pas de bonne réponse. Utilisez celui que vous connaissez le mieux, avec lequel vous vous sentez le plus à l’aise. Si vous connaissez FreeCAD, utilisez le, si vous connaissez Fusion360, utilisez-le… Après ça peut aussi être l’occasion d’apprendre un nouveau logiciel. En général je profite d’avoir des projets à réaliser pour me mettre à un nouveau logiciel. Ça motive ! Vous trouverez sur le blog plusieurs articles sur FreeCAD.
Pour ma part j’utilise les deux mais ça fait un grand moment que je n’ai pas utilisé Fusion 360. C’est celui que j’ai choisi pour réviser un peu (vous verrez, après quelques semaines/mois, des choses qui semblaient faciles et intuitives… bin on ne sait plus les faire, il faut chercher un peu 😛 )

La première partie de la vidéo montre le boîtier dans Fusion 360. Je l’ai rendu transparent pour plus de visibilité. Les composants (Pico, DIP switch, prise d’alim, convertisseur DC/DC…) sont disponibles et peuvent être intégrés pour créer un boîtier autour des composants en taille réelle. La seconde partie de la vidéo montre le boîtier dans CURA tel qu’il sera imprimé par l’imprimante 3D.

Pour transformer votre dessin 3D en impression 3D, il faut passer par un logiciel chargé de découper votre modèle en tranches (slicer = découper) que l’imprimante 3D déposera couche après couche pour reconstituer « en vrai » ce que vous aurez dessiné. Ici j’ai utilisé CURA qui est open-source et gratuit pour faire la conversion du fichier .STL (le modèle en 3D) en gcode (le code qui va piloter l’imprimante 3D).

Reste ensuite l’étape de l’impression 3D du boîtier. J’ai choisi le PLA car le boîtier ne subira pas de chocs, ni de contraintes thermiques…

Pour ceux que ça peut intéresser voici le boîtier. IL est vraiment brut et ce n’est qu’un prototype !

 

Créer son schéma

Là aussi (dans mon cas) c’est souvent la feuille de papier qui est le support pour créer un schéma.

Pour diffuser les schémas j’utilise souvent Frietzing, un logiciel open-source gratuit pour lequel de nombreux composants et modules sont disponibles. Il permet de travailler sur breadboard et de générer ensuite un circuit imprimé de la réalisation.

On obtient un schéma propre qu’on peut enregistrer et éventuellement diffuser.

Alimentation

Vous remarquerez une diode Shottky entre la sortie du convertisseur et le Raspberry Pi PICO. Si on regarde le schéma de l’alimentation du Raspberry Pi PICO :

VBUS est l’alimentation 5V qui arrive de la prise micro-USB. Elle arrive sur VSYS (l’entrée de l’alimentation à découpage du PICO) via une diode MBR120VLS qui est une diode Shottky. En amenant une autre tension via une autre diode, on crée un OU logique et c’est la tension la plus importante qui l’emportera. Le PICO est donc alimenté indifféremment par l’une ou l’autre alimentation sans que cela ne les perturbe. J’ai choisi une 1N5819 que j’avais en stock… mais toute autre diode Shottky (mini 20V/1A) fera l’affaire.

On voit ici que la diode Shottky 1N5819 a une tension de seuil dans le sens passant de seulement 0,2 volt. Elle provoquera une chute de tension bien moindre que celle ramenée par les diodes classiques (0,6 volt) utilisées habituellement (1N4001, 1N4004…)

Reset

Pour éviter d’avoir à débrancher/rebrancher la prise d’alimentation quand il faut redémarrer le PICO, j’ai opté pour un bouton poussoir de RESET. Le modèle Captain RESETTI de Pimoroni est sympa et ne tient pas de place ! Il va venir se souder sur les pastilles de la carte PICO, entre les broches (physiques) 28 à 30. Quand on appuie sur le bouton poussoi, la broche RUN (30) du PICO est mise à la masse (28), ce qui provoque le redémarrage du programme (RESET).

 

Ici le Captain Resetti est entouré en rouge. On voit qu’il est « naturellement  » à sa place. Cela inspirera peut-être les concepteurs du PICO pour la prochaine génération ?

DIP Switch

Le DIP Switch (Dual In-line Package) est un petit bloc de plusieurs interrupteurs (ici 4) qui vont permettre, dans notre cas, de configurer un certain nombre de paramètres :

  • Mode Démo
  • UP/DOWN
  • Luminosité
  • Taille du bloc

 

Si vous avez plus de choses à paramétrer il faudra opter pour un DIP Switch plus grand. On pourrait aussi utiliser les interrupteurs en binaire. Dans ce cas ce DIP Switch de 4 interrupteurs pourrait générer 16 valeurs (de 0 à 15).

J’ai choisi de les relier aux broches 24 à 27, GPIO18 à GPIO21. LA masse est prise en broche 23 du PICO.

Ruban de LEDs

Le ruban est constitué de LEDs WS2812B. Ce sont des LEDs RVB (ou RGB en français) intelligentes et adressables. Elles s’alimentent en 5 volts.

Chaque LED comporte un circuit de commande (rectangle sombre) et trois LEDs de couleur rouge, verte et bleue. Chaque couleur est codée sur 8 bits (un octet), soit 256 valeurs (de 0 à 255). Les 3 LEDs peuvent donc afficher 256x256x256 = 16 777 216 de couleurs différentes. Par exemple :
R    V    B
00 00 00    toutes les LEDs sont éteintes
FF 00 00    La LED rouge est allumée à fond (0xFF = 255)
FF FF 00    La LED rouge est la verte sont allumées. On voit du jaune…
Si la colorimétrie vous intéresse reportez vous à cet article de Wikipedia.

Chaque couleur pour une LED est donc codée sur 3 octets soit 24 bits. Le mécanisme est le suivant :

Le microcontrôleur (ici le PICO) envoie les bits un par un sur le fil Din de la première LED WS2812B. Celle-ci intercepte les 24 premiers bits puisqu’ils lui sont destinés. Elle affiche alors la couleur que ces 3 octets lui ont fournie. Ensuite elle va laisser passer tous les autres bits qui arrivent vers sa sortie Dout.

Cette sortie arrive sur Din de la deuxième WS2812B. Celle-ci va donc intercepter les 24 premiers bits et afficher la couleur correspondante. Tous les autres bits sont envoyés sur sa sortie Dout qui va vers Din de la LED suivante etc. etc.

C’est ainsi que vous pouvez adresser séparément chaque LED d’un anneau ou d’un ruban. Il suffit d’envoyer autant de bits que nécessaire. Si vous avez 12 LEDs que un anneau il faudra 12 x24 = 288 bits. Pour mon ruban de LEDs qui comporte 288 LEDs il faudra 288*24 = 6912 bits. Heureusement des bibliothèques existent pour gérer ce protocole et tout ce que vous aurez à faire est d’ajouter la bibliothèque ws2812b.py dans votre PICO. (C’est expliqué dans l’article précédent).

On peut aussi estimer la consommation globale en prenant la valeur de 20 mA par LED R, V ou B, soit 60 mA maxi par LED WS2812B. Si vous avez 100 LEDs, il faudra prévoir 100×0.060A soit 6 Ampères ! Pour mes 288 LEDs il faudrait 288×0.060A = 15A. Je n’avais qu’une alim de 5V/10A et ça fonctionne. Après toutes les LEDs ne sont pas forcément allumées en même temps (pas toujours) et elles consomment sans doute un peu moins de 60mA par WS2812B. En tout cas, ça fonctionne.

Le programme

Le programme permet de lancer la démo (Arc en ciel) ou les Bouncing LEDs. Dans ce cas on peut régler La taille des blocs, le sens de chute et la luminosité des LEDs. Vous pouvez télécharger le programme main.py en cliquant sur le lien.

# Bouncing LED par KenKen pour le Raspberry Pi Pico
# Télécharger ws2812b.py avec le lien ci-dessous et
# enregistrez le sur le Raspberry Pi Pico avec le même nom
# https://github.com/benevpi/pico_python_ws2812b
# Version française framboise314 - Mai 2021

from machine import Pin
import time
import ws2812b

LED_NUM = 288                                  # Nombre de Neopixels sur le ruban
DIN_GPIO = 0                                   # GPIO sur lequel le ruban est connecté
SENS_GPIO = Pin(20, Pin.IN, Pin.PULL_UP)       # GPIO pour inverser le sens de défilement avec R de pull-up
LUMIERE_GPIO = Pin(19, Pin.IN, Pin.PULL_UP)    # GPIO pour modifier la luminosité 40% ou 80% avec R de pull-up
RAINBOW_GPIO = Pin(21, Pin.IN, Pin.PULL_UP)    # GPIO pour lancer RAINBOW
BLOCK_SIZE_GPIO = Pin(18, Pin.IN, Pin.PULL_UP) # GPIO pour changer la taille du bloc

REVERSE = False                             # If True, LED block will fall off from the end of the LED strip

# Modifier la taille du bloc - Défaut => 8
if BLOCK_SIZE_GPIO.value() == 1 :
    BLOCK = 8      # Longueur d'un bloc de LEDs - Défaut 8
else :
    BLOCK = 12

BRIGHT = 40    # Luminosité des LED - Défaut 40 
GRAVITY = 20   # Accélération de la gravité - Défaut 20

# Coefficient de rebond = R1/R2
R1 = 3         # Coefficient de rebond R1 - Défaut 3
R2 = 5         # Coefficient de rebond R2 - Défaut 5
REFMINV = -80  # Vitesse minimum de rebond (Ajuster si le rebond ne s'arrête pas) - Défaut -80

rouge = 255, 0, 0
vert = 0, 255, 0
bleu = 0, 0, 255
jaune = 255, 255, 0
cyan = 0, 255, 255
magenta = 255, 0, 255
blanc = 255, 255, 255
noir = 0, 0, 0

# création de l'instance du ruban
strip = ws2812b.ws2812b(LED_NUM, 0, DIN_GPIO)

def wheel(pos):
    # Les couleurs ont une valeur de 0 à 255
    # et sont une transition entre rouge, vert et bleu
    if pos < 0 or pos > 255:
        r = g = b = 0
    elif pos < 85:
        r = int(pos * 3)
        g = int(255 - pos * 3)
        b = 0
    elif pos < 170:
        pos -= 85
        r = int(255 - pos * 3)
        g = 0
        b = int(pos * 3)
    else:
        pos -= 170
        r = 0
        g = int(pos * 3)
        b = int(255 - pos * 3)
    
    return r, g, b

def rainbow_cycle(wait):
    for j in range(255):
        for i in range(LED_NUM):
            pixel_index = (i * 256 // LED_NUM) + j
            r, v, b = wheel(pixel_index & 255)
            strip.set_pixel(i, r, v, b)
        strip.show()
        time.sleep(wait)


def set_block(pos, c):
# Crée un bloc de LEDs
# pos: Position de début du bloc de LEDs
# c: Couleur 0=noir, 1=rouge ... 8=vert ... 16=bleu ... 24=rouge

    if c == 0:
        r = 0; g = 0; b = 0
    elif c <= 8: r = (8 - c) * BRIGHT >> 3
        g = c * BRIGHT >>3
        b = 0
    elif c <= 16: r = 0 g = (16 - c) * BRIGHT >> 3
        b = (c - 8) * BRIGHT >> 3
    elif c <= 24: r = (c - 16) * BRIGHT >> 3
        g = 0
        b = (24 - c) * BRIGHT >> 3
    else:
        return
    for i in range(BLOCK):
        if pos < 0: return if REVERSE: strip.set_pixel(LED_NUM - pos -1, r, g, b) else: strip.set_pixel(pos, r, g, b) pos -= 1 col = 1 # Couleur du blog de LED qui chute # Tester si on doit inverser le sens de chute if SENS_GPIO.value() == 0 : REVERSE = True # Modifier la luminosité à 80% - Défaut => 40%

# Régler la luminosité des LEDs en fonction de la position du switch
if LUMIERE_GPIO.value() == 0 :
    BRIGHT = 90
    
# Tester s'il faut lancer RAINBOW (mode démo)
# Si le switch est OFF (1) 
# On lance le programme Bouncing LEDs
if RAINBOW_GPIO.value() == 1 :
    while True:
    # Note: La position et la vitesse sont décalés de 8 bits vers la gauche pour travailler avec des entiers
        bottom = LED_NUM << 8 # Configurer la fin sur la dernière LED du ruban # Boucler la chute des blocs while bottom >0:      # Répéter jusqu'à ce que la fin dépasse le haut du ruban
            y = 0             # Début du bloc de LEDs
            v = 0             # Vitesse de chute
            while y < bottom: # Répéter tant que le bloc de Leds est au dessus de la fin set_block(y >> 8, col) # Configurer les LEDs du bloc
                strip.show()           # Afficher le ruban   
                time.sleep_ms(5)       # Attendre 5 ms 
                set_block(y >> 8, 0)   # Effacer les LEDs
                v += GRAVITY           # Mettre à jour la vitesse de chute
                y += v                 # Mettre à jour la position
                if y >= bottom:        # Quand on atteint la fin
                    y = bottom - 256   #  Mettre la position du bloc de LEDs à Une position au dessus de la fin
                    v = -v * R1 // R2  #  Rebondir
                    if v > REFMINV:    #  Arrêter quand la vitesse de rebond est inférieure à REFMINV
                        set_block((bottom >> 8) - 1, col) # Fixer le bloc de LEDs à une position au dessus de la fin
                        bottom -= BLOCK << 8         # Augmenter la position de fin de la longueur d'un bloc
                        col = (col + 18) % 24 + 1    # Passer à la couleur suivante

        strip.show()
        time.sleep_ms(500)

        y = 0 # Position du bout de la ligne de LEDs
        v = 0 # Vitesse de chute

    # On vide toute la ligne de LEDs
    while y < (LED_NUM << 8): # Répéter jusqu'à la disparition de l'extrémité de la ligne de LEDs y += v # Mettre à jour la position v += GRAVITY // 2 # Mettre à jour la vitesse de chute (avec frottement) for i in range(LED_NUM-1, (y >> 8) - 1, -1):
            y1 = (i << 8) + (y & 0xff) - v # Position actuelle de la LED arrivant en position 1 if y1 >= y:       # Copier la couleur de la LED en position y1 en i
                if REVERSE:
                    strip.pixels[LED_NUM - i -1] = strip.pixels[LED_NUM - (y1 >> 8) -1]
                else :
                    strip.pixels[i] = strip.pixels[y1 >> 8]
            else:             # Eteindre les LEDs au dessus du bout de la ligne de LEDs
                if REVERSE:
                    strip.set_pixel(LED_NUM - i -1, 0, 0, 0)
                else :
                    strip.set_pixel(i, 0, 0, 0)
        strip.show()
        time.sleep_ms(5)

    time.sleep_ms(500)        # Attendre 500 ms

# Sinon si le Switch démo est à ON (0)
# On lance la démo arc en ciel
# qui fait changer progressivement la couleur des LEDs

else:
    while True:
    # LEDs rouges
        r,v,b = rouge
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.5)

    # LEDs vertes
        r,v,b = vert
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.5)

    # LEDs bleues
        r,v,b = bleu
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.5)
    
    # LEDs cyan
        r,v,b = cyan
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.5)

    # LEDs jaune
        r,v,b = jaune
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.5)

    # LEDs magenta
        r,v,b = magenta
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.5)

    # LEDs blanches
        r,v,b = blanc
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.5)

    # LEDs éteintes
        r,v,b = noir
        strip.fill (r, v, b)
        strip.show()
        time.sleep(0.05)

        rainbow_cycle(0.001)  # Boucle affichant un arc en ciel - Attente 1 ms

Une fois le programme chargé sous le nom de main.py dans le PICO, lorsque vous connecterez l’alimentation ou que vous appuierez sur le bouton RESET

Ensuite si vous devez le modifier il suffit de rouvrir le programme dans Thonny.

Câbler le montage

Une fois tous ces aspects vus et compris, on va pouvoir passer au câblage du montage. Soyez précautionneux et attentif. On a vite fait de se tromper d’une broche et parfois les conséquences sont dramatiques. J’ai souvent vu des circuits intégrés se transformer en… circuits désintégrés !

Début de câblage du PICO. La diode Shottky est montée avec une gaine thermorétractable pour éviter les risques de contacts involontaires. Les 4 fils du DIP Switch sont soudés (jaune) plus le fil noir de masse. La broche en haut à gauche du PICO est la sortie de données vers les WS2812B (GPIO0)

Le DIP Switch en bas à droite est relié au PICO. Les fils partant vers le ruban de LED (avec la prise récupérée en bout du ruban) entrent par un trou (en bas à gauche).

En bas à gauche le boîtier en cours de montage. A droite la breadboard et la plaque proto qui ont servi pour la mise au point du prototype. Au fond le Raspberry Pi 4 que j’utilise pour programmer les PICO.

En bas on voit la prise 3 broches qui servira à raccorder le ruban de LEDs.

 

Quelques tests avec l’alimentation DC/DC (sa LED bleue est allumée et la tension est OK). Le port USB est relié au Raspberry Pi 4.

Pour fixer le PICO j’avais prévu… des picots mais le diamètre des trous du PICO est tellement petit que le PLA n’est pas assez costaud et casse quand on met la prise micro-USB en place. Ca pousse sur le PICO et ça casse les picots. Du coup solution dégradée, un bout de double face sous le PICO 🙂  pas de problème, le dessous est complètement lisse…

Tout est en place, le ruban de LEDs est connecté… L’ensemble est alimenté par l’alimentation 5V/10A. Il va falloir coller la prise d’alim pour éviter qu’elle ne se promène.

Et les blocs de LEDs commencent à tomber et à rebondir. Presque prêt pour exposer ce projet à Nantes Maker Campus du 2 au 4 juillet. Si vous passez par là, venez faire un tour su le stand….

Conclusion

Voilà un petit projet sympa qui met en œuvre peu de composants et… pas très cher à réaliser.

On arrive à un prix de 44 € pour ce projet qu’on pourrait mettre au programme d’un FabLab ou d’une association. Au delà de la réalisation, il faut noter la mise en oeuvre d’un certain nombre de connaissances et compétences qui seront plus ou moins approfondies ou partagées selon le cas. Je les ai notées au fur et à mesure de la réalisation mais ce n’est pas exhaustif :

  • Bases d’électronique (courant, diode…)
  • Microcontrôleur (GPIO, RESET, programme MicroPython)
  • Diodes LEDs adressables WS2812B
  • Modélisation d’un boîtier en 3D (Fusion 360, FreeCAD)
  • Utiser un Slicer pour préparer l’impression 3D (CURA)
  • Utiliser une imprimante 3D (principe, choix du métériau, lancement d’une impression…)
  • Savoir souder (principe, étamage, brasure…)
  • Ajouter une bibliothèque microPython sur le Pico
  • Programmer (MicroPython, lire un programme, le modifier, créer un programme)
  • Créer un schéma
  • Lire un schéma
  • Notions de binaire, hexadécimal
  • Bases de colorimétrie (RVB, R+V, R+B…)
  • Démarrer un programme automatiquement sur Pico (main.py)

De quoi animer quelques séances dans un club ou un FabLab… avec un projet pratique en ligne de mire. Après on peut se contenter de créer un « Kit » de découverte. En tout cas vous avez les billes dans cet article (et le précedent) pour le faire.

N’hésitez pas à faire part de vos remarques dans les commentaires ci-dessous.

Sources

Ce projet est développé sur la base d’une publication de KenKenMkIISR et du programme qu’il a publié sur github. Un grand merci à lui.

À propos François MOCQ

Électronicien d'origine, devenu informaticien, et passionné de nouvelles technologies, formateur en maintenance informatique puis en Réseau et Télécommunications. Dès son arrivée sur le marché, le potentiel offert par Raspberry Pi m’a enthousiasmé j'ai rapidement créé un blog dédié à ce nano-ordinateur (www.framboise314.fr) pour partager cette passion. Auteur de plusieurs livres sur le Raspberry Pi publiés aux Editions ENI.

2 réflexions au sujet de « Faites rebondir les LED avec le Raspberry Pi Pico (Episode 2) »

  1. Antoine MERCIER

    Salut!
    Une micro-erreur s’est glissée dans le cahier des charges  😉

    Alimentation de l’ensemble par alimentation 5V/10A (et non 10V)

    Merci pour l’article !

    Répondre
  2. Ping : Réalisation d'un circuit imprimé PCB pour les LED bondissantes sur PCBgogo - Framboise 314, le Raspberry Pi à la sauce française....

  3. Ping : Visualiseur de GERBER et promo sur les circuits imprimés chez JLCPCB - Framboise 314, le Raspberry Pi à la sauce française....

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Complétez ce captcha SVP *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.