Created
March 31, 2018 14:57
-
-
Save perigalacticon/90c906b70c0d695cf9ff2843f2ed1fc7 to your computer and use it in GitHub Desktop.
TwinkleFox custom color palette, starts line 446
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// twinkle_fox_Easter_spillar.ino | |
// TwinkleFox + NeoPixelBus + WebUpdate | |
// Perigalacticon 3/30/18 | |
// needs 80MHz will not run on 160MHz | |
#include "FastLED.h" | |
#include <ESP8266WiFi.h> | |
#include <ESP8266mDNS.h> | |
#include <WiFiClient.h> | |
#include <ESP8266WebServer.h> | |
#include <ESP8266HTTPUpdateServer.h> | |
#include <NeoPixelBus.h> | |
#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000) | |
#warning "Requires FastLED 3.1 or later; check github for latest code." | |
#endif | |
#define NUM_LEDS 40 | |
#define LED_TYPE WS2812B | |
#define COLOR_ORDER GRB //GRB | |
#define DATA_PIN 2 | |
//#define CLK_PIN 4 | |
#define VOLTS 5 | |
#define MAX_MA 10000 | |
#define FASTLED_ALLOW_INTERRUPTS 0 | |
#define FASTLED_INTERRUPT_RETRY_COUNT 0 | |
CRGBArray<NUM_LEDS> leds; | |
// Overall twinkle speed. | |
// 0 (VERY slow) to 8 (VERY fast). | |
// 4, 5, and 6 are recommended, default is 4. | |
#define TWINKLE_SPEED 3 | |
// Overall twinkle density. | |
// 0 (NONE lit) to 8 (ALL lit at once). | |
// Default is 5. | |
#define TWINKLE_DENSITY 8 | |
// How often to change color palettes. | |
#define SECONDS_PER_PALETTE 100 | |
// Also: toward the bottom of the file is an array | |
// called "ActivePaletteList" which controls which color | |
// palettes are used; you can add or remove color palettes | |
// from there freely. | |
// Background color for 'unlit' pixels | |
// Can be set to CRGB::Black if desired. | |
CRGB gBackgroundColor = CRGB::Black; | |
// Example of dim incandescent fairy light background color | |
// CRGB gBackgroundColor = CRGB(CRGB::FairyLight).nscale8_video(16); | |
// If AUTO_SELECT_BACKGROUND_COLOR is set to 1, | |
// then for any palette where the first two entries | |
// are the same, a dimmed version of that color will | |
// automatically be used as the background color. | |
#define AUTO_SELECT_BACKGROUND_COLOR 0 | |
// If COOL_LIKE_INCANDESCENT is set to 1, colors will | |
// fade out slighted 'reddened', similar to how | |
// incandescent bulbs change color as they get dim down. | |
#define COOL_LIKE_INCANDESCENT 0 | |
const char* host = "esp8266-webupdate-spillar"; | |
const char* ssid = ""; | |
const char* password = ""; | |
ESP8266WebServer httpServer(80); | |
ESP8266HTTPUpdateServer httpUpdater; | |
CRGBPalette16 gCurrentPalette; | |
CRGBPalette16 gTargetPalette; | |
uint8_t colorsHSV[8][3] = | |
{ | |
{192, 255, 150}, //purple | |
{250, 255, 200}, //pink1 not accurate see rgb | |
{240, 255, 200}, //pink2 not accurate see rgb | |
{230, 255, 200}, //pink3 not accurate see rgb | |
{55, 220, 222}, //yellow1 not accurate see rgb | |
{57, 220, 222}, //yellow2 not accurate see rgb | |
{85, 255, 200}, //lime green | |
{115, 255, 220} //teal | |
}; | |
uint8_t colorsRGB[8][3] = | |
{ | |
{29, 0, 59}, //purple | |
{147, 0, 9}, //pink | |
{131, 0, 25}, //pink2 | |
{114, 0, 42}, //pink3 | |
{114, 98, 3}, //yellow1 | |
{100, 115, 3}, //yellow2 | |
{36, 139, 0}, //lime green | |
{0, 152, 38} //teal | |
}; | |
// 0x1D003B //purple | |
// 0x930009 //pink1 | |
// 0x830019 //pink2 | |
// 0x72002A //pink3 | |
// 0x726203 //yellow1 | |
// 0x647303 //yellow2 | |
// 0x248B03 //lime green | |
// 0x009826 //teal | |
//NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod> NPBStrip(NUM_LEDS, DATA_PIN); | |
NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod> NPBStrip(NUM_LEDS, DATA_PIN); | |
byte brightness = 255; | |
void setup() { | |
delay( 3000 ); //safety startup delay | |
Serial.begin(115200); | |
Serial.println(); | |
Serial.println("twinkle_fox_Easter_spillar"); | |
Serial.println("Booting"); | |
WiFi.mode(WIFI_AP_STA); | |
while (WiFi.waitForConnectResult() != WL_CONNECTED) | |
{ | |
WiFi.begin(ssid, password); | |
Serial.println("WiFi failed, retrying."); | |
} | |
MDNS.begin(host); | |
httpUpdater.setup(&httpServer); | |
httpServer.begin(); | |
MDNS.addService("http", "tcp", 80); | |
Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser MOD1\n", host); | |
FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA); | |
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS) | |
.setCorrection(TypicalLEDStrip); | |
NPBStrip.Begin(); | |
chooseNextColorPalette(gTargetPalette); | |
for(uint8_t color = 0; color < 8; color++) | |
{ | |
CHSV hsv(colorsHSV[color][0], colorsHSV[color][1], colorsHSV[color][2]); | |
CRGB rgb; | |
hsv2rgb_rainbow( hsv, rgb); | |
Serial.print("color = "); | |
Serial.print(color); | |
Serial.print("\t"); | |
Serial.print("r = "); | |
Serial.print(rgb.r); | |
Serial.print("\t"); | |
Serial.print("g = "); | |
Serial.println(rgb.g); | |
Serial.print("\t"); | |
Serial.print("b = "); | |
Serial.println(rgb.b); | |
} | |
} | |
void loop() | |
{ | |
EVERY_N_SECONDS( SECONDS_PER_PALETTE ) { | |
chooseNextColorPalette( gTargetPalette ); | |
} | |
EVERY_N_MILLISECONDS( 10 ) { | |
nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 12); | |
} | |
EVERY_N_MILLISECONDS( 500 ) { | |
httpServer.handleClient(); | |
} | |
EVERY_N_MILLISECONDS( 10000 ) | |
{ | |
//connect wifi if not connected | |
if (WiFi.status() != WL_CONNECTED) | |
{ | |
delay(1); | |
startWIFI(); | |
return; | |
} | |
} | |
delay(1); | |
drawTwinkles( leds); | |
TransferToNeoPixelBus(); | |
NPBStrip.Show(); | |
} | |
// This function loops over each pixel, calculates the | |
// adjusted 'clock' that this pixel should use, and calls | |
// "CalculateOneTwinkle" on each pixel. It then displays | |
// either the twinkle color of the background color, | |
// whichever is brighter. | |
void drawTwinkles( CRGBSet& L) | |
{ | |
// "PRNG16" is the pseudorandom number generator | |
// It MUST be reset to the same starting value each time | |
// this function is called, so that the sequence of 'random' | |
// numbers that it generates is (paradoxically) stable. | |
uint16_t PRNG16 = 11337; | |
uint32_t clock32 = millis(); | |
// Set up the background color, "bg". | |
// if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of | |
// the current palette are identical, then a deeply faded version of | |
// that color is used for the background color | |
CRGB bg; | |
if ( (AUTO_SELECT_BACKGROUND_COLOR == 1) && | |
(gCurrentPalette[0] == gCurrentPalette[1] )) { | |
bg = gCurrentPalette[0]; | |
uint8_t bglight = bg.getAverageLight(); | |
if ( bglight > 64) { | |
bg.nscale8_video( 16); // very bright, so scale to 1/16th | |
} else if ( bglight > 16) { | |
bg.nscale8_video( 64); // not that bright, so scale to 1/4th | |
} else { | |
bg.nscale8_video( 86); // dim, scale to 1/3rd. | |
} | |
} else { | |
bg = gBackgroundColor; // just use the explicitly defined background color | |
} | |
uint8_t backgroundBrightness = bg.getAverageLight(); | |
for ( CRGB& pixel : L) { | |
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number | |
uint16_t myclockoffset16 = PRNG16; // use that number as clock offset | |
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number | |
// use that number as clock speed adjustment factor (in 8ths, from 8/8ths to 23/8ths) | |
uint8_t myspeedmultiplierQ5_3 = ((((PRNG16 & 0xFF) >> 4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08; | |
uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16; | |
uint8_t myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel | |
// We now have the adjusted 'clock' for this pixel, now we call | |
// the function that computes what color the pixel should be based | |
// on the "brightness = f( time )" idea. | |
CRGB c = computeOneTwinkle( myclock30, myunique8); | |
uint8_t cbright = c.getAverageLight(); | |
int16_t deltabright = cbright - backgroundBrightness; | |
if ( deltabright >= 32 || (!bg)) { | |
// If the new pixel is significantly brighter than the background color, | |
// use the new color. | |
pixel = c; | |
} else if ( deltabright > 0 ) { | |
// If the new pixel is just slightly brighter than the background color, | |
// mix a blend of the new color and the background color | |
pixel = blend( bg, c, deltabright * 8); | |
} else { | |
// if the new pixel is not at all brighter than the background color, | |
// just use the background color. | |
pixel = bg; | |
} | |
} | |
} | |
// This function takes a time in pseudo-milliseconds, | |
// figures out brightness = f( time ), and also hue = f( time ) | |
// The 'low digits' of the millisecond time are used as | |
// input to the brightness wave function. | |
// The 'high digits' are used to select a color, so that the color | |
// does not change over the course of the fade-in, fade-out | |
// of one cycle of the brightness wave function. | |
// The 'high digits' are also used to determine whether this pixel | |
// should light at all during this cycle, based on the TWINKLE_DENSITY. | |
CRGB computeOneTwinkle( uint32_t ms, uint8_t salt) | |
{ | |
uint16_t ticks = ms >> (8 - TWINKLE_SPEED); | |
uint8_t fastcycle8 = ticks; | |
uint16_t slowcycle16 = (ticks >> 8) + salt; | |
slowcycle16 += sin8( slowcycle16); | |
slowcycle16 = (slowcycle16 * 2053) + 1384; | |
uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8); | |
uint8_t bright = 0; | |
if ( ((slowcycle8 & 0x0E) / 2) < TWINKLE_DENSITY) { | |
bright = attackDecayWave8( fastcycle8); | |
} | |
uint8_t hue = slowcycle8 - salt; | |
CRGB c; | |
if ( bright > 0) { | |
c = ColorFromPalette( gCurrentPalette, hue, bright, NOBLEND); | |
if ( COOL_LIKE_INCANDESCENT == 1 ) { | |
coolLikeIncandescent( c, fastcycle8); | |
} | |
} else { | |
c = CRGB::Black; | |
} | |
return c; | |
} | |
// This function is like 'triwave8', which produces a | |
// symmetrical up-and-down triangle sawtooth waveform, except that this | |
// function produces a triangle wave with a faster attack and a slower decay: | |
// | |
// / \ | |
// / \ | |
// / \ | |
// / \ | |
// | |
uint8_t attackDecayWave8( uint8_t i) | |
{ | |
if ( i < 86) { | |
return i * 3; | |
} else { | |
i -= 86; | |
return 255 - (i + (i / 2)); | |
} | |
} | |
// This function takes a pixel, and if its in the 'fading down' | |
// part of the cycle, it adjusts the color a little bit like the | |
// way that incandescent bulbs fade toward 'red' as they dim. | |
void coolLikeIncandescent( CRGB& c, uint8_t phase) | |
{ | |
if ( phase < 128) return; | |
uint8_t cooling = (phase - 128) >> 4; | |
c.g = qsub8( c.g, cooling); | |
c.b = qsub8( c.b, cooling * 2); | |
} | |
// A mostly red palette with green accents and white trim. | |
// "CRGB::Gray" is used as white to keep the brightness more uniform. | |
const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM = | |
{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, | |
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, | |
CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, | |
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green | |
}; | |
const TProgmemRGBPalette16 RedGreen_p FL_PROGMEM = | |
{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, | |
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, | |
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green, | |
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green | |
}; | |
// A mostly (dark) green palette with red berries. | |
#define Holly_Green 0x00580c | |
#define Holly_Red 0xB00402 | |
const TProgmemRGBPalette16 Holly_p FL_PROGMEM = | |
{ Holly_Green, Holly_Green, Holly_Green, Holly_Green, | |
Holly_Green, Holly_Green, Holly_Green, Holly_Green, | |
Holly_Green, Holly_Green, Holly_Green, Holly_Green, | |
Holly_Green, Holly_Green, Holly_Green, Holly_Red | |
}; | |
// A red and white striped palette | |
// "CRGB::Gray" is used as white to keep the brightness more uniform. | |
const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM = | |
{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, | |
CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray, | |
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, | |
CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray | |
}; | |
// A mostly blue palette with white accents. | |
// "CRGB::Gray" is used as white to keep the brightness more uniform. | |
const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM = | |
{ CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, | |
CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, | |
CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, | |
CRGB::Blue, CRGB::Gray, CRGB::Gray, CRGB::Gray | |
}; | |
// "CRGB::Gray" is used as white to keep the brightness more uniform. | |
const TProgmemRGBPalette16 Green1_p FL_PROGMEM = | |
{ CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green, | |
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green, | |
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green, | |
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green | |
}; | |
// Blue and white for greek independence day: | |
const TProgmemRGBPalette16 Blue_White_p FL_PROGMEM = | |
{ CRGB::Blue, CRGB::Gray, CRGB::Blue, CRGB::Gray, | |
CRGB::Blue, CRGB::Gray, CRGB::Blue, CRGB::Gray, | |
CRGB::Blue, CRGB::Gray, CRGB::Blue, CRGB::Gray, | |
CRGB::Blue, CRGB::Gray, CRGB::Blue, CRGB::Gray | |
}; | |
// A pure "fairy light" palette with some brightness variations | |
#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2) | |
#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4) | |
const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM = | |
{ CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, | |
HALFFAIRY, HALFFAIRY, CRGB::FairyLight, CRGB::FairyLight, | |
QUARTERFAIRY, QUARTERFAIRY, CRGB::FairyLight, CRGB::FairyLight, | |
CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight | |
}; | |
// A palette of soft snowflakes with the occasional bright one | |
const TProgmemRGBPalette16 Snow_p FL_PROGMEM = | |
{ 0x304048, 0x304048, 0x304048, 0x304048, | |
0x304048, 0x304048, 0x304048, 0x304048, | |
0x304048, 0x304048, 0x304048, 0x304048, | |
0x304048, 0x304048, 0x304048, 0xE0F0FF | |
}; | |
// A palette reminiscent of large 'old-school' C9-size tree lights | |
// in the five classic colors: red, orange, green, blue, and white. | |
#define C9_Red 0xB80400 | |
#define C9_Orange 0x902C02 | |
#define C9_Green 0x046002 | |
#define C9_Blue 0x070758 | |
#define C9_White 0x606820 | |
const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM = | |
{ C9_Red, C9_Orange, C9_Red, C9_Orange, | |
C9_Orange, C9_Red, C9_Orange, C9_Red, | |
C9_Green, C9_Green, C9_Green, C9_Green, | |
C9_Blue, C9_Blue, C9_Blue, | |
C9_White | |
}; | |
// A cold, icy pale blue palette | |
#define Ice_Blue1 0x0C1040 | |
#define Ice_Blue2 0x182080 | |
#define Ice_Blue3 0x5080C0 | |
const TProgmemRGBPalette16 Ice_p FL_PROGMEM = | |
{ | |
Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, | |
Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, | |
Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, | |
Ice_Blue2, Ice_Blue2, Ice_Blue2, Ice_Blue3 | |
}; | |
// Easter Colors hsv, rgb: | |
//purple: 192, 255, 150 | |
//pink: 250, 255, 200 | |
//yellow: 55, 220, 222 | |
//lime green: 85, 255, 200 | |
//teal: 115, 255, 220 | |
// CRGB purple = CHSV(192, 255, 150); | |
// CRGB pink = CHSV(250, 255, 200); | |
// CRGB yellow = CHSV(55, 220, 222); | |
// CRGB lime_green = CHSV(85, 255, 200); | |
// CRGB teal = CHSV(115, 255, 220); | |
#define easter_purple 0x1D003B //purple | |
#define easter_pink1 0x930009 //pink1 | |
#define easter_pink2 0x830019 // pink2 | |
#define easter_pink3 0x72002A // pink3 | |
#define easter_yellow1 0x726203 //yellow1 | |
#define easter_yellow2 0x647303 // yellow2 | |
#define easter_lime_green 0x248B03 //lime green | |
#define easter_teal 0x009826 //teal | |
const TProgmemRGBPalette16 Easter_p FL_PROGMEM = | |
{ | |
easter_purple, easter_pink3, easter_yellow2, easter_lime_green, | |
easter_teal, easter_purple, easter_pink3, easter_yellow2, | |
easter_lime_green, easter_teal, easter_purple, easter_pink3, | |
easter_yellow2, easter_lime_green, easter_teal, easter_purple | |
}; | |
// Add or remove palette names from this list to control which color | |
// palettes are used, and in what order. | |
const TProgmemRGBPalette16* ActivePaletteList[] = { | |
// &RedGreen_p | |
// &RetroC9_p, | |
// &BlueWhite_p, | |
// &RainbowColors_p, | |
// &FairyLight_p, | |
// &RedGreenWhite_p, | |
// &PartyColors_p | |
// &RedWhite_p, | |
// &Snow_p, | |
// &Holly_p, | |
// &Ice_p, | |
// &Green1_p, | |
// &Blue_White_p, | |
&Easter_p | |
}; | |
// Advance to the next color palette in the list (above). | |
void chooseNextColorPalette( CRGBPalette16& pal) | |
{ | |
const uint8_t numberOfPalettes = sizeof(ActivePaletteList) / sizeof(ActivePaletteList[0]); | |
static uint8_t whichPalette = -1; | |
whichPalette = addmod8( whichPalette, 1, numberOfPalettes); | |
pal = *(ActivePaletteList[whichPalette]); | |
} | |
void TransferToNeoPixelBus(void) | |
{ | |
RgbColor NPBPixel; | |
for ( int i = 0; i < NUM_LEDS; i++) | |
{ | |
NPBPixel = RgbColor(leds[i].r, leds[i].g, leds[i].b); | |
NPBStrip.SetPixelColor(i, NPBPixel); | |
} | |
} | |
void startWIFI(void) | |
{ | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) { | |
Serial.print("."); | |
delay(500); | |
} | |
Serial.println(""); | |
Serial.println("WiFi reconnected"); | |
// MDNS.begin(host); | |
// | |
// httpUpdater.setup(&httpServer); | |
// httpServer.begin(); | |
// | |
// MDNS.addService("http", "tcp", 80); | |
// Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser MOD1\n", host); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment