Skip to content

Instantly share code, notes, and snippets.

@perigalacticon
Created March 31, 2018 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save perigalacticon/90c906b70c0d695cf9ff2843f2ed1fc7 to your computer and use it in GitHub Desktop.
Save perigalacticon/90c906b70c0d695cf9ff2843f2ed1fc7 to your computer and use it in GitHub Desktop.
TwinkleFox custom color palette, starts line 446
// 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