• slidebg1
    RGB LED PANEL

    Ce projet propose la réalisation
    d’une dalle lumineuse programmable
    à partir de LEDs WS2812B et de la librairie
    Adafruit_NeoPixel pour Arduino.

Les NeoPixels

Les LEDs compatibles avec la librairie NeoPixel permettent un large contrôle de la couleur et des comportements.
Ces dernières peuvent être contrôlées en grand nombre et individuellement grâce à une seule pin d'Arduino.


Téléchargements :


Adafruit_NeoPixel.zip
RGB_codefinal.zip
RGB_codefinal+bluetooth.zip

Grâce à la réalisation de cette lampe programmable, nous tenterons de cerner le fonctionnement en boucle de l'Arduino ainsi que celui de la communication série par à l'implémentation d'un module bluetooth contrôlé via un smartphone.

  • Arduino Nano
  • x16 LEDs WS2812B
  • Module Bluetooth HC-06
  • Medium transparent la 5mm pour diffusion
  • Medium 5mm pour la fabrication de la boîte (bois, plexiglas, carton ...)

ÉTAPE 1 : LE MONTAGE

Commencez par réaliser le montage de vos différents composants comme sur le schéma. Les bandes de LEDs sont découpables au niveau des pastilles en cuivres, libre à vous de réaliser une matrice de plus de 4x4 pixels, cependant attention à respecter le sens indiqué par les petites flèches sur les LEDs. Pour ce qui est du module Bluetooth, il peut aussi bien fonctionner avec le VCC branché en 5V qu'en 3.5V cependant la vitesse de communication en sera légèrement affecté. Attention toutefois à débrancher le Bluetooth lorsque vous téléverserez le code dans l'Arduino, le bluetooth bloque la connection série USB.

ÉTAPE 2 : LA DIFFUSION

Il s'agit désormais de trouver une surface plane pour diffuser la lumière des nos LEDs. Il existe de nombreuses technique efficaces : sac plastiques, papier, plexiglas poncé ou peint ... Dans notre cas nous utiliserons le film de protection du plexiglas qui filtre parfaitement la lumière. Attention également à trouver la bonne distance entre votre surface et vos LEDs, cette distance affecte le rendu visuel de la diffusion. Une fois que vous avez trouvé la diffusion qui vous convient, vous pouvez désormais construire une dalle aux bonnes côtes pour y encastrer votre montage. Vous pouvez également penser à prévoir une connectique de sortie a la fin de votre dernière bande pour pouvoir connecter une autre dalle à la suite.

ÉTAPE 3 : LE CODE

Il s'agit désormais de programmer les comportements de nos LEDs via l'Arduino. Commencez par installer la librairie Adafruit_NeoPixel à votre IDE Arduino.
Dans cet exemple, les comportements correspondent à deux types de dégradés "arc-en-ciel", ces deux comportements sont définis dans void rainbow(uint8_t wait) {} et void rainbowCycle(uint8_t wait) {} . Ils sont ensuite exécutés dans le void loop() {} Le loop est le corps de notre programme, il exécute en boucle les actions qui y sont inscrites, en l'occurence, ici exécutera le comportement "rainbow" avant d'exécuter "rainbowCycle" et recommencera cet enchainement à l'infini.

// Libraries
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

// Define PIN as Pin6
#define PIN 6

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}
// Loop
void loop() {
  rainbow(20);
  rainbowCycle(20);
}
// Rainbow
void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
// RainbowCycle
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

Vous pouvez maintenant implémanter d'autres comportements à la fin de votre code avant de les rappeller dans votre boucle principale. Vous pouvez trouver plus de documentation sur les NeoPixel et leur possibilités sur le site d'Adafruit. Il existe également d'autres librairies prévues pour ce type de LEDs comme NeoMatrix ou Adafruit_GFX.

// ColorWipe
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}
// RainbowCycle
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

ÉTAPE 4 : LE BLUETOOTH

Maintenant que l'on sait programmer des comportements et les intégrer à une boucle, nous voulons les activer via un contrôleur bluetooth comme un smartphone. Commencez par télécharger un terminal bluetooth dans l'AppStore ou le PlayStore. Les module HC-06 utilisent un Bluetooth 2.0 et leur code d'appairage est généralement 0000 ou 1234. On remarque un témoin lumineux rouge sur le dessus du module, celui-ci clignote lorsqu'il est actif mais non appairé et reste allumé de manière constante une fois connecté à un appareil. Encore une fois, n'oubliez pas de débrancher le module avant chaque téléversement.

La communication Bluetooth fonctionne comme une communication série classique grâce à la librairie SofwareSerial. Une fois les deux pins affectées à la communication et la vitesse de communication définie, il s'agit d'envoyer des caractère via le terminal de notre smartphone, et de les analyser avec la fonction BT.read.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);

#include <SoftwareSerial.h>
SoftwareSerial BT(10, 11); 
// creates a "virtual" serial port/UART
// connect BT module TX to D10
// connect BT module RX to D11
// connect BT Vcc to 5V(or 3.5V), GND to GND

#define PIN 6


void setup()  
{  
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code
  
  strip.begin();
  // Initialize all pixels to 'off'
  strip.show(); // Initialize all pixels to 'off'
  // set the data rate for the SoftwareSerial port
  BT.begin(9600);
  // Send test message to other device
  BT.println("Hello from Arduino");
}
char a; // stores incoming character from other device
void loop() 
{
  if (BT.available())
  // if text arrived in from BT serial...
  {
    a=(BT.read());
    if (a=='1')
    {
      colorWipe(strip.Color(255, 0, 0), 50); // Red
      colorWipe(strip.Color(0, 255, 0), 50); // Green
      colorWipe(strip.Color(0, 0, 255), 50); // Blue
      colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW;
      BT.println("colorWipe");
    }
    
    if (a=='2')
    {
    theaterChase(strip.Color(127, 127, 127), 50); // White
    theaterChase(strip.Color(127, 0, 0), 50); // Red
    theaterChase(strip.Color(0, 0, 127), 50); // Blue
      BT.println("theaterChase");
    }
    
    if (a=='3')
    {
      rainbow(20);
      BT.println("rainbow");
    }
    
    if (a=='4')
    {
      theaterChaseRainbow(50);
      BT.println("theaterChaseRainbow");
    }
    
    if (a=='?')
    {
      BT.println("Send '1' to turn LED colorWipe");
      BT.println("Send '2' to turn LED theaterChase");
      BT.println("Send '3' to turn LED rainbow");
      BT.println("Send '4' to turn LED theaterChaseRainbow");
      BT.println("Else rainbowCycle");
    }   
    // you can add more "if" statements with other characters to add more commands
  }
  rainbowCycle(20);
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Ce tutoriel a été inspiré par :

http://www.instructables.com/id/Make-your-own-15x10-RGB-LED-Matrix/
http://www.instructables.com/id/Rainbow-Jar-RGB-Pixel-Strip-Controlled-via-Ardui/