Jak zrobić panel kontrolny z diod LED WS2812?

W projektach elektronicznych dużą popularnością cieszą się taśmy LED Są tanie, efektowne i  wygodne w użyciu. Taśmy LED to nic innego jak połączone ze sobą diody RBG. Zwykle sprzedawane są ze sterownikiem, za pomocą którego możemy zarządzać diodami (ich kolorem, jasnością).

Taśma LED
Taśmy LED dostępne są praktycznie w każdym sklepie budowlanym.

Moduł WS2812

Na listwie modułu znajduje się 8 małych diod LED RGB 5050 (5 mm x 5 mm) z otworami montażowymi i łańcuchową konstrukcją. Każda dioda LED jest adresowana, dzięki sterownikowi, który znajduje się wewnątrz diody.

Moduł WS2812 z 8 diodami LED
Moduł WS2812 z 8 diodami LED.

Moduł może być zasilany napięciem od 4 do 7V. Koszt tego urządzenia jest niewielki (około 15 zł).

W jednym z projektów w naszej firmie postanowiliśmy zastosować ten moduł jako panel informujący o pracy czujników w ramach danego urządzenia.

Skąd ten wybór?

Możemy sterować 8 diodami korzystając wyłącznie z jednego portu GPIO. W przypadku zastosowania klasycznych diod byłoby to aż 8 zajętych portów mikrokontrolera (w tym przypadku ESP8266).

O ile istnieją biblioteki do zarządzania diodami pozwalające zapalać i gasić wiele diod naraz to gdy chcemy sterować wyłącznie jedną diodą bez zmiany stanu pozostałych to możemy napotkać się z nie lada problemem. W tym artykule podpowiemy jak ten problem rozwiązać.

WS2812 i ESP8266

W tym przypadku za serce naszego układu będzie odpowiadać ESP8266 ale nie ma żadnego problemu by było to np. Arduino. Wszelkie opisywane metody będą działać dokładnie tak samo na Arduino.

Do zarządzania diodami użyjemy popularnej biblioteki NeoPixel od Adafruit.

Poniżej przykładowy kod, który zapali diody jedna po drugiej na kolor czerwony.

#include <Adafruit_NeoPixel.h>
 
 
// PIXELS
#define PIXELS_PIN D6
#define PIXEL_COUNT 8
 
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXEL_COUNT, PIXELS_PIN, NEO_GRB + NEO_KHZ800);
 
 
void setup() {
 
  // PIXELS
  pixels.begin(); 
  pixels.clear();
  pixels.setBrightness(80);
 
  for (int i = 0; i < PIXEL_COUNT; i++)
  {
    pixels.setPixelColor(i, 255,0,0);
    pixels.show();
    delay(100);
  }
 
}
 
void loop() {
 
}

Użyte funkcje:

  • begin() - włączenie modułu.

  • setBrightness() - ustawianie jasności paska z diodami. Funkcja przyjmuje wartości od 0 do 255.

  • setPixelColor() - za pomocą tej funkcji deklarujemy kolor jaki my wyświetlać poszczególna dioda. Diody oznaczamy od zaczynając od numeru 0. W naszym przykładzie nr diody przypisany jest do zmiennej i. W dalszej części funkcji deklarujemy kolor w postaci wartości RGB.

  • pixels.show() - zadeklarowanie koloru nic nam nie da dopóki nie włączymy diod, robimy to za pomocą tej funkcji. Gdy zmienimy cokolwiek w diodach to by zauważyć różnicę musimy wywołać tę funkcję po każdej zmianie.

Wynik naszego programu prezentuje się w następujący sposób:

przykład włączenia każdej diody led
Przykład włączenia każdej diody.

WS2812 i utrzymanie stanu diody

Jak zauważyliście możemy zapalić wszystkie diody na raz (z lekkim opóźnieniem). Możemy zmienić kolor poszczególnej diody ale gdy to zrobimy to nadpiszemy stan pozostałych diod. Ich ustawienia zostaną “zresetowane”.

Co zatem zrobić gdy chcemy wyłączyć / wyłączyć jedną diodę i zachować stan pozostałych? Musimy stan z każdej z diody zapisać w tablicy.

