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));
}