From 513bc2c0ab1577dff4638592277c9f5f89019938 Mon Sep 17 00:00:00 2001 From: Def3nder Date: Sun, 23 Feb 2020 22:21:32 +0100 Subject: [PATCH 1/3] Correct SunRise/NightLight with Color Fade (#710) --- wled00/wled08_led.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/wled08_led.ino b/wled00/wled08_led.ino index 8aeac5dfb..d1ccc0d66 100644 --- a/wled00/wled08_led.ino +++ b/wled00/wled08_led.ino @@ -231,15 +231,15 @@ void handleNightlight() nightlightDelayMs = (int)(nightlightDelayMins*60000); nightlightActiveOld = true; briNlT = bri; - for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color + for (byte i=0; i<4; i++) colNlT[i] = colT[i]; // remember starting color } float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs); if (nightlightFade) { bri = briNlT + ((nightlightTargetBri - briNlT)*nper); - if (nightlightColorFade) // color fading only is enabled with "NF=2" + if (nightlightColorFade) // color fading only is enabled with "NF=2" { - for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color + for (byte i=0; i<4; i++) colT[i] = colNlT[i]+ ((colSecT[i] - colNlT[i])*nper); // fading from actual color to secondary color } colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY); } From 8be72f6f2353e87c36a4ee93804fa83793128b23 Mon Sep 17 00:00:00 2001 From: jwingefeld Date: Sun, 23 Feb 2020 22:24:51 +0100 Subject: [PATCH 2/3] DMX Support for WLED (#704) * initial dmx setup * adds support for multiple fixtures, addr gaps, start addresses and all that good DMX stuff * removes init function. do not need. * adds some comments, removes others. words. * added menu entry and dummy HTML * added server request handler * cloned options page UI for DMX * only add code when DMX is enabled * added infobutton to HTML * DMX settings form * procedurally generated HTML form. OBACHT: Values still not coming from the EEPROM. * upped eeprom version to 15 * changed index for set to 255 to 6 because web interface wants it that way * gets values for XML from actual settings * changes the default values for dmx to blanks * reads and writes DMX settings from EEPROM (2550 - 2569) * fixes addressing bug in DMX EEPROM read * saves settings from WebUI to memory * disables DMX by default * changed a comment in the ENABLE_DMX line * makes the display of the DMX entry in settings dependant on WLED_DMX_ENABLE * adds the server listener for the DMX map * fixes a bug when selecting 255 for a channel at the dmx settings page * now actually reads the DMX settings back to the HTML UI. * cleans up a little * adds a warning message to the HTML UI when setting up defunct DMX settings * changed DMX EEPROM addressing to close a gap * basic DMX map * fixes a few styling flaws and bugs in the DMX map * changes config variables to uint16_t Co-authored-by: Aircoookie --- wled00/html_other.h | 30 +++++++ wled00/html_settings.h | 69 +++++++++++++-- wled00/wled00.ino | 187 +++++++++++++++++++++------------------ wled00/wled01_eeprom.ino | 26 +++++- wled00/wled02_xml.ino | 27 +++++- wled00/wled03_set.ino | 28 +++++- wled00/wled05_init.ino | 4 +- wled00/wled18_server.ino | 49 +++++++++- wled00/wled21_dmx.ino | 55 ++++++++++++ 9 files changed, 378 insertions(+), 97 deletions(-) create mode 100644 wled00/wled21_dmx.ino diff --git a/wled00/html_other.h b/wled00/html_other.h index c7d3e855a..e27c64dde 100644 --- a/wled00/html_other.h +++ b/wled00/html_other.h @@ -15,6 +15,36 @@ const char PAGE_msg[] PROGMEM = R"=====(

%MSG%)====="; +//DMX channel map +const char PAGE_dmxmap[] PROGMEM = R"=====( + +DMX Map + + +
...
)====="; + //firmware update page const char PAGE_update[] PROGMEM = R"=====( diff --git a/wled00/html_settings.h b/wled00/html_settings.h index a3ba54a2e..157d6b4ca 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -1,23 +1,23 @@ /* - * Settings html - */ + Settings html +*/ //common CSS of settings pages const char PAGE_settingsCss[] PROGMEM = R"=====()====="; - //settings menu const char PAGE_settings[] PROGMEM = R"=====( -WLED Settings +WLED Settings
-
+
%DMXMENU%
+ )====="; @@ -172,6 +172,64 @@ Skip first LED:
)====="; +#ifdef WLED_ENABLE_DMX +//DMX Output settings +const char PAGE_settings_dmx[] PROGMEM = R"=====( +DMX Settings"); } diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index f7485917d..0f2cb9ef3 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -27,8 +27,9 @@ bool isAsterisksOnly(const char* str, byte maxLen) //called upon POST settings form submit void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) { - //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec - if (subPage <1 || subPage >6) return; + + //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX + if (subPage <1 || subPage >7) return; //WIFI SETTINGS if (subPage == 1) @@ -293,6 +294,29 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) aOtaEnabled = request->hasArg("AO"); } } + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled + if (subPage == 7) + { + int t = request->arg("CN").toInt(); + if (t>0 && t<16) { + DMXChannels = t; + } + t = request->arg("CS").toInt(); + if (t>0 && t<513) { + DMXStart = t; + } + t = request->arg("CG").toInt(); + if (t>0 && t<513) { + DMXGap = t; + } + for (int i=0; i<15; i++) { + String argname = "CH" + String((i+1)); + t = request->arg(argname).toInt(); + DMXFixtureMap[i] = t; + } + } + + #endif if (subPage != 6 || !doReboot) saveSettingsToEEPROM(); //do not save if factory reset if (subPage == 2) { strip.init(useRGBW,ledCount,skipFirstLed); diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index c4f0b45bd..bf1be5d99 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -83,7 +83,9 @@ void wledInit() if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS); } #endif - + #ifdef WLED_ENABLE_DMX + dmx.init(512); // initialize with bus length + #endif //HTTP server page init initServer(); } diff --git a/wled00/wled18_server.ino b/wled00/wled18_server.ino index f7162d3e5..cf67e79f8 100644 --- a/wled00/wled18_server.ino +++ b/wled00/wled18_server.ino @@ -82,6 +82,11 @@ void initServer() serveMessage(request, 200,"UI settings saved.","Redirecting...",1); }); + server.on("/settings/dmx", HTTP_POST, [](AsyncWebServerRequest *request){ + handleSettingsSet(request, 7); + serveMessage(request, 200,"UI settings saved.","Redirecting...",1); + }); + server.on("/settings/sync", HTTP_POST, [](AsyncWebServerRequest *request){ handleSettingsSet(request, 4); serveMessage(request, 200,"Sync settings saved.","Redirecting...",1); @@ -201,6 +206,16 @@ void initServer() }); } + + #ifdef WLED_ENABLE_DMX + server.on("/dmxmap", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send_P(200, "text/html", PAGE_dmxmap , dmxProcessor); + }); + #else + server.on("/dmxmap", HTTP_GET, [](AsyncWebServerRequest *request){ + serveMessage(request, 501, "Not implemented", "DMX support is not enabled in this build.", 254); + }); + #endif server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ if (captivePortal(request)) return; serveIndexOrWelcome(request); @@ -301,10 +316,38 @@ String settingsProcessor(const String& var) getSettingsJS(optionType, buf); return String(buf); } + + #ifdef WLED_ENABLE_DMX + + if (var == "DMXMENU") { + return String("
"); + } + + #endif if (var == "SCSS") return String(FPSTR(PAGE_settingsCss)); return String(); } +String dmxProcessor(const String& var) +{ + String mapJS; + #ifdef WLED_ENABLE_DMX + if (var == "DMXVARS") { + mapJS += "\nCN=" + String(DMXChannels) + ";\n"; + mapJS += "CS=" + String(DMXStart) + ";\n"; + mapJS += "CG=" + String(DMXGap) + ";\n"; + mapJS += "LC=" + String(ledCount) + ";\n"; + mapJS += "var CH=["; + for (int i=0;i<15;i++) { + mapJS += String(DMXFixtureMap[i]) + ","; + } + mapJS += "0];"; + } + #endif + + return mapJS; +} + void serveSettings(AsyncWebServerRequest* request) { @@ -318,6 +361,9 @@ void serveSettings(AsyncWebServerRequest* request) else if (url.indexOf("sync") > 0) subPage = 4; else if (url.indexOf("time") > 0) subPage = 5; else if (url.indexOf("sec") > 0) subPage = 6; + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled + else if (url.indexOf("dmx") > 0) subPage = 7; + #endif } else subPage = 255; //welcome page if (subPage == 1 && wifiLock && otaLock) @@ -339,7 +385,8 @@ void serveSettings(AsyncWebServerRequest* request) case 4: request->send_P(200, "text/html", PAGE_settings_sync, settingsProcessor); break; case 5: request->send_P(200, "text/html", PAGE_settings_time, settingsProcessor); break; case 6: request->send_P(200, "text/html", PAGE_settings_sec , settingsProcessor); break; + case 7: request->send_P(200, "text/html", PAGE_settings_dmx , settingsProcessor); break; case 255: request->send_P(200, "text/html", PAGE_welcome); break; - default: request->send_P(200, "text/html", PAGE_settings); + default: request->send_P(200, "text/html", PAGE_settings , settingsProcessor); } } diff --git a/wled00/wled21_dmx.ino b/wled00/wled21_dmx.ino new file mode 100644 index 000000000..4230f07d8 --- /dev/null +++ b/wled00/wled21_dmx.ino @@ -0,0 +1,55 @@ +/* + * Support for DMX via MAX485. + * Needs the espdmx library. You might have to change the output pin within the library. Sketchy, i know. + * https://github.com/Rickgg/ESP-Dmx + */ +#ifdef WLED_ENABLE_DMX + +void handleDMX() { + // TODO: calculate brightness manually if no shutter channel is set + + uint8_t brightness = strip.getBrightness(); + + for (int i = 0; i < ledCount; i++) { // uses the amount of LEDs as fixture count + + uint32_t in = strip.getPixelColor(i); // time to get the colors for the individual fixtures as suggested by AirCookie at issue #462 + byte w = in >> 24 & 0xFF; + byte r = in >> 16 & 0xFF; + byte g = in >> 8 & 0xFF; + byte b = in & 0xFF; + + int DMXFixtureStart = DMXStart + (DMXGap * i); + for (int j = 0; j < DMXChannels; j++) { + int DMXAddr = DMXFixtureStart + j; + switch (DMXFixtureMap[j]) { + case 0: // Set this channel to 0. Good way to tell strobe- and fade-functions to fuck right off. + dmx.write(DMXAddr, 0); + break; + case 1: // Red + dmx.write(DMXAddr, r); + break; + case 2: // Green + dmx.write(DMXAddr, g); + break; + case 3: // Blue + dmx.write(DMXAddr, b); + break; + case 4: // White + dmx.write(DMXAddr, w); + break; + case 5: // Shutter channel. Controls the brightness. + dmx.write(DMXAddr, brightness); + break; + case 6:// Sets this channel to 255. Like 0, but more wholesome. + dmx.write(DMXAddr, 255); + break; + } + } + } + + dmx.update(); // update the DMX bus +} + +#else +void handleDMX() {} +#endif From e8fd5de5b26ec084d09e48749fb8608f6c182b5a Mon Sep 17 00:00:00 2001 From: Def3nder Date: Mon, 24 Feb 2020 12:18:30 +0100 Subject: [PATCH 3/3] HTML API "/url" for the current effect settings (#664) --- wled00/wled02_xml.ino | 47 ++++++++++++++++++++++++++++++++++++++++ wled00/wled18_server.ino | 4 ++++ 2 files changed, 51 insertions(+) diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino index 561f7723d..e5083131d 100644 --- a/wled00/wled02_xml.ino +++ b/wled00/wled02_xml.ino @@ -99,6 +99,53 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr) if (request != nullptr) request->send(200, "text/xml", obuf); } +char* URL_response(AsyncWebServerRequest *request) +{ + char sbuf[256]; //allocate local buffer if none passed + char s2buf[100]; + obuf = s2buf; + olen = 0; + + char s[16]; + oappend("http://"); + IPAddress localIP = WiFi.localIP(); + sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); + oappend(s); + oappend("/win&A="); + oappendi(bri); + oappend("&CL=h"); + for (int i = 0; i < 3; i++) + { + sprintf(s,"%02X", col[i]); + oappend(s); + } + oappend("&C2=h"); + for (int i = 0; i < 3; i++) + { + sprintf(s,"%02X", colSec[i]); + oappend(s); + } + oappend("&FX="); + oappendi(effectCurrent); + oappend("&SX="); + oappendi(effectSpeed); + oappend("&IX="); + oappendi(effectIntensity); + oappend("&FP="); + oappendi(effectPalette); + + obuf = sbuf; + olen = 0; + + oappend(""); + oappend(s2buf); + oappend(""); + + if (request != nullptr) request->send(200, "text/html", obuf); +} + //append a numeric setting to string buffer void sappend(char stype, const char* key, int val) { diff --git a/wled00/wled18_server.ino b/wled00/wled18_server.ino index cf67e79f8..826425d13 100644 --- a/wled00/wled18_server.ino +++ b/wled00/wled18_server.ino @@ -143,6 +143,10 @@ void initServer() request->send_P(200, "text/html", PAGE_usermod); }); + server.on("/url", HTTP_GET, [](AsyncWebServerRequest *request){ + URL_response(request); + }); + server.on("/teapot", HTTP_GET, [](AsyncWebServerRequest *request){ serveMessage(request, 418, "418. I'm a teapot.", "(Tangible Embedded Advanced Project Of Twinkling)", 254); });