Witam,
dzisiaj postaram się opisać sterowanie diodami ws2812b za pomocą modułów radiowych. Aby móc odbierać i nadawać informacje potrzebujemy jakiegoś mikrokontrolera do sterowania. Ja wykorzystałem arduino nano i pro mini (ze względu na małe rozmiary), ale to jakie arduino się użyje nie ma znaczenia.
Piszę diody ws2812 jednak producent podaje, że są to inteligentne sterowniki LED z wbudowanym źródłem światła. Czyli jest to sterownik umieszczony w obudowie diody RGB. Możemy spotkać te diody jako taśmy, pojedyncze tht lub smd. Zaletą jest to, że diody łączymy szeregowo i do sterowania całym “sznurem” diod wystarczy nam pojedynczy pinu cyfrowy mikrokontrolera. Diody są zasilane napięciem od 3.5V. do 5.3V. Należy uważać, aby nie przekroczyć tego napięcia, bo grozi to spaleniem diody. Do sterowania diod będzie potrzebna biblioteka NeoPixel Library.
Potrzebne elementy:
–Moduł radiowy nadajnik FS100A + odbiornik 433 MHz
-2 x Arduino(każdy wybiera jakie mu pasuje)
I coś, aby zrobić prototyp i sprawdzić czy działa:
–Przewody połączeniowe męsko-męskie
Zaczniemy od hardwar’u:
WS2812b:
Ja użyłem pojedynczych diod ws2812b smd. Każda dioda posiada 4 piny(Vcc,Gnd,DOUT,DIN). Diody łączymy poprzez podłączenie pinu “DOUT” pierwszej diody do pinu “DIN” drugiej diody(połączenie szeregowe). Gnd i Vcc podłączamy do każdej kolejnej diody. Robimy to tyle razy ile chcemy podłączyć diod. W razie jakich kolwiek wątpliwości zawsze możemy zajrzeć do noty katalogowej.
Tak wygląda schemat podłączenia z noty katalogowej:
Nie możemy zapominać też to podłączeniu kondensatorów(na schemacie oznaczone C1,C2).
Moduł radiowy nadajnik i odbiornik:
Odbiornik i nadajnik komunikują się ze sobą na częstotliwości 433 MHz. Urządzenia zasilane są napięciem od 2,5 V do 12 V. Z mikrokontrolerem komunikują się pomocą interfejsu jednoprzewodowego. Do obsługi modułów użyjemy biblioteki VirtualWire.
Podłączenie nadajnika:
Nadajnik posiada 3 piny pierwszy z lewej to szyna danych, pierwszy z prawej to Gnd a środkowy to Vcc.
Podłączenie odbiornika:
Odbiornik posiada 4 piny pierwszy z lewej to Vcc a pierwszy z prawej to Gnd, piny 2 i 3 są zmostkowane (jeśli przyjrzymy się na ścieżki w płytce możemy zobaczyć, że są zmostkowane) i jest to szyna danych.
Software:
Biblioteka NeoPixel Library:
Definiujemy liczbę diod i na którym pinie jest wyjście sygnału do sterowania diodami. Trzeba pamiętać, że pin sterujący musi być PWM.
1 2 3 4 |
#define lb_diod 9 #define pin 3 Adafruit_NeoPixel diody = Adafruit_NeoPixel(lb_diod, pin , NEO_GRB + NEO_KHZ800); |
begin() – Inicjalizacja biblioteki
1 2 3 4 |
void setup() { diody.begin(); } |
setPixelColor(poz , R, G, B) – ustawienie na pozycji (poz) diody i ustawienie jasności świecenia każdego z poszczególnych składowych (R-czerwony,G-zielony,B-niebieski)
poz – numer pozycji diody liczymy od zera, czyli pierwsza dioda ma wartość “0”
R,G,B- wartości każdego z kolorów zawierają się w zakresie <0:255>
show() – wysyła dane do diod
1 2 |
diody.setPixelColor(poz, R, G, B); diody.show(); |
Biblioteka VirtualWire:
Nadajnik:
Ustawienie do którego pinu jest podpięta szyna danych ( vw_set_tx_pin(10) ) i z jaką prędkością pracuje moduł ( vw_setup(2000) ).
1 2 |
vw_set_tx_pin(10); vw_setup(2000); |
1 2 3 |
char *msg; vw_send((uint8_t *)msg, strlen(msg)); //wysyłanie danych vw_wait_tx(); |
Odbiornik:
Dodatkowo w odbiorniku dochodzi opcja inicjalizacji odbierania danych ( vw_rx_start() ).
1 2 3 4 5 |
void setup() { vw_set_rx_pin(receive_pin); vw_setup(2000); vw_rx_start();} |
1 2 |
uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; |
1 2 3 4 5 6 7 |
if (vw_get_message(buf, &buflen)) //sprawdza czy odebraliśmy jakieś dane { for (i = 0; i < buflen; i++) // zczytujemy dane z odbiornika { dane +=char(buf[i]); // zapisujemy dane do zmiennej tekstowej "dane" } } |
Cały kod do nadajnika:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <VirtualWire.h> int but=9; void setup() { pinMode(but, INPUT_PULLUP); vw_set_tx_pin(10); vw_setup(2000); } void loop() { char *msg; if (digitalRead (but)==LOW) {msg="dziala"; } else {msg="nie"; } ; vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); delay(100); } |
Cały kod do odbiornika:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
#include <VirtualWire.h> #include <Adafruit_NeoPixel.h> #define PIN 3 #define LICZBA_DIOD 20 #define sekwencje 9 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(LICZBA_DIOD,PIN, NEO_GRB + NEO_KHZ800); int w=1; String dane; void setup() { pixels.begin(); Serial.begin(9600); vw_setup(2000); vw_set_rx_pin(4); vw_rx_start(); } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; if (vw_get_message(buf, &buflen)) { int i; String dane; for (i = 0; i < buflen; i++) { dane +=char(buf[i]); } Serial.println(dane); if ( dane =="dziala") { w=w+1; delay(100); rozne(w); if(w==sekwencje) { w=0; } } } } void rozne(int w) { switch(w) { case 1:czarny(); break; case 2:czerwony(); break; case 3:niebieski(); break; case 4:zielony(); break; case 5:zolty(); break; case 6:jasny_niebieski(); break; case 7:fioletowy(); break; case 8:pomaranczowy(); break; case 9:nowy(); break; } } void czarny() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i, 0, 0, 0); pixels.show(); delay(20); } } void czerwony() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i, 255, 0, 0); pixels.show(); delay(20); } } void niebieski() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i, 0, 0, 255); pixels.show(); delay(20); } } void zielony() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i, 0, 255, 0); pixels.show(); delay(20); } } void zolty() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i,253, 253, 0); pixels.show(); delay(20); } } void fioletowy() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i,122, 5,122); pixels.show(); delay(20); } } void jasny_niebieski() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i,0,255,255 ); pixels.show(); delay(20); } } void pomaranczowy() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i,255,128,0); pixels.show(); delay(20); } } void nowy() { for(int i=0;i<LICZBA_DIOD;i++) { pixels.setPixelColor(i,0,128,64); pixels.show(); delay(20); } } |
Działanie:
Jeśli przycisk nie jest wciśnięty wysyłane jest “nie” podłączając mikrokontroler z odbiornikiem do komputera możemy zobaczyć przez monitor szeregowy co jest w danej chwili odbierane. jeśli wciśniemy przycisk odbiornik odbiera “dziala” w tym momencie diody zapalają się w danym kolorze, ponowne kliknięcie powoduje, że kolor się zmienia na taki jaki jest ustawiony po nim w programie. Jeśli klikniemy tyle razy, że wszystkie opcje będą wykorzystane diody gasną i ponownie zaczyna się pętla kolorów.
Na zakończenie chciałbym powiedzieć, że opcje jakie dałem w kodzie czyli zmiana kolorów są dość proste, ale i też fajne w swojej prostocie, lecz zachęcam do pokombinowania z rożnymi sposobami zapalenia diod np. do połowy jeden kolor i od połowy drugi ipt. ;)
Interesujące ale dodaj sterowanie tych diod za pomocą smartphona.
Powoli powstaje projekt związany z esp8266 i sterowaniem z poziomu telefonu lub komputera różnego rodzaju elementami(w tym przypadku patrz diodami ws2812b). Jak coś wyjdzie i będzie działało postaram się umieścić ten projekt na stronie ;)
Sterowanie z telefonu można by zrealizować na kilka sposobów. Część z nich niestety wiąże się jednak z dość sporą ingerencją w kod, a przede wszystkim w hardware.
Ja bym tutaj polecał jedno z trzech rozwiązań:
– zamiast radia na 433MHz, dać ESP8266 i zaimplementować REST na arduino (czasochłonne, mało przystępna opcja wiążąca się z przepisaniem kodu)
– jeśli radio na 433 jest konieczne, to napisać prosty interfejs w nodeJS (lub zwykłym PHP), rozpakować na RPi, które wszystko obsłuży (minus to posiadanie RPI, albo konieczność posiadania komputera działającego jako serwer, który byłby podpięty do nadajnika poprzez USB)
– zastąpić radio na 433 odbiornikiem bluetooth i bawić się z pisaniem apki na andka (jak wspomniałem, spora zmiana w kodzie, zmiana hardware’u plus czas potrzebny na naukę SDK androida).
W swoim projekcie wykorzystałem tę pierwszą opcję. Początkowo ESP8266 odpowiadał tylko za komunikację, ale ostatecznie skończył jako serce systemu. Plus to to, że może być w prosty sposób sterowany z androida, strony www hostowanej na moim serwerze domowym, a nawet z terminala poprzez curl.
Zamiast WS2812 dałem zwykłą taśmę ledów rgb 5050, 6 mosfetów do sterowania 3-strefowego (ważniejsza była kontrola z zewnątrz i możliwość załączenia każdej strefy z osobna z poziomu jednego sterownika niż bajery z adresowaniem każdej diody z osobna. W końcu to nie jest duży problem gdy wszystkie strefy mają ten sam kolor). Całość zasilana na 9V zamiast 12V, żeby nie upalić za szybko diód (Jest ciemniej, ale służy o wiele dłużej). Żeby sterownik i mosfety się nie przegrzały, dodałem sterowanie wentylatorem na 5V. Samo sterowanie chłodzeniem nie jest już sterowane z kontrolera. Za kontrolę obrotów odpowiada mały, 100K termistor, potencjometr do ustawienia czułości i kilka śmieci, które mają to trzymać w kupie.
Dzięki za artykuł, mam już pomysł jak wykorzystać nowe informacje
Bardzo praktyczny opis, dziękuję.
niestety obrazki się nie ładują…