Actions simultanées dans une Boucle sur plusieurs PIN

Bonjour ,

Je souhaiterais effectuer un Groupe d'actions dans ma Boucle , actuellement je passe un élément après l'autre mais je souhaiterais effectuer 3 actions identique sur 3 pin différents au même moment , avez bous une idée de comment écrire ce code ?

Merci d'avance

#include <FastLED.h>


#define NUM_LEDS1 31
#define NUM_LEDS2 31
#define NUM_LEDS3 28
#define NUM_LEDS4 38
#define NUM_LEDS5 170
#define NUM_LEDS6 25
#define NUM_LEDS7 24

#define DATA_PIN2 2
#define DATA_PIN3 3
#define DATA_PIN4 4
#define DATA_PIN5 5
#define DATA_PIN6 6
#define DATA_PIN7 7
#define DATA_PIN8 8




#define BRIGHTNESS 160 //luminosité entre 0 et 255.


CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
CRGB leds3[NUM_LEDS3];
CRGB leds4[NUM_LEDS4];
CRGB leds5[NUM_LEDS5];
CRGB leds6[NUM_LEDS6];
CRGB leds7[NUM_LEDS7];





void setup() {

  FastLED.addLeds<WS2812B, DATA_PIN2, GRB>(leds1, NUM_LEDS1).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN3, GRB>(leds2, NUM_LEDS2).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN4, GRB>(leds3, NUM_LEDS3).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN5, BRG>(leds4, NUM_LEDS4).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN6, GRB>(leds5, NUM_LEDS5).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN7, BRG>(leds6, NUM_LEDS6).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN8, BRG>(leds7, NUM_LEDS7).setCorrection(TypicalLEDStrip);

  pinMode(DATA_PIN2, OUTPUT); // la broche led (2) est initialisée en sortie BRANCHE 1
  pinMode(DATA_PIN3, OUTPUT); // la broche led (3) est initialisée en sortie BRANCHE 2
  pinMode(DATA_PIN4, OUTPUT); // la broche led (4) est initialisée en sortie BRANCHE 3
  pinMode(DATA_PIN5, OUTPUT); // la broche led (5) est initialisée en sortie BRANCHE 4
  pinMode(DATA_PIN6, OUTPUT); // la broche led (6) est initialisée en sortie BRANCHE 5
  pinMode(DATA_PIN7, OUTPUT); // la broche led (7) est initialisée en sortie BRANCHE 6
  pinMode(DATA_PIN8, OUTPUT); // la broche led (8) est initialisée en sortie BRANCHE 7




  FastLED.setBrightness(BRIGHTNESS);

  digitalWrite(DATA_PIN2, LOW); // Eteindre PIN 2
  digitalWrite(DATA_PIN3, LOW); // Eteindre PIN 3
  digitalWrite(DATA_PIN4, LOW); // Eteindre PIN 4
  digitalWrite(DATA_PIN5, LOW); // Eteindre PIN 5
  digitalWrite(DATA_PIN6, LOW); // Eteindre PIN 6
  digitalWrite(DATA_PIN7, LOW); // Eteindre PIN 7
  digitalWrite(DATA_PIN8, LOW); // Eteindre PIN 8



}

void loop() {


  //DEBUT ALLUMAGE

  for (int i = 31; i >= 0; i--) {
    leds1[i - 4] = CRGB::White;
    FastLED.show();
    delay(15);
    leds1[i] = CRGB::Black;
    FastLED.show();
  }

  for (int i = 31; i >= 0; i--) {
    leds2[i - 4] = CRGB::White;
    FastLED.show();
    delay(15);
    leds2[i] = CRGB::Black;
    FastLED.show();
  }

  for (int i = 28; i >= 0; i--) {
    leds3[i - 4] = CRGB::White;
    FastLED.show();
    delay(15);
    leds3[i] = CRGB::Black;
    FastLED.show();
  }

  for (int i = 38; i >= 0; i--) {
    leds4[i - 4 ] = CRGB::White;
    FastLED.show();
    delay(15);
    leds4[i] = CRGB::Black;
    FastLED.show();
  }

  for (int i = 29; i >= 0; i--) {
    leds5[i - 4 ] = CRGB::White;
    FastLED.show();
    delay(15);
    leds5[i] = CRGB::Black;
    FastLED.show();
  }

  for (int i = 25; i >= 0; i--) {
    leds6[i - 4 ] = CRGB::White;
    FastLED.show();
    delay(15);
    leds6[i] = CRGB::Black;
    FastLED.show();
  }

  for (int i = 24; i >= 0; i--) {
    leds7[i - 4 ] = CRGB::White;
    FastLED.show();
    delay(15);
    leds7[i] = CRGB::Black;
    FastLED.show();
  }

}

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

