Huzzah32 Loads Website Slowly

BuffaloFan32
Posts: 1
Joined: Sun Aug 08, 2021 5:05 pm

Huzzah32 Loads Website Slowly

Postby BuffaloFan32 » Mon Aug 09, 2021 4:30 am

I pieced together some of Rui Santos' scripts (thank you!) below to make a website that is hosted on a Huzzah32 by Adafruit. The Huzzah32 is controlling a bunch of WS2812 LEDs based on the button the user pushes when they load the website. Everything seems to work except that the website takes forever to load (>30 sec) when users first go to it. My network doesn't usually have problems loading websites. The lights run fast and buttons load quickly after the website is up - it's just that initial load that takes awhile. If you want to try it out, the website is only accessible by devices on your network and the serial monitor will output the IP address you need to enter in your web browser.

Also, if anyone knows how to pre-load a color into the color picker bar (preferably by RGB) I am struggling with that too.

sorry for the long code!

Code: Select all

// A basic everyday NeoPixel strip test program.

// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
//   connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#include <WiFi.h>
#include <Preferences.h>
#include <NTPClient.h>

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN    16

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 240

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)

const char* ssid     = "JoshAllen4eva";
const char* password = "17171717";
Preferences preferences;
String valueString = String(5);
String header;
String currentShow;
String lmnStr;
int counter;
int pos1;
int pos2;
int pos3;
int pos4;
int redVal;
int blueVal;
int greenVal;
float lumens;
int lumenInt;
String saver;
String formattedDate;
String dayStamp;
String timeStamp;
float phase;

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

WiFiServer server(80);

void setup()
{
    strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
    strip.show();            // Turn OFF all pixels ASAP
    strip.setBrightness(255); // Set BRIGHTNESS (max = 255)

    //Load previous session from memory
    preferences.begin("moon-app", false);
    lumens = preferences.getFloat("lumens", .5);
    redVal = preferences.getUInt("redVal", 100);
    blueVal = preferences.getUInt("blueVal", 100);
    greenVal = preferences.getUInt("greenVal", 100);
    currentShow = preferences.getString("currentShow", "M");
    //preferences.end();
    saver = "N";
    
    Serial.begin(115200);
    pinMode(5, OUTPUT);      // set the LED pin mode

    delay(10);

    // We start by connecting to a WiFi network

    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");

            
    }

    Serial.println("");
    Serial.println("WiFi connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    
    server.begin();

    //Moon Phase
    timeClient.begin();
    timeClient.update();
    timeClient.setTimeOffset(-8*3600);
    formattedDate = timeClient.getFormattedDate();
    // Extract date
    int splitT = formattedDate.indexOf("T");
    dayStamp = formattedDate.substring(0, splitT);
    Serial.print("DATE: ");
    Serial.println(dayStamp);
    int yrInt = dayStamp.substring(0, 4).toInt();
    int mthInt = dayStamp.substring(5, 7).toInt();
    int dayInt = dayStamp.substring(8, 10).toInt();
    phase = MoonPhase(yrInt, mthInt, dayInt);
    Serial.print("Moon Phase: ");
    Serial.println(phase);
}

int value = 0;

