Même animation sur plusieurs bandeaux de LEDs

Bonjour ! :wink:

J'ai besoin de votre aide car je rencontre un problème qui, je l'espère, ne doit pas être compliqué à résoudre. Mais ça fait quelques années que je n'ai pas fait d'Arduino ou de C, donc je suis un peu perdu et ne trouve pas ma réponse. C'est pour un cadeau de Noël alors j'aimerais y arriver :christmas_tree:
Bref, voici mon montage. J'ai cinq bandeaux de LEDs, sur les PINs pairs 2 à 10.
Mes bandeaux de LEDs font 29 LEDs chacun, sauf un qui n'en fait que 28.
Je n'ai pour l'instant pas d'alimentation dédiée car le nombre de LEDs n'est pas immense.
J'aimerais tout simplement recréer l'animation suivante (avant de complexifier) :

Pour ce faire, l'idéal serait une boucle du type :

for(int i = NUM_LEDS_PER_STRIP-1; i >=0 ; i--) {
        leds[:][i] = CRGB::Yellow;
        leds[:][i-1] = CRGB::Yellow;
        leds[:][i-2] = CRGB::Yellow;
}

Mais je ne sais pas comment indiquer à l'Arduino de prendre toute la ligne du tableau leds (mes deux points ne fonctionnent pas). Quand j'essaye de le faire manuellement en indiquant 5 fois mes trois lignes de codes, le programme plante (avec un seulement, il marque une pause quand les LEDs ont parcouru une première fois le bandeau, ce qui n'est pas le cas quand je n'allume qu'une LED).

Je vous joins mon code complet ci-dessous pour y voir plus clair.

Merci énormément à tous ceux qui prendront un peu de temps pour m'aider !
Bonne journée à vous :slight_smile:

#include <FastLED.h>

#define NUM_STRIPS 5 // nombre de bandeaux
#define NUM_LEDS_PER_STRIP 29 // nombre de LEDs par bandeau
#define LED_TYPE NEOPIXEL // type de LEDs

struct CRGB leds[NUM_STRIPS][NUM_LEDS_PER_STRIP]; // initialise le tablelau (array) de LEDs
uint8_t hue = 0;

void setup() {
  delay(1000); // délai de 1s en cas de pic de tension au démarrage (protège LEDs)
  // ensuite, on déclare les bandeaux sur les PINs correspondants, chaque bandeau étant de type "leds" déclaré précedemment.
  FastLED.addLeds<LED_TYPE, 2>(leds[0], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<LED_TYPE, 4>(leds[1], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<LED_TYPE, 6>(leds[2], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<LED_TYPE, 8>(leds[3], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<LED_TYPE, 10>(leds[4], NUM_LEDS_PER_STRIP);

  FastLED.setBrightness(10); // on définit la luminosité
  }
  
void loop() {
    // This outer loop will go over each strip, one at a time
    //for(int k = 0; k < NUM_STRIPS; k++) {
      // This inner loop will go over each led in the current strip, one at a time
      for(int i = NUM_LEDS_PER_STRIP-1; i >=0 ; i--) {
        leds[0][i] = CRGB::Yellow;
        leds[0][i-1] = CRGB::Yellow;
        leds[0][i-2] = CRGB::Yellow;
        FastLED.show();
        leds[0][i+1] = CRGB::Black;
        leds[0][i] = CRGB::Black;
        leds[0][i-1] = CRGB::Black;
        delay(100);
      }
  }

Pour clarifier, comme je ne pouvais mettre qu'une image sur le message précédent, voici mon montage (j'utilise une Arduino Nano, et pas une R3) :

rassurez nous, vous n'utilisez pas vraiment le 5V de l'arduino pour les LEDs... ?

c'est quelque chose comme ça que tu cherche

Et si ! Apparemment j'ai tort... En tout cas, quand le bandeau n'était qu'un (144 Leds pour 1m), il n'y avait aucun problème...
Mais si c'est nécessaire je mettrai une alimentation externe.

J'étudie tout ceci, merci en tout cas !
Vu la simulation, ça a l'air d'être proche.

J'ai fait ça vite fait, il est possible que l'animation bug au borne :slight_smile:

Alors quand j'essaie le code, j'ai bien un problème (les deux LEDs rouges et jaunes identiques à l'animation restent allumées en permanence, mais pas les verte et bleue).
J'analyse tout ça !

Je pense que ça sera compliqué quand je voudrais modifier mon code pour ajouter des effets individuels, mais ça devrait le faire.
Du coup, pas de solution pour une notation du type

for(int i = NUM_LEDS_PER_STRIP-1; i >=0 ; i--) {
        leds[:][i] = CRGB::Yellow;
        leds[:][i-1] = CRGB::Yellow;
        leds[:][i-2] = CRGB::Yellow;
}

?

Merci encore :slight_smile:

Si tu veux faire des animations différentes en parallèle, je te conseillerais de passer par une machine à état.
@J-M-L a un lien sur un tutoriel concernant ce sujet.

Mais je pense qu'il vaut mieux y aller petit à petit.
Fait déjà marcher ton animation pour avoir une bonne idée de comment il faut procéder, puis petit à petit tu pourra passer sur une machine à état.
Une fois bien à l'aise avec ça, tu pourra facilement créer une deuxième animation s'exécutant en parallèle.

Sinon tu peux mettre ton code, car c'est difficile de te répondre, dans l'extraction de code, il n'y a que des LED jaunes :frowning:

1 Like

Finalement, sur la même simulation, ça plante quand j'ajoute un troisième bandeau, comme sur mon montage réel. Donc je ne sais pas si le problème est matériel et si sketch.ino arrive à le reproduire, ou si c'est le code que j'ai encore massacré, mais je suis perdu :joy:

Je ne connais pas les machines à état, je vais me renseigner sur le sujet. Mais effectivement, je vais commencer sur animation, je ne savais pas que cela existait !

En ce qui concerne mon "code", il n'y en a pas d'autre que celui que j'ai partagé pour l'instant... Je voulais juste savoir si je pouvais le condenser, mais finalement ma demande est stupide.

Merci encore beaucoup.

Avant de le condenser, il faudrait qu'il corresponde à ce que tu veux faire, notamment, l'animation circulaire.
Je ne sais pas si tu as vu mon code, il faut gérer les bornes des indices de tes LED.
si tu fait un for de NUMLEDS - 1 à 0, tu ne peux(doit) pas accéder au case 0-1 et 0-2

Après peut être tu ne veux pas que l'animation tourne en boucle?

cf mon tuto éventuellement

Tu veux dire que tu as alimenté 144 leds via l'Arduino :question: :question: :question:
Au minimum, c'est à dire avec une seule des 3 mini leds allumée (dans chaque boitier du ruban il y a 3 mini leds, rouge, verte et bleue) donc 20mA consommé par led du ruban, ça fait 144 * 0.02 = 2.88 A. Le pauvre Arduino peut fournir 200 mA sur sa sortie 5V donc il est peu probable que tu aies réussi à allumer les 144 leds!

Il te faut déjà faire une alimentation correcte pour tous tes rubans. Lis ceci (et les pages qui suivent) :

Ce schéma est important :

Il montre comment alimenter ton montage. Tu as besoin d'une alim 5V qui puisse fournir non pas 3A comme calculé au début mais jusqu'à 9A au cas où tu mets toutes tes leds en blanc en même temps. En effet dans ce cas, chaque mini led sera allumée, consommera 20mA soit 60mA pour chacune de tes 144 leds. Ca fait 8.7A au total, on arrondit à 9A.

Dans ton montage, tu mettras une capa au niveau du connecteur qui alimente l'ensemble, mais une résistance à l'entrée de chaque ruban.

Pour ton code, cette syntaxe n'existe pas en C, c'est plutôt du Python. Donc, tu dois faire une boucle imbriquée dans la boucle sur i, pour remplir la première dimension de chaque tableau.

for (int n = 0; n < NUM_STRIPS; n++) {
  for (int i = NUM_LEDS_PER_STRIP-1; i >=0 ; i--) {
        leds[n][i] = CRGB::Yellow;
        leds[n][i-1] = CRGB::Yellow;
        leds[n][i-2] = CRGB::Yellow;
  }
}

Il a la luminosité positionné à 10 sur 256, ça doit aider à limiter l'intensité

Mouais... J'ai pas de led sous la main, mais 10/256 ça fait pas beaucoup de luminosité...

un petit exemple qui doit ressembler à ce que vous voulez faire

lancez la simulation ➜


#include <FastLED.h>

CRGB s0[29];
CRGB s1[29];
CRGB s2[29];
CRGB s3[28];
CRGB s4[29];

CRGB* leds[] = {s0, s1, s2, s3, s4,};
constexpr byte nbStrips = sizeof leds / sizeof * leds;
constexpr byte pins[nbStrips] = {2, 4, 6, 8, 10};

struct Animation {
  CRGB couleur;
  unsigned long periode;
  const byte nbLeds;
  unsigned long chrono;
  byte position;
};

Animation animation[] = {
  {CRGB::Blue,  50, sizeof s0 / sizeof * s0},
  {CRGB::Blue, 100, sizeof s1 / sizeof * s1},
  {CRGB::White, 80, sizeof s2 / sizeof * s2},
  {CRGB::Red,   60, sizeof s3 / sizeof * s3},
  {CRGB::Red,   30, sizeof s4 / sizeof * s4},
};

void france() {
  fill_solid(s0, animation[0].nbLeds, CRGB::Blue);
  fill_solid(s1, animation[1].nbLeds, CRGB::Blue);
  fill_solid(s2, animation[2].nbLeds, CRGB::White);
  fill_solid(s3, animation[3].nbLeds, CRGB::Red);
  fill_solid(s4, animation[4].nbLeds, CRGB::Red);
  FastLED.show();
}

void eteindre() {
  for (byte i = 0; i < nbStrips; i++)
    fill_solid(leds[i], animation[i].nbLeds, CRGB::Black);
  FastLED.show();
}

void preparerUnPas(const byte index) {
  fill_solid(leds[index], animation[index].nbLeds, CRGB::Black);
  for (byte i = 0; i < 4; i++)
    if (animation[index].position + i < animation[index].nbLeds)
      leds[index][animation[index].position + i] = animation[index].couleur;
  animation[index].position++;
  if (animation[index].position >= animation[index].nbLeds) animation[index].position = 0;
}

void setup() {

  // on ne fait pas de boucle for car le template attend des expressions constantes
  FastLED.addLeds<WS2812B, pins[0], GRB>(s0, sizeof s0 / sizeof * s0);
  FastLED.addLeds<WS2812B, pins[1], GRB>(s1, sizeof s1 / sizeof * s1);
  FastLED.addLeds<WS2812B, pins[2], GRB>(s2, sizeof s2 / sizeof * s2);
  FastLED.addLeds<WS2812B, pins[3], GRB>(s3, sizeof s3 / sizeof * s3);
  FastLED.addLeds<WS2812B, pins[4], GRB>(s4, sizeof s4 / sizeof * s4);

  france();
  delay(1000);
  eteindre();
  for (byte i = 0; i < nbStrips; i++) animation[i].chrono = millis();
}

void loop() {
  bool affichageRequis = false;
  for (byte i = 0; i < nbStrips; i++) {
    if (millis() - animation[i].chrono >= animation[i].periode) {
      affichageRequis = true;
      preparerUnPas(i);
      animation[i].chrono = millis();
    }
  }
  if (affichageRequis) FastLED.show();
}

Bonsoir à tous !

@lesept
Je suis quasiment sûr de moi, même quand la luminosité n'était pas à 10/256... Mon Arduino était connectée via USB-C au PC, même si je pense que ça ne change pas grand chose.
Je notre pour la résistance et le condensateur, j'imagine que c'est pour lisser ?
Je note aussi pour la boucle !
Merci beaucoup

@J-M-L
Merci pour le lien vers le tuto, ça me sera bien utile quand j'aurai mes différents bouts de code pour les différentes animations !
Et merci encore plus pour le code, c'est effectivement très proche de ce que je voudrais ! Je ne suis plus familié avec les structures mais je vais étudier tout ça. :slight_smile:

amusez vous bien :slight_smile:

1 Like

Si c'est la même animation sur les 5 bandeaux, il devrait suffire de brancher les bandeaux ainsi:
image
Et de programmer comme si il n'y avait qu'un seul ruban. Non?

Enfin sauf l'alim....

1 Like