Décoration de Noël à faire soi-même

Ça y est, on peut dire qu’on y est presque, les fêtes arrivent. Comme vous avez pu le voir dans l’article précédent, je me suis amusé à faire une matrice de LEDs pour mettre en place ma décoration de Noël. Donc, je vais vous partager la mise en place, le logiciel de la matrice ainsi que le rendu final.

Mise en place

Pour mettre en place ma décoration de Noël, je suis parti sur la réalisation d’une matrice de LEDs avec un bandeau de LEDs WS2812 + un autre bandeau de LEDs WS2812 d’extérieur + un bandeau de LED RGB classique d’extérieur en 12VDC.

L’objectif est d’habiller la cabane en bois de ma fille et d’éclairer un bonhomme de neige.

Première difficulté : Ma source d’énergie la plus proche (tableau électrique de mon cabanon) est à 40mètres linéaire de la cabane sur pilotis.

Deuxième difficulté : Je dois gérer 2 tensions différentes : 12VDC et 5VDC avec un peu de puissance.

Pour la décoration, Je suis parti sur l’idée suivante:

Achats

Je suis parti du bloc d’alimentation 12VDC du bandeau de LEDs RGB. Le bloc peut fournir 6A à 12VDC et le 12VDC « voyage » mieux que le 5VDC.

J’ai donc acheté une rallonge électrique de 40 mètres sur lequel va « voyager » le 12VDC. Comme il y a un peu de puissance la section 2,5² sera suffisante pour mon montage.

Ensuite, j’ai fait l’acquisition d’un convertisseur 12VDC-5VDC pour les LEDs WS2812 et pour mon NodeMCU.

1x Rallonge électrique 40m panier-acheter-ecommerce-shopping-icone-8314-4824.99€
1x Convertisseur 12vdc 5vdc panier-acheter-ecommerce-shopping-icone-8314-4813.24€

Pour le reste des achats, il suffit d’aller sur l’article précédent.

Voici le schéma de mon installation : (de la prise 220vdc jusqu’à la cabane sur pilotis)

Tout ce petit beau monde est pilotable en Z-wave par l’intermédiaire de Jeedom. Voici quelques photos de l’installation à l’intérieur de la cabane (un peu jeté):

C’est pas très beau mais je voulais quand même le montrer. (Heureusement que le schéma est là pour comprendre).

Pour la partie « bonhomme de neige », j’avoue que c’est ma compagne qui l’a fait. Elle a suivi un tutoriel sur Pinterest et je trouve que c’est une super idée. D’ailleurs, je trouve que le rendu est top. J’ai juste rajouté un nez en impression 3D et deux ronds en carton noir pour les yeux. Le tout fixer à la colle chaude.

Voici un exemple :

Pour la partie éclairage, je n’ai eu qu’à insérer à l’intérieur un bout de bandeau de LEDs. Les gobelets blancs feront bien leur travail de diffusion de la lumière.

Logiciel de la décoration

Le logiciel est un mélange de plusieurs exemples de librairies. En particulier, les différents scénarios de lumières sont tirés des exemples de la librairie FastLed. J’ai aussi mis en place les librairies LEDmatrix et LEDtext pour l’affichage de texte sur la matrice. Enfin, j’ai mis en place un serveur Web afin de pouvoir changer la couleur et le texte que je fais défiler sur la matrice.

Vu que c’était juste pour une décoration de Noël, je n’ai pas poussé les fonctionnalités et j’ai fait beaucoup de copier/coller mais « ça fait le job ».

Voici en détail le code.


#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <FS.h>
#include "FastLED.h"
#include <LEDMatrix.h>
#include <LEDText.h>
#include <FontRobotron.h>

#define DBG_OUTPUT_PORT Serial

const char* ssid = "***********";
const char* password = "********";
const char* host = "esp8266fs";


#define DATA_PIN    8 //
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define NUM_LEDS    150 //NOMBRE DE LEDS SUR LE BANDEAU
CRGB leds[2][NUM_LEDS];