il faut définir au même moment - est-ce que quelques dizaine de micro-secondes d'écart est un souci ?
si ce n'est pas un soucis vous faites vos 3 digitalWrite() les uns à la suite des autres
si c'est un souci, il faut regarder de plus près les registres des ports I/O, sur un AVR on peut commander l'état de 8 pins du même port d'un seul coup

https://docs.arduino.cc/hacking/software/PortManipulation

si c'est pour faire vos affichages de LEDs et que les 3 animations soient en simultanées, ce n'est pas juste du contrôle de pin mais la logique d'affichage

regardez comment utiliser millis Using millis() for timing. A beginners guide et Several things at the same time

c'est une définition de programme qui se prête bien aussi à la programmation par machine à états (cf mon tuto éventuellement)

Non cela n'est pas un soucis pour le décalage de quelques microsecondes , je vais essayer de voir comment je pourrais écrire le programme

@J-M-L , je suis entrain de faire des essais pour réaliser dans ma boucle un FOR qui accepte plusieurs sortie en même temp mais mon programme n'est pas valide aurait-tu un exemple de comment écrire cela ?

merci

un exemple synchrone (qui va bien parce qu'il y a le même nombre de leds)

  for (int i = 31; i >= 4; i--) { // <== modifié car si on va plus loin que 4  i-4 devient négatif
    leds1[i - 4] = CRGB::White;
    leds2[i - 4] = CRGB::White;
    FastLED.show();
    delay(15);
    leds1[i] = CRGB::Black;
    leds2[i] = CRGB::Black;
    FastLED.show();
  }

pour l'usage de millis, faut lire les tutos existants et essayer

hello

:thinking:je suis surpris que tu puisses adresser une case de tableau : 0-4, je me demande si dans ce cas là, tu ne vas pas ecrire nimporte ou dans la memoire. à ce qui est ecrit 4 adresses avant l'adresse de la case 0 du tableau :thinking:

sinon, meme réponse que jml
voir l'exemple multi Arrays, s'il y a le meme nombre de leds dans les differentes branches

// MultiArrays - see https://github.com/FastLED/FastLED/wiki/Multiple-Controller-Examples for more info on
// using multiple controllers.  In this example, we're going to set up three NEOPIXEL strips on three
// different pins, each strip getting its own CRGB array to be played with

#include <FastLED.h>

#define NUM_LEDS_PER_STRIP 60
CRGB redLeds[NUM_LEDS_PER_STRIP];
CRGB greenLeds[NUM_LEDS_PER_STRIP];
CRGB blueLeds[NUM_LEDS_PER_STRIP];

// For mirroring strips, all the "special" stuff happens just in setup.  We
// just addLeds multiple times, once for each strip
void setup() {
  // tell FastLED there's 60 NEOPIXEL leds on pin 10
  FastLED.addLeds<NEOPIXEL, 10>(redLeds, NUM_LEDS_PER_STRIP);

  // tell FastLED there's 60 NEOPIXEL leds on pin 11
  FastLED.addLeds<NEOPIXEL, 11>(greenLeds, NUM_LEDS_PER_STRIP);

  // tell FastLED there's 60 NEOPIXEL leds on pin 12
  FastLED.addLeds<NEOPIXEL, 12>(blueLeds, NUM_LEDS_PER_STRIP);

}

void loop() {
  for(int i = 0; i < NUM_LEDS_PER_STRIP; i++) {
    // set our current dot to red, green, and blue
    redLeds[i] = CRGB::Red;
    greenLeds[i] = CRGB::Green;
    blueLeds[i] = CRGB::Blue;
    FastLED.show();
    // clear our current dot before we move on
    redLeds[i] = CRGB::Black;
    greenLeds[i] = CRGB::Black;
    blueLeds[i] = CRGB::Black;
    delay(100);
  }

  for(int i = NUM_LEDS_PER_STRIP-1; i >= 0; i--) {
    // set our current dot to red, green, and blue
    redLeds[i] = CRGB::Red;
    greenLeds[i] = CRGB::Green;
    blueLeds[i] = CRGB::Blue;
    FastLED.show();
    // clear our current dot before we move on
    redLeds[i] = CRGB::Black;
    greenLeds[i] = CRGB::Black;
    blueLeds[i] = CRGB::Black;
    delay(100);
  }
}

faut pas conclure trop vite :slight_smile:

L'opérateur [] a été surchargé pour la struct CRGB donc dans l'absolu on aurait pu se dire que la struct traitait le débordement, mais je suis allé voir le code et ce n'est pas le cas... d'où le commentaire

@jml, :innocent:ce n'est pas ton code qui m'a chagriné :+1:,
c'est celui d'origine

oui c'est pour cela que j'ai mis en commentaire que j'avais effectué la modification :slight_smile:

mon point c'était qu'il ne faut pas croire que les [] sont uniquement de l'adressage de tableau et qu'on est coincé

C'est ce qu'on appelle le Subscript operator et il peut être surchargé pour faire autre chose, par exemple détecter qu'on essaye de lire ou écrire en dehors des bornes

testez par exemple

class Tableau {
  private:
    int* ptr;
    int size;

  public:
    Tableau(int* p = NULL, int s = 0) : ptr(p), size(s) {}

    int& Tableau::operator[](int index)
    {
      if (size == 0) {
        Serial.println("ERREUR TABLEAU VIDE");
        while (true) yield();
      }

      if (index < 0) {
        Serial.println("ERREUR INDEX NEGATIF. j'utilise le premier élément");
        return ptr[0];
      }
      if (index >= size) {
        Serial.println("ERREUR INDEX TROP GRAND. j'utilise le dernier élément");
        return ptr[size - 1];
      }
      return ptr[index];
    }


    void Tableau::print() const
    {
      for (int i = 0; i < size; i++) {
        Serial.print(ptr[i]);
        Serial.write(' ');
      }
      Serial.println();
    }
};

int donnees[] = { 1, 2, 4, 8 };
Tableau unTableau(donnees, 4);

void setup() {
  Serial.begin(115200);
  unTableau.print();

  unTableau[2] = 42;
  unTableau.print();

  unTableau[8] = 42;
  unTableau.print();

  unTableau[-3] = 42;
  unTableau.print();
}

void loop() {}

Je ne suis pas d'accord avec vous

si je met la Valeur a 4 alors l'effet va aller de -4led en 4-led jusqu'à la 4eme led et non pas jusqu'à la led 0 ce qui me laisse les 4 premières Led allumée . ( Je viens de faire l'essai )
@J-M-L @dfgh

