Communication en temps réel entre 120 RGBW Neopixel <=> Arduino

Bonjour à tous! Avant de donner plus de détails sur ma question je vous présente rapidement mon projet.
Ma réalisation en cours est un Photo Booth qui intègre un système d'éclairage utilisant les LEDS RGBW Neopixel. Il y a 8 rectangles de 15 LEDS + un Ring de 12 LEDS pour un beau total de 134 LEDS :).
Actuellement tout fonctionne super bien. J'ai créer des scénarios directement dans un Arduino Uno pour déclencher des effets, par exemple lors de la prise photos.

Mon objectif : Souhaitant aller plus loin dans le développement de ce projet je cherche un réaliser une communication en temps réel entre l'arduino et mon programme. Si j'arrive à faire une communication temps réel je pourrais par exemple ressortir les couleurs dominante sur la caméra pendant la prise de vus les diffuser sur les LEDS :smiley:

Mon expérimentation : Je fonctionne actuellement avec une application développé en Node (Javascript) et j'utilise Serialport pour la communication. Mon idée de base ne paraissait pas mauvaise : Transmettre à l'arduino l'information des LEDS qui changes, ex : 02,150,20,20 (Id, R, G, B). Mais je me suis très vite heurter au soucis de la quantité de données transféré qui fut vite saturé et donc impossible de faire du temps réel sur 134 LEDS!

Des idées? : Je suis donc la pour avoir un peu d'aide afin de pousser la réflection plus loin :slight_smile: Je suis tout à fait ouvert à changer hardware et software (sauf le système d'exploitation) pour réussir mon objectif. Pour vous donnez un exemple je travail parfois avec le logiciel LightJams (https://www.lightjams.com) qui fait exactement ce que je souhaite faire. Le soucis est que le logiciel ne tourne que sous windows et mon Photo Booth tourne sur Linux. d'où mon ambition de développer par moi même de quoi :smiley: Ça me fait pensais que je n'ai pas regarder si il existais des équivalents sur linux :o Je vais continuer mes investigations!

Si il manque de précision n'hésitez pas à me demander et si vous avez des idées / pistes je suis preneur! Merci d'avance!

Superbe ! Bravo.

Par contre, je n'ai pas compris ce que tu veux faire avec l'Arduino, ni ce que fait le code sous Linux...

Pour contrôler des LEDs adressables type WS2812 sur Arduino, je pense que la meilleure bibliothèque est Fastled. Elle est un peu complexe à prendre en main, mais quand on a compris le principe d'utilisation, elle est très rapide te très puissante.

Il est beau ton bidule, mais j'ai pas compris grand-chose.
Tu parles de photo, il y a un capteur photo dans le rond au dessus? C'est lui qui donne aux leds leur couleur?

La captation des couleurs avec la caméra est un idée que je veux développé après avoir rendu la communication en temps réel entre mon application développé avec Node (javascript) et l'arduino uno.

Mon but est tout simplement être capable de communiquer en temps réel. Donc envoyer en continue 134* 4 = 536 bytes avec Serialport :slight_smile:

Sinon oui pour la précision il y bien une camera dans le rond au dessus, mais il ne fait pas parti de l'équation pour le moment :stuck_out_tongue:

Fastled ma l'air très intéressant! Je vais regarder cela de plus proche!

Bon j'ai regardé FastLed et malheureusement pour le moment ce n'est pas compatible avec le RGBW :confused:

fiouuuuu… Ce ne fut pas une mince affaire mais j’ai une ébauche fonctionnelle de ce que je voudrais faire.
La majorité de mes soucis provenais du transfert d’information entre nodejs et l’arduino via serial port.
J’ai pris le temps d’aller cherche de l’information et j’ai trouvé comment transférer en hexadecimal mes valeurs pour ne prendre que 5 Bytes par LED (Id, Red, Blue, Green, White)

Coté Javascript :

Pour mon test je suis parti avec l’envoi des informations pour 5 LEDS par paquets. Comme la limite est de 36 bytes par paquet pour l’arduino j’ai créé un buffer avec 30 bytes (6x5) donc 5 LEDS

function sendLEDS(indexStart){
  var buffer = new Buffer(30);
  var idLed = indexStart;
  var r = increase, g=0,b=increase ,w=0
  for (var i = 0; i < 30; i=i+5) {
    //72 : 7*5
    buffer[i] = "0x"+idLed.toString(16);
    buffer[i+1] = "0x"+r.toString(16);
    buffer[i+2] = "0x"+g.toString(16);
    buffer[i+3] = "0x"+b.toString(16);
    buffer[i+4] = "0x"+w.toString(16);
    // console.log(idLed+" : "+r+"-"+g+"-"+b+" : "+w);
    // console.log(buffer);
    idLed++;
  }
  return buffer;
}

Par la suite je fait la transmission des paquets au 30 MS. SendLeds et la fonction juste au dessus qui retourne le buffer mesurant 30 BYTES.

      setInterval(function(){
        for (var i = 0; i < nbLeds; i= i+6) {
          port.write(sendLEDS(i),function(err){
            if(err) return console.log(err);
          });
        }
      },30);

Coté Arduino :
La partie un peu plus compliqué, qui fonctionne pour le moment mais qui mériterais certainement d’être amélioré :smiley: Je ne mettrais pas le code au complet mais juste les parties importantes pour avoir vos avis

Réception des paquets, rien de particulier dans cette partie :

void serialEvent() {
   while (Serial.available () > 0){
        processIncomingByte (Serial.read ());
   }
}

Comme les paquets à la reception suivent toujours le même ordre : ID - R - G - B - W
j’incréments ma valeur pos et lorsque j’atteint le White, j’utilise les valeurs pour Définir les couleurs de ma LED et par la suite lorsque j’ai reçu les informations de toutes les LEDS (maxLedsUpdate) J’actualise la strip de LED pour afficher les couleurs.

int pos = 0;
int idLed = 0;
int nbLedsUpdate = 0;
int maxLedsUpdate = 120;
int R,G,B,W = 0;

void processIncomingByte (const byte inByte) {
 
  if(pos == 0) idLed = inByte;
  if(pos == 1) R = inByte;
  if(pos == 2) G = inByte;
  if(pos == 3) B = inByte;
  if(pos == 4){
    W = inByte;
    //Set value of the Pixel 
    strip.setPixelColor(idLed, strip.Color(R,G,B, neopix_gamma[W] ) );
    pos = 0;
    nbLedsUpdate++;
    //When reach maximum LED : update all the strip and reset
    if(nbLedsUpdate >= maxLedsUpdate){
       strip.show();
       nbLedsUpdate = 0;
    }
  }else{
    pos++;
  }
}

Ce n’est certainement pas la manière la plus élégante mais ça fonctionne pour le moment. Je laisse actuellement tourner depuis 30 minutes et je n’ai pas eu d’issue.

Autre points important j’ai mis le baudRate à 1000000 afin d’être capable de recevoir correctement les paquets. En dessous je me retrouvais avec des glitch :confused:

Voilà pour moi c’est un bon début mais j’aimerais améliorer le code. Si vous avez des suggestions n’hésitez pas!