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