Added palette selector

* Added palette selector and supporting code.
* Switched several patterns to use the selected palette: Confetti,
Sinelon, BPM, Juggle
* Limit EEPROM writes in autoplay mode.
This commit is contained in:
Jason Coon 2017-02-18 13:24:05 -06:00
parent 9bc7b7a5e7
commit 681c29a877
3 changed files with 148 additions and 28 deletions

View File

@ -52,9 +52,13 @@
<label for="inputPattern" class="col-sm-2 control-label">Pattern</label> <label for="inputPattern" class="col-sm-2 control-label">Pattern</label>
<div class="col-sm-6"> <div class="col-sm-6">
<select class="form-control" id="inputPattern"> <select class="form-control" id="inputPattern">
<option>Rainbow</option> </select>
<option>Sinelon</option> </div>
<option>Juggle</option> </div>
<div class="form-group">
<label for="inputPalette" class="col-sm-2 control-label">Palette</label>
<div class="col-sm-6">
<select class="form-control" id="inputPalette">
</select> </select>
</div> </div>
</div> </div>

View File

@ -70,6 +70,10 @@ $("#inputPattern").change(function() {
setPattern($("#inputPattern option:selected").index()); setPattern($("#inputPattern option:selected").index());
}); });
$("#inputPalette").change(function() {
setPalette($("#inputPalette option:selected").index());
});
$("#inputColor").change(function() { $("#inputColor").change(function() {
if(ignoreColorChange) return; if(ignoreColorChange) return;
@ -105,15 +109,30 @@ function getAll() {
updatePowerButtons(data.power); updatePowerButtons(data.power);
// clear pattern list
$("#inputPattern").find("option").remove(); $("#inputPattern").find("option").remove();
// load pattern list
for(var i = 0; i < data.patterns.length; i++) { for(var i = 0; i < data.patterns.length; i++) {
var pattern = data.patterns[i]; var pattern = data.patterns[i];
$("#inputPattern").append("<option value='" + i + "'>" + pattern + "</option>"); $("#inputPattern").append("<option value='" + i + "'>" + pattern + "</option>");
} }
// select the current pattern
$("#inputPattern").val(data.currentPattern.index); $("#inputPattern").val(data.currentPattern.index);
// clear palette list
$("#inputPalette").find("option").remove();
// load palette list
for(var i = 0; i < data.palettes.length; i++) {
var palette = data.palettes[i];
$("#inputPalette").append("<option value='" + i + "'>" + palette + "</option>");
}
// select the current palette
$("#inputPalette").val(data.currentPalette.index);
$("#status").html("Ready"); $("#status").html("Ready");
}); });
} }
@ -154,6 +173,12 @@ function setPattern(value) {
}); });
} }
function setPalette(value) {
$.post(urlBase + "palette?value=" + value, function(data) {
$("#status").html("Set Palette: " + data.name);
});
}
function delaySetColor(value) { function delaySetColor(value) {
clearTimeout(colorTimer); clearTimeout(colorTimer);
colorTimer = setTimeout(function() { colorTimer = setTimeout(function() {

View File

@ -1,20 +1,20 @@
/* /*
* ESP8266 + FastLED + IR Remote + MSGEQ7: https://github.com/jasoncoon/esp8266-fastled-webserver ESP8266 + FastLED + IR Remote + MSGEQ7: https://github.com/jasoncoon/esp8266-fastled-webserver
* Copyright (C) 2015 Jason Coon Copyright (C) 2015 Jason Coon
*
* This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "FastLED.h" #include "FastLED.h"
FASTLED_USING_NAMESPACE FASTLED_USING_NAMESPACE
@ -46,7 +46,7 @@ const char* password = "";
ESP8266WebServer server(80); ESP8266WebServer server(80);
#define DATA_PIN 13 // for Huzzah: Pins w/o special function: #4, #5, #12, #13, #14; // #16 does not work :( #define DATA_PIN D8 // for Huzzah: Pins w/o special function: #4, #5, #12, #13, #14; // #16 does not work :(
#define LED_TYPE WS2812 #define LED_TYPE WS2812
#define COLOR_ORDER GRB #define COLOR_ORDER GRB
#define NUM_LEDS 24 #define NUM_LEDS 24
@ -89,6 +89,8 @@ bool autoplayEnabled = false;
uint8_t autoPlayDurationSeconds = 10; uint8_t autoPlayDurationSeconds = 10;
unsigned int autoPlayTimeout = 0; unsigned int autoPlayTimeout = 0;
uint8_t currentPaletteIndex = 0;
uint8_t gHue = 0; // rotating "base color" used by many of the patterns uint8_t gHue = 0; // rotating "base color" used by many of the patterns
CRGB solidColor = CRGB::Blue; CRGB solidColor = CRGB::Blue;
@ -245,6 +247,16 @@ void setup(void) {
sendBrightness(); sendBrightness();
}); });
server.on("/palette", HTTP_GET, []() {
sendPalette();
});
server.on("/palette", HTTP_POST, []() {
String value = server.arg("value");
setPalette(value.toInt());
sendPalette();
});
server.serveStatic("/index.htm", SPIFFS, "/index.htm"); server.serveStatic("/index.htm", SPIFFS, "/index.htm");
server.serveStatic("/fonts", SPIFFS, "/fonts", "max-age=86400"); server.serveStatic("/fonts", SPIFFS, "/fonts", "max-age=86400");
server.serveStatic("/js", SPIFFS, "/js"); server.serveStatic("/js", SPIFFS, "/js");
@ -260,7 +272,6 @@ void setup(void) {
} }
typedef void (*Pattern)(); typedef void (*Pattern)();
typedef Pattern PatternList[];
typedef struct { typedef struct {
Pattern pattern; Pattern pattern;
String name; String name;
@ -283,6 +294,36 @@ PatternAndNameList patterns = {
const uint8_t patternCount = ARRAY_SIZE(patterns); const uint8_t patternCount = ARRAY_SIZE(patterns);
typedef struct {
CRGBPalette16 palette;
String name;
} PaletteAndName;
typedef PaletteAndName PaletteAndNameList[];
const CRGBPalette16 palettes[] = {
RainbowColors_p,
RainbowStripeColors_p,
CloudColors_p,
LavaColors_p,
OceanColors_p,
ForestColors_p,
PartyColors_p,
HeatColors_p
};
const uint8_t paletteCount = ARRAY_SIZE(palettes);
const String paletteNames[paletteCount] = {
"Rainbow",
"Rainbow Stripe",
"Cloud",
"Lava",
"Ocean",
"Forest",
"Party",
"Heat",
};
void loop(void) { void loop(void) {
// Add entropy to random number generator; we use a lot of it. // Add entropy to random number generator; we use a lot of it.
random16_add_entropy(random(65535)); random16_add_entropy(random(65535));
@ -559,6 +600,12 @@ void loadSettings()
{ {
solidColor = CRGB(r, g, b); solidColor = CRGB(r, g, b);
} }
currentPaletteIndex = EEPROM.read(5);
if (currentPaletteIndex < 0)
currentPaletteIndex = 0;
else if (currentPaletteIndex >= paletteCount)
currentPaletteIndex = paletteCount - 1;
} }
void sendAll() void sendAll()
@ -572,6 +619,10 @@ void sendAll()
json += "\"index\":" + String(currentPatternIndex); json += "\"index\":" + String(currentPatternIndex);
json += ",\"name\":\"" + patterns[currentPatternIndex].name + "\"}"; json += ",\"name\":\"" + patterns[currentPatternIndex].name + "\"}";
json += ",\"currentPalette\":{";
json += "\"index\":" + String(currentPaletteIndex);
json += ",\"name\":\"" + paletteNames[currentPaletteIndex] + "\"}";
json += ",\"solidColor\":{"; json += ",\"solidColor\":{";
json += "\"r\":" + String(solidColor.r); json += "\"r\":" + String(solidColor.r);
json += ",\"g\":" + String(solidColor.g); json += ",\"g\":" + String(solidColor.g);
@ -587,6 +638,15 @@ void sendAll()
} }
json += "]"; json += "]";
json += ",\"palettes\":[";
for (uint8_t i = 0; i < paletteCount; i++)
{
json += "\"" + paletteNames[i] + "\"";
if (i < paletteCount - 1)
json += ",";
}
json += "]";
json += "}"; json += "}";
server.send(200, "text/json", json); server.send(200, "text/json", json);
@ -610,6 +670,16 @@ void sendPattern()
json = String(); json = String();
} }
void sendPalette()
{
String json = "{";
json += "\"index\":" + String(currentPaletteIndex);
json += ",\"name\":\"" + paletteNames[currentPaletteIndex] + "\"";
json += "}";
server.send(200, "text/json", json);
json = String();
}
void sendBrightness() void sendBrightness()
{ {
String json = String(brightness); String json = String(brightness);
@ -663,8 +733,10 @@ void adjustPattern(bool up)
if (currentPatternIndex >= patternCount) if (currentPatternIndex >= patternCount)
currentPatternIndex = 0; currentPatternIndex = 0;
EEPROM.write(1, currentPatternIndex); if (autoplay == 0) {
EEPROM.commit(); EEPROM.write(1, currentPatternIndex);
EEPROM.commit();
}
} }
void setPattern(int value) void setPattern(int value)
@ -677,7 +749,23 @@ void setPattern(int value)
currentPatternIndex = value; currentPatternIndex = value;
EEPROM.write(1, currentPatternIndex); if (autoplay == 0) {
EEPROM.write(1, currentPatternIndex);
EEPROM.commit();
}
}
void setPalette(int value)
{
// don't wrap around at the ends
if (value < 0)
value = 0;
else if (value >= paletteCount)
value = paletteCount - 1;
currentPaletteIndex = value;
EEPROM.write(5, currentPaletteIndex);
EEPROM.commit(); EEPROM.commit();
} }
@ -748,7 +836,8 @@ void confetti()
// random colored speckles that blink in and fade smoothly // random colored speckles that blink in and fade smoothly
fadeToBlackBy( leds, NUM_LEDS, 10); fadeToBlackBy( leds, NUM_LEDS, 10);
int pos = random16(NUM_LEDS); int pos = random16(NUM_LEDS);
leds[pos] += CHSV( gHue + random8(64), 200, 255); // leds[pos] += CHSV( gHue + random8(64), 200, 255);
leds[pos] += ColorFromPalette(palettes[currentPaletteIndex], gHue + random8(64));
} }
void sinelon() void sinelon()
@ -756,14 +845,15 @@ void sinelon()
// a colored dot sweeping back and forth, with fading trails // a colored dot sweeping back and forth, with fading trails
fadeToBlackBy( leds, NUM_LEDS, 20); fadeToBlackBy( leds, NUM_LEDS, 20);
int pos = beatsin16(13, 0, NUM_LEDS - 1); int pos = beatsin16(13, 0, NUM_LEDS - 1);
leds[pos] += CHSV( gHue, 255, 192); // leds[pos] += CHSV( gHue, 255, 192);
leds[pos] += ColorFromPalette(palettes[currentPaletteIndex], gHue, 192);
} }
void bpm() void bpm()
{ {
// colored stripes pulsing at a defined Beats-Per-Minute (BPM) // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62; uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p; CRGBPalette16 palette = palettes[currentPaletteIndex];
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255); uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
for ( int i = 0; i < NUM_LEDS; i++) { //9948 for ( int i = 0; i < NUM_LEDS; i++) { //9948
leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10)); leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
@ -777,7 +867,8 @@ void juggle()
byte dothue = 0; byte dothue = 0;
for ( int i = 0; i < 8; i++) for ( int i = 0; i < 8; i++)
{ {
leds[beatsin16(i + 7, 0, NUM_LEDS)] |= CHSV(dothue, 200, 255); // leds[beatsin16(i + 7, 0, NUM_LEDS)] |= CHSV(dothue, 200, 255);
leds[beatsin16(i + 7, 0, NUM_LEDS)] |= ColorFromPalette(palettes[currentPaletteIndex], dothue);
dothue += 32; dothue += 32;
} }
} }