LEDs RGB Pilotables

Exemple d’un arc de cercle de 15 LEDs (4 arcs de cercle = 60 Leds… = 1 heure ?)

LED WS2812

Les LEDs de type WS2812 sont la combinaison de 3 LEDs trichromes (rouge, verte et bleue) et d’un circuit de commande numérique (registres à décalage et PWM pour chacune des couleurs).

Elles se pilotent donc en numérique par le biais d’une trame binaire de 8 bits par couleur (vert, rouge, bleu – 256 niveaux par couleur), soient 24 bits au total.

Les ‘0’ et les ‘1’ sont codés de la façon suivante :

Les temps haut et bas sont quantifiés : T0H = 0.35us / T0L = 0.8us / T1H = 0.7us / T1L = 0.6us / RES > 50 us.

L’intérêt de ces modules de LED est la possibilité de les mettre en cascade :

Ainsi, on peut transmettre une suite de N x 24 bits successifs pour pouvoir contrôler l’intégralité des N LEDs.

ATTENTION Il existe des matrices de LED basées sur des LED de type SK6812, qui se programme de la même façon que les WS2812, à ceci prêt qu’il faut envoyer 32 bits par LED et non 24 bits. Le dernier octet à émettre est vide (‘0’), mais il faut l’émettre 🙂

Utilisation sous MBED

L’exemple d’application suivant est réalisé autour d’une carte Nucléo L476RG : https://os.mbed.com/teams/IOGS_France/code/EITI_Neopixel/

Bibliothèques nécessaires

Pour pouvoir utiliser cet exemple, les deux bibliothèques suivantes sont nécessaires (à importer) :

Bibliothèque PixelArray

La bibliothèque PixelArray permet de créer et de mettre à jour un tableau de pixels de 3 octets (RGB).
Il est créé à l’aide de la commande suivante :

PixelArray px(10);

L’objet px est alors un tableau de 10 pixels contenant chacun les champs : (R)ed (B)lue (G)reen.

Il est alors possible de modifier chacun de ces pixels à l’aide de 3 fonctions :

void SetR(int i, int val);
void SetB(int i, int val);
void SetG(int i, int val);

qui permettent respectivement de changer la couleur rouge (SetR), la couleur bleu (SetB) et la couleur verte (SetG) de la LED numéro i (la première ayant le numéro 0 et la dernière N-1) avec la valeur val comprise entre 0 et 255 (0 = 0% – 255 = 100%).

Par exemple, pour mettre la couleur R = 20% – B = 40% – G = 20% sur la troisième LED, on peut utiliser les instructions suivantes :

px.SetR(2, 20*255/100.0); px.SetB(2, 40*255/100.0); px.SetG(2, 20*255/100.0);

Sur les versions White des LED, la fonction SetI permet de rajouter du blanc.

Il est également possible d’aller lire chacune des valeurs des pixels grâce aux commandes :

int GetR(int i);
int GetB(int i);
int GetG(int i);

qui permettent respectivement de récupérer la couleur rouge (SetR), la couleur bleu (SetB) et la couleur verte (SetG) de la LED numéro i (la première ayant le numéro 0 et la dernière N-1).

Pour récupérer la valeur rouge de la 5ème LED, il faudra par exemple faire :

int k = px.GetR(4);

Bibliothèque WS2812

La bibliothèque WS2812 permet de mettre à jour la matrice de LED en respectant le protocole demandé par le fabricant de ces LED.
Il est créé à l’aide de la commande suivante :

WS2812 ws(D9, NB_LED, 3, 12, 9, 12);

L’objet ws permet alors de piloter un bandeau de NB_LED LEDs sur la broche D9 de la carte Nucléo. Les valeurs qui suivent permettent de respecter les contraintes de temps imposées par le fabricant pour la carte Nucléo L476RG.

Pour les versions White des LED, il est nécessaire d’utiliser la bibliothèque WS2812 modifiée et d’ajouter le paramètre 1 à la fin de l’initialisation.

WS2812 ws(D9, NB_LED, 3, 12, 9, 12, 1);

Il est indispensable d’initialiser la matrice à l’aide de la commande suivante :

ws.useII(WS2812::GLOBAL);

pour pouvoir modifier de manière globale la luminosité de l’ensemble des LEDs.

On peut alors utiliser la commande suivante pour modifier globalement l’intensité des LEDs avec une valeur val comprise entre 0 et 255 :

void setII(int val);

Par exemple, pour limiter la luminosité à 100 sur 255 l’intensité du bandeau, on peut utiliser la commande suivante :

ws.setII(100);

Enfin, il faut pouvoir transmettre l’ensemble des informations aux différentes LEDs. Pour cela, il faut utiliser la fonction suivante :

void write(int tab[]);

où le paramètre est un tableau de N entiers, pouvant correspondre à un objet de type PixelArray.

Exemple d’application

Ne prêtez pas attention à mes qualités d’artiste pour ce code… Je me suis contenté de faire un exemple fonctionnel sur un arc de cercle de 15 LED.

Jpeg

Pour la partie artistique, laissez libre cours à votre imagination… Et n’hésitez pas à m’envoyer vos meilleurs programmes !

#include "mbed.h"
#include "PixelArray.h"
#include "WS2812.h"

#define NB_LED  15    // Nombre de LEDs en cascade

// Variables globales 
PixelArray px(NB_LED);           // Tableau de pixels / Nb de LEDs en cascade
// For Nucleo F476 : 3, 12, 9, 12
WS2812 ws(D9, NB_LED, 3, 12, 9, 12);    // Lien vers la série de LEDs / Sortie utilisée-Nb de LEDs
// NE PAS MODIFIER LES 4 DERNIERS PARAMETRES

int main() {
    int i, k = 0;
    ws.useII(WS2812::GLOBAL);  // Initialisation de la liaison avec les LEDs
    ws.setII(0);               // Luminosité maximale à 0/255
    
    // Reinitialisation ecran
    for (i = 0; i < NB_LED; i++) {
        px.Set(i, 0);
    }  
    ws.write(px.getBuf());      // Mise à jour de la matrice
    ws.setII(30);               // Luminosité maximale à 30/255

    while(1) {
        for(i = 0; i < NB_LED; i++){
            px.SetR(i, k);
        }
        ws.write(px.getBuf());   // Mise à jour de la matrice
        if(k == 255) k = 0;
        else k++;
        wait_us(200000);               // 200 ms
    }
}
Nucléo – Utiliser des LEDs RGB pilotables indépendamment