FAST LED problème lenteur

Bonjour à vous la communauté.

Je me permets de vous adresser ce petit sujet car j'ai un soucis de lenteur sur mon projet.
Voila j'ai acquis 3 bandeaux de LED de type WS2812B ( 900 leds en tout )relié en série avec ajout de puissance sur chacun des bandeaux mais contrôlés avec une seule sortie.
J'ai un arduino ATMega 2560 avec une alimentation 5V 10A.
Mon programme s'effectue correctement mais lorsque je souhaite faire des effets de vague ou autre (voir mon programme ) cela s'effectue très lentement.
Auriez-vous une ptite idée ?

Hello to you community.

I take the liberty of addressing this little subject to you because I have a problem with the slowness of my project.
Here I have acquired 3 LED strips of the WS2812B type (900 LEDs in all) connected in series with addition of power on each strip but controlled with a single output.
I have an arduino ATMega 2560 with a 5V 10A power supply.
My program is done correctly but when I want to do wave effects or other (see my program) it is done very slowly.
Do you have any idea?

#include <FastLED.h>
#define DATA_PIN 6

#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS 844

#define BRIGHTNESS         200
#define FRAMES_PER_SECOND  220

CRGB leds[NUM_LEDS];

CRGBPalette16 paletterouge = CRGBPalette16 (
    CRGB::Red,
    CRGB::Red,
    CRGB::Red,
    CRGB::Red,
    
    CRGB::GhostWhite ,
    CRGB::GhostWhite ,
    CRGB::Red,
    CRGB::GhostWhite ,
    
    CRGB::GhostWhite ,
    CRGB::GhostWhite ,
    CRGB::Red,
    CRGB::Red,

    CRGB::Red,
    CRGB::Red,
    CRGB::GhostWhite ,
    CRGB::Red
);

CRGBPalette16 palettebleue = CRGBPalette16 (
    CRGB::Blue,
    CRGB::Blue,
    CRGB::Blue,
    CRGB::Blue,
    
    CRGB::White,
    CRGB::White,
    CRGB::Blue,
    CRGB::White,
    
    CRGB::White,
    CRGB::White,
    CRGB::Blue,
    CRGB::Blue,

    CRGB::Blue,
    CRGB::Blue,
    CRGB::White,
    CRGB::Blue
);
uint16_t hue = 0;
uint16_t paletteIndex = 0;
uint16_t colorIndex[NUM_LEDS];

void setup() {
  fill_solid(leds,NUM_LEDS,CRGB (0,0, 0));
  delay(5000); // 3 second delay for recovery
  
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

  FastLED.setBrightness(BRIGHTNESS);
}

typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {Vague_Bleue_Blanc,Scintillement,Vague_Rouge_Vert,Scintillement,Defilement,Scintillement,bpm,Scintillement,juggle,Scintillement,sinelon};

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0;

void loop() {
  gPatterns[gCurrentPatternNumber]();
  FastLED.show();  

  //FastLED.delay(1000/FRAMES_PER_SECOND); 

  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
  EVERY_N_SECONDS( 120 ) { nextPattern(); } // change patterns periodically
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
////////////////////////////////////////////////////////////////////////////////////
void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(random8(200,255), 200, 255);
    dothue += 32;
  }
}

void bpm()
{
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
  uint8_t BeatsPerMinute = 62;
  CRGBPalette16 palette = paletterouge;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < NUM_LEDS; i++) { //9948
    leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
  }
}

void sinelon()
{
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16( 23, 0, NUM_LEDS-1 );
  leds[pos] += CHSV( random8(200,255), 255, 192);
}

void Scintillement() {
       // FastLED.setBrightness (255);
  FastLED.show();
leds[random(0,NUM_LEDS)]=CRGB::White;
leds[random(0,NUM_LEDS)]=CRGB::Blue;

   FastLED.show();
 fill_solid(leds,NUM_LEDS,CRGB (0,0, 0));
  // delay(1);
}

