DIY-Beleuchtung mit WLED: Programmierung eines ESP Lichtmixers
Einführung
Nachdem der vorangegangene Teil 3 in die Kommunikationsprotokolle eingeführt hat, werden wir diese im aktuellen Beitrag nutzen, um mit einem ESP32 ein Lichtsteuerpult zu bauen, auf welchem mit Rotaryencodern die gewünschte Farbe einfach aus den RGB-Anteilen gemischt werden kann. Des Weiteren gibt es noch einen Encoder für den Effekt. Somit wird die bisherige Softwaresteuerung um eine einfach zu bedienende haptische Steuerung erweitert.
Um einen Überblick über die eingestellten Parameter zu erhalten, verwenden wir noch ein kleines 0.96“ OLED Display.
Hardware
An Hardware benötigen Sie:
ESP32 Board
5x Rotaryencoder
OLED Display
Breadboard groß
Breadboard klein
Jumperkabel
Für den Aufbau müssen Sie eine Stromschiene des kleinen Breadboards abtrennen, damit der Abstand klein genug ist, um den ESP32 darauf stecken zu können. Verkabeln Sie als Nächstes die Komponenten wie folgt:
GPIO: |
Encoder Pin: |
|
27 |
Helligkeit CLK |
|
26 |
Helligkeit DT |
|
14 |
Rot CLK |
|
13 |
Rot DT |
|
17 |
Grün CLK |
|
16 |
Grün DT |
|
19 |
Blau CLK |
|
18 |
Blau DT |
|
34 |
Effekt CLK |
|
35 |
Effekt DT |
GPIO: |
Display Pin: |
|
22 |
SCL |
|
21 |
SDA |
|
Software
In den anderen Teilen (Teil 1, Teil 2, Teil 3) kamen wir ohne Programmieren aus. Dieses Mal nutzen wir einen Sketch, den wir über die Arduino IDE auf den Mikrocontroller laden.
Falls Sie das erste Mal einen ESP32 programmieren, kopieren Sie folgenden Link in die Arduino IDE unter: File->Preferences->Additional boards manager URLs : https://dl.espressif.com/dl/package_esp32_index.json
und installieren Sie in der Boardverwaltung das ESP32 Packet.
Der Treiber (CP2102) für dieses Board sollte schon vom Betriebssystem vorinstalliert sein.
Installieren Sie folgende Libraries:
‚Adafruit GFX‘ und ‚Adafruit SSD1306‘ über den Library Manager in der Arduino IDE (Sketch > Include Library > Manage Libraries)
‚ESP32Encoder‘: Laden Sie die ZIP-Datei von GitHub herunter und installieren Sie diese in der Arduino IDE über Sketch > Include Library > Add .ZIP Library
Wählen Sie als Nächstes das Board (ESP32 Dev Module) am richtigen COM-Port aus und laden Sie folgenden Code auf ihr Board:
Download
Die Erklärungen finden Sie dieses Mal als Kommentare im Quellcode
//Einbindung der LIbrarys #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <ESP32Encoder.h> #include <WiFi.h> #include <HTTPClient.h> // Display Konfiguration #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); //Wlan Zugangsdaten const char* ssid = "ssid"; const char* password = "pswrd"; // IP-Adresse des WLED-Controllers String wled_ip = "192.168.xxx.xxx"; //Objekte der Encoder Klasse für jeden Rotaryencoder ESP32Encoder brightnessEncoder, redEncoder, greenEncoder, blueEncoder, effectEncoder; // Encoder Pins #define BRIGHTNESS_A 26 #define BRIGHTNESS_B 27 #define RED_A 13 #define RED_B 14 #define GREEN_A 16 #define GREEN_B 17 #define BLUE_A 18 #define BLUE_B 19 #define EFFECT_A 35 #define EFFECT_B 34 // Variablen für WLED-Steuerung int brightness = 128; // Helligkeit: 0-255 int red = 128; // Rotwert: 0-255 int green = 128; // Grünwert: 0-255 int blue = 128; // Blauwert: 0-255 int effect = 0; // Effekt-ID in WLED //Array mit Effektnamen für Anzeige auf dem Display const char* effectNames[] = { "Solid", "Blink", "Breathe", "Wipe", "Wipe Random", "Random Colors", "Sweep", "Dynamic", "Colorloop", "Rainbow", "Scan", "Dual Scan", "Fade", "Chase", "Chase Rainbow", "Running", "Saw", "Twinkle", "Dissolve", "Dissolve Rnd", "Sparkle", "Dark Sparkle", "Sparkle+", "Strobe", "Strobe Rainbow", "Mega Strobe", "Blink Rainbow", "Android", "Chase", "Chase Random", "Chase Rainbow", "Chase Flash", "Chase Flash Rnd", "Rainbow Runner", "Colorful", "Traffic Light", "Sweep Random", "Running 2", "Red & Blue","Stream", "Scanner", "Lighthouse", "Fireworks", "Rain", "Tetrix", "Fire Flicker", "Gradient", "Loading", "In Out", "In In", "Out Out", "Out In", "Circus", "Halloween", "Tri Chase", "Tri Wipe", "Tri Fade", "Lightning", "ICU", "Multi Comet", "Dual Scanner", "Stream 2", "Oscillate", "Pride 2015", "Juggle", "Palette", "Fire 2012", "Colorwaves", "BPM", "Fill Noise", "Noise 1", "Noise 2", "Noise 3", "Noise 4", "Colortwinkle", "Lake", "Meteor", "Smooth Meteor", "Railway", "Ripple" }; //Hilfvariable bei http Kommunikationsproblem boolean ERR = 0; void updateWLED(); void displayValuesOnScreen(); void setup() { Serial.begin(115200); // Display initialisieren if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("OLED nicht gefunden!")); while (true); } display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); //interne Pullup Widerstände setzen ESP32Encoder::useInternalWeakPullResistors = puType::up; // Rotary Encoder initialisieren brightnessEncoder.attachHalfQuad(BRIGHTNESS_A, BRIGHTNESS_B); redEncoder.attachHalfQuad(RED_A, RED_B); greenEncoder.attachHalfQuad(GREEN_A, GREEN_B); blueEncoder.attachHalfQuad(BLUE_A, BLUE_B); effectEncoder.attachHalfQuad(EFFECT_A, EFFECT_B); //Encoder auf Standardwerte setzen brightnessEncoder.setCount(brightness); redEncoder.setCount(red); greenEncoder.setCount(green); blueEncoder.setCount(blue); effectEncoder.setCount(effect); // WLAN-Verbindung herstellen WiFi.begin(ssid, password); display.clearDisplay(); display.setCursor(0, 0); display.print("Connect to WiFi:"); display.setCursor(0, 16); display.print(ssid); display.display(); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); if(millis() > 30000) ESP.restart(); //falls nach 30sek keine Verbindung aufgebaut ist dann neustarten } display.clearDisplay(); display.setCursor(0, 0); display.println("WiFi connected!"); display.display(); delay(1000); } void loop() { // Encoder Werte lesen (constrain begrenzt den Wert) brightness = constrain(brightnessEncoder.getCount(), 0, 255); red = constrain(redEncoder.getCount(), 0, 255); green = constrain(greenEncoder.getCount(), 0, 255); blue = constrain(blueEncoder.getCount(), 0, 255); effect = constrain(effectEncoder.getCount(), 0, 80); // WLED unterstützt Effekte bis ID 80 updateWLED(); displayValuesOnScreen(); delay(100); // Abfragerate } // Funktion sendet die HTTP-Requests an WLED void updateWLED() { if (WiFi.status() == WL_CONNECTED) { // Verbindung überprüfen HTTPClient http; // Adresse aus bestandteilen zusammenbauen String url = "http://" + wled_ip + "/win"; url += "&A=" + String(brightness); url += "&R=" + String(red); url += "&G=" + String(green); url += "&B=" + String(blue); url += "&FX=" + String(effect); http.begin(url); // Request initialisieren int httpCode = http.GET(); // GET-Request senden if (httpCode > 0) { Serial.printf("WLED aktualisiert: %d\n", httpCode); ERR = false; } else { //Fehler beim verbinden Serial.printf("Fehler bei WLED-Update: %s\n", http.errorToString(httpCode).c_str()); ERR = true; } http.end(); } } // Funktion zur Anzeige der Werte auf dem OLED-Display void displayValuesOnScreen() { display.clearDisplay(); display.setCursor(0, 0); display.setTextSize(1); // Titel display.println("WLED Control Panel"); if(ERR) {//Verbindungsproblem!! display.println("xxxxxxxxxxxxxxxxxx"); return; } else { display.println("=================="); } // Helligkeit anzeigen display.setCursor(0, 16); display.print("Brightness: "); display.println(brightness); // Rot-Wert anzeigen display.setCursor(0, 24); display.print("Red: "); display.println(red); // Grün-Wert anzeigen display.setCursor(0, 32); display.print("Green: "); display.println(green); // Blau-Wert anzeigen display.setCursor(0, 40); display.print("Blue: "); display.println(blue); // Effekt anzeigen display.setCursor(0, 48); display.print("Effect: "); display.println(effectNames[effect]); display.display(); }
Fazit
Mit dem neuen Lichtcontroller lassen sich einfach Farben mischen und Effekte abspielen. Um noch mehr Flexibilität zu erhalten, könnte zum Beispiel noch ein weiterer Encoder hinzugefügt werden, um die Effektgeschwindigkeit (&SX=) einstellen zu können. Aber es können auch Schiebepotentiometer statt der Encoder verwendet werden, um die Parameter flüssiger zu mischen. Sie können auch den Breadboardaufbau in ein 3D-gedrucktes Gehäuse einsetzen.
Hier wird das Potenziometer als Spannungsteiler verschaltet, sodass die Spannung einfach über den Schleifkontakt abgegriffen werden kann. Im Programm muss der encoder.getCount() Befehl durch analogRead(pin) ersetzt werden.
Falls eine schnellere Reaktion auf die eingestellten Parameter gewünscht ist, empfiehlt es sich, einen Blick auf die Steuerung über UDP zu werfen (WLED doc).
Der eigenen Kreativität sind hier keine Grenzen gesetzt.
Sollten Sie an dieser Stelle kein Video sehen, ändern Sie bitte die Cookie-Einstellungen Ihres Internetbrowsers
Viel Spaß beim Nachbauen:)