Amiblight avec Arduino et ruban WS2811S
Rédigé par SuperGNU Aucun commentaireIntroduction
J'ai récupéré à mon club robotique un grand morceau de ruban de LED RGB inutilisé. J'ai eu l'idée d'en faire un clone d'ambilight (lumière d'ambiance adaptative au contenu de l'écran) pour mon grand écran de PC. Je pensais qu'avec quelques lignes de Python et une Arduino le problème serai vite réglé. J'ai en fait rencontré deux principaux obstacles, la génération d'une consigne pour le ruban et le pilotage du ruban en lui-même. Je poste donc ici la solution si jamais quelqu'un rencontre le même problème.
Génération de la consigne
Je pensais naïvement que la détermination de la couleur moyenne d'une image se faisait simplement en faisant une moyenne par composante de chaque pixel d'une image. PAS DU TOUT ! ;-)
La couleur obtenue avec cette technique étant désespérément gris~marron, j'ai réfléchi un peu et je me suis rendu compte que le mieux était non pas de faire la moyenne des couleurs mais de chercher la couleur dominante de l'image pour déterminer la couleur de l'ambiance. Là encore, ce n'est pas facile à déterminer, comme l'explique assez bien ce site, la détection de la couleur perçue comme étant la couleur dominante est plus compliqué que de chercher la couleur la plus présente dans l'image. Au passage un autre [site intéressant]( http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/) sur la question présentant un algorithme un peu différent et la bibliothèque que j'ai utilisé en python pour faire mes tests.
In fine (on ne dit pas au final ...;-)), j'ai réussi à avoir un programme donnant des résultats satisfaisants pour une capture d'écran et là .... katastroph ! Lorsque je fais boucler le script, pour prendre une capture, analyser, envoyer la couleur au ruban la couleur n'est mise à jour qu'un peu plus d'une fois par seconde et un cœur de mon processeur est monopolisé à 100%. Même en optimisant le code et en repartissant sur plusieurs threads pour améliorer l'utilisation des cœurs, je sentais que mon script resterait lent et consommateur de ressources. Avant d'envisager la réécriture en C, j'ai voulu regarder "ce qui ce faisait ailleurs et comment ça ce faisait" (Note à moi-même : la prochaine fois, COMMENCER par étudier l'état de l'art !).
Je suis tombé (sans me faire mal !) sur le projet Adalight (Opensource !) qui bien que n'étant pas compatible avec mon ruban (évidement, c'est compatible avec leur ruban :-)) correspondait exactement à ce que je souhaitais faire. Avec en plus comme bonus non négligeable la gestion du multi-écran et le traitement de l'image de l'écran de façon à faire correspondre la couleur du morceau de ruban avec la couleur du bout d'écran accolé (pas clair) ce qui correspondait à la deuxième étape (laborieuse) de mon projet. Le script tournant sous processing, il était donc de plus théoriquement compatible Linux (évidement) et Windows ce qui pouvait être sympa pour quand je reboot sous Windows. Lien du dépôt Github avec le code J'ai donc décidé d'utiliser le script d'Adafruit avec quelques modifications.
ATTENTION : Ce script ne fonctionne correctement qu'avec Processing 2.X.X Personnellement je n'ai aucun soucis avec Processing 2.2.1, il ne fonctionne par contre plus avec Processing 3.
Pilotage du ruban
Ayant décidé d’utiliser le code d'Adalight, il me fallait du coup coder un script Arduino compatible avec le WS2811, le driver de mon ruban. Le script d'Adalight permettait le controle d'un ruban en SPI tandis que le WS2811 se comporte plutôt comme un shift register. Le code est fortement inspiré du code original d'Adafruit et d'exemples d'utilisation de la librairie FastLed trouvés sur internet (je sais plus ou :-°). Les deux scripts dans le dépôts fonctionnement parfaitement ensemble, si vous cherchez à faire un Adalight, vous ne devriez avoir à modifier que la définition de votre écran dans le script Processing. Lien du dépôt Github avec le code
Conclusion
Une petite vidéo de démonstration (Adalightception) : https://youtu.be/6d2rLEUgs84
Sur mon i5 de 4ème génération, le programme consomme environ 10% de ressources, c'est beaucoup mais ça reste raisonnable et surtout le rafraîchissement est plutôt rapide (comme on peut le voir dans la vidéo).