void Defilement() {
 // EVERY_N_MILLISECONDS(1) {
    // Create a new HSV color for led[0]
    leds[0] = CHSV(0, random8(), random8(100, 255));
    for (int i = NUM_LEDS - 1; i > 0; i--) {
      leds[i] = leds[i - 1];
    }
  FastLED.show();
//}
}

void Vague_Rouge_Vert () {
   uint16_t sinBeat   = beatsin16(30, 0, NUM_LEDS - 1, 0, 0);
   uint16_t sinBeat2  = beatsin16(30, 0, NUM_LEDS - 1, 0, 21845);
   uint16_t sinBeat3  = beatsin16(30, 0, NUM_LEDS - 1, 0, 43690);
    uint16_t sinBeat4  = beatsin16(30, 0, NUM_LEDS - 1, 0, 31845);

  leds[sinBeat]   = CRGB::Red;
  leds[sinBeat2]  = CRGB::Green;
  leds[sinBeat3]  = CRGB::Red;
  leds[sinBeat4]  = CRGB::Green;
  
  fadeToBlackBy(leds, NUM_LEDS, 10);

  FastLED.show();
}

void Vague_Bleue_Blanc() { //defilment couleur palette
  fill_palette (leds, NUM_LEDS, paletteIndex, 255 / 100, palettebleue, 255 , LINEARBLEND);
  //  EVERY_N_MILLISECONDS(1){
    paletteIndex++;
 // }
  FastLED.show();
}

Bonjour,
Avant tout, il est urgent de lire le message épinglé et de l'appliquer à ta demande.
Merci

Dans le setup, déplace fillsolid après addled
Dans tes fonctions d'animation, enlève les fastled.show

Merci beaucoup pour ton retour.
Effectivement j'ai gagné un peu en rapidité mais 900 leds ça l'air d'être de trop pour la CPU, pourtant en mémoire dynamique je ne suis qu'à 37%......

Alors essaye de déclarer plusieurs rubans. Chaque ruban aura sa Pin de commande et son array led1, led2, etc.
Ce sera comme si tu faisais du parallèle

Je ne pense pas que ce soit un problème pour le CPU. Pour chaque led, il faut envoyer 3 octets pour les 3 couleurs sans compter les bits de contrôle. Pour un ruban de 900 leds, il faut donc envoyer 2700 bits. La doc dit:

Le CPU va donc envoyer les infos en 3,4ms. Et il ne peut pas faire beaucoup mieux ou beaucoup moins (on pourrait jouer sur la tolérance). Avec un CPU 1000 fois plus rapide, cela prendrait aussi 3,4ms.

Bon. ça c'est pour l'envoi. Mais il y a aussi la préparation de la couleur. Et si on y met des random, cela va prendre beaucoup de temps.

Si on rafraîchit les rubans les uns après les autres, le temps de préparation sera inchangé et le temps d'envoi aussi. Pour y gagner, il faudrait envoyer les données en même temps. Je ne pense pas que la bibliothèque le fasse.

Comme les leds sont chainées je pensais que c'était dû au temps de passage d'une led à l'autre, et qu'en attaquant par plusieurs endroits on réduirait ces temps.

De mémoire je crois qu'il faut environ en moyenne 30µs pour écrire les données d'une LED. donc pour envoyer un tableau tout prêt à tout le bandeau (900 pixels) il vous faut 27ms.

Ensuite bien sûr vous avez du code pour remplir votre tableau de leds. si vous avez des fonctions de calculs compliqués sur les couleurs (fade, conversion HSV vers RGB etc) vous allez aussi prendre du temps. disons 3 à 5ms

on est donc à 32ms

➜ au mieux, si votre code ne faisait rien d'autres vous pourriez obtenir une fréquence de rafraîchissement de ~30Hz.

Messieurs merci pour vos retours.
Avec le fait d'enlever le Fastled.show comme indiqué par lesept j'ai déjà gagné pas mal en temps.
De tout mon code de programmation c'est le code ci-dessous qui me prend énormément de temps.
Effectivement je pense que c'est le fait de recopier la couleur pour la led suivante qui doit prendre du temps, car si je mets 300 leds cela passe à une vitesse folle et plus j'en ajoute plus cela mets du temps.
Je n'ai malheureusement pas trop de possibilité pour mon problème j'ai l'impression.