#define BRIGHTNESS          96 //LUMINOSITE
#define FRAMES_PER_SECOND  120

#define MATRIX_WIDTH   15
#define MATRIX_HEIGHT  10
#define MATRIX_TYPE    HORIZONTAL_ZIGZAG_MATRIX

cLEDMatrix<MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_TYPE> ledsText;
cLEDText ScrollingMsg;
char TxtDemo[] = {EFFECT_CHAR_DOWN "   JOYEUSES FETES!"};

int RedText=255;
int GreenText=0;
int BlueText=0;

ESP8266WebServer server(80);

void handleFileChangeText() {
  if(!server.hasArg("text")) {server.send(500, "text/plain", "BAD ARGS"); return;}

  String Txt=server.arg("text");
  String R=server.arg("R");
  String G=server.arg("G");
  String B=server.arg("B");
  TxtDemo[100]={};
  Txt.toCharArray(TxtDemo,100);

  if ((R!="") && (G!="") &&(B!=""))
  {
    RedText=R.toInt();
    GreenText=G.toInt();
    BlueText=B.toInt();
  }
   server.send(200, "text/plain", "ok");
}

void setup(void){

  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds[0], NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<LED_TYPE,5,COLOR_ORDER>(leds[1], NUM_LEDS).setCorrection(TypicalLEDStrip);

  //WIFI INIT
  DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
  if (String(WiFi.SSID()) != String(ssid)) {
    WiFi.begin(ssid, password);
  }
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    DBG_OUTPUT_PORT.print(".");
  }
  DBG_OUTPUT_PORT.println("");
  DBG_OUTPUT_PORT.print("Connected! IP address: ");
  DBG_OUTPUT_PORT.println(WiFi.localIP());

  MDNS.begin(host);
  
  //SERVER INIT
   //list directory
  server.on("/text", HTTP_GET, handleFileChangeText);
 
  server.onNotFound([](){
    if(!handleFileRead(server.uri()))
      server.send(404, "text/plain", "FileNotFound");
  });

  server.begin();
  DBG_OUTPUT_PORT.println("HTTP server started");

}

// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm,  text };

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the 


void loop(void){
  // Call the current pattern function once, updating the 'leds' array
  gPatterns[gCurrentPatternNumber]();

  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 

  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
  EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
  server.handleClient();
}

#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);
}

bool gReverseDirection = false;


void text() 
{
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(ledsText[0], NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  
  ScrollingMsg.SetFont(FredFontData);
  ScrollingMsg.Init(&ledsText, ledsText.Width(), ScrollingMsg.FontHeight() + 1, 0, 2);
  ScrollingMsg.SetText((unsigned char *)TxtDemo, sizeof(TxtDemo) - 1);
  ScrollingMsg.SetTextColrOptions(COLR_RGB | COLR_SINGLE, RedText, GreenText, BlueText);
  ScrollingMsg.SetTextDirection(CHAR_DOWN);
 
  for(int i = 0; i < 150; i++) {  
      leds[1][i] = CRGB::Black; 
  }

  for(int i=0;i<500;i++)
  {
    if (ScrollingMsg.UpdateText() == -1)
      ScrollingMsg.SetText((unsigned char *)TxtDemo, sizeof(TxtDemo) - 1);
    else
      FastLED.show();
    delay(100);
    server.handleClient();
    leds[1][ random16(NUM_LEDS) ] += CRGB::White;
  }
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds[0], NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<LED_TYPE,5,COLOR_ORDER>(leds[1], NUM_LEDS).setCorrection(TypicalLEDStrip);
}

void rainbow() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds[0], NUM_LEDS, gHue, 7);
  fill_rainbow( leds[1], NUM_LEDS, gHue, 7);
}

void rainbowWithGlitter() 
{
  // built-in FastLED rainbow, plus some random sparkly glitter
  rainbow();
  addGlitter(80);
}