En effet cela s'applique pour le même nombre de led sur plusieurs strip mais si tu regarde mon code d'origine je n'est pas le même nombres de led a chaque fois

vous écrivez

i va donc aller de 31 jusqu'à 0 compris en décrémentant de 1 en 1.

quand i vaut 3, combien vaut i-4 qui est utilisé dans leds1[i - 4] ??
quand i vaut 2, combien vaut i-4 qui est utilisé dans leds1[i - 4] ??
quand i vaut 1, combien vaut i-4 qui est utilisé dans leds1[i - 4] ??
quand i vaut 0, combien vaut i-4 qui est utilisé dans leds1[i - 4] ??

Ok dans ton raisonnement sauf que pour i >= 4 les led passe bien white mais les 4ere reste allumée

dans ton cas cela revient a écrire cela , ce qui en plus évité de surcharger ma mémoire quand pense-tu ?

#include <FastLED.h>


#define NUM_LEDS1 31
#define NUM_LEDS2 31
#define NUM_LEDS3 0
#define NUM_LEDS4 0
#define NUM_LEDS5 170
#define NUM_LEDS6 0
#define NUM_LEDS7 0
#define NUM_LEDS8 220
#define NUM_LEDS9


#define DATA_PIN2 2
#define DATA_PIN3 3
#define DATA_PIN4 4
#define DATA_PIN5 5
#define DATA_PIN6 6
#define DATA_PIN7 7
#define DATA_PIN8 8
#define DATA_PIN9 9
#define DATA_PIN10 10



#define BRIGHTNESS 160 //luminosité entre 0 et 255.


CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
CRGB leds3[NUM_LEDS3];
CRGB leds4[NUM_LEDS4];
CRGB leds5[NUM_LEDS5];
CRGB leds6[NUM_LEDS6];
CRGB leds7[NUM_LEDS7];
CRGB leds8[NUM_LEDS8];
CRGB leds9[NUM_LEDS8];





