Ci-dessous, j’ai indiqué les étapes détaillées de l’écriture du code disponible en libre accès sur mon GitLab (et en fin de page). J’espère que cela donnera quelques clés de compréhension, en tout cas n’hésitez pas à me contacter si je peux vous donner plus de renseignements, ou si vous avez trouvé une technique plus pratique pour la parallélisation d’événements!

Setup

  1. Première étape: télécharger l’IDE Arduino afin de pouvoir transférer le code vers notre carte. Les instructions parlent d’elles-même, attention de bien choisir le bon port lors de la première connexion et tout ira bien!

  2. On télécharge ensuite la librairie FastLED afin de pouvoir contrôler nos leds addressables individuellement. Tools > Manage library > Library Manager

#define FASTLED_INTERNAL
#include <FastLED.h>
  1. Il suffit ensuite d’indiquer le nombre de leds, leur type, ainsi que le numéro pin qui correspond.
#define NUM_LEDS 17
#define LED_PIN 13
#define LED_TYPE NEOPIXEL

CRGB leds[NUM_LEDS];
  1. Les cartes Arduino ont besoin de deux fonctions: setup() et loop(). Dans la première, nous indiquons des informations sur le port à écouter (ce qui nous sera utile plus tard pour communiquer avec la carte), ainsi que la mise ne place des leds (voir la documentation FastLED pour plus d’informations).
void setup() {
  Serial.begin(9600); // Listen to the Arduino
  delay(100); // Sanity delay
  FastLED.addLeds<LED_TYPE, LED_PIN>(leds, NUM_LEDS); // Setup LEDs
}
  1. Maintenant que tout est en place, nous pouvons faire un premier test! Allumons toutes nos lampes en vert…
void loop() {
  FastLED.clear();
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB(0, 255, 0);
  }
  FastLED.show();
}
  1. Et on peut s’amuser un peu en les faisant clignoter.
void loop() {
  FastLED.clear();
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB(0, 255, 0);
  }
  FastLED.show();
  delay(500);
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB(0, 0, 0);
  }
  FastLED.show();
  delay(500);
}

Sections et événements

  1. Passons aux choses sérieuses! Nous avons une scène à animer, et la première étape est de séparer les différentes zones de celle-ci. Nous pouvons donc construire des tableaux qui indiquent en première position la première led de la série, et en deuxième la dernière. Cette méthode ne fonctionne que dans le cas où on a soudé nos leds dans l’ordre. Sinon, il faudrait modifier la fonction du point suivant.
int OLLIVANDERS[] = {0, 5};
int QUIDDITCH[] = {6, 7};
int FLOURISH[] = {8, 9};
int FLOURISH_ROOM[] = {10, 11};
int QUIDDITCH_ROOM[] = {12, 13};
int SKY[] = {14, 16};
int ALL[] = {0, 16};

void loop() {
  FastLED.clear();
  for (int i = ALL[0]; i <= ALL[1]; i++) {
    leds[i] = CRGB(0, 0, 0);
  }
  FastLED.show();
}
  1. Grâce à la fonction ci-dessous, on peut désormais fixer la couleur d’une section plus facilement. A noter, la couleur peut être donnée en RGB ou HSV (voir le wiki de FastLED pour les détails des couleurs).
void defineSectionColor(int SECTION[], CRGB color) {
  for (int i = SECTION[0]; i <= SECTION[1]; i++) {
    leds[i] = color;
  }
}

defineSectionColor(OLLIVANDERS, CRGB::Red);
  1. Voilà la partie qui m’a donné le plus de fil à retordre. En effet, on a vu qu’allumer des leds et les faire clignoter était plutôt simple. En revanche, créer un scénario c’est autre chose: on doit paralléliser les traitements afin de pouvoir allumer les lumières d’Ollivanders d’une certaine couleur, et celles de Flourish and Blotts d’une autre, tandis que la vitrine de Quality Quidditch Supplies clignote de son côté.

Pour cela, j’ai choisi d’utiliser à mon avantage la loop() imposée par la carte Arduino. Chaque boucle va durer 10 millisecondes, grâce à l’ajout d’un delai (delay(10)) à la fin de celle-ci. Toutes les 10ms, la boucle recommence, ce qui nous permet de donner une illusion de parallélisation. Grâce à de simples conditions, on peut désormais décider de la couleur d’une led (ou d’un groupe de led) sur une période donnée.

Pour simplifier (voir exemple ci-dessous): entre “deux heures” et “huit heures”, les fenêtres de Flourish and Blotts seront vertes, et entre “six heures” et “dix-huit heures”, les fenêtres d’Ollivanders seront rouges.

int timer(int t) {
  int h = t / 1000;
    if (t % 1000 == 0) {
      Serial.println(h);
      return h;
    }
}

void HedwigsTheme() {
  for (int t = 0; t < 25000; t++) {
    int hour = timer(t);

    if (hour > 2 && hour < 8){
      defineSectionColor(FLOURISH, CRGB::Blue);
    }

    if (hour > 6 && hour < 18){
      defineSectionColor(OLLIVANDERS, CRGB::Red);
    }
  FastLED.show();
  delay(10); // 1t == 10ms
  }
}

void loop() {
  HedwigsTheme();
}

Effets spéciaux

  1. On peut désornais s’amuser! J’ai créé quelques fonctions pour ajouter un peu de piment à mon scénario musical.

9.1. Blinks

void blinks(int SECTION[]) {
  int chance = random(0, 2);
  int value = 255;
  if (chance == 1) {  
    value = 0;
  }
  defineSectionColor(SECTION, CHSV(128, 0, value));
}

9.2. Waves

// Cosinus effect - "Waves"
void waves(int SECTION[], int t) {
  int value = 0;
  int tt = t% 628;
  double angle = (float) tt / 100;
  double st = (- cos(angle) + 1.0) * 128.0;
  value = ((int) st) % 256;
  defineSectionColor(SECTION, CHSV(64, 255, value));
}

9.3. Wand Choice

// Random color effect - "Wand Choice"
void wandChoice(int SECTION[]) {
  int randomChance = random(0, 100);
  if (randomChance == 1) {
    int hue = random(0, 255);
    defineSectionColor(OLLIVANDERS, CHSV(hue, 255, 255));  
  }
}

9.4. Wand Battle

// Moving colors - "Wand battle"
void wandBattle(int SECTION[], int t) {
  int nb_leds = (SECTION[1] + 1) - SECTION[0];
  int tt = t / 10;
  int led_number = tt % nb_leds + SECTION[0];
  int hue = tt % 255;
  int LIGHT[] = {led_number, led_number};
  defineSectionColor(LIGHT, CHSV(hue, 255, 255));
}

9.5. Daylight

// Linear effect - "Daylight"
void dayLight(int SECTION[], int t, int h) {
  int value = 0;
  float tt = 0;

  if (h >= 6 && h < 16) {
    value = 255;  
  }
  
  else if (h >= 4 && h < 6) {
    tt = ((float) t - 4000.0) / 2000.0;
    value = 255 * tt;
  }

  else if (h >= 16 && h < 18) {
    tt = (18000.0 - (float) t) / 2000.0;
    value = 255 * tt; 
  }
  
  defineSectionColor(SECTION, CHSV(60, 128, value));
}

Scenario

  1. Coming soon

Code

Coming soon