diff --git a/readme.md b/readme.md
index 8225e21517..b6abc86f3b 100644
--- a/readme.md
+++ b/readme.md
@@ -3,22 +3,25 @@
WLED is a fast and (relatively) secure implementation of an ESP8266 webserver to control NeoPixel (WS2812B) LEDs!
Now also with experimental ESP32 support.
-### Features: (V0.5.0)
+### Features: (V0.6.0)
- RGB, HSB, and brightness sliders
- Settings page - configuration over network
- Access Point and station mode - automatic failsafe AP
- WS2812FX library integrated for over 50 special effects!
- Secondary color support lets you use even more effect combinations
+- Alexa smart home device server (including dimming)
+- Beta syncronization to Philips hue lights
- Support for RGBW strips
- 25 user presets! Save your favorite colors and effects and apply them easily!
+- HTTP request API for simple integration
+- Macro functions to automatically execute API calls
- Nightlight function (gradually dims down)
- Notifier function (multiple ESPs sync color via UDP broadcast)
- Support for power pushbutton
- Custom Theater Chase
- Full OTA software update capability (HTTP and ArduinoOTA)
- Password protected OTA page for added security (OTA lock)
-- Alexa smart home device server (including dimming)
-- NTP and experimental analog clock function
+- NTP and configurable analog clock function
- Support for the Cronixie Clock kit by Diamex
- Realtime UDP Packet Control (WARLS) possible
- Client HTML UI controlled, customizable themes
diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp
index 7e60af38da..0d6958cee7 100644
--- a/wled00/WS2812FX.cpp
+++ b/wled00/WS2812FX.cpp
@@ -2040,12 +2040,17 @@ void WS2812FX::setBrightness(byte b)
void WS2812FX::show()
{
#ifdef ARDUINO_ARCH_ESP32
+ #ifdef WORKAROUND_ESP32_BITBANG
delay(1);
portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
+ #endif
+ #endif
NeoPixelBrightnessBus::Show();
+
+ #ifdef ARDUINO_ARCH_ESP32
+ #ifdef WORKAROUND_ESP32_BITBANG
portENABLE_INTERRUPTS();
- #else
- NeoPixelBrightnessBus::Show();
+ #endif
#endif
}
diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h
index 87755e46ef..047df7fd73 100644
--- a/wled00/WS2812FX.h
+++ b/wled00/WS2812FX.h
@@ -1,10 +1,16 @@
//#define RGBW
#define PIN 2 //strip pin. Only change for ESP32
+#define WORKAROUND_ESP32_BITBANG
+//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support
//automatically uses the right driver method for each platform
#ifdef ARDUINO_ARCH_ESP32
+#ifdef WORKAROUND_ESP32_BITBANG
#define PIXELMETHOD NeoEsp32BitBangWs2813Method
#else
+#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method
+#endif
+#else
#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod
#endif
diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm
index 44368c827a..324a226d22 100644
Binary files a/wled00/data/settings_leds.htm and b/wled00/data/settings_leds.htm differ
diff --git a/wled00/htmls01.h b/wled00/htmls01.h
index 2bd7b7bdf9..54e0600013 100644
--- a/wled00/htmls01.h
+++ b/wled00/htmls01.h
@@ -117,6 +117,7 @@ Default Target brightness:
Advanced
Reverse LED order (rotate 180):
+Init LEDs after WiFi:
WARLS offset:
Back Save
diff --git a/wled00/wled00.ino b/wled00/wled00.ino
index b1de3ff703..10ea871d2e 100644
--- a/wled00/wled00.ino
+++ b/wled00/wled00.ino
@@ -33,7 +33,7 @@
#include "WS2812FX.h"
//version in format yymmddb (b = daily build)
-#define VERSION 1803144
+#define VERSION 1803146
const String versionString = "0.6.0";
//AP and OTA default passwords (change them!)
@@ -74,6 +74,7 @@ IPAddress staticSubnet(255, 255, 255, 0);
IPAddress staticDNS(8, 8, 8, 8); //only for NTP
bool useHSB = false, useHSBDefault = false;
bool turnOnAtBoot = true;
+bool initLedsLast = false;
byte bootPreset = 0;
byte colS[]{255, 159, 0};
byte colSecS[]{0, 0, 0};
@@ -99,8 +100,7 @@ byte effectSpeedDefault = 75;
byte effectIntensityDefault = 128;
//NTP stuff
bool ntpEnabled = false;
-IPAddress ntpServerIP;
-const char* ntpServerName = "0.wled.pool.ntp.org";
+String ntpServerName = "0.wled.pool.ntp.org";
//custom chase
byte ccNumPrimary = 2;
byte ccNumSecondary = 4;
@@ -123,20 +123,13 @@ unsigned long countdownTime = 1514764800L;
double transitionResolution = 0.011;
//hue
-long hueLastRequestSent = 0;
bool huePollingEnabled = false, hueAttempt = false;
uint16_t huePollIntervalMs = 2500;
-uint32_t huePollIntervalMsTemp = 2500;
String hueApiKey = "api";
byte huePollLightId = 1;
IPAddress hueIP = (0,0,0,0);
bool notifyHue = true;
bool hueApplyOnOff = true, hueApplyBri = true, hueApplyColor = true;
-String hueError = "Inactive";
-uint16_t hueFailCount = 0;
-float hueXLast=0, hueYLast=0;
-uint16_t hueHueLast=0, hueCtLast=0;
-byte hueSatLast=0, hueBriLast=0;
//Internal vars
byte col[]{0, 0, 0};
@@ -176,15 +169,19 @@ String cssFont="Verdana";
String cssColorString="";
//NTP stuff
bool ntpConnected = false;
-unsigned int ntpLocalPort = 2390;
-const uint16_t NTP_PACKET_SIZE = 48;
-byte ntpPacketBuffer[NTP_PACKET_SIZE];
-unsigned long ntpLastSyncTime = 999000000L;
-unsigned long ntpPacketSentTime = 999000000L;
byte currentTimezone = 0;
time_t local;
int utcOffsetSecs = 0;
+//hue
+String hueError = "Inactive";
+uint16_t hueFailCount = 0;
+float hueXLast=0, hueYLast=0;
+uint16_t hueHueLast=0, hueCtLast=0;
+byte hueSatLast=0, hueBriLast=0;
+long hueLastRequestSent = 0;
+uint32_t huePollIntervalMsTemp = huePollIntervalMs;
+
//overlay stuff
byte overlayDefault = 0;
byte overlayCurrent = 0;
@@ -242,6 +239,12 @@ HTTPClient hueClient;
ESP8266HTTPUpdateServer httpUpdater;
WiFiUDP notifierUdp;
WiFiUDP ntpUdp;
+IPAddress ntpServerIP;
+unsigned int ntpLocalPort = 2390;
+const uint16_t NTP_PACKET_SIZE = 48;
+byte ntpPacketBuffer[NTP_PACKET_SIZE];
+unsigned long ntpLastSyncTime = 999000000L;
+unsigned long ntpPacketSentTime = 999000000L;
WS2812FX strip = WS2812FX(LEDCOUNT);
diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino
index 78d1aafb58..c91af4be07 100644
--- a/wled00/wled01_eeprom.ino
+++ b/wled00/wled01_eeprom.ino
@@ -6,13 +6,14 @@
#define EEPSIZE 3072
//eeprom Version code, enables default settings instead of 0 init on update
-#define EEPVER 5
+#define EEPVER 6
//0 -> old version, default
//1 -> 0.4p 1711272 and up
//2 -> 0.4p 1711302 and up
//3 -> 0.4 1712121 and up
//4 -> 0.5.0 and up
-//5 -> 0.6.0 and up
+//5 -> 0.5.1 and up
+//6 -> 0.6.0 and up
//todo add settings
void clearEEPROM()
@@ -145,6 +146,7 @@ void saveSettingsToEEPROM()
EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF);
EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF);
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
+ EEPROM.write(397, initLedsLast);
for (int k=0;k<6;k++){
int in = 900+k*8;
@@ -380,6 +382,8 @@ void loadSettingsFromEEPROM(bool first)
hueApplyBri = EEPROM.read(2104);
hueApplyColor = EEPROM.read(2105);
huePollLightId = EEPROM.read(2106);
+ }
+ if (lastEEPROMversion > 5) {
overlayMin = EEPROM.read(2150);
overlayMax = EEPROM.read(2151);
analogClock12pixel = EEPROM.read(2152);
@@ -415,6 +419,7 @@ void loadSettingsFromEEPROM(bool first)
wifiLock = EEPROM.read(393);
utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00);
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
+ initLedsLast = EEPROM.read(397);
//favorite setting memory (25 slots/ each 20byte)
//400 - 899 reserved
@@ -519,6 +524,7 @@ String loadMacro(byte index)
if (EEPROM.read(i) == 0) break;
m += char(EEPROM.read(i));
}
+ if (m.charAt(0) < 65 || m.charAt(0) > 90) return ""; //do simple check if macro is valid (capital first letter)
return m;
}
diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino
index ee7039e1d5..a6cc53c3c0 100644
--- a/wled00/wled02_xml.ino
+++ b/wled00/wled02_xml.ino
@@ -166,6 +166,7 @@ String getSettings(byte subPage)
resp += ds + "TL" + v + nightlightDelayMins +";";
resp += ds + "TW" + c + nightlightFade +";";
resp += ds + "RV" + c + reverseMode +";";
+ resp += ds + "EI" + c + initLedsLast +";";
resp += ds + "WO" + v + arlsOffset +";";
}
diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino
index 3800d6256c..5f84cebb74 100644
--- a/wled00/wled03_set.ino
+++ b/wled00/wled03_set.ino
@@ -231,6 +231,7 @@ void handleSettingsSet(byte subPage)
}
nightlightFade = server.hasArg("TW");
reverseMode = server.hasArg("RV");
+ initLedsLast = server.hasArg("EI");
strip.setReverseMode(reverseMode);
if (server.hasArg("WO"))
{
diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino
index 2501762a6f..a0c66d8324 100644
--- a/wled00/wled05_init.ino
+++ b/wled00/wled05_init.ino
@@ -4,27 +4,19 @@
void wledInit()
{
+ EEPROM.begin(EEPSIZE);
+ if (!EEPROM.read(397)) strip.init(); //quick init
+
Serial.begin(115200);
-
+
#ifdef USEFS
SPIFFS.begin();
- {
- Dir dir = SPIFFS.openDir("/");
- while (dir.next()) {
- String fileName = dir.fileName();
- size_t fileSize = dir.fileSize();
- #ifdef DEBUG
- Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
- #endif
- }
- DEBUG_PRINTF("\n");
- }
#endif
- DEBUG_PRINTLN("Init EEPROM");
- EEPROM.begin(EEPSIZE);
+ DEBUG_PRINTLN("Load EEPROM");
loadSettingsFromEEPROM(true);
- DEBUG_PRINT("CC: SSID: ");
+ if (!initLedsLast) initStrip();
+ DEBUG_PRINT("C-SSID: ");
DEBUG_PRINT(clientSSID);
buildCssColorString();
userBeginPreConnection();
@@ -140,7 +132,7 @@ void wledInit()
});
server.on("/reset", HTTP_GET, [](){
- serveMessage(200,"Rebooting now...","(takes ~20 seconds, wait for auto-redirect)",139);
+ serveMessage(200,"Rebooting now...","(takes ~20 seconds, wait for auto-redirect)",79);
reset();
});
@@ -301,10 +293,15 @@ void wledInit()
ArduinoOTA.begin();
}
+ if (initLedsLast) initStrip();
userBegin();
+ if (macroBoot>0) applyMacro(macroBoot);
+}
- // Initialize NeoPixel Strip
- strip.init();
+void initStrip()
+{
+ // Initialize NeoPixel Strip and button
+ if (initLedsLast) strip.init();
strip.setLedCount(ledCount);
strip.setReverseMode(reverseMode);
strip.setColor(0);
@@ -314,7 +311,6 @@ void wledInit()
pinMode(buttonPin, INPUT_PULLUP);
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
- if (macroBoot>0) applyMacro(macroBoot);
colorUpdated(0);
if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally
}
@@ -331,17 +327,32 @@ void initCon()
int fail_count = 0;
if (clientSSID.length() <1 || clientSSID.equals("Your_Network")) fail_count = apWaitTimeSecs*2;
WiFi.begin(clientSSID.c_str(), clientPass.c_str());
- while(WiFi.status() != WL_CONNECTED) {
- delay(500);
- DEBUG_PRINTLN("C_NC");
- fail_count++;
- if (!recoveryAPDisabled && fail_count > apWaitTimeSecs*2)
+ unsigned long lastTry = 0;
+ bool con = false;
+ while(!con)
+ {
+ yield();
+ if (!initLedsLast)
{
- WiFi.disconnect();
- DEBUG_PRINTLN("Can't connect. Opening AP...");
- onlyAP = true;
- initAP();
- return;
+ handleTransitions();
+ handleButton();
+ handleOverlays();
+ if (briT) strip.service();
+ }
+ if (millis()-lastTry > 499) {
+ con = (WiFi.status() == WL_CONNECTED);
+ if (con) DEBUG_PRINTLN("rofl");
+ lastTry = millis();
+ DEBUG_PRINTLN("C_NC");
+ if (!recoveryAPDisabled && fail_count > apWaitTimeSecs*2)
+ {
+ WiFi.disconnect();
+ DEBUG_PRINTLN("Can't connect. Opening AP...");
+ onlyAP = true;
+ initAP();
+ return;
+ }
+ fail_count++;
}
}
}
diff --git a/wled00/wled07_notify.ino b/wled00/wled07_notify.ino
index 3898e580a7..0a96ae220f 100644
--- a/wled00/wled07_notify.ino
+++ b/wled00/wled07_notify.ino
@@ -28,12 +28,14 @@ void notify(byte callMode, bool followUp=false)
udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed;
udpOut[10] = white;
- udpOut[11] = 3; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet
+ udpOut[11] = 4; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet 4: supports transitionDelay
udpOut[12] = colSec[0];
udpOut[13] = colSec[1];
udpOut[14] = colSec[2];
udpOut[15] = whiteSec;
udpOut[16] = effectIntensity;
+ udpOut[17] = (transitionDelay >> 0) & 0xFF;
+ udpOut[18] = (transitionDelay >> 8) & 0xFF;
IPAddress broadcastIp;
broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP();
diff --git a/wled00/wled10_ntp.ino b/wled00/wled10_ntp.ino
index c9b5fd713b..c3224764f3 100644
--- a/wled00/wled10_ntp.ino
+++ b/wled00/wled10_ntp.ino
@@ -69,7 +69,8 @@ void handleNetworkTime()
void sendNTPPacket()
{
- WiFi.hostByName(ntpServerName, ntpServerIP);
+ const char* ntpsrv = ntpServerName.c_str();
+ WiFi.hostByName(ntpsrv, ntpServerIP);
DEBUG_PRINTLN("send NTP packet");
memset(ntpPacketBuffer, 0, NTP_PACKET_SIZE);
diff --git a/wled00/wled11_ol.ino b/wled00/wled11_ol.ino
index a6a094fde8..1cdc9cddb6 100644
--- a/wled00/wled11_ol.ino
+++ b/wled00/wled11_ol.ino
@@ -118,19 +118,19 @@ void _nixieNumber(int number, int dur)
void handleOverlays()
{
- if (overlayCurrent == 0) return;
-
if (millis() - overlayRefreshedTime > overlayRefreshMs)
{
initCronixie();
updateLocalTime();
switch (overlayCurrent)
{
+ case 0: break;//no overlay
case 1: _overlaySolid(); break;//solid secondary color
case 2: _overlayAnalogClock(); break;//2 analog clock
case 3: _overlayNixieClock(); break;//nixie 1-digit
case 4: _overlayCronixie();//Diamex cronixie clock kit
}
+ if (!countdownMode || overlayCurrent < 2) checkCountdown(); //countdown macro activation must work
overlayRefreshedTime = millis();
}
}
diff --git a/wled00/wled15_hue.ino b/wled00/wled15_hue.ino
index 6f3789b528..39ead60467 100644
--- a/wled00/wled15_hue.ino
+++ b/wled00/wled15_hue.ino
@@ -64,7 +64,7 @@ bool sendHuePoll(bool sAuth)
st = false;
}
if (!st){ //error
- if (hueFailCount<7) huePollIntervalMsTemp*=2; // only poll every 5min when unable to connect
+ if (huePollIntervalMsTemp<300000) huePollIntervalMsTemp*=2; // only poll every ~5min when unable to connect
hueFailCount++;
if (hueFailCount > 150) huePollingEnabled = false; //disable after many hours offline
}