void loop(){
 WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    Serial.println("New Client.");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);
        header += c;
        // print it out the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();

            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            client.println("<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\">");
            client.println("<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.min.js\"></script>");

            
            // the content of the HTTP response follows the header:
            //Title
            client.println("</head><body><div class=\"container\"><div class=\"row\"><h1>Darby's Moon</h1></div></div>");
            //Color Picker
            client.println("<input class=\"jscolor {onFineChange:'update(this)'}\" id=\"rgb\" value=\"rgb(greenVal, redVal,blueVal)\"></div>");
            client.println("<script>function update(picker) {document.getElementById('rgb').innerHTML = Math.round(picker.rgb[0]) + ', ' +  Math.round(picker.rgb[1]) + ', ' + Math.round(picker.rgb[2]);");
            client.println("document.getElementById(\"change_color\").href=\"?r&&\" + Math.round(picker.rgb[0]) + \"g&&\" +  Math.round(picker.rgb[1]) + \"b&&\" + Math.round(picker.rgb[2]) + \"&&&\";}</script></body></html>");
            client.println("<a class=\"btn btn-primary btn-sm\" href=\"#\" id=\"change_color\" role=\"button\">Change Color</a> ");
            // The HTTP response ends with another blank line
            client.println("<br><br>");
            //Brightness
            client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");
            client.println("<p>Brightness (%): <span id=\"brightPos\"></span></p>");     
            lmnStr = String(lumens * 100);     
            client.println("<input type=\"range\" min=\"0\" max=\"100\" value=" + lmnStr + " class=\"slider\" id=\"brightSlider\" onchange=\"bright(this.value)\" value=\""+valueString+"\"/>");      
            client.println("<script>var slider = document.getElementById(\"brightSlider\");");
            client.println("var brightP = document.getElementById(\"brightPos\"); brightP.innerHTML = slider.value;");
            client.println("slider.oninput = function() { slider.value = this.value; brightP.innerHTML = this.value; }");
            client.println("$.ajaxSetup({timeout:1000}); function bright(pos) { ");
            client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}</script>");

            //Color picker output
            if(header.indexOf("r&&") >= 0) {
              pos1 = header.lastIndexOf("r&&");
              pos2 = header.lastIndexOf("g&&");
              pos3 = header.lastIndexOf("b&&");
              pos4 = header.lastIndexOf("&&&");
              redVal = header.substring(pos1+3, pos2).toInt();
              greenVal = header.substring(pos2+3, pos3).toInt();
              blueVal = header.substring(pos3+3, pos4).toInt();
            }

            //Brightness output
            if(header.indexOf("GET /?value=")>=0) {
              pos1 = header.lastIndexOf("?value=");
              pos2 = header.lastIndexOf("& HTTP");
              lumenInt = header.substring(pos1+7, pos2).toInt();
              lumens = float(lumenInt)/100;
            }
            
            //Preloaded Buttons
            client.println("<div class=\"container\"><div class=\"row\">Preloaded Effects:</div></div>");
            client.println("<a class=\"btn btn-primary btn-lg\" href=\"/U\" id=\"All On\" role=\"button\">All On</a> ");
            client.println("<a class=\"btn btn-primary btn-lg\" href=\"/O\" id=\"All Off\" role=\"button\">All Off</a> ");
            client.println("<br><br>");
            client.println("<a class=\"btn btn-primary btn-lg\" href=\"/R\" id=\"Rainbow\" role=\"button\">Rainbow</a> ");
            client.println("<a class=\"btn btn-primary btn-lg\" href=\"/D\" id=\"Disco\" role=\"button\">Disco</a> ");
            client.println("<a class=\"btn btn-primary btn-lg\" href=\"/M\" id=\"Moon\" role=\"button\">Moon</a> ");
            client.println("<br><br>");
            client.println("<a class=\"btn btn-primary btn-lg\" href=\"/S\" id=\"Saver\" role=\"button\">Save Settings</a> ");

            client.println("</body></html>");
            
            // The HTTP response ends with another blank line:
            client.println();
            // break out of the while loop:
            break;
          } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }

        // Check the client request:
        //Moon request
        if (currentLine.endsWith("GET /M")) {
          currentShow = "M";
        }
        //Rainbow request
        if (currentLine.endsWith("GET /R")) {
          currentShow = "R";
        }
        //Disco request
        if (currentLine.endsWith("GET /D")) {
          currentShow = "D";
          counter = 0;
        }
        //On request
        if (currentLine.endsWith("GET /U")) {
          currentShow = "U";
        }
        //Off request
        if (currentLine.endsWith("GET /O")) {
          currentShow = "O";
          strip.clear(); // Turn the lights out
          strip.show();
        }
        //Save request
        if (currentLine.endsWith("GET /S")) {
          saver = "S";
          counter = 0;
        }
      }
    }
    // Clear the header variable
    header = "";
    // close the connection:
    client.stop();
    Serial.println("Client Disconnected.");
  }


