/* Web and switch control of "addressable" WS2811 controlled leds. Deid Reimer 2020-01 deid@drsol.com */ #include #include #include #include #include // About the leds #define NUM_LEDS 50 #define LED_PIN 1 #define LED_TYPE WS2811 // Instantiate and tell the web server to listen on port 80 ESP8266WebServer server(80); // ID and Password for web control const char* id = "ws2811"; const char* pw = "neopixel"; // Initialization values for the various led programs. // Rainbow colours for the rainbow program - this vector is shifted to move the rainbow int rainbow[] = {0xff0000, 0xff4800, 0xffff00, 0x00ff00, 0x0000ff, 0x3000ff, 0x9400d3}; // RGB colours for the chase and random programs. These are incremented byte cred = 0; byte cgreen = 0; byte cblue = 0; // Variables for the multi pattern long multiC1 = 0xff0000; long multiC2 = 0x0000ff; int multiSp = 20; int multiSz = 5; String multiDr = ">"; // Miscellaneous int rbStart = 0; // Rainbow start led int chase = 0; // chase first led int chaser = NUM_LEDS - 1; // reverse chase first led byte colour[] = {255, 0, 0}; // chasing primaries program const int webSafe = 51; // Number of web safe colours bool dirty = false; // Set if the lights need to be changed int dot = 0; // moving pixel position int rc = 0; // dot colour from rainbow long colourVal = 0xffffff; // colour value for several patterns bool doRefresh = false; // switch to prevent refresh in patterns //bool rgFirst = true; // switch to set group rain only first time. // Variables for the push button and debouncing. const int selectButton = 4; // GPIO pin // Overal Program variables int lightProgram = 0; // Current program selected int maxProgram = 13; // Maximum program number // Count millis for timing of random colour/time programs unsigned long currentTime; unsigned long loopTime[NUM_LEDS]; // Web page button variables String onColour = "style=\"background-color: #f4a742\""; String offColour = "style=\"background-color: #CCCCCC\""; String s[] = {offColour, offColour, offColour, offColour, offColour, offColour, offColour, offColour, offColour, offColour, offColour, offColour, offColour, offColour}; // Tell the library about the number of leds CRGB led[NUM_LEDS]; static unsigned long last_interrupt_time = 0; // ******** Functions ******** // Handle button interrupt void buttonISR() { unsigned long interrupt_time = millis(); // If interrupt sooner than 300ms ignore it. if (interrupt_time - last_interrupt_time > 300) { lightProgram++; if (lightProgram > maxProgram) { lightProgram = 0; } } last_interrupt_time = interrupt_time; doRefresh = true; makePage(); showPage(); } // Get credentials void checkCreds () { // If we don't have the credentials ask for them if (!server.authenticate(id, pw)) { return server.requestAuthentication(); } } // Display the page. void showPage() { server.send(200, "text/html", makePage()); } // Function to build the select light program web page. String makePage() { // Clear all the button colours to offColour and set the selected to onColour; for (int i = 0; i <= maxProgram ; i++) { s[i] = offColour; } s[lightProgram] = onColour; char cva [12]; sprintf(cva, "#%06X", colourVal); String colourValAsc = cva; sprintf(cva, "#%06X", multiC1); String multiC1Asc = cva; sprintf(cva, "#%06X", multiC2); String multiC2Asc = cva; String multiSpAsc = String(multiSp); String multiSzAsc = String(multiSz); // Web page String webPage = "" "Xmas Leds" "" "

Addressable Leds Christmas V0.1