void Defilement() {
 // EVERY_N_MILLISECONDS(1) {
    // Create a new HSV color for led[0]
    leds[0] = CHSV(0, random8(), random8(100, 255));
    for (int i = NUM_LEDS - 1; i > 0; i--) {
      leds[i] = leds[i - 1];
    }
//}
}

Bonjour,

Pour accélérer un peu les choses tu peux utiliser memmove
memmove(leds+1,leds,sizeof leds-sizeof leds[0]);

Mais je ne suis pas certain que ce soit ça qui provoque la lenteur mais plutôt la transmission du tableau leds[] aux leds neopixel

Je ne comprend pas bien ce que tu veux faire. L'affectation de la nouvelle couleur à leds[0] devrait être faite après le décalage et non avant.

Le souci de ce genre de LED c’est que le temps d’affichage est proportionnel au nombre de LEDs et qu’il est fixé par LED - il ne s’agit généralement pas du temps mis pour construire le tableau de LEDs (qu’on pourrait résoudre en passant sur un processeur plus rapide). En plus le rafraîchissement met de la pression sur les interruptions ce qui a des conséquences potentiellement néfastes pour le reste du code.

Ce sont les principales raisons pour lesquelles je prends des APA102 pour les longs bandeaux. C’est plus cher mais on n’a pas ces soucis. (Les SK9822/APA102C seront moins chères)

Une approche sinon consiste à couper la strip en plusieurs sous strips de manière à minimiser le temps d’affichage et de ne mettre a jour que les bandeaux qui en ont besoin (si l’animation le permet)

Un article qui résume les bandeaux

Bien choisir sa bande de LEDs pour faire de l'Ambilight - Site de ambimod !!!

Merci pour vos retours, c'est gentil.

Je vais essayer la méthode que tu m'as indiqué Kamill voir si cela joue en ma faveur.
En faite ce que je souhaite faire c'est un défilement de couleur aléatoire entre le blanc et le rouge sur toute la longueur.
Du coup mon programme fonctionne à merveille mais il part de 0 pour pouvoir aller jusqu'à la fin de mon bandeau et par la suite défiler à l'infinie...
Du coup cela mets du temps à arriver jusqu'au bout, je t'avoue que je n'arrive pas à le faire partir de la fin .....

Effectivement J-M-L j'avais pensé à ta solution mais comme tu dis j'ai une animation qui va de bout en long et du coup je suis bloqué....
Je vais regarder la marque de tes LEDS l'article que tu m'as envoyé à l'air sympa.

Petite question je bloque sur un autre truc, je souhaite afficher 4 couleurs différentes , et le tout répété sur toutes la longueurs de la bande j'ai essayé tout un tas de commande mais impossible pour moi , pourtant cela parait simple mais je n'y arrive pas vous auriez une idée ?

Tu veux faire des groupes {couleur 0, couleur 1, couleur 2, couleur 3} périodiques ?
Tu peux faire ça avec une boucle :

  • Tu fais une boucle sur i qui va de 0 à numleds/4
    • Tu copies dans numled(4i) la valeur couleur0 <-- '4i' vaut 4 fois i
    • Tu copies dans numled(4i+1) la valeur couleur1
    • Tu copies dans numled(4i+2) la valeur couleur2
    • Tu copies dans numled(4i+3) la valeur couleur3
  • Et tu termines avec le reste :
  • Pour i = 0 à numleds%4
    • leds[4*(numleds/4)+i] = leds[i];

A tester...

Si par défilement vous voulez dire qu'il n'y a que quelques LEDs qui sont allumées et elles avancent sur le bandeau et si vous pouvez couper le bandeau en 2 et mettre l'arduino au milieu alors ça ce gère en logiciel pour calculer sur quel bandeau sont les pixels allumés - avec un petit cas particulier au milieu

Merci messieurs pour tous vos conseils.
Je vais me contenter de faire que certains effets sur mes bandeaux :wink:
Il faudra peut être que je vois autrement l'année prochaine pour un autre système du coup.