//Current show is Moon
  if (currentShow == "M") {
    lightMoon(phase, strip.Color(greenVal*lumens, redVal*lumens, blueVal*lumens));
  } 
//Current show is All On
  if (currentShow == "U") {
    strip.fill(strip.Color(greenVal*lumens, redVal*lumens, blueVal*lumens), 0, LED_COUNT); // Turn the lights on
    strip.show();
  } 
//Current show is Rainbow
  if (currentShow == "R") {
    rainbow(counter, lumens);
    counter = counter + 256;
    if (counter > 5*65536) {counter = 0;}
  } 
//Current show is Disco
  if (currentShow == "D") {
    theaterChase(strip.Color(greenVal*lumens, redVal*lumens, blueVal*lumens), counter);
    counter = counter + 1;
    if (counter > 2) {counter = 0;}
  }
//Current show is Save
  if (saver == "S") {
    preferences.putString("currentShow", currentShow);
    preferences.putUInt("redVal", redVal);
    preferences.putUInt("greenVal", greenVal);
    preferences.putUInt("blueVal", blueVal);
    preferences.putFloat("lumens", lumens);
    saver = "N";
  }
}

// Some functions of our own for creating animated effects -----------------

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int b) {
  int wait = 50;
  strip.clear();         //   Set all pixels in RAM to 0 (off)
  // 'c' counts up from 'b' to end of strip in steps of 3...
  for(int c=b; c<strip.numPixels(); c += 3) {
    strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
  }
  strip.show(); // Update strip with new contents
  delay(wait);  // Pause for a moment    
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(long firstPixelHue, float lumens) {
  int wait = 10;
  //unsigned int lumens = preferences.getUInt("lumens", 50);
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this outer loop:
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    // Offset pixel hue by an amount to make one full revolution of the
    // color wheel (range of 65536) along the length of the strip
    // (strip.numPixels() steps):
    int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
    // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
    // optionally add saturation and value (brightness) (each 0 to 255).
    // Here we're using just the single-argument hue variant. The result
    // is passed through strip.gamma32() to provide 'truer' colors
    // before assigning to each pixel:
    
    strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue, 255, lumens * 255)));
  }
  strip.show(); // Update strip with new contents
  delay(wait);  // Pause for a moment
}

//Show current phase of moon
void lightMoon(float phase, uint32_t color) {
  if ((phase >=0) && (phase <= 1)) {
    strip.clear(); // Turn the lights out
    strip.setPixelColor(12, color);
    strip.setPixelColor(17, color);
    strip.setPixelColor(78, color);
    strip.show();
  }
}

float MoonPhase(int nYear, int nMonth, int nDay) // calculate the current phase of the moon
{
  float age, phase, frac, days_since;
  long YY, MM, K1, K2, K3, JD;
  YY = nYear - floor((12 - nMonth) / 10);
  MM = nMonth + 9;
  if (MM >= 12)
  {
    MM = MM - 12;
  }
  K1 = floor(365.25 * (YY + 4712));
  K2 = floor(30.6 * MM + 0.5);
  K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;
  JD = K1 + K2 + nDay + 59;  //Julian day
  if (JD > 2299160) //1582, Gregorian calendar
  {
    JD = JD - K3;
  }

  // Serial.print(" JD ");  //Julian Day, checked OK
  // Serial.print(JD);
  // Serial.print(" ");

  days_since = JD - 2451550L; //since new moon on Jan. 6, 2000 (@18:00)
  phase = (days_since - 0.25) / 29.53059; //0.25 = correct for 6 pm that day
  phase -= floor(phase);  //phase in cycle

  return phase; //phase or age or frac, as desired
}
// https://forum.arduino.cc/t/simple-lunar-clock/421406/9

Who is online

Users browsing this forum: No registered users and 97 guests