" "
Colour (#hhhhhh):
" "
" //"" " **

" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
1 - Primary
2 - Random
3 - Web Safe
4 - Follow
5 - Lead
6 - Random On **
7 - All On
8 - All Off
9 - Rainbow
10- Moving **
11- Colour **
12- Christmas
13- Rainbow Group

" "" "" "" "" "" "
Size: " "Dly µs: " "
14- Dual Colour
"; return webPage; } void newPage() { checkCreds(); makePage(); showPage(); } // Function to get and execute a query selecting a program void execQuery() { // Check Credentials and Build the new web page. checkCreds(); // Get the program number. If there is an argument separate out the value.//???? if (server.args() >= 1) { String m = server.arg("s"); int n = m.toInt(); // check the validity of the supplied number. if (n <2 or n > maxProgram + 2) { // Got an invalid number just redisplay the web page and return makePage(); showPage(); return; } // Set the number back to 0 base and set the new selected program. // We started at 2 so that toInt returning 0 on fail can be caught. lightProgram = n - 2; makePage(); showPage(); // Reset pattern variables. doRefresh = true; //rgFirst = true; // number of arguments not equal to 1 - just redisplay the page. } else { newPage(); delay(100); return; } } // Get colour value. void getColour() { checkCreds(); char c[] = "0000000"; String m; if (server.arg("cv") != NULL) { m = server.arg("cv"); m.remove(0, 1); m.toCharArray(c, 7); //Serial.println(c); colourVal = strtol(c, NULL, 16); //Serial.println(colourVal); } //Serial.println("arg"); //Serial.println(m); //Serial.println(colourVal); makePage(); showPage(); } void getMulti() { char c[] = "0000000"; // Get first colour from and convert from String to long. String m = server.arg("cv1"); m.remove(0, 1); m.toCharArray(c, 7); multiC1 = strtol(c, NULL, 16); // Same with second colour. m = server.arg("cv2"); m.remove(0, 1); m.toCharArray(c, 7); multiC2 = strtol(c, NULL, 16); // And Speed in milliseconds? m = server.arg("sp"); multiSp = m.toInt(); // Size in pixels m = server.arg("sz"); multiSz = m.toInt(); // Direction - no conversion multiDr = server.arg("dr"); Serial.println("colours, speed, size, direction"); Serial.println(multiC1); Serial.println(multiC2); Serial.println(multiSp); Serial.println(multiSz); Serial.println(multiDr); makePage(); showPage(); } // Get the current program number and display it. void getNumber() { server.send(200, "text/plain", String(lightProgram)); } // Invalid request just redisplay the main page. void handleNotFound() { newPage(); } // ************************************************** void setup() { Serial.begin(9600); WiFi.hostname("NeoLeds1"); Serial.print("MAC: "); Serial.println(WiFi.macAddress()); // Initialize the fast led library FastLED.addLeds(led, NUM_LEDS); delay(2000); //Initialize WiFi WiFiManager wifiManager; //reset settings //wifiManager.resetSettings(); //set timeout until configuration portal gets turned off //in seconds wifiManager.setConfigPortalTimeout(300); wifiManager.autoConnect("GetNeoLedsIP"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); if (! WiFi.localIP()) { Serial.println("Continuing without IP"); } delay(1000); // Display the last octet of the IP address Serial.println("IPs"); Serial.println(WiFi.localIP()[3]); int ipl = WiFi.localIP()[3]; int offOn[] = {0x00ff00, 0xff0000}; for (int i = 0; i < 8; i++) { led[i] = offOn[ipl % 2]; ipl = ipl >> 1; } // Mark the high order bit, show the bits and wait 10 seconds. led[8] = 0xffffff; FastLED.show(); delay(10000); // Set up the responders for the possible web requests. // If no command just serve the program select web page. checkCreds will call the build web page server.on("/", newPage); // is a command get the query and set light program to display server.on("/program", execQuery); // Get and display the current light program number. server.on("/getNumber", getNumber); // get request for colour server.on("/get", getColour); // get info for multi colour server.on("/get1", getMulti); // 404 server.onNotFound(handleNotFound); // Set up the button interrupt pinMode(selectButton, INPUT); // Setup and enable interrupts. attachInterrupt(digitalPinToInterrupt(selectButton), buttonISR, FALLING); sei(); // Clear the random times to 0 for (int i; i < NUM_LEDS; i++) { loopTime[i] = 0; } // Set all the leds to off for one second. for (int i = 0; i < NUM_LEDS; i++) { led[i] = CRGB(0, 0, 0); } FastLED.show(); delay(1000); // Start the web server server.begin(); } // *************************************************** void loop() { // Look for and handle a web request. //Serial.println("at handle client"); //Serial.println(lightProgram); server.handleClient(); // Find the light program to execute. // -------------------------- // Chasing primaries if (lightProgram == 0) { for (int i = 0; i < NUM_LEDS; i++) { led[i] = CRGB(colour[i % 3], colour[(i + 1) % 3], colour[(i + 2) % 3]); } dirty = true; byte s = colour[0]; for (int i = 0 ; i < 3; i++) { colour[i] = colour[i + 1]; } colour[2] = s; delay(400); // -------------------------- // Random colours and times } else if (lightProgram == 1) { currentTime = millis(); for (int i = 0; i < NUM_LEDS; i++) { if (currentTime >= loopTime[i]) { loopTime[i] = currentTime + random(900, 2000); byte red = random(0, 256); byte green = random(0, 256); byte blue = random(0, 256); led[i] = CRGB(red, green, blue); dirty = true; } } // -------------------------- // Web safe } else if (lightProgram == 2) { currentTime = millis(); for (int i = 0; i < NUM_LEDS; i++) { if (currentTime >= loopTime[i]) { loopTime[i] = currentTime + random(900, 2000); byte red = random(0, 5) * webSafe; byte green = random(0, 5) * webSafe; byte blue = random(0, 5) * webSafe; led[i] = CRGB(red, green, blue); dirty = true; } } // -------------------------- // Chasing increasing colour } else if (lightProgram == 3) { for ( int i = 0; i < NUM_LEDS; i++) { led[i] = CRGB(0, 0, 0); } cred += 3; cgreen += 5; cblue += 7; led[chase++] = CRGB(cred, cgreen, cblue); dirty = true; //Serial.println(j); if (chase == NUM_LEDS) { chase = 0; } delay(200); // -------------------------- // Chasing reverse increasing colour } else if (lightProgram == 4) { for ( int i = NUM_LEDS - 1 ; i >= 0; i--) { led[i] = CRGB(0, 0, 0); } cred += 3; cgreen += 5; cblue += 7; led[chaser--] = CRGB(cred, cgreen, cblue); dirty = true; if (chaser < 0) { chaser = NUM_LEDS - 1; } delay(200); // -------------------------- // Twinkle } else if (lightProgram == 5 ) { for ( int i = 0; i < NUM_LEDS; i++) { led[i] = CRGB(0, 0, 0); } if (colourVal == 0) { led[random(0, NUM_LEDS)] = CRGB(random(0, 255), random(0, 255), random(0, 255)); } else { for (int i = 1; i <= 7; i++) { led[random(0, NUM_LEDS)] = CRGB(colourVal); } } dirty = true; delay(150); // -------------------------- // All on } else if (lightProgram == 6) { if (doRefresh) { for ( int i = 0; i < NUM_LEDS; i++) { led[i] = CRGB(255, 255, 255); } dirty = true; doRefresh = false; } // -------------------------- // All off } else if (lightProgram == 7) { if (doRefresh) { for ( int i = 0; i < NUM_LEDS; i++) { //led[i] = CRGB(0, 0, 0); led[i] = 0x0000; } dirty = true; doRefresh = false; } // -------------------------- // Rainbow } else if (lightProgram == 8) { int i = 0; int k = 0; while (i <= NUM_LEDS - 1) { led[i++] = rainbow[k++]; if (k > 6) { k = 0; } } int t = rainbow[6]; for (int i = 6; i > 0; i--) { //Serial.println(i); rainbow[i] = rainbow[i - 1]; } rainbow[0] = t; dirty = true; delay(500); delay(500); // Moving // -------------------------- } else if (lightProgram == 9) { if (colourVal == 0) { led[dot] = CRGB(rainbow[rc]); } else { led[dot] = CRGB(colourVal); } FastLED.show(); // clear this led for the next time around the loop led[dot++] = CRGB(0x000000); if (dot >= NUM_LEDS) { dot = 0; if (rc++ >= 7) { rc = 0; } } delay(50); // Set to colourVal // --------------------- } else if (lightProgram == 10) { if (doRefresh) { for ( int i = 0; i < NUM_LEDS; i++) { led[i] = CRGB(colourVal); } doRefresh = false; dirty = true; } // Christmas // ---------- } else if (lightProgram == 11) { if (doRefresh) { int i = 1; int nr = random(0, 7); int r = nr; led[0] = rainbow[nr]; while (i <= NUM_LEDS - 1) { while (nr == r) { nr = random(0, 7); } r = nr; led[i++] = rainbow[nr]; } dirty = true; doRefresh = false; } // Rainbow Group // -------------------------- } else if (lightProgram == 12) { int i = 0; int j = 0; int k = 0; // Create the group led array only once. if (doRefresh) { doRefresh = false; while (i <= NUM_LEDS - 1) { while (j <= 7) { led[i++] = rainbow[k]; if (i >= NUM_LEDS) { break; } j++; } j = 0; k++; if (k > 6) { k = 0; } } } // Rotate the array right by 1 CRGB t; t = led[NUM_LEDS - 1]; memmove8( &led[1], &led[0], (NUM_LEDS - 1) * sizeof( CRGB) ); led[0] = t; dirty = true; delay(20); // Multi Group // -------------------------- } else if (lightProgram == 13) { int i = 0; // led count int j = 0; // group count int k = 0; // colour count int a[] = {multiC1, multiC2}; // Create the group led array only once. if (doRefresh) { doRefresh = false; while (i <= NUM_LEDS - 1) { while (j < multiSz) { led[i++] = a[k]; if (i >= NUM_LEDS) { break; } j++; } j = 0; k++; if (k >= 2) { k = 0; } } } // Rotate the array by 1 or not. // dest, source CRGB t; if (multiDr == ">") { t = led[NUM_LEDS - 1]; memmove8(&led[1], &led[0], (NUM_LEDS - 1) * sizeof(CRGB)); led[0] = t; dirty = true; } else if (multiDr == "<") { t = led[0]; memmove8(&led[0], &led[1], (NUM_LEDS - 1) * sizeof(CRGB)); led[NUM_LEDS - 1] = t; Serial.println(led[0]); dirty = true; } delay(multiSp); } // Refresh the leds if anything has changed if (dirty) { FastLED.show(); dirty = false; } // Delay to allow the web pages to work. delay(1); //Serial.println("program: "); //Serial.println(lightProgram); }