void setup() {

  FastLED.addLeds<WS2812B, DATA_PIN2, GRB>(leds1, NUM_LEDS1).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN3, GRB>(leds1, NUM_LEDS2).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN4, GRB>(leds1, NUM_LEDS3).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN5, BRG>(leds2, NUM_LEDS4).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN6, GRB>(leds5, NUM_LEDS5).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN7, BRG>(leds2, NUM_LEDS6).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN8, BRG>(leds2, NUM_LEDS7).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN9, GRB>(leds8, NUM_LEDS8).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<WS2812B, DATA_PIN10, GRB>(leds8, NUM_LEDS8).setCorrection(TypicalLEDStrip);

  pinMode(DATA_PIN2, OUTPUT); // la broche led (2) est initialisée en sortie BRANCHE 1
  pinMode(DATA_PIN3, OUTPUT); // la broche led (3) est initialisée en sortie BRANCHE 2
  pinMode(DATA_PIN4, OUTPUT); // la broche led (4) est initialisée en sortie BRANCHE 3
  pinMode(DATA_PIN5, OUTPUT); // la broche led (5) est initialisée en sortie BRANCHE 4
  pinMode(DATA_PIN6, OUTPUT); // la broche led (6) est initialisée en sortie BRANCHE 5
  pinMode(DATA_PIN7, OUTPUT); // la broche led (7) est initialisée en sortie BRANCHE 6
  pinMode(DATA_PIN8, OUTPUT); // la broche led (8) est initialisée en sortie BRANCHE 7
  pinMode(DATA_PIN9, OUTPUT); // la broche led (9) est initialisée en sortie
  pinMode(DATA_PIN10, OUTPUT); // la broche led (10) est initialisée en sortie




  FastLED.setBrightness(BRIGHTNESS);

  digitalWrite(DATA_PIN2, LOW); // Eteindre PIN 2
  digitalWrite(DATA_PIN3, LOW); // Eteindre PIN 3
  digitalWrite(DATA_PIN4, LOW); // Eteindre PIN 4
  digitalWrite(DATA_PIN5, LOW); // Eteindre PIN 5
  digitalWrite(DATA_PIN6, LOW); // Eteindre PIN 6
  digitalWrite(DATA_PIN7, LOW); // Eteindre PIN 7
  digitalWrite(DATA_PIN8, LOW); // Eteindre PIN 8
  digitalWrite(DATA_PIN9, LOW); // Eteindre PIN 9
  digitalWrite(DATA_PIN10, LOW); // Eteindre PIN 10


}




void loop() {

  //ALLUMAGE FLOCON

  for (int i = 0; i < NUM_LEDS8; i += 1) {
    leds8[i] = CRGB::Blue;
    if (random(100) < 2) {
      leds8[i] = CRGB::White;
      delay(2);
    }
  }

  for (int i = 32; i < NUM_LEDS5; i += 1) {
    leds5[i] = CRGB::Blue;
    if (random(100) < 2) {
      leds5[i] = CRGB::White;
      delay(2);
    }
  }
  FastLED.show();


  //DEBUT ALLUMAGE Branche


  for (int i = 31; i >= 0; i--) {
    leds1[i - 3] = CRGB::White;
    FastLED.show();
    delay(80);
    leds1[i] = CRGB::Black;
    FastLED.show();
  }

  for (int i = 31; i >= 0; i--) {
    leds2[i - 3] = CRGB::White;
    FastLED.show();
    delay(80);
    leds2[i] = CRGB::Black;

    FastLED.show();

  }

}

oui mais ce n'est pas une raison pour écrire n'importe où en mémoire :slight_smile:
il faut traiter le cas de la fin du ruban séparément


dans votre code il y a toujours le souci

  for (int i = 31; i >= 0; i--) {
    leds1[i - 3] = CRGB::White;
    FastLED.show();
    delay(80);
    leds1[i] = CRGB::Black;
    FastLED.show();
  }

quand i vaut 2, 1 ou 0 alors le i-3 qui est dans leds1[i - 3] = CRGB::White; devient négatif ce qui fait que vous écrasez quelque chose en mémoire