Tworzymy nową tablicę zawierającą 8 elementów. Każdy element będzie reprezentować jedną diodę.

int PIXELS_DATA[8]={0,0,0,0,0,0,0,0};

Gdzie:

0 - dioda wyłączona
1 - dioda włączona

Wyłączenie diody uzyskamy nadając jej “czarny” kolor. Parametry RGB ustawiamy na zero.

Zanim napiszemy funkcję do zmiany stanu poszczególnej diody warto zoptymalizować możliwość zmiany jej koloru. Możemy stworzyć np. taką funkcję:

void setPixel(int pixel, byte red, byte green, byte blue) {
   pixels.setPixelColor(pixel, pixels.Color(red, green, blue));
}

Oczywiście możemy dowolnie ustalać kolory. W moim urządzeniu pierwsza dioda informuje czy urządzenie działa a pozostałe pokazują czy dany czujnik pracuje prawidłowo.

Jak zmienić stan poszczególnej diody?

Musimy zmienić wartość z 0 do 1 lub z 0 do 1 w tablicy PIXELS_DATA.

Stwórzmy do tego funkcję:

void setLED(int led, int state){
 
  PIXELS_DATA[led] = state;
 
  for (int i = 0; i < PIXEL_COUNT; i++){    
    if(PIXELS_DATA[i] == 1){
      setPixel(i, colors[i][0], colors[i][1], colors[i][2]); 
    } else{
      setPixel(i, 0, 0, 0);
    }  
  }  
  pixels.show();
}

Funkcja początkowo zmienia stan na poszczególnym elemencie tablicy a następnie przechodzi kolejno po tablicy PIXELS_DATA i w zależności od wartości stanu ustala kolor przypisany w tablicy colors lub ustala kolor czarny.

Przykład użycia:

setLED(0,1); 
setLED(1,0);
delay(500);
setLED(1,1); 

setLED(2,1);
setLED(3,1);
delay(500);

Wywołanie tego kodu w funkcji loop spowoduje zapalenie pierwszej diody na kolor czerwony. Druga dioda będzie migać a 3 i 4 będą świeciły się na kolor zielony.

Cały kod prezentuje się w ten sposób:

#include <Adafruit_NeoPixel.h>


// PIXELS
#define PIXELS_PIN D6
#define PIXEL_COUNT 8

int PIXELS_DATA[8]={0,0,0,0,0,0,0,0};


const byte colors[8][3] = {
  {255, 0, 0}, //red
  {0, 255, 0}, //green
  {0, 255, 0}, //green
  {0, 255, 0}, //green
  {0, 255, 0}, //green
  {0, 255, 0}, //green
  {0, 255, 0}, //green
  {0, 255, 0}, //green
};


Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXEL_COUNT, PIXELS_PIN, NEO_GRB + NEO_KHZ800);


void setup() {

  // PIXELS
  pixels.begin();
  pixels.clear();
  pixels.setBrightness(80);

  for (int i = 0; i < PIXEL_COUNT; i++)
  {
    setPixel(i, 255, 0, 0);
    pixels.show();
    delay(100);
  }  

}

void loop() {

 setLED(0,1); 
 setLED(1,0);
 delay(500);
 setLED(1,1); 

 setLED(2,1);
 setLED(3,1);
 delay(500);

}


void setPixel(int pixel, byte red, byte green, byte blue) {
  pixels.setPixelColor(pixel, pixels.Color(red, green, blue));
}


void setLED(int led, int state){
 
  PIXELS_DATA[led] = state;
 
  for (int i = 0; i < PIXEL_COUNT; i++){    
    if(PIXELS_DATA[i] == 1){
      setPixel(i, colors[i][0], colors[i][1], colors[i][2]); 
    } else{
      setPixel(i, 0, 0, 0);
    }  
  }  
  pixels.show();
}

Wynik naszego programu:

Przykład użycia funkcji setLED.
Przykład użycia funkcji setLED.
Kod możecie pobrać na naszym repozytorium.
Marek Golan

Założyciel Dogtronica. Specjalista IT z kilkunastoletnim stażem. Miłośnik elektroniki oraz technologii blockchain. Pamięta czasy IE6 jakby to było wczoraj :)

Zostaw komentarz

siedemnaście + 16 =

Top