void addGlitter( fract8 chanceOfGlitter) 
{
  if( random8() < chanceOfGlitter) {
    leds[0][ random16(NUM_LEDS) ] += CRGB::White;
    leds[1][ random16(NUM_LEDS) ] += CRGB::White;
  }
}

void confetti() 
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds[0], NUM_LEDS, 10);
  fadeToBlackBy( leds[1], NUM_LEDS, 10);
  int pos = random16(NUM_LEDS);
  leds[0][pos] += CHSV( gHue + random8(64), 200, 255);
  leds[1][pos] += CHSV( gHue + random8(64), 200, 255);
}

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

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

void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds[0], NUM_LEDS, 20);
  fadeToBlackBy( leds[1], NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[0][beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
    leds[1][beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
}
Décoration de Noël

Ce code permet de gérer différents scénarios de décoration sur la matrice mais aussi sur un autre bandeau de LEDs.

La matrice se retrouve sur le port D8 du NodeMCU et le bandeau sur le port D5

 FastLED.addLeds<LED_TYPE,8,COLOR_ORDER>(leds[0], NUM_LEDS).setCorrection(TypicalLEDStrip);
 FastLED.addLeds<LED_TYPE,5,COLOR_ORDER>(leds[1], NUM_LEDS).setCorrection(TypicalLEDStrip);

Ensuite, j’ai mis en place une serveur Web qui va me permettre de changer le texte et la couleur du texte de la matrice. Il suffira de se connecter sur le NodeMCU de la manière suivante :

http://<IP_NODEMCU>/text?text=    JOYEUX NOEL!&R=255&G=0&B=0

(Si vous avez des questions sur le code, n’hésitez pas à poster un commentaire). Le code est trop long pour tout expliquer.

Conclusion

Voici le résultat terminé:

Cabane avant décoration de Noël

Cabane sur pilotis avec décoration de Noël

Une petite vidéo pour agrémenter le tout :

Vous pouvez retrouver l’ensemble du projet sur mon github

[Total : 0    Moyenne : 0/5]

6 comments

  1. Bonjour,
    Quand vous dites:
    « Tout ce petit beau monde est pilotable en Z-wave par l’intermédiaire de Jeedom »!?
    Ne faite vous pas un abus de language!?
    Vous utilisez un nodemcu, donc du wifi, pour commander à distance votre installation depuis Jeedom je n’ai pas vu d’équipement Zwave.
    Désolé pour ce besoin de précision. Sinon l’idée est géniale, je vous dis merci car grâce à vous l’année prochaine j’aurai de plus belle déco de Noël.

    1. Bonjour,
      En effet, ça mérite une précision. La partie zwave piloté par Jeedom est la prise 220v pilotable sur le schéma de fonctionnement. (Dans mon cas j’ai utilisé une prise greenwave). Je n’ai approfondi cette partie car ce n’était pas l’objet principal de l’article mais tu as raison, la précision était importante. Merci à toi.

      1. Ok merci pour cette précision. Parce que je ne voyais pas d’équipement Zwave.
        Sinon dans l’absolu, cela commence à devenir courant sur le net, on pourrait utiliser un relais sur le nodemcu, pour commander en wifi l’alimentation de l’éclairage depuis jeedom. Seul soucis pas de retour d’info conso comme tu pourrais l’avoir sur la prise greenwave. Mais depuis la même tuile de Jeedom tu pourrais commander l’allumage, le mode et les couleurs de cette décos.
        Le but n’étant pas de faire comme dans la pub d’orange avec les décos de Noël lol…

  2. J’ai pris un peu de temps pour me lancer, mais à force de relire ton article j’ai fini par acheté un afficheur led WS2812 de 8×8 avec Nodemcu pour commencer à faire joujou.

    J’ai lu ton code, je n’ai pas tout compris, donc je vais tester de mon côté et voir ce que j’arrive à faire.
    Le but étant d’obtenir un ptit afficheur à led RGB (à terme de 8×8 ou 16×8) que l’on pourrait commander par une page web et me permettre d’afficher des notifications visuelles.

    A bientôt.

Leave a Reply

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *