Stonelamp with Wemos D1 mini and 5050 NeoPixel

Just wanted to add the Version 1.1 of the program adding EEPROM functionality to save current settings of the lamp. Whenever you power on the stonelamp or after a reset last settings are restored.`

/*
  Neopixel stonelamp by Markus Rohner
  Version 1.1     17. 5. 2017

  Funtion: 12 activities
  
Aknowledgements:
  1. Adafruit Neopixel library: http://learn.adafruit.com/adafruit-neopixel-uberguide/neomatrix-library
  2. Arduino – LEDStrip effects for NeoPixel and FastLED: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
  
Pin assignments:
 * Wemos
D2 to DI 5050 RGB LED string 

Blynk Virtual Pins:
V0: ON OFF Button 
V1: Activity slider
V2: Terminal
V8: Blink button
V10: Brightness slider
V11: Speed slider
V12: Colour select
V13: ON OFF LED
V14: UP LED

Bill of material:
  -Wemos D1 mini
  -Adafruit Neopixelstring 60 LEDs
  -1000uF capacitor 
  -5V 4A Power Supply

*/

#include <ESPEEPROM.h>
int eeAddress = 0;
struct MyObject {
  bool lamp_on;
  bool blinkon;
  long current_color;
  int current_activity;
  int brightness;
  int standard_speed;
};
  MyObject stonelamp; //Variable to store custom object read from EEPROM.
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

// Set ESP8266 Serial object
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
SimpleTimer timer;

// Blynk
//#define BLYNK_DEBUG
//#define BLYNK_PRINT Serial
int ONOFF_LED = V13;
int UP_LED = V14;
long int last_UP_change = millis();
bool runn = 1;
WidgetTerminal terminal(V2);

// RGB Lights
#include <Adafruit_NeoPixel.h>
#define NUM_LEDS 60
const int NUM_LEDS4 = NUM_LEDS/4;
#define PIN D2
//const int long red = 16711680;
//const int long green = 65280;
const int long blue = 255;
int brightness = 155;
int standard_speed = 50;
int current_activity = 0;
int this_activity = 0;
long current_color = blue;
bool lamp_on = false;
bool blinkon = false;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);


// Wireless settings
const char AUTH[] = "***";
const char SSID[] = "***"; 
const char PASSWORD[] = "***";

// Timing
volatile int WDTCount = 0;


void setup() {
 Serial.begin(115200);
 Serial.println(F("setup start"));
 
//Blynk
 WiFi.mode(WIFI_STA);
 Blynk.begin(AUTH, SSID, PASSWORD,"192.168.178.59",8442);
   while (Blynk.connect() == false) {  // Wait until connected
     if ((millis() - last_UP_change) > 30000) { // 30s before reset
       Serial.println(F("resetting"));
       terminal.println(F("resetting"));
       terminal.flush();
       ESP.restart();
    }
  }
 wait(500);
 
// Init Neopixels
  strip.begin();
  all_lights(0);


//OTA
  // Port defaults to 8266
  // ArduinoOTA.setPort(8266);
  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("D1-Stonelamp");
  // No authentication by default
  ArduinoOTA.setPassword((const char *)"***");
  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();

  //EEPROM
  EEPROM.begin(512);
  EEPROM.get(eeAddress, stonelamp);
  lamp_on = stonelamp.lamp_on;
  blinkon = stonelamp.blinkon;
  current_color = stonelamp.current_color;
  current_activity = stonelamp.current_activity;
  brightness = stonelamp.brightness;
  standard_speed = stonelamp.standard_speed;

  Serial.println(F("Entering loop"));
  wait(3000);
  timer.setInterval(2003L, blinkonoff);
  //timer.setInterval(1000L, ISRwatchdog);
  printStatus();
  Serial.println();
  Blynk.virtualWrite(ONOFF_LED,0); 
  Blynk.virtualWrite(UP_LED,0); 
}


void loop() {
  Blynk.run();
  if(!Blynk.connected()) {
    Serial.println(F("Resetting in loop"));
    ESP.restart();
  }
  WDTCount = 0;
  timer.run();
  ArduinoOTA.handle();
  activity(current_activity);
}

 
void activity(int activity_button) {
  if (lamp_on) {
    this_activity = activity_button;
    strip.setBrightness(brightness);
    switch (activity_button) {
      case 0:  // no activity
        all_lights(current_color);
        if (blinkon) {
          wait(standard_speed*2);
          strip.setBrightness(0);
          strip.show();
          wait(standard_speed*2);
          strip.setBrightness(brightness);
         }
      break;
      case 1:  // colorWipe
      colorWipe(0); 
      colorWipe(current_color); 
    break;
    case 2:  // theaterChase
      theaterChase(strip.Color(random(255), random(255), random(255)));
    break;
    case 3:  // rainbow
      rainbow();
    break;
    case 4:  // rainbowCycle
      rainbowCycle();
    break;
    case 5:  // theaterChaseRainbow
      theaterChaseRainbow();
    break;
    case 6:  // CylonBounce
      CylonBounce(splitColor (current_color,'r'), splitColor (current_color,'g'), splitColor (current_color,'b'), 3);
    break;
    case 7:  // TwinkleRandom
      TwinkleRandom(20,false);
    break;
    case 8:  // Sparkle
      Sparkle(random(255), random(255), random(255));
     break;
    case 9:  // RunningLights
      RunningLights(splitColor (current_color,'r'), splitColor (current_color,'g'), splitColor (current_color,'b'));
    break;
    case 10:  // Fire
      Fire(55,120);// was 55,120
    break;
    case 11:  // fade
      FadeInOut(splitColor (current_color,'r'), splitColor (current_color,'g'), splitColor (current_color,'b'));
    break;
    case 12:  // rotate
      rotate();
    break; 
   }
 }
 else {
  strip.setBrightness(0);
  strip.show();
 }
}


// Fill the dots one after the other with a color (1)
void colorWipe(uint32_t c) {
    for (int i = 0; i < NUM_LEDS4; i++) {
      if (!lamp_on || this_activity != current_activity) break;
      for (int j = 0; j < 4; j++) {
      strip.setPixelColor(i+j*NUM_LEDS4,c);
      }
      strip.show();
      wait(standard_speed/3);
   }
}


//Theatre-style crawling lights. (2)
void theaterChase(uint32_t c) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    if (!lamp_on || this_activity != current_activity) break;
    for (int q = 0; q < 3; q++) {
      if (!lamp_on || this_activity != current_activity) break;
      for (int i = 0; i < NUM_LEDS4; i = i + 3) {
        if (!lamp_on || this_activity != current_activity) break;
        for (int m = 0; m < 4; m++) {
        strip.setPixelColor(i + q + m*NUM_LEDS4, c);  //turn every third pixel on
        }
      }
      strip.show();
      wait(standard_speed*3);
      for (int i = 0; i < NUM_LEDS; i = i + 3) {
        if (!lamp_on || this_activity != current_activity) break;
        for (int m = 0; m < 4; m++) {
        strip.setPixelColor(i + q + m*NUM_LEDS4, 0);      //turn every third pixel off
        }
      }
    }
  }
}


// (3)
void rainbow() {
  uint16_t i, j;
  for (j = 0; j < 256; j+=2) {
    if (!lamp_on || this_activity != current_activity) break;
    for (i = 0; i < NUM_LEDS4; i++) {
      if (!lamp_on || this_activity != current_activity) break;
      for (int m = 0; m < 4; m++) {
        strip.setPixelColor(i + m*NUM_LEDS4,Wheel((i + j) & 255));
        strip.show();
        wait(standard_speed/5);
      }
     }
   }
}


// Slightly different, this makes the rainbow equally distributed throughout (4)
void rainbowCycle() {
  uint16_t i, j;
  for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
    if (!lamp_on || this_activity != current_activity) break;
    for (i = 0; i < NUM_LEDS4; i++) {
      if (!lamp_on || this_activity != current_activity) break;
      for (int m = 0; m < 4; m++) {
        strip.setPixelColor(i + m*NUM_LEDS4, Wheel(((i * 256 / NUM_LEDS4) + j) & 255));
       }
     }
    strip.show();
    wait(standard_speed/2);
  }
}


//Theatre-style crawling lights with rainbow effect (5)
void theaterChaseRainbow() {
  for (int j = 0; j < 256; j+=2) {   // cycle all 256 colors in the wheel
    if (!lamp_on || this_activity != current_activity) break;
    for (int q = 0; q < 3; q++) {
      if (!lamp_on || this_activity != current_activity) break;
      for (int i = 0; i < NUM_LEDS4; i = i + 3) {
        if (!lamp_on || this_activity != current_activity) break;
        for (int m = 0; m < 4; m++) {
        strip.setPixelColor(i + q + m*NUM_LEDS4, Wheel( (i + j) % 255)); //turn every third pixel on
        }
      }
      strip.show();
      wait(standard_speed*3);
      for (int i = 0; i < NUM_LEDS4; i = i + 3) {
        if (!lamp_on || this_activity != current_activity) break;
        for (int m = 0; m < 4; m++) {
        strip.setPixelColor(i + q + m*NUM_LEDS4, 0);      //turn every third pixel off
        }
      }
    }
  }
}


// (6)
void CylonBounce(byte red, byte green, byte blue, int EyeSize){
  for(int i = 0; i < NUM_LEDS4-EyeSize-2; i++) {
    if (!lamp_on || this_activity != current_activity) break;
    all_lights(0);
     for (int m = 0; m < 4; m++) {
       setPixel(i+ m*NUM_LEDS4, red/10, green/10, blue/10);
     }
    for(int j = 1; j <= EyeSize; j++) {
      if (!lamp_on || this_activity != current_activity) break;
       for (int m = 0; m < 4; m++) {
         setPixel(i + j + m*NUM_LEDS4, red, green, blue); 
       }
    }
      for (int m = 0; m < 4; m++) {
        setPixel(i + EyeSize + 1 + m*NUM_LEDS4, red/10, green/10, blue/10);
      }
    strip.show();
    wait(standard_speed/2);
  }
  wait(standard_speed);

  for(int i = NUM_LEDS4-EyeSize-2; i > 0; i--) {
    if (!lamp_on || this_activity != current_activity) break;
    all_lights(0);
    for (int m = 0; m < 4; m++) {
      setPixel(i + m*NUM_LEDS4, red/10, green/10, blue/10);
    }
    for(int j = 1; j <= EyeSize; j++) {
      if (!lamp_on || this_activity != current_activity) break;
      for (int m = 0; m < 4; m++) {
        setPixel(i + j + m*NUM_LEDS4, red, green, blue); 
      }
    }
    for (int m = 0; m < 4; m++) {
      setPixel(i +EyeSize + 1 + m*NUM_LEDS4, red/10, green/10, blue/10);
    }
    strip.show();
    wait(standard_speed/2);
  }
  wait(standard_speed);
}


// (7)
void TwinkleRandom(int Count,boolean OnlyOne) {
  all_lights(0);
   for (int i=0; i<Count; i++) {
     if (!lamp_on || this_activity != current_activity) break;
     setPixel(random(NUM_LEDS),random(0,255),random(0,255),random(0,255));
     strip.show();
     wait(standard_speed);
     if(OnlyOne) { 
       all_lights(0); 
     }
   }
   wait(standard_speed/2);
}


// (8)
void Sparkle(byte red, byte green, byte blue) {
  all_lights(0);
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel,red,green,blue);
  strip.show();
  wait(standard_speed);
  setPixel(Pixel,0,0,0);
}


// (9)
void RunningLights(byte red, byte green, byte blue) {
  int Position=0;
  for(int i=0; i<NUM_LEDS4*2; i++)  {
    if (!lamp_on || this_activity != current_activity) break;
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS4; i++) {
        if (!lamp_on || this_activity != current_activity) break;
          for (int m = 0; m < 4; m++) {
            if (!lamp_on || this_activity != current_activity) break;
            setPixel(i + m*NUM_LEDS4,((sin(i+Position) * 127 + 128)/255)*red,
                   ((sin(i+Position) * 127 + 128)/255)*green,
                   ((sin(i+Position) * 127 + 128)/255)*blue);
        }
      }
      strip.show();
      wait(standard_speed*2);
  }
}


// (10)
void Fire(int Cooling, int Sparking) {
  static byte heat[NUM_LEDS];
  int cooldown;
  // Step 1.  Cool down every cell a little
  for (int m = 0; m < 4; m++) {
    for( int i = 0; i < NUM_LEDS4; i++) {
      cooldown = random(0, ((Cooling * 10) / NUM_LEDS4) + 2);
      if(cooldown>heat[i + m*NUM_LEDS4]) {
        heat[i + m*NUM_LEDS4]=0;
     } else {
        heat[i + m*NUM_LEDS4]=heat[i + m*NUM_LEDS4]-cooldown;
      }
    }
  }
  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for (int m = 0; m < 4; m++) {
    for( int k = NUM_LEDS4 - 1; k >= 2; k--) {
      if (!lamp_on || this_activity != current_activity) break;
      heat[k + m*NUM_LEDS4] = (heat[k + m*NUM_LEDS4 - 1] + heat[k + m*NUM_LEDS4 - 2] + heat[k + m*NUM_LEDS4 - 2]) / 3;
    }
  }
  // Step 3.  Randomly ignite new 'sparks' near the bottom
  for (int m = 0; m < 4; m++) {
    if( random(255) < Sparking ) {
      int y = random(3); //was 7
      heat[y + m*NUM_LEDS4] = heat[y + m*NUM_LEDS4] + random(160,255);
    }
  }
  // Step 4.  Convert heat to LED colors
  for( int j = 0; j < NUM_LEDS; j++) {
    if (!lamp_on || this_activity != current_activity) break;
    setPixelHeatColor(j, heat[j]);
  }
  strip.show();
  wait(standard_speed);
}


void setPixelHeatColor (int Pixel, byte temperature) {
  // Scale 'heat' down from 0-255 to 0-191
  byte t192 = round((temperature/255.0)*191);
  // calculate ramp up from
  byte heatramp = t192 & 0x3F; // 0..63
  heatramp <<= 2; // scale up to 0..252
  // figure out which third of the spectrum we're in:
  if( t192 > 0x80) {                     // hottest
    setPixel(Pixel, 255, 255, heatramp);
  } else if( t192 > 0x40 ) {             // middle
    setPixel(Pixel, 255, heatramp, 0);
  } else {                               // coolest
    setPixel(Pixel, heatramp, 0, 0);
  }
}


//(11)
void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
      
  for(int k = 20; k < 256; k=k+1) {
    if (!lamp_on || this_activity != current_activity) break; 
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    all_lights(r,g,b);
    wait(standard_speed/6);
  }
     
  for(int k = 255; k >= 20; k=k-2) {
    if (!lamp_on || this_activity != current_activity) break;
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    all_lights(r,g,b);
    wait(standard_speed/6);
  }
}


//Rotate (12)
void rotate() {
  all_lights(0);
  for (int m = 0; m < 4; m++) {
    for (int i = m*NUM_LEDS4; i < (m+1)*NUM_LEDS4; i++) {
      if (!lamp_on || this_activity != current_activity) break;
        strip.setPixelColor(i,current_color);
       }
      strip.show();
      wait(standard_speed*2);
    for (int i = m*NUM_LEDS4; i < (m+1)*NUM_LEDS4; i++) {
      if (!lamp_on || this_activity != current_activity) break;
        strip.setPixelColor(i,0);
       }
      strip.show();
  }
}


void all_lights(int g, int r, int b) {
  wait(1);
    for (int x = 0; x < NUM_LEDS; x++) {
      strip.setPixelColor(x, g, r, b);
    }
    strip.show();
}


void all_lights(int color) {
  wait(1);
    for (int x = 0; x < NUM_LEDS; x++) {
      strip.setPixelColor(x,color);
    }
    strip.show();
    }


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
    WheelPos -= 170;
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}


/**
   splitColor() - Receive a uint32_t value, and spread into bits.
*/
byte splitColor ( uint32_t c, char value )
{
  switch ( value ) {
    case 'r': return (uint8_t)(c >> 16);
    case 'g': return (uint8_t)(c >>  8);
    case 'b': return (uint8_t)(c >>  0);
    default:  return 0;
  }
}


void printStatus() {
  Serial.print(F(" ON: "));
  Serial.print(lamp_on);
  Serial.print(F(" Blink: "));
  Serial.print(blinkon);
  Serial.print(F(" Activity: "));
  Serial.print(current_activity);
  Serial.print(F(" Color: "));
  Serial.print(current_color);
  Serial.print(F(" Brightness: "));
  Serial.print(brightness);
  Serial.print(F(" Speed: "));
  Serial.println(standard_speed);
  terminal.print(F(" ON:"));
  terminal.print(lamp_on);
  terminal.print(F(" Blk:"));
  terminal.print(blinkon);
  terminal.print(F(" Act:"));
  terminal.print(current_activity);
  terminal.print(F(" Col:"));
  terminal.print(current_color);
  terminal.print(F(" Bright:"));
  terminal.print(brightness);
  terminal.print(F(" Spd:"));
  terminal.println(standard_speed);
  terminal.flush();
  EEPROM.begin(512);
  stonelamp.lamp_on = lamp_on;
  stonelamp.blinkon = blinkon;
  stonelamp.current_color = current_color;
  stonelamp.current_activity = current_activity;
  stonelamp.brightness = brightness;
  stonelamp.standard_speed = standard_speed;
  EEPROM.put(eeAddress, stonelamp);
  EEPROM.commit();
}


void wait (int ms) {
  long current_time = millis();
  long end_time = current_time + ms; 
  while (current_time < end_time) {
    if (!lamp_on || this_activity != current_activity) break;
    current_time = millis();
  }
  Blynk.run();
  timer.run();
}


void blinkonoff(){
 // Turn runn LED on/off
   Blynk.virtualWrite(UP_LED,runn * 255);  // turn Up off
   runn = !runn;
   last_UP_change = millis();  
   WDTCount = 0;
}

BLYNK_WRITE(V0) { //ON Off
    if (param.asInt()) lamp_on = 1;
    else {
      all_lights(0);
      lamp_on = 0;
    }
    Blynk.virtualWrite(ONOFF_LED,lamp_on * 255);  // turn Up off
    printStatus();
}

BLYNK_WRITE(V1) { //Activity slider
   current_activity = param.asInt();
   printStatus();
}
  
BLYNK_WRITE(V8) { //Blink
  if (param.asInt()) blinkon = true;
  else blinkon = false;
  printStatus();
}

BLYNK_WRITE(V10) { // Brightness slider
    brightness = param.asInt();
    strip.setBrightness(brightness);
    strip.show();
  printStatus();
}

BLYNK_WRITE(V11) { // Speed
  standard_speed = param.asInt();
  printStatus();
}

BLYNK_WRITE(V12) { //RGB light
  current_color = param[2].asInt() + 256*param[1].asInt() + 256*256*param[0].asInt();
  printStatus();  
}


void ISRwatchdog() {
  WDTCount++;
  if (WDTCount == 5) {
    Serial.println(F("WDT reset"));
    terminal.println(F("WDT reset"));
    terminal.flush();
    ESP.reset();
  }
}


void setPixel(int Pixel, byte red, byte green, byte blue) {
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
}
3 Likes

Hi this is FAB!!! is the app details shared somewhere and what does the zergba do ? is it a manual colour override ?

Cheers

kev

Yes, you can select the colour for some of the activities. See Virtual pin 12.

 BLYNK_WRITE(V12) { //RGB light
      current_color = param[2].asInt() + 256*param[1].asInt() + 256*256*param[0].asInt();
      printStatus();  
    }

Cheers and the app code ?

I wouldn’t know how to do that, sorry

ah ok no worries - it is in the blynk app where you can share a 2d code image on here and people can then upload you app automatically

Cheers

kev

could you stick a pic up of how you mounted everything in the base please ?

cheers

kev

Thanks for that but I actually meant a photo of the bottom of the base to see how it is physically mounted in the wood ?

Sorry to be a pain!!!

Cheers

kev

Blynk runs on my own server and I just do not have this functionality, maybe because I use an older server version?

1 Like

Brill thanks!!!

New Local Server versions do seem to allow cloning of Apps again :slight_smile:

I have been experimenting with your prior code with my 90 LED RGB Shower… Fire and Water :stuck_out_tongue: (click image for full effect)

So far so good, but there appears to be an auto shut off somewhere in your code? but I haven’t found it yet.

Not that I know.

@Gunner: i am using his code for a long time now, my lamp never shuts off…

@mhroner: THANK YOU!
I have replicate your work with very few modifications. Works perfect.
Then i was thinking to add to this the vocal control using Alexa. The library is wemo.manager.
Given the fact that Alexa already works, i was thinking why not asking alexa to set the lamp to one color.
And so the pain begins. Your code is almost rocket science for me, please do not laugh :slight_smile:

So, where i am now? If your code is untouched (posting below) the lamp is working as espected. But Alexa says “OK” and the lap is turning red (for example) and switch back to whatever the lamp was doing before the voice request. If i am commenting activity(current_activity); from the void loop, all voice requests work, but none of the lamp activities anymore. So i am thinking that activity running in loop will override whatever alexa set, and that is why is going back to current activity.

Can someone please help me to solve this? Meaning the lamp to work as intended, and the voice control to work also? For me it is enough to work with just 3 colors on voice request, that is why are just 3 there.


    #include <ESP8266WiFi.h>
    #include <ESP8266mDNS.h>
    #include <BlynkSimpleEsp8266.h>
    #include <WiFiUdp.h>
    #include <SimpleTimer.h>
    SimpleTimer timer;
    #include "WemoSwitch.h"
    #include "WemoManager.h"
    #include "CallbackFunction.h"

        // Wireless settings
    const char AUTH[] = "xxx";
    const char SSID[] = "xxx"; 
    const char PASSWORD[] = "xxx";
    
WemoManager wemoManager;
WemoSwitch *red1 = NULL;
WemoSwitch *green1 = NULL;
WemoSwitch *blue1 = NULL;
    
    int ONOFF_LED = V13;
    int UP_LED = V14;
    long int last_UP_change = millis();
    bool runn = 1;

    // RGB Lights
    #include <Adafruit_NeoPixel.h>
    #define NUM_LEDS 60
    const int NUM_LEDS4 = 15;
    #define PIN 0

    Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
    
    //const int long red = 16711680;
    //const int long green = 65280;
    const int long blue = 255;
    int brightness = 155;
    int standard_speed = 50;
    int current_activity = 1;
    int this_activity = 0;
    long current_color = blue;
    bool lamp_on = false;
    bool blinkon = false;

    // Timing
    volatile int WDTCount = 0;

    void setup() {
     Serial.begin(115200);
     
    //Blynk
     WiFi.mode(WIFI_STA);
     Blynk.begin(AUTH, SSID, PASSWORD,"myserver.com",8442);
       while (Blynk.connect() == false) {  // Wait until connected
         if ((millis() - last_UP_change) > 30000) { // 30s before reset
           ESP.restart();
        }
      }
     wait(500);
     
    // Init Neopixels
      strip.begin();
      all_lights(0);


      wait(3000);
      timer.setInterval(500L, blinkonoff);
      timer.setInterval(1000L, ISRwatchdog);

      Blynk.virtualWrite(ONOFF_LED,0); 
      Blynk.virtualWrite(UP_LED,0); 
      wemoManager.begin();
  // Format: Alexa invocation name, local port no, on callback, off callback
  red1 = new WemoSwitch("Red", 80, redOn, redOff);
  green1 = new WemoSwitch("Green", 81, greenOn, greenOff);
  blue1 = new WemoSwitch("Blue", 82, blueOn, blueOff);
  
  wemoManager.addDevice(*red1);
  wemoManager.addDevice(*green1);
  wemoManager.addDevice(*blue1);
    // Init Neopixels
      strip.begin();
  for (int i = 0; i < NUM_LEDS; i++)
  strip.setPixelColor(i, strip.Color(0, 0, 0)); 
  strip.show(); // This sends the updated pixel color to the hardware.
  
    }


    void loop() {
       wemoManager.serverLoop();
      Blynk.run();
      if(!Blynk.connected()) {
        //Serial.println(F("Resetting in loop"));
        ESP.restart();
      }
      WDTCount = 0;
      timer.run();
      activity(current_activity);
    }

     
    void activity(int activity_button) {
      if (lamp_on) {
        this_activity = activity_button;
        strip.setBrightness(brightness);
        switch (activity_button) {
          case 0:  // no activity
            all_lights(current_color);
            if (blinkon) {
              wait(standard_speed*2);
              strip.setBrightness(0);
              strip.show();
              wait(standard_speed*2);
              strip.setBrightness(brightness);
             }
          break;
          case 1:  // colorWipe
          colorWipe(0); 
          colorWipe(current_color); 
        break;
        case 2:  // theaterChase
          theaterChase(strip.Color(random(255), random(255), random(255)));
        break;
        case 3:  // rainbow
          rainbow();
        break;
        case 4:  // rainbowCycle
          rainbowCycle();
        break;
        case 5:  // theaterChaseRainbow
          theaterChaseRainbow();
        break;
        case 6:  // CylonBounce
          CylonBounce(splitColor (current_color,'r'), splitColor (current_color,'g'), splitColor (current_color,'b'), 3);
        break;
        case 7:  // TwinkleRandom
          TwinkleRandom(20,false);
        break;
        case 8:  // Sparkle
          Sparkle(random(255), random(255), random(255));
         break;
        case 9:  // RunningLights
          RunningLights(splitColor (current_color,'r'), splitColor (current_color,'g'), splitColor (current_color,'b'));
        break;
        case 10:  // Fire
          Fire(55,120);// was 55,120
        break;
        case 11:  // fade
          FadeInOut(splitColor (current_color,'r'), splitColor (current_color,'g'), splitColor (current_color,'b'));
        break;
        case 12:  // rotate
          rotate();
        break; 
       }
     }
     else {
      strip.setBrightness(0);
      strip.show();
     }
    }


    // Fill the dots one after the other with a color (1)
    void colorWipe(uint32_t c) {
        for (int i = 0; i < NUM_LEDS4; i++) {
          if (!lamp_on || this_activity != current_activity) break;
          for (int j = 0; j < 4; j++) {
          strip.setPixelColor(i+j*NUM_LEDS4,c);
          }
          strip.show();
          wait(standard_speed/3);
       }
    }


    //Theatre-style crawling lights. (2)
    void theaterChase(uint32_t c) {
      for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
        if (!lamp_on || this_activity != current_activity) break;
        for (int q = 0; q < 3; q++) {
          if (!lamp_on || this_activity != current_activity) break;
          for (int i = 0; i < NUM_LEDS4; i = i + 3) {
            if (!lamp_on || this_activity != current_activity) break;
            for (int m = 0; m < 4; m++) {
            strip.setPixelColor(i + q + m*NUM_LEDS4, c);  //turn every third pixel on
            }
          }
          strip.show();
          wait(standard_speed*3);
          for (int i = 0; i < NUM_LEDS; i = i + 3) {
            if (!lamp_on || this_activity != current_activity) break;
            for (int m = 0; m < 4; m++) {
            strip.setPixelColor(i + q + m*NUM_LEDS4, 0);      //turn every third pixel off
            }
          }
        }
      }
    }


    // (3)
    void rainbow() {
      uint16_t i, j;
      for (j = 0; j < 256; j+=2) {
        if (!lamp_on || this_activity != current_activity) break;
        for (i = 0; i < NUM_LEDS4; i++) {
          if (!lamp_on || this_activity != current_activity) break;
          for (int m = 0; m < 4; m++) {
            strip.setPixelColor(i + m*NUM_LEDS4,Wheel((i + j) & 255));
            strip.show();
            wait(standard_speed/5);
          }
         }
       }
    }


    // Slightly different, this makes the rainbow equally distributed throughout (4)
    void rainbowCycle() {
      uint16_t i, j;
      for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
        if (!lamp_on || this_activity != current_activity) break;
        for (i = 0; i < NUM_LEDS4; i++) {
          if (!lamp_on || this_activity != current_activity) break;
          for (int m = 0; m < 4; m++) {
            strip.setPixelColor(i + m*NUM_LEDS4, Wheel(((i * 256 / NUM_LEDS4) + j) & 255));
           }
         }
        strip.show();
        wait(standard_speed/2);
      }
    }


    //Theatre-style crawling lights with rainbow effect (5)
    void theaterChaseRainbow() {
      for (int j = 0; j < 256; j+=2) {   // cycle all 256 colors in the wheel
        if (!lamp_on || this_activity != current_activity) break;
        for (int q = 0; q < 3; q++) {
          if (!lamp_on || this_activity != current_activity) break;
          for (int i = 0; i < NUM_LEDS4; i = i + 3) {
            if (!lamp_on || this_activity != current_activity) break;
            for (int m = 0; m < 4; m++) {
            strip.setPixelColor(i + q + m*NUM_LEDS4, Wheel( (i + j) % 255)); //turn every third pixel on
            }
          }
          strip.show();
          wait(standard_speed*3);
          for (int i = 0; i < NUM_LEDS4; i = i + 3) {
            if (!lamp_on || this_activity != current_activity) break;
            for (int m = 0; m < 4; m++) {
            strip.setPixelColor(i + q + m*NUM_LEDS4, 0);      //turn every third pixel off
            }
          }
        }
      }
    }


    // (6)
    void CylonBounce(byte red, byte green, byte blue, int EyeSize){
      for(int i = 0; i < NUM_LEDS4-EyeSize-2; i++) {
        if (!lamp_on || this_activity != current_activity) break;
        all_lights(0);
         for (int m = 0; m < 4; m++) {
           setPixel(i+ m*NUM_LEDS4, red/10, green/10, blue/10);
         }
        for(int j = 1; j <= EyeSize; j++) {
          if (!lamp_on || this_activity != current_activity) break;
           for (int m = 0; m < 4; m++) {
             setPixel(i + j + m*NUM_LEDS4, red, green, blue); 
           }
        }
          for (int m = 0; m < 4; m++) {
            setPixel(i + EyeSize + 1 + m*NUM_LEDS4, red/10, green/10, blue/10);
          }
        strip.show();
        wait(standard_speed/2);
      }
      wait(standard_speed);

      for(int i = NUM_LEDS4-EyeSize-2; i > 0; i--) {
        if (!lamp_on || this_activity != current_activity) break;
        all_lights(0);
        for (int m = 0; m < 4; m++) {
          setPixel(i + m*NUM_LEDS4, red/10, green/10, blue/10);
        }
        for(int j = 1; j <= EyeSize; j++) {
          if (!lamp_on || this_activity != current_activity) break;
          for (int m = 0; m < 4; m++) {
            setPixel(i + j + m*NUM_LEDS4, red, green, blue); 
          }
        }
        for (int m = 0; m < 4; m++) {
          setPixel(i +EyeSize + 1 + m*NUM_LEDS4, red/10, green/10, blue/10);
        }
        strip.show();
        wait(standard_speed/2);
      }
      wait(standard_speed);
    }


    // (7)
    void TwinkleRandom(int Count,boolean OnlyOne) {
      all_lights(0);
       for (int i=0; i<Count; i++) {
         if (!lamp_on || this_activity != current_activity) break;
         setPixel(random(NUM_LEDS),random(0,255),random(0,255),random(0,255));
         strip.show();
         wait(standard_speed);
         if(OnlyOne) { 
           all_lights(0); 
         }
       }
       wait(standard_speed/2);
    }


    // (8)
    void Sparkle(byte red, byte green, byte blue) {
      all_lights(0);
      int Pixel = random(NUM_LEDS);
      setPixel(Pixel,red,green,blue);
      strip.show();
      wait(standard_speed);
      setPixel(Pixel,0,0,0);
    }


    // (9)
    void RunningLights(byte red, byte green, byte blue) {
      int Position=0;
      for(int i=0; i<NUM_LEDS4*2; i++)  {
        if (!lamp_on || this_activity != current_activity) break;
          Position++; // = 0; //Position + Rate;
          for(int i=0; i<NUM_LEDS4; i++) {
            if (!lamp_on || this_activity != current_activity) break;
              for (int m = 0; m < 4; m++) {
                if (!lamp_on || this_activity != current_activity) break;
                setPixel(i + m*NUM_LEDS4,((sin(i+Position) * 127 + 128)/255)*red,
                       ((sin(i+Position) * 127 + 128)/255)*green,
                       ((sin(i+Position) * 127 + 128)/255)*blue);
            }
          }
          strip.show();
          wait(standard_speed*2);
      }
    }


    // (10)
    void Fire(int Cooling, int Sparking) {
      static byte heat[NUM_LEDS];
      int cooldown;
      // Step 1.  Cool down every cell a little
      for (int m = 0; m < 4; m++) {
        for( int i = 0; i < NUM_LEDS4; i++) {
          cooldown = random(0, ((Cooling * 10) / NUM_LEDS4) + 2);
          if(cooldown>heat[i + m*NUM_LEDS4]) {
            heat[i + m*NUM_LEDS4]=0;
         } else {
            heat[i + m*NUM_LEDS4]=heat[i + m*NUM_LEDS4]-cooldown;
          }
        }
      }
      // Step 2.  Heat from each cell drifts 'up' and diffuses a little
      for (int m = 0; m < 4; m++) {
        for( int k = NUM_LEDS4 - 1; k >= 2; k--) {
          if (!lamp_on || this_activity != current_activity) break;
          heat[k + m*NUM_LEDS4] = (heat[k + m*NUM_LEDS4 - 1] + heat[k + m*NUM_LEDS4 - 2] + heat[k + m*NUM_LEDS4 - 2]) / 3;
        }
      }
      // Step 3.  Randomly ignite new 'sparks' near the bottom
      for (int m = 0; m < 4; m++) {
        if( random(255) < Sparking ) {
          int y = random(3); //was 7
          heat[y + m*NUM_LEDS4] = heat[y + m*NUM_LEDS4] + random(160,255);
        }
      }
      // Step 4.  Convert heat to LED colors
      for( int j = 0; j < NUM_LEDS; j++) {
        if (!lamp_on || this_activity != current_activity) break;
        setPixelHeatColor(j, heat[j]);
      }
      strip.show();
      wait(standard_speed);
    }


    void setPixelHeatColor (int Pixel, byte temperature) {
      // Scale 'heat' down from 0-255 to 0-191
      byte t192 = round((temperature/255.0)*191);
      // calculate ramp up from
      byte heatramp = t192 & 0x3F; // 0..63
      heatramp <<= 2; // scale up to 0..252
      // figure out which third of the spectrum we're in:
      if( t192 > 0x80) {                     // hottest
        setPixel(Pixel, 255, 255, heatramp);
      } else if( t192 > 0x40 ) {             // middle
        setPixel(Pixel, 255, heatramp, 0);
      } else {                               // coolest
        setPixel(Pixel, heatramp, 0, 0);
      }
    }


    //(11)
    void FadeInOut(byte red, byte green, byte blue){
      float r, g, b;
          
      for(int k = 20; k < 256; k=k+1) {
        if (!lamp_on || this_activity != current_activity) break; 
        r = (k/256.0)*red;
        g = (k/256.0)*green;
        b = (k/256.0)*blue;
        all_lights(r,g,b);
        wait(standard_speed/6);
      }
         
      for(int k = 255; k >= 20; k=k-2) {
        if (!lamp_on || this_activity != current_activity) break;
        r = (k/256.0)*red;
        g = (k/256.0)*green;
        b = (k/256.0)*blue;
        all_lights(r,g,b);
        wait(standard_speed/6);
      }
    }


    //Rotate (12)
    void rotate() {
      all_lights(0);
      for (int m = 0; m < 4; m++) {
        for (int i = m*NUM_LEDS4; i < (m+1)*NUM_LEDS4; i++) {
          if (!lamp_on || this_activity != current_activity) break;
            strip.setPixelColor(i,current_color);
           }
          strip.show();
          wait(standard_speed*2);
        for (int i = m*NUM_LEDS4; i < (m+1)*NUM_LEDS4; i++) {
          if (!lamp_on || this_activity != current_activity) break;
            strip.setPixelColor(i,0);
           }
          strip.show();
      }
    }


    void all_lights(int g, int r, int b) {
      wait(1);
        for (int x = 0; x < NUM_LEDS; x++) {
          strip.setPixelColor(x, g, r, b);
        }
        strip.show();
    }


    void all_lights(int color) {
      wait(1);
        for (int x = 0; x < NUM_LEDS; x++) {
          strip.setPixelColor(x,color);
        }
        strip.show();
        }


    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos) {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85) {
        return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
      } else if (WheelPos < 170) {
        WheelPos -= 85;
        return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
      } else {
        WheelPos -= 170;
        return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }


    /**
       splitColor() - Receive a uint32_t value, and spread into bits.
    */
    byte splitColor ( uint32_t c, char value )
    {
      switch ( value ) {
        case 'r': return (uint8_t)(c >> 16);
        case 'g': return (uint8_t)(c >>  8);
        case 'b': return (uint8_t)(c >>  0);
        default:  return 0;
      }
    }

    void wait (int ms) {
      long current_time = millis();
      long end_time = current_time + ms; 
      while (current_time < end_time) {
        if (!lamp_on || this_activity != current_activity) break;
        current_time = millis();
      }
      Blynk.run();
      timer.run();
    }


    void blinkonoff(){
     // Turn runn LED on/off
       Blynk.virtualWrite(UP_LED,runn * 255);  // turn Up off
       runn = !runn;
       last_UP_change = millis();  
       WDTCount = 0;
    }

    BLYNK_WRITE(V0) { //ON Off
        if (param.asInt()) lamp_on = 1;
        else {
          all_lights(0);
          lamp_on = 0;
        }
        Blynk.virtualWrite(ONOFF_LED,lamp_on * 255);  // turn Up off      
    }

    BLYNK_WRITE(V1) { //Activity slider
       current_activity = param.asInt();      
    }
      
    BLYNK_WRITE(V8) { //Blink
      if (param.asInt()) blinkon = true;
      else blinkon = false;     
    }

    BLYNK_WRITE(V10) { // Brightness slider
        brightness = param.asInt();
        strip.setBrightness(brightness);
        strip.show();     
    }

    BLYNK_WRITE(V11) { // Speed
      standard_speed = param.asInt();      
    }

    BLYNK_WRITE(V12) { //RGB light
      current_color = param[2].asInt() + 256*param[1].asInt() + 256*256*param[0].asInt();  
    }


    void ISRwatchdog() {
      WDTCount++;
      if (WDTCount == 5) {
        ESP.reset();
      }
    }


    void setPixel(int Pixel, byte red, byte green, byte blue) {
       strip.setPixelColor(Pixel, strip.Color(red, green, blue));
    }

    
    
// Toggle the GREEN on
void greenOn() {
   for (int i = 0; i < NUM_LEDS; i++)
    strip.setPixelColor(i, strip.Color(0, 255, 0)); 
    strip.show(); // This sends the updated pixel color to the hardware.
    Blynk.virtualWrite(V9, 1023);     // Sync the Blynk button widget state
    Blynk.virtualWrite(V7, 0);      // Sync the Blynk button widget state
    Blynk.virtualWrite(V6, 0);     // Sync the Blynk button widget state
}

// Toggle the GREEN off
void greenOff() {
   for (int i = 0; i < NUM_LEDS; i++)
    strip.setPixelColor(i, strip.Color(0, 0, 0)); 
    strip.show(); // This sends the updated pixel color to the hardware
    Blynk.virtualWrite(V9, 0);      // Sync the Blynk button widget state
    Blynk.virtualWrite(V7, 0);      // Sync the Blynk button widget state
    Blynk.virtualWrite(V6, 0);     // Sync the Blynk button widget state
}
 
    // Toggle the RED on
void redOn() {
  for (int i = 0; i < NUM_LEDS; i++)
    strip.setPixelColor(i, strip.Color(255, 0, 0));
    strip.show(); // This sends the updated pixel color to the hardware.
    Blynk.virtualWrite(V7, 1023);     // Sync the Blynk button widget state
    Blynk.virtualWrite(V9, 0);      // Sync the Blynk button widget state
    Blynk.virtualWrite(V6, 0);     // Sync the Blynk button widget state
}

// Toggle RED off
void redOff() {
   for (int i = 0; i < NUM_LEDS; i++)
    strip.setPixelColor(i, strip.Color(0, 0, 0)); 
    strip.show(); // This sends the updated pixel color to the hardware.
    Blynk.virtualWrite(V7, 0);      // Sync the Blynk button widget state
    Blynk.virtualWrite(V9, 0);      // Sync the Blynk button widget state
    Blynk.virtualWrite(V6, 0);     // Sync the Blynk button widget state
}

void blueOn() {
   for (int i = 0; i < NUM_LEDS; i++)
    strip.setPixelColor(i, strip.Color(0, 0, 255)); 
    strip.show(); // This sends the updated pixel color to the hardware.
    Blynk.virtualWrite(V6, 1023);     // Sync the Blynk button widget state
    Blynk.virtualWrite(V9, 0);     // Sync the Blynk button widget state
    Blynk.virtualWrite(V7, 0);      // Sync the Blynk button widget state
}


void blueOff() {
   for (int i = 0; i < NUM_LEDS; i++)
    strip.setPixelColor(i, strip.Color(0, 0, 0)); 
    strip.show(); // This sends the updated pixel color to the hardware
    Blynk.virtualWrite(V6, 0);     // Sync the Blynk button widget state
    Blynk.virtualWrite(V9, 0);      // Sync the Blynk button widget state
    Blynk.virtualWrite(V7, 0);      // Sync the Blynk button widget state
}

Me again.
Well, maybe i was not waiting enough. Mine also stops after some time.

You did not populate the necessary variables.
For a light to be on set the current_activity to zero and current_color must be set to a color value (i.e. 255 for blue or 16711680 for red etc. and lamp_on must be true.

My lamp never stops, but if it looses connection it restarts and reloads the latest status from the EEPROM in order to continue with the same activity where it stops (see my updated code V1.1. for EEPROM support). Second you could try to uncomment this line
//timer.setInterval(1000L, ISRwatchdog);
this could help to stabilize your system

It worked :slight_smile: Thank you
Is there anyplace where i can find espeeprom.h library to test your latest version of the code?

P.S. ISRwatchdog timer was already uncommented…

I used this library; https://github.com/esp8266/Arduino/tree/master/libraries/EEPROM from Ivan Grokhotkov. I had to rename it and make some changes in the files as I already had an EEPROM library for Arduinos