Popularny post crbjsfso Napisano Październik 5, 2019 Popularny post Udostępnij Napisano Październik 5, 2019 (edytowany) 1. Wprowadzenie Pewnego dnia zapragnąłem stać się właścicielem lampki nocnej RGB, którą mógłbym sterować smartfonem przy wykorzystaniu przeglądarki internetowej. Z możliwością sterowania w przyszłości takimi systemami, jak Domoticz, czy też asystentem takim jak Google Home Mini, czy Alexa Amazon. Nie potrzebuje dużej mocy, aby na przykład móc czytać przy jej świetle literaturę piękną, a raczej preferuję podejście proekologiczne w zużyciu energii. Lampka ma pełnić funkcję głównie dekoracyjną tworząc przyjemny nastrój w pomieszczeniu. Przeglądając ofertę dostępnych na rynku rozwiązań doszedłem do wniosku, że ceny tego typu urządzeń są w moim mniemaniu bardzo wysokie, więc postanowiłem zbudować lampkę własnoręcznie. Moją uwagę przykuł jeden z modeli marki Xiaomi, a mianowicie Mi Bedside Lamp (cena to około 250 pln). Na tym projekcie będę bazował podczas budowy. Całość planuję wykonać z materiałów ekologicznych, oczywiście w miarę moich skromnych możliwości. 1.1. Lampka nocna Mi Bedside Lamp Silver. 1.2. Lampka nocna Mi Bedside Lamp Silver – schemat budowy wewnętrznej. 1.3. Lampka nocna Mi Bedside Lamp Silver – prezentacja wyglądu podświetlenia w różnych kolorach. 2. WS2812 Według producenta WS2812 jest on inteligentnym sterownikiem LED z wbudowanym źródłem światła. Bliższe rzeczywistości jest jednak stwierdzenie, że układ ten składa się zazwyczaj z diody RGB 5050 z wbudowanym w nią sterownikiem WS2811. Należy zaznaczyć, że rozwiązanie to produkowane jest wielu typach obudów. Ogromną zaletą takiego rozwiązania w przeciwieństwie do konwencjonalnych diod RGB jest możliwość szeregowego łączenia i sterowania niemalże dowolną liczbą diod za pomocą pojedynczego przewodu sygnałowego z cyfrowego pinu mikrokontrolera. 2.1. Schemat szeregowego połączenia WS2812. Na rynku dostępne jest wiele wersji WS2812 w różnych obudowach. Dość popularną wersją, która została wykorzystana tym w projekcie jest wersja WS2812B w obudowie 5050. Wersja WS2812 posiada sześć nóżek, natomiast wersja z dopiskiem B tylko cztery. Największą różnicą między modelami bez dopisku B i z dopiskiem jest zabezpieczenie przed odwrotnym podłączeniem zasilania diody dla wersji B, co w przypadku standardowej wersji skutkuje zniszczeniem elementu. 2.2. Pojedyncza dioda WS2812 w wersji obudowy 5050. 2.3. Pojedyncza dioda WS2812B w wersji obudowy 5050. 2.4. Schemat szeregowego łączenia WS2812B. Podczas pracy z WS2812 niezależnie od wersji należy pamiętać, aby: Nie przekraczać napięcia zasilania powyżej 5V, ponieważ uszkodzimy układ. Dodać kondensator elektrolityczny o pojemności od 100µF do 1000µF (na 6.3V lub wyższy) przy zasilaniu pierwszej diody. Dodać rezystor o wartości od 300Ω do 1kΩ pomiędzy mikrokontrolerem, a pierwszym pinem DIN i aby umieść go jak najbliżej diody. W miarę możliwości jak najbardziej skrócić odległość pomiędzy mikrokontrolerem, a pierwszą diodą. Nie podłączać diod przy włączonym zasilaniu. Jeśli nie mamy innego wyboru, to należy zachować kolejność: masa, zasilanie, linia sterująca, a odłączamy w odwrotnej kolejności. Jeżeli diody zasilane są z oddzielnego źródła zasilania, to najpierw należy doprowadzić zasilanie do diod, a następnie do mikrokontrolera. 3. Projekt i narzędzia Główną część lampy stanowi szklany słoik, wewnątrz są warstwy rozpraszające światło w postaci arkusza kalki technicznej i białego papieru. Całość została osadzona w kartonowej podstawie. Całość będzie składała się z: Szklany słoik, najlepiej wypiaskowany aby dobrze rozpraszał światło. Ja użyłem słoika Ikea Dropper, ale nada się każdy inny podobny. Ten, którego użyłem nie jest idealny, ponieważ nie jest w całości wypiaskowany. Kalka techniczna do rozpraszania światła. Pomaga uzyskać lepsze rozproszenie, zwłaszcza gdy piaskowanie nie jest całkowite. Kartka białego papieru A4. Również pomocna przy rozpraszaniu, warto wąski pasek umieścić przy tuż przy diodach. Karton, tektura. Do do budowy podstawy, jeśli nie umiemy sobie takiej podstawy wyrzeźbić na przykład z drewna lub nie mamy drukarki 3D. Klej biurowy, przeźroczysta taśma klejąca. Ładowarka z wyjściem USB 5V 1A+. Taka, jakiej używa się się do ładowania większości smartfonów. Kabel USB – micro USB o długości dostosowanej do własnych potrzeb. W projekcie zastosowałem taki o długość 100 cm. Kondensator elektrolityczny w przedziale od 100µF do 1000µF na 6.3V. W projekcie został użyty 1000µF 6.3V. Rezystor o wartości od 300Ω do 1kΩ. W projekcie został użyty 470Ω ¼W. Gniazdo wejściowe microUSB do zasilania układu. Z racji braku gniazda użyłem moduły TP4056, co daje dodatkową możliwość zastosowania w przyszłości zasilania bateryjnego z ogniw 18650. Koło / pierścień diod WS2812B + moduł ESP8266 (ESP-01 / ESP-01S) + łącznik ESP-01S/ESP-01 RGB LED. W tym konkretnym projekcie zostało użyte koło z 16 diodami. Lutownica lub stacja lutownicza, stop lutowniczy i topnik. Przewody, kilka cm. Cążki do metalu. Śrubokręt, nożyczki, czy inne narzędzia potrzebne do obróbki wybranego materiału. 3.1. Zestaw składający się z WS2812B, ESP-01 i łącznika. 4. Schemat połączeń Jeśli korzystamy z gotowego zestawu, to schemat połączeń jest bardzo prosty. 4.1. Schemat połączeń wszystkich podzespołów. 5. Kod i programowanie #include <adafruit_neopixel.h> #include <esp8266wifi.h> const char* ssid = "<nazwa_sieci_wifi>"; const char* password = "<haslo_do_sieci_wifi>"; Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 2, NEO_GRB + NEO_KHZ800); WiFiServer server(80); long aniMillis = 0; byte aniFlag = 0; void setup() { Serial.begin(115200); delay(100); strip.begin(); for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0); strip.show(); } IPAddress ip(192, 168, 0, 100); IPAddress gateway(192, 168, 0, 1); IPAddress subnet(255, 255, 255, 0); WiFi.config(ip, gateway, subnet); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } server.begin(); } void loop() { while (WiFi.status() == WL_CONNECTED) { WiFiClient client = server.available(); if (!client) { return; } while (!client.available()) { delay(10); } String request = client.readStringUntil('\r'); client.flush(); if (request.indexOf("/off") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0); strip.show(); } } // jasnosc if (request.indexOf("/b0") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setBrightness(30); strip.show(); } } if (request.indexOf("/b1") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setBrightness(128); strip.show(); } } if (request.indexOf("/b2") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setBrightness(255); strip.show(); } } // jasnosc end // kolory // bialy if (request.indexOf("/c0") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 255, 255, 255); strip.show(); } } // zoly if (request.indexOf("/c1") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 255, 255, 0); strip.show(); } } // pomaranczowy if (request.indexOf("/c2") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 255, 127, 0); strip.show(); } } // czerwony if (request.indexOf("/c3") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 255, 0, 0); strip.show(); } } // rozany if (request.indexOf("/c4") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 255, 0, 127); strip.show(); } } // magenta if (request.indexOf("/c5") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 255, 0, 255); strip.show(); } } // fioletowy if (request.indexOf("/c6") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 127, 0, 255); strip.show(); } } // niebieski if (request.indexOf("/c7") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 0, 255); strip.show(); } } // blekitny if (request.indexOf("/c8") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 127, 255); strip.show(); } } // cyjan if (request.indexOf("/c9") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 255, 255); strip.show(); } } // wiosenna zielen if (request.indexOf("/c10") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 255, 127); strip.show(); } } // zielony if (request.indexOf("/c11") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 255, 0); strip.show(); } } // zielen chartreuse if (request.indexOf("/c12") > 0) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 127, 255, 0); strip.show(); } } // kolory end client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(""); client.println(""); client.println(""); client.println(""); client.println("<title>Lampka</title>"); client.println("<meta charset="\"utf-8\"">"); client.println("<meta name="\"apple-mobile-web-app-capable\"" content="\"yes\"">"); client.println("<meta name="\"apple-mobile-web-app-status-bar-style\"" content="\"black\"">"); client.println("<meta name="\"robots\"" content="\"none\"">"); client.println("<meta name="\"viewport\"" content="\"width=device-width," initial-scale="1\"">"); client.println("<style>"); client.println("body {background: #313236; text-align: center; padding: 0; margin: 50px 0;}"); client.println("button {border: 0; font: bold 12px Verdana, sans-serif; color: #000000; width: 85px; height: 85px; border-radius: 50%;}"); client.println(".b0 {background: #000000; color: #ffffff;}"); client.println(".b1 {background: #949494;}"); client.println(".b2 {background: #bdbebd;}"); client.println(".b3 {background: #e9e9e9;}"); client.println(".c0 {background: rgb(255, 255, 255); margin-right: 266px;}"); // bialy client.println(".c1 {background: rgb(255, 255, 0);}"); // zolty client.println(".c2 {background: rgb(255, 127, 0);}"); // pomaranczowy client.println(".c3 {background: rgb(255, 0, 0);}"); //czerwony client.println(".c4 {background: rgb(255, 0, 127);}"); // rozany client.println(".c5 {background: rgb(255, 0, 255);}"); // magenta client.println(".c6 {background: rgb(127, 0, 255);}"); // fioletowy client.println(".c7 {background: rgb(0, 0, 255);}"); // niebieski client.println(".c8 {background: rgb(0, 127, 255);}"); // blekitny client.println(".c9 {background: rgb(0, 255, 255);}"); // cyjan client.println(".c10 {background: rgb(0, 255, 127);}"); // wiosenna zielen client.println(".c11 {background: rgb(0, 255, 0);}"); // zielony client.println(".c12 {background: rgb(127, 255, 0);}"); // zielen chartreuse client.println(".mgb4 {margin-bottom: 4px;}"); client.println(".mgb50 {margin-bottom: 50px;}"); client.println("</style>"); client.println(""); client.println(""); client.println("<a href="\"/b0\""><button class="\"b1" mgb50\"="">MIN</button></a>"); client.println("<a href="\"/b1\""><button class="\"b2" mgb50\"="">50%</button></a>"); client.println("<a href="\"/b2\""><button class="\"b3" mgb50\"="">MAX</button></a>"); client.println("<a href="\"/off\""><button class="\"b0" mgb50\"="">OFF</button></a><br>"); client.println("<a href="\"/c0\""><button class="\"c0" mgb4\"=""></button></a><br>"); client.println("<a href="\"/c1\""><button class="\"c1" mgb4\"=""></button></a>"); client.println("<a href="\"/c2\""><button class="\"c2" mgb4\"=""></button></a>"); client.println("<a href="\"/c3\""><button class="\"c3" mgb4\"=""></button></a>"); client.println("<a href="\"/c4\""><button class="\"c4" mgb4\"=""></button></a><br>"); client.println("<a href="\"/c5\""><button class="\"c5" mgb4\"=""></button></a>"); client.println("<a href="\"/c6\""><button class="\"c6" mgb4\"=""></button></a>"); client.println("<a href="\"/c7\""><button class="\"c7" mgb4\"=""></button></a>"); client.println("<a href="\"/c8\""><button class="\"c8" mgb4\"=""></button></a><br>"); client.println("<a href="\"/c9\""><button class="\"c9\""></button></a>"); client.println("<a href="\"/c10\""><button class="\"c10\""></button></a>"); client.println("<a href="\"/c11\""><button class="\"c11\""></button></a>"); client.println("<a href="\"/c12\""><button class="\"c12\""></button></a>"); client.println(""); client.println(""); delay(10); } setup(); } 6. Efekt końcowy Efekt końcowy prezentuje się tak, jak to widać na poniższych zdjęciach. Należy zaznaczyć, że w rzeczywistości podświetlenie jest bardziej jednolite, niż widać to na zdjęciach. Prawdopodobnie ekspozycja podczas robienia zdjęcia byłą zbyt długa, ale ciężko zrobić w inny sposób zdjęcia w nocy bez dobrego sprzętu. Obsługa lampki odbywa się przez interfejs sieciowy pod adresem 192.168.0.100. 6.1. Interfejs sieciowy pod adresem 192.168.0.100. 6.2. Wnętrze podstawy lampy. 6.3. Warstwy rozpraszające światło bez i z koszem. 6.4. Wybrane kolory. Edytowano Październik 5, 2019 przez Treker Poprawiłem formatowanie 7 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Październik 5, 2019 Udostępnij Październik 5, 2019 @crbjsfso witam na forum i gratuluję ciekawego projektu 🙂 1 Cytuj Link do komentarza Share on other sites More sharing options...
Leoneq Październik 8, 2019 Udostępnij Październik 8, 2019 Muszę powiedzieć, rewelacyjny artykuł, który opisuje wszystko i taki typowy początkujący raczej nie będzie mieć pytań. Sam projekt podoba mi się, dość kreatywne zastosowanie zasobów wtórnych. Życzę powodzenia w dalszych projektach. 2 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!