éventuellement testez

  for (int i = 31; i >= 0; i--) {
    if (i-3 >= 0) leds1[i - 3] = CRGB::White; // <=== ON EVITE LE DEBORDEMENT MEMOIRE
    FastLED.show();
    delay(80);
    leds1[i] = CRGB::Black;
    FastLED.show();
  }

Parfait cela résout le problème de débordement en mémoire :slight_smile:

@jml, merci pou ta réponse ci dessus
mais ayant voulu démontrer le débordement sur un tableau réservé en mémoire juste avant celui sur lequel on applique un decalage, j'ai écrit ce petit prg

byte decalage = 15;
byte tabavant [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte tab [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
void setup() {
  Serial.begin(115200);
  Serial.print(" avec décalage = "); Serial.println(decalage);
  for (int f = 0; f <= 9; f++) {
    Serial.print(tabavant[f]);
  } Serial.print("  ");
  for (int f = 0; f <= 9; f++) {
    Serial.print(tab[f]);
  }
  Serial.println("fin init   ");

  for (int i = 9; i >= 0; i--) {
    tab[i - decalage ] = 1;
  }
  for (int f = 0; f <= 9; f++) {
    Serial.print(tabavant[f]);
  } Serial.print("  ");
  for (int f = 0; f <= 9; f++) {
    Serial.print(tab[f]);
  }
  Serial.println("fin modif"); Serial.println("");;
}

void loop() {}

voici le résultat avec différents décalages

comme vous pouvez le voir, j'ai changé le décage à chaque execution
et je pensais voir les 1 déborder sur le premier tableau. mais ce ne fut pas le cas
par contre le serial print est perturbé et il mange de plus en plus de texte sur le message de fin de modif

je ne comprends pas ce qui se passe, en assembleur, si j'écris à coté, il n'y a pas de cadeau.
le compilateur fait il quelque chose ?

J'ai un peu modifié le programme.
On voit que les tableaux ne sont pas placés en mémoire dans l'ordre que l'on pourrait supposer.
On peut voir aussi que les chaînes de caractères sont aussi placées en mémoire car elles sont corrompues pour certaines valeurs de decalage (> à 11 chez moi)

byte tab1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte tabavant[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte tab2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };


void setup() {
  Serial.begin(115200);
  Serial.print("tab1 ");
  Serial.println((unsigned int)tab1);
  Serial.print("tabavant ");
  Serial.println((unsigned int)tabavant);
  Serial.print("tab2 ");
  Serial.println((unsigned int)tab2);
  for (byte decalage = 0; decalage < 16; decalage++) {
    memset(tab1, 0, sizeof(tab1));
    memset(tabavant, 0, sizeof(tabavant));
    memset(tab2, 0, sizeof(tab2));
    Serial.println();
    Serial.print(" avec décalage = ");
    Serial.println(decalage);
    for (int f = 0; f <= 9; f++) {
      Serial.print(tab1[f]);
    }
    Serial.print("  ");
    for (int f = 0; f <= 9; f++) {
      Serial.print(tabavant[f]);
    }
    Serial.print("  ");
    for (int f = 0; f <= 9; f++) {
      Serial.print(tab2[f]);
    }
    Serial.println(" fin init");

    Serial.println("    tab1     tabavant      tab2");
    for (int i = 9; i >= 0; i--) {
      tabavant[i - decalage] = i;
    }
    for (int f = 0; f <= 9; f++) {
      Serial.print(tab1[f]);
    }
    Serial.print("  ");
    for (int f = 0; f <= 9; f++) {
      Serial.print(tabavant[f]);
    }
    Serial.print("  ");
    for (int f = 0; f <= 9; f++) {
      Serial.print(tab2[f]);
    }
    Serial.println(" fin modif");
    Serial.println("");
  }
}

void loop() {}

Je note que je reçois un message du compilateur

In function 'main':
/tmp/.arduinoIDE-unsaved20221024-7209-7ueqab.vw5zx/sketch_nov24a/sketch_nov24a.ino:36:30: warning: iteration 10 invokes undefined behavior [-Waggressive-loop-optimizations]
       tabavant[i - decalage] = i;
                              ^
/tmp/.arduinoIDE-unsaved20221024-7209-7ueqab.vw5zx/sketch_nov24a/sketch_nov24a.ino:14:36: note: within this loop
   for (byte decalage = 0; decalage < 16; decalage++) {

le compilateur est libre de choisir l'organisation qu'il veut pour la mémoire. Pas de garantie que tout soit rangé dans l'ordre que vous voulez