Dzisiejszy artykuł będzie kontynuacją wpisu związanego z układem WS2812b. Chciałem Wam przedstawić krok po kroku, jak w prosty sposób zbudować sterowanie RGB WS2812b za pomocą pilota IR. Nauczymy się pisać własne funkcje oraz wykorzystamy instrukcję switch. Funkcje są głównym narzędziem służącym do tworzenia przejrzystych szkiców, które można łatwo modyfikować bez ryzyka uszkodzenia całej aplikacji. Po przeczytaniu wpisu, może ktoś z Was zdecyduje się zrobić oświetlenie świąteczne, wykorzystując możliwości Arduino i diod z układem WS2812b. Zapraszam do dalszej lektury.
Dla przypomnienia, listwa Arduino NEOPIXEL WS2812B to moduł 8×1 znaków zgodny z bibliotekami Adafriut NEOPIXEL. Każda dioda RGB na module może zostać włączona indywidualnie na dowolny kolor. Jedna dioda posiada 3X PWM 8bit. Pobór prądu dla jednej diody to około 18 mA. Listwę można zakupić w serwisie allegro oraz w sklepie botland.com.pl Ceny zaczynają się od 13zł za pasek.
Aby wykonać projekt potrzebujemy:
- Arduino UNO
- pasek LED RGB WS2812B
- Odbiornik podczerwieni TSOP31236 (lub podobny)
- Dowolny pilot z diodą IR
- płytka stykowa, przewody
Wykorzystane biblioteki:
Funkcje układu:
- zmiana kolorów za pomocą pilota
- 6 kolorów do wyboru (możliwość dołożenia dodatkowych)
- kolory: zielony, czerwony, niebieski, żółty, biały, fioletowy
- przycisk wyłączenia OFF
Zasada działania:
Wciskając przycisk na pilocie wysyłamy odpowiednie sygnały IR. Odbiornik podczerwieni odbiera sygnały z pilota. Następnie, instrukcja switch sprawdza czy dany przycisk jest przypisany do odpowiedniej funkcji. Każda funkcja to inny kolor. Jeżeli instrukcja switch odnalazła kod (np.: 0xFD00FF) odpowiadający naszej funkcji – następuje zmiana koloru.
Zaczynamy!
Po zbudowaniu układu, musimy odczytać jakie sygnały wysyła nasz pilot. Do tego wykorzystamy prosty sketch, który ma za zadanie odebrać i wyświetlić w monitorze portu szeregowego odpowiednie wartości.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <IRremote.h> #define irPin 11 IRrecv irrecv(irPin); decode_results results; void setup() { Serial.begin(9600); irrecv.enableIRIn(); } void loop() { if (irrecv.decode(&results)) { Serial.print("0x"); Serial.println(results.value, HEX); delay(250); irrecv.resume(); } } |
Po wgraniu szkicu, uruchamiamy monitor portu szeregowego, wybierając z menu Narzędzia-> Monitor portu szeregowego. Po skierowaniu pilota w stronę odbiornika i wciśnięciu dowolnego przycisku, powinny się wyświetlać odpowiednie wartości. Warto zapisać, które wartości odpowiadają konkretnym przyciskom, gdyż łatwiej nam później będzie przypisać przycisk do odpowiedniej funkcji. Ja zapisałem sobie przyciski od 1 do 6 oraz przycisk OFF. Te przyciski będę wykorzystywał do sterowania listwą. Przyciski od 1 do 6 to konkretne kolory, natomiast przycisk OFF wyłącza listwę.
Funkcje w Arduino
Funkcja odgrywa rolę małego programu występującego w pisanym przez nas większym programie. W funkcji można zawrzeć pojedyncze czynności, które chcemy wykonać. Zdefiniowana
funkcja może być użyta w dowolnym miejscu szkicu, zawiera własne zmienne i własną listę poleceń. Gdy polecenia zawarte w funkcji zostaną wykonane, program powraca do miejsca w szkicu, gdzie znajdował się kod wywołujący funkcję, a następnie wykonywane są kolejne polecenia.
Przykład (Arduino dla początkujących – podstawy i szkice Simon Monk)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
int ledPin = 13; int delayPeriod = 250; void setup() { pinMode(ledPin, OUTPUT); } void loop() { for (int i = 0; i < 20; i ++) { flash(); } delay(3000); } void flash() { digitalWrite(ledPin, HIGH); delay(delayPeriod); digitalWrite(ledPin, LOW); delay(delayPeriod); } |
Tak naprawdę jedyne, co zrobiliśmy, to przeniesienie kodu powodującego błyskanie diody LED ze środka pętli for do oddzielnej funkcji o nazwie flash. Teraz możesz spowodować dowolną liczbę błysków, wywołując nową funkcję przy użyciu polecenia flash(). Zwróć uwagę na puste nawiasy umieszczone bezpośrednio za nazwą funkcji. Oznaczają one, że funkcja nie pobiera żadnych parametrów. Wartość opóźnienia jest określana przez funkcję delayPeriod, która była zastosowana wcześniej.
Instrukcja switch
Instrukcja switch zwana jest także instrukcją wyboru. Działa ona w ten sposób, że wybiera spośród dostępnego zbioru określoną wartość na podstawie wartości pewnego wyrażenia i wykonuje zdefiniowany dla niej kod.
1 2 3 4 5 6 7 8 9 10 11 |
switch(wyrażenie_kluczowe) { case wartosc_1: instrukcje; break; case wartosc_2: instrukcje; break; //// to słowo kluczowe przerywa dalsze wykonywanie instrukcji i wychodzi z bloku <em>switch</em> } |
Opis sketch:
Na samym początku podpinamy wcześniej wymienione biblioteki oraz definiujemy użyte piny. Uruchamiamy biblioteki odpowiedzialne za listwę oraz odbiornik IR. Następnie przechodzimy do instrukcji switch, która sprawdza, czy w odebranych danych (results.value) znajduje się któryś z naszych kodów. Jeżeli instrukcja znajdzie odpowiedni, kod uruchamia zdefiniowaną funkcję. Każda funkcja to inny kolor. Kolor definiujemy za pomocą składowej (R,G,B) wartościami od 0 do 255. Np. kolor niebieski posiada wartość (o,0,255). Do generowaniem kolorów przyda nam się paleta RGB. Aby dodać kolejne kolory tworzymy nową funkcję, nadajemy jej nazwę oraz ustawiamy odpowiedni kolor. Pamiętamy, aby dodać do instrukcji switch odpowiedni case dla konkretnego przycisku.
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 |
#include <Adafruit_NeoPixel.h> #include <IRremote.h> #define PIN 6 // numer portu do ktorego podlaczony jest pasek #define irPin 7 #define ILOSCDIOD 8 // ilosc diod w pasku Adafruit_NeoPixel pixels = Adafruit_NeoPixel(ILOSCDIOD, PIN, NEO_GRB + NEO_KHZ800); IRrecv irrecv(irPin); decode_results results; void setup() { Serial.begin(9600); pixels.begin(); // Inicjalizacja biblioteki irrecv.enableIRIn(); // uruchomienie odbiornika IR } void loop() { if (irrecv.decode(&results)) { switch (results.value) { case 0xFD00FF: //przycisk off off(); break; case 0xFD08F7: //przycisk nr1 red(); break; case 0xFD8877: //przycisk nr2 green(); break; case 0xFD48B7: //przycisk nr3 blue(); break; case 0xFD28D7: //przycisk nr4 yellow(); break; case 0xFDA857: //przycisk nr5 white(); break; case 0xFD6897: //przycisk nr6 violet(); break; } irrecv.resume(); } } ////////////////////////// funkcje zawierające skladowe kolorow //////////////////// void red() //funkcja koloru czerwonego { for(int i=0; i<8; i++) { pixels.setPixelColor(i, 255, 0, 0); // Dioda "i" oraz odpowiednie skladowe RGB pixels.show(); // Wysylanie danych do lancucha } } void green() //funkcja koloru zielonego { for(int i=0; i<8; i++) { pixels.setPixelColor(i, 0, 255, 0); // Dioda "i" oraz odpowiednie skladowe RGB pixels.show(); // Wysylanie danych do lancucha } } void blue() //funkcja koloru niebieskiego { for(int i=0; i<8; i++) { pixels.setPixelColor(i, 0, 0, 255); // Dioda "i" oraz odpowiednie skladowe RGB pixels.show(); // Wysylanie danych do lancucha } } void yellow() //funkcja koloru żółtego { for(int i=0; i<8; i++) { pixels.setPixelColor(i, 255, 255, 0); // Dioda "i" oraz odpowiednie skladowe RGB pixels.show(); // Wysylanie danych do lancucha } } void white() //funkcja koloru białego { for(int i=0; i<8; i++) { pixels.setPixelColor(i, 255, 255, 255); // Dioda "i" oraz odpowiednie skladowe RGB pixels.show(); // Wysylanie danych do lancucha } } void violet() //funkcja koloru fioletowego { for(int i=0; i<8; i++) { pixels.setPixelColor(i, 204, 0, 102); // Dioda "i" oraz odpowiednie skladowe RGB pixels.show(); // Wysylanie danych do lancucha } } void off() //funkcja wylaczenia paska { for(int i=0; i<8; i++) { pixels.setPixelColor(i, 0, 0, 0); // Dioda "i" oraz odpowiednie skladowe RGB pixels.show(); // Wysylanie danych do lancucha } } |
Zakończenie
Mam nadzieję że artykuł jest zrozumiały. Życzę Wam miłego majsterkowania i jak zwykle, pozostaję do Waszej dyspozycji w przypadku problemów czy pytań.