2016-03-10 14:57:02 +01:00
/*
2017-07-13 15:46:28 +02:00
ESP8266 + FastLED + IR Remote : https : //github.com/jasoncoon/esp8266-fastled-webserver
Copyright ( C ) 2015 - 2016 Jason Coon
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
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
# include <FastLED.h>
2016-03-10 14:57:02 +01:00
FASTLED_USING_NAMESPACE
extern " C " {
# include "user_interface.h"
}
# include <ESP8266WiFi.h>
2016-12-18 23:02:44 +01:00
# include <ESP8266mDNS.h>
2016-03-10 14:57:02 +01:00
# include <ESP8266WebServer.h>
2016-12-18 23:02:44 +01:00
# include <ESP8266HTTPUpdateServer.h>
# include <WebSocketsServer.h>
2016-03-10 14:57:02 +01:00
# include <FS.h>
# include <EEPROM.h>
# include <IRremoteESP8266.h>
# include "GradientPalettes.h"
2016-12-18 23:02:44 +01:00
# define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
# include "Field.h"
# define HOSTNAME "ESP8266-" ///< Hostname. The setup function adds the Chip ID at the end.
2017-07-13 15:46:28 +02:00
# define RECV_PIN 1
2016-03-10 14:57:02 +01:00
IRrecv irReceiver ( RECV_PIN ) ;
# include "Commands.h"
const bool apMode = false ;
// AP mode password
const char WiFiAPPSK [ ] = " " ;
// Wi-Fi network to connect to (if not in AP mode)
const char * ssid = " " ;
const char * password = " " ;
2016-12-18 23:02:44 +01:00
ESP8266WebServer webServer ( 80 ) ;
WebSocketsServer webSocketsServer = WebSocketsServer ( 81 ) ;
ESP8266HTTPUpdateServer httpUpdateServer ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
# include "FSBrowser.h"
2017-07-13 15:46:28 +02:00
# define DATA_PIN MOSI
# define CLK_PIN SCK
# define LED_TYPE APA102
# define COLOR_ORDER BGR
# define MatrixWidth 8 * 3
# define MatrixHeight 8
# define NUM_LEDS MatrixWidth * MatrixHeight
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
# define MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
2016-03-10 14:57:02 +01:00
# define FRAMES_PER_SECOND 120 // here you can control the speed. With the Access Point / Web Server the animations run a bit slower.
CRGB leds [ NUM_LEDS ] ;
const uint8_t brightnessCount = 5 ;
uint8_t brightnessMap [ brightnessCount ] = { 16 , 32 , 64 , 128 , 255 } ;
2016-12-18 23:02:44 +01:00
uint8_t brightnessIndex = 0 ;
2016-03-10 14:57:02 +01:00
// ten seconds per color palette makes a good demo
// 20-120 is better for deployment
2016-12-18 23:02:44 +01:00
uint8_t secondsPerPalette = 10 ;
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames. More cooling = shorter flames.
// Default 50, suggested range 20-100
uint8_t cooling = 49 ;
// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire. Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
uint8_t sparking = 60 ;
uint8_t speed = 30 ;
2016-03-10 14:57:02 +01:00
///////////////////////////////////////////////////////////////////////
// Forward declarations of an array of cpt-city gradient palettes, and
// a count of how many there are. The actual color palette definitions
// are at the bottom of this file.
extern const TProgmemRGBGradientPalettePtr gGradientPalettes [ ] ;
uint8_t gCurrentPaletteNumber = 0 ;
CRGBPalette16 gCurrentPalette ( CRGB : : Black ) ;
CRGBPalette16 gTargetPalette ( gGradientPalettes [ 0 ] ) ;
2016-12-18 23:02:44 +01:00
CRGBPalette16 IceColors_p = CRGBPalette16 ( CRGB : : Black , CRGB : : Blue , CRGB : : Aqua , CRGB : : White ) ;
2016-03-10 14:57:02 +01:00
uint8_t currentPatternIndex = 0 ; // Index number of which pattern is current
2016-12-18 23:02:44 +01:00
uint8_t autoplay = 0 ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
uint8_t autoplayDuration = 10 ;
unsigned long autoPlayTimeout = 0 ;
2016-03-10 14:57:02 +01:00
2017-02-18 20:48:33 +01:00
uint8_t currentPaletteIndex = 0 ;
2016-03-10 14:57:02 +01:00
uint8_t gHue = 0 ; // rotating "base color" used by many of the patterns
CRGB solidColor = CRGB : : Blue ;
2016-12-18 23:02:44 +01:00
// scale the brightness of all pixels down
void dimAll ( byte value )
{
for ( int i = 0 ; i < NUM_LEDS ; i + + ) {
leds [ i ] . nscale8 ( value ) ;
}
}
2017-07-13 15:46:28 +02:00
const bool MatrixSerpentineLayout = true ;
uint16_t XY ( uint8_t x , uint8_t y )
{
uint16_t i ;
if ( MatrixSerpentineLayout = = false ) {
i = ( y * MatrixWidth ) + x ;
}
if ( MatrixSerpentineLayout = = true ) {
if ( x & 0x01 ) {
// Odd columns run backwards
uint8_t reverseY = ( MatrixHeight - 1 ) - y ;
i = ( x * MatrixHeight ) + reverseY ;
} else {
// Even rows run forwards
i = ( x * MatrixHeight ) + y ;
}
}
return i ;
}
2016-12-18 23:02:44 +01:00
typedef void ( * Pattern ) ( ) ;
typedef Pattern PatternList [ ] ;
typedef struct {
Pattern pattern ;
String name ;
} PatternAndName ;
typedef PatternAndName PatternAndNameList [ ] ;
# include "Twinkles.h"
# include "TwinkleFOX.h"
2017-07-13 15:46:28 +02:00
# include "Sunrise.h"
2016-12-18 23:02:44 +01:00
// List of patterns to cycle through. Each is defined as a separate function below.
PatternAndNameList patterns = {
2017-07-13 15:46:28 +02:00
{ sunrise , " Sunrise " } ,
2016-12-18 23:02:44 +01:00
{ pride , " Pride " } ,
{ colorWaves , " Color Waves " } ,
// twinkle patterns
{ rainbowTwinkles , " Rainbow Twinkles " } ,
{ snowTwinkles , " Snow Twinkles " } ,
{ cloudTwinkles , " Cloud Twinkles " } ,
{ incandescentTwinkles , " Incandescent Twinkles " } ,
// TwinkleFOX patterns
{ retroC9Twinkles , " Retro C9 Twinkles " } ,
{ redWhiteTwinkles , " Red & White Twinkles " } ,
{ blueWhiteTwinkles , " Blue & White Twinkles " } ,
{ redGreenWhiteTwinkles , " Red, Green & White Twinkles " } ,
{ fairyLightTwinkles , " Fairy Light Twinkles " } ,
{ snow2Twinkles , " Snow 2 Twinkles " } ,
{ hollyTwinkles , " Holly Twinkles " } ,
{ iceTwinkles , " Ice Twinkles " } ,
{ partyTwinkles , " Party Twinkles " } ,
{ forestTwinkles , " Forest Twinkles " } ,
{ lavaTwinkles , " Lava Twinkles " } ,
{ fireTwinkles , " Fire Twinkles " } ,
{ cloud2Twinkles , " Cloud 2 Twinkles " } ,
{ oceanTwinkles , " Ocean Twinkles " } ,
{ rainbow , " Rainbow " } ,
{ rainbowWithGlitter , " Rainbow With Glitter " } ,
{ rainbowSolid , " Solid Rainbow " } ,
{ confetti , " Confetti " } ,
{ sinelon , " Sinelon " } ,
{ bpm , " Beat " } ,
{ juggle , " Juggle " } ,
{ fire , " Fire " } ,
{ water , " Water " } ,
{ showSolidColor , " Solid Color " }
} ;
const uint8_t patternCount = ARRAY_SIZE ( patterns ) ;
2017-02-18 20:48:33 +01:00
typedef struct {
CRGBPalette16 palette ;
2017-07-13 15:46:28 +02:00
String name ;
} PaletteAndName ;
2017-02-18 20:48:33 +01:00
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 " ,
2017-07-13 15:46:28 +02:00
" Forest " ,
2017-02-18 20:48:33 +01:00
" Party " ,
2017-07-13 15:46:28 +02:00
" Heat " ,
} ;
2017-02-18 20:48:33 +01:00
2016-12-18 23:02:44 +01:00
# include "Fields.h"
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
void setup ( ) {
2016-03-10 14:57:02 +01:00
Serial . begin ( 115200 ) ;
delay ( 100 ) ;
Serial . setDebugOutput ( true ) ;
2017-07-13 15:46:28 +02:00
// FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS); // for WS2812 (Neopixel)
FastLED . addLeds < LED_TYPE , DATA_PIN , CLK_PIN , COLOR_ORDER > ( leds , NUM_LEDS ) ; // for APA102 (Dotstar)
2016-12-18 23:02:44 +01:00
FastLED . setDither ( false ) ;
2016-03-10 14:57:02 +01:00
FastLED . setCorrection ( TypicalLEDStrip ) ;
FastLED . setBrightness ( brightness ) ;
FastLED . setMaxPowerInVoltsAndMilliamps ( 5 , MILLI_AMPS ) ;
2016-12-18 23:02:44 +01:00
fill_solid ( leds , NUM_LEDS , CRGB : : Black ) ;
2016-03-10 14:57:02 +01:00
FastLED . show ( ) ;
EEPROM . begin ( 512 ) ;
loadSettings ( ) ;
2016-12-18 23:02:44 +01:00
FastLED . setBrightness ( brightness ) ;
2016-03-10 14:57:02 +01:00
irReceiver . enableIRIn ( ) ; // Start the receiver
Serial . println ( ) ;
Serial . print ( F ( " Heap: " ) ) ; Serial . println ( system_get_free_heap_size ( ) ) ;
Serial . print ( F ( " Boot Vers: " ) ) ; Serial . println ( system_get_boot_version ( ) ) ;
Serial . print ( F ( " CPU: " ) ) ; Serial . println ( system_get_cpu_freq ( ) ) ;
Serial . print ( F ( " SDK: " ) ) ; Serial . println ( system_get_sdk_version ( ) ) ;
Serial . print ( F ( " Chip ID: " ) ) ; Serial . println ( system_get_chip_id ( ) ) ;
Serial . print ( F ( " Flash ID: " ) ) ; Serial . println ( spi_flash_get_id ( ) ) ;
Serial . print ( F ( " Flash Size: " ) ) ; Serial . println ( ESP . getFlashChipRealSize ( ) ) ;
Serial . print ( F ( " Vcc: " ) ) ; Serial . println ( ESP . getVcc ( ) ) ;
Serial . println ( ) ;
SPIFFS . begin ( ) ;
{
Dir dir = SPIFFS . openDir ( " / " ) ;
while ( dir . next ( ) ) {
String fileName = dir . fileName ( ) ;
size_t fileSize = dir . fileSize ( ) ;
Serial . printf ( " FS File: %s, size: %s \n " , fileName . c_str ( ) , String ( fileSize ) . c_str ( ) ) ;
}
Serial . printf ( " \n " ) ;
}
2016-12-18 23:02:44 +01:00
// Set Hostname.
String hostname ( HOSTNAME ) ;
hostname + = String ( ESP . getChipId ( ) , HEX ) ;
WiFi . hostname ( hostname ) ;
char hostnameChar [ hostname . length ( ) + 1 ] ;
memset ( hostnameChar , 0 , hostname . length ( ) + 1 ) ;
for ( uint8_t i = 0 ; i < hostname . length ( ) ; i + + )
hostnameChar [ i ] = hostname . charAt ( i ) ;
MDNS . begin ( hostnameChar ) ;
// Add service to MDNS-SD
MDNS . addService ( " http " , " tcp " , 80 ) ;
// Print hostname.
Serial . println ( " Hostname: " + hostname ) ;
2016-03-10 14:57:02 +01:00
if ( apMode )
{
WiFi . mode ( WIFI_AP ) ;
// Do a little work to get a unique-ish name. Append the
// last two bytes of the MAC (HEX'd) to "Thing-":
uint8_t mac [ WL_MAC_ADDR_LENGTH ] ;
WiFi . softAPmacAddress ( mac ) ;
String macID = String ( mac [ WL_MAC_ADDR_LENGTH - 2 ] , HEX ) +
String ( mac [ WL_MAC_ADDR_LENGTH - 1 ] , HEX ) ;
macID . toUpperCase ( ) ;
2016-12-18 23:02:44 +01:00
String AP_NameString = " ESP8266- " + macID ;
2016-03-10 14:57:02 +01:00
char AP_NameChar [ AP_NameString . length ( ) + 1 ] ;
memset ( AP_NameChar , 0 , AP_NameString . length ( ) + 1 ) ;
for ( int i = 0 ; i < AP_NameString . length ( ) ; i + + )
AP_NameChar [ i ] = AP_NameString . charAt ( i ) ;
WiFi . softAP ( AP_NameChar , WiFiAPPSK ) ;
Serial . printf ( " Connect to Wi-Fi access point: %s \n " , AP_NameChar ) ;
Serial . println ( " and open http://192.168.4.1 in your browser " ) ;
}
else
{
2016-11-23 00:15:02 +01:00
WiFi . mode ( WIFI_STA ) ;
2016-03-10 14:57:02 +01:00
Serial . printf ( " Connecting to %s \n " , ssid ) ;
if ( String ( WiFi . SSID ( ) ) ! = String ( ssid ) ) {
WiFi . begin ( ssid , password ) ;
}
2017-07-13 15:46:28 +02:00
}
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
httpUpdateServer . setup ( & webServer ) ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
webServer . on ( " /all " , HTTP_GET , [ ] ( ) {
String json = getFieldsJson ( fields , fieldCount ) ;
webServer . send ( 200 , " text/json " , json ) ;
} ) ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
webServer . on ( " /fieldValue " , HTTP_GET , [ ] ( ) {
String name = webServer . arg ( " name " ) ;
String value = getFieldValue ( name , fields , fieldCount ) ;
webServer . send ( 200 , " text/json " , value ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /fieldValue " , HTTP_POST , [ ] ( ) {
String name = webServer . arg ( " name " ) ;
String value = webServer . arg ( " value " ) ;
String newValue = setFieldValue ( name , value , fields , fieldCount ) ;
webServer . send ( 200 , " text/json " , newValue ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /power " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
2016-03-10 14:57:02 +01:00
setPower ( value . toInt ( ) ) ;
2016-12-18 23:02:44 +01:00
sendInt ( power ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /cooling " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
cooling = value . toInt ( ) ;
broadcastInt ( " cooling " , cooling ) ;
sendInt ( cooling ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /sparking " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
sparking = value . toInt ( ) ;
broadcastInt ( " sparking " , sparking ) ;
sendInt ( sparking ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /speed " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
speed = value . toInt ( ) ;
broadcastInt ( " speed " , speed ) ;
sendInt ( speed ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /twinkleSpeed " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
twinkleSpeed = value . toInt ( ) ;
2017-07-13 15:46:28 +02:00
if ( twinkleSpeed < 0 ) twinkleSpeed = 0 ;
2016-12-18 23:02:44 +01:00
else if ( twinkleSpeed > 8 ) twinkleSpeed = 8 ;
broadcastInt ( " twinkleSpeed " , twinkleSpeed ) ;
sendInt ( twinkleSpeed ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /twinkleDensity " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
twinkleDensity = value . toInt ( ) ;
2017-07-13 15:46:28 +02:00
if ( twinkleDensity < 0 ) twinkleDensity = 0 ;
2016-12-18 23:02:44 +01:00
else if ( twinkleDensity > 8 ) twinkleDensity = 8 ;
broadcastInt ( " twinkleDensity " , twinkleDensity ) ;
sendInt ( twinkleDensity ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /solidColor " , HTTP_POST , [ ] ( ) {
String r = webServer . arg ( " r " ) ;
String g = webServer . arg ( " g " ) ;
String b = webServer . arg ( " b " ) ;
setSolidColor ( r . toInt ( ) , g . toInt ( ) , b . toInt ( ) ) ;
sendString ( String ( solidColor . r ) + " , " + String ( solidColor . g ) + " , " + String ( solidColor . b ) ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /pattern " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
setPattern ( value . toInt ( ) ) ;
sendInt ( currentPatternIndex ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /patternName " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
setPatternName ( value ) ;
sendInt ( currentPatternIndex ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2017-02-18 20:48:33 +01:00
webServer . on ( " /palette " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
setPalette ( value . toInt ( ) ) ;
sendInt ( currentPaletteIndex ) ;
} ) ;
webServer . on ( " /paletteName " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
setPaletteName ( value ) ;
sendInt ( currentPaletteIndex ) ;
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /brightness " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
setBrightness ( value . toInt ( ) ) ;
sendInt ( brightness ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /autoplay " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
setAutoplay ( value . toInt ( ) ) ;
sendInt ( autoplay ) ;
2016-03-10 14:57:02 +01:00
} ) ;
2016-12-18 23:02:44 +01:00
webServer . on ( " /autoplayDuration " , HTTP_POST , [ ] ( ) {
String value = webServer . arg ( " value " ) ;
setAutoplayDuration ( value . toInt ( ) ) ;
sendInt ( autoplayDuration ) ;
} ) ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
//list directory
webServer . on ( " /list " , HTTP_GET , handleFileList ) ;
//load editor
webServer . on ( " /edit " , HTTP_GET , [ ] ( ) {
if ( ! handleFileRead ( " /edit.htm " ) ) webServer . send ( 404 , " text/plain " , " FileNotFound " ) ;
} ) ;
//create file
webServer . on ( " /edit " , HTTP_PUT , handleFileCreate ) ;
//delete file
webServer . on ( " /edit " , HTTP_DELETE , handleFileDelete ) ;
//first callback is called after the request has ended with all parsed arguments
//second callback handles file uploads at that location
webServer . on ( " /edit " , HTTP_POST , [ ] ( ) {
webServer . send ( 200 , " text/plain " , " " ) ;
} , handleFileUpload ) ;
webServer . serveStatic ( " / " , SPIFFS , " / " , " max-age=86400 " ) ;
webServer . begin ( ) ;
Serial . println ( " HTTP web server started " ) ;
webSocketsServer . begin ( ) ;
webSocketsServer . onEvent ( webSocketEvent ) ;
Serial . println ( " Web socket server started " ) ;
autoPlayTimeout = millis ( ) + ( autoplayDuration * 1000 ) ;
}
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
void sendInt ( uint8_t value )
{
sendString ( String ( value ) ) ;
2016-03-10 14:57:02 +01:00
}
2016-12-18 23:02:44 +01:00
void sendString ( String value )
{
webServer . send ( 200 , " text/plain " , value ) ;
}
2016-03-12 18:28:33 +01:00
2016-12-18 23:02:44 +01:00
void broadcastInt ( String name , uint8_t value )
{
String json = " { \" name \" : \" " + name + " \" , \" value \" : " + String ( value ) + " } " ;
webSocketsServer . broadcastTXT ( json ) ;
}
2016-03-12 18:28:33 +01:00
2016-12-18 23:02:44 +01:00
void broadcastString ( String name , String value )
{
String json = " { \" name \" : \" " + name + " \" , \" value \" : \" " + String ( value ) + " \" } " ;
webSocketsServer . broadcastTXT ( json ) ;
}
2016-03-12 18:28:33 +01:00
2016-12-18 23:02:44 +01:00
void loop ( ) {
2016-03-10 14:57:02 +01:00
// Add entropy to random number generator; we use a lot of it.
random16_add_entropy ( random ( 65535 ) ) ;
2016-12-18 23:02:44 +01:00
webSocketsServer . loop ( ) ;
webServer . handleClient ( ) ;
2016-03-10 14:57:02 +01:00
handleIrInput ( ) ;
if ( power = = 0 ) {
fill_solid ( leds , NUM_LEDS , CRGB : : Black ) ;
FastLED . show ( ) ;
2016-12-18 23:02:44 +01:00
// FastLED.delay(15);
2016-03-10 14:57:02 +01:00
return ;
}
// EVERY_N_SECONDS(10) {
// Serial.print( F("Heap: ") ); Serial.println(system_get_free_heap_size());
// }
// change to a new cpt-city gradient palette
2016-12-18 23:02:44 +01:00
EVERY_N_SECONDS ( secondsPerPalette ) {
2016-03-10 14:57:02 +01:00
gCurrentPaletteNumber = addmod8 ( gCurrentPaletteNumber , 1 , gGradientPaletteCount ) ;
gTargetPalette = gGradientPalettes [ gCurrentPaletteNumber ] ;
}
EVERY_N_MILLISECONDS ( 40 ) {
2016-12-18 23:02:44 +01:00
// slowly blend the current palette to the next
nblendPaletteTowardPalette ( gCurrentPalette , gTargetPalette , 8 ) ;
gHue + + ; // slowly cycle the "base color" through the rainbow
2016-03-10 14:57:02 +01:00
}
2016-07-19 01:52:44 +02:00
2016-12-18 23:02:44 +01:00
if ( autoplay & & ( millis ( ) > autoPlayTimeout ) ) {
2016-03-10 14:57:02 +01:00
adjustPattern ( true ) ;
2016-12-18 23:02:44 +01:00
autoPlayTimeout = millis ( ) + ( autoplayDuration * 1000 ) ;
2016-03-10 14:57:02 +01:00
}
// Call the current pattern function once, updating the 'leds' array
patterns [ currentPatternIndex ] . pattern ( ) ;
FastLED . show ( ) ;
// insert a delay to keep the framerate modest
2016-12-18 23:02:44 +01:00
// FastLED.delay(1000 / FRAMES_PER_SECOND);
}
void webSocketEvent ( uint8_t num , WStype_t type , uint8_t * payload , size_t length ) {
switch ( type ) {
case WStype_DISCONNECTED :
Serial . printf ( " [%u] Disconnected! \n " , num ) ;
break ;
case WStype_CONNECTED :
{
IPAddress ip = webSocketsServer . remoteIP ( num ) ;
Serial . printf ( " [%u] Connected from %d.%d.%d.%d url: %s \n " , num , ip [ 0 ] , ip [ 1 ] , ip [ 2 ] , ip [ 3 ] , payload ) ;
// send message to client
// webSocketsServer.sendTXT(num, "Connected");
}
break ;
case WStype_TEXT :
Serial . printf ( " [%u] get Text: %s \n " , num , payload ) ;
// send message to client
// webSocketsServer.sendTXT(num, "message here");
// send data to all connected clients
// webSocketsServer.broadcastTXT("message here");
break ;
case WStype_BIN :
Serial . printf ( " [%u] get binary length: %u \n " , num , length ) ;
hexdump ( payload , length ) ;
// send message to client
// webSocketsServer.sendBIN(num, payload, lenght);
break ;
}
2016-03-10 14:57:02 +01:00
}
void handleIrInput ( )
{
2016-12-18 23:02:44 +01:00
InputCommand command = readCommand ( ) ;
2016-03-10 14:57:02 +01:00
if ( command ! = InputCommand : : None ) {
Serial . print ( " command: " ) ;
Serial . println ( ( int ) command ) ;
}
switch ( command ) {
case InputCommand : : Up : {
adjustPattern ( true ) ;
break ;
}
case InputCommand : : Down : {
adjustPattern ( false ) ;
break ;
}
case InputCommand : : Power : {
2016-12-18 23:02:44 +01:00
setPower ( power = = 0 ? 1 : 0 ) ;
2016-03-10 14:57:02 +01:00
break ;
}
case InputCommand : : BrightnessUp : {
adjustBrightness ( true ) ;
break ;
}
case InputCommand : : BrightnessDown : {
adjustBrightness ( false ) ;
break ;
}
case InputCommand : : PlayMode : { // toggle pause/play
2016-12-18 23:02:44 +01:00
setAutoplay ( ! autoplay ) ;
2016-03-10 14:57:02 +01:00
break ;
}
// pattern buttons
case InputCommand : : Pattern1 : {
setPattern ( 0 ) ;
break ;
}
case InputCommand : : Pattern2 : {
setPattern ( 1 ) ;
break ;
}
case InputCommand : : Pattern3 : {
setPattern ( 2 ) ;
break ;
}
case InputCommand : : Pattern4 : {
setPattern ( 3 ) ;
break ;
}
case InputCommand : : Pattern5 : {
setPattern ( 4 ) ;
break ;
}
case InputCommand : : Pattern6 : {
setPattern ( 5 ) ;
break ;
}
case InputCommand : : Pattern7 : {
setPattern ( 6 ) ;
break ;
}
case InputCommand : : Pattern8 : {
setPattern ( 7 ) ;
break ;
}
case InputCommand : : Pattern9 : {
setPattern ( 8 ) ;
break ;
}
case InputCommand : : Pattern10 : {
setPattern ( 9 ) ;
break ;
}
case InputCommand : : Pattern11 : {
setPattern ( 10 ) ;
break ;
}
case InputCommand : : Pattern12 : {
setPattern ( 11 ) ;
break ;
}
// custom color adjustment buttons
case InputCommand : : RedUp : {
solidColor . red + = 8 ;
setSolidColor ( solidColor ) ;
break ;
}
case InputCommand : : RedDown : {
solidColor . red - = 8 ;
setSolidColor ( solidColor ) ;
break ;
}
case InputCommand : : GreenUp : {
solidColor . green + = 8 ;
setSolidColor ( solidColor ) ;
break ;
}
case InputCommand : : GreenDown : {
solidColor . green - = 8 ;
setSolidColor ( solidColor ) ;
break ;
}
case InputCommand : : BlueUp : {
solidColor . blue + = 8 ;
setSolidColor ( solidColor ) ;
break ;
}
case InputCommand : : BlueDown : {
solidColor . blue - = 8 ;
setSolidColor ( solidColor ) ;
break ;
}
// color buttons
case InputCommand : : Red : {
setSolidColor ( CRGB : : Red ) ;
break ;
}
case InputCommand : : RedOrange : {
setSolidColor ( CRGB : : OrangeRed ) ;
break ;
}
case InputCommand : : Orange : {
setSolidColor ( CRGB : : Orange ) ;
break ;
}
case InputCommand : : YellowOrange : {
setSolidColor ( CRGB : : Goldenrod ) ;
break ;
}
case InputCommand : : Yellow : {
setSolidColor ( CRGB : : Yellow ) ;
break ;
}
case InputCommand : : Green : {
setSolidColor ( CRGB : : Green ) ;
break ;
}
case InputCommand : : Lime : {
setSolidColor ( CRGB : : Lime ) ;
break ;
}
case InputCommand : : Aqua : {
setSolidColor ( CRGB : : Aqua ) ;
break ;
}
case InputCommand : : Teal : {
setSolidColor ( CRGB : : Teal ) ;
break ;
}
case InputCommand : : Navy : {
setSolidColor ( CRGB : : Navy ) ;
break ;
}
case InputCommand : : Blue : {
setSolidColor ( CRGB : : Blue ) ;
break ;
}
case InputCommand : : RoyalBlue : {
setSolidColor ( CRGB : : RoyalBlue ) ;
break ;
}
case InputCommand : : Purple : {
setSolidColor ( CRGB : : Purple ) ;
break ;
}
case InputCommand : : Indigo : {
setSolidColor ( CRGB : : Indigo ) ;
break ;
}
case InputCommand : : Magenta : {
setSolidColor ( CRGB : : Magenta ) ;
break ;
}
case InputCommand : : White : {
setSolidColor ( CRGB : : White ) ;
break ;
}
case InputCommand : : Pink : {
setSolidColor ( CRGB : : Pink ) ;
break ;
}
case InputCommand : : LightPink : {
setSolidColor ( CRGB : : LightPink ) ;
break ;
}
case InputCommand : : BabyBlue : {
setSolidColor ( CRGB : : CornflowerBlue ) ;
break ;
}
case InputCommand : : LightBlue : {
setSolidColor ( CRGB : : LightBlue ) ;
break ;
}
}
}
void loadSettings ( )
{
brightness = EEPROM . read ( 0 ) ;
currentPatternIndex = EEPROM . read ( 1 ) ;
if ( currentPatternIndex < 0 )
currentPatternIndex = 0 ;
else if ( currentPatternIndex > = patternCount )
currentPatternIndex = patternCount - 1 ;
byte r = EEPROM . read ( 2 ) ;
byte g = EEPROM . read ( 3 ) ;
byte b = EEPROM . read ( 4 ) ;
if ( r = = 0 & & g = = 0 & & b = = 0 )
{
}
else
{
solidColor = CRGB ( r , g , b ) ;
}
2016-12-18 23:02:44 +01:00
power = EEPROM . read ( 5 ) ;
autoplay = EEPROM . read ( 6 ) ;
autoplayDuration = EEPROM . read ( 7 ) ;
2017-02-18 20:48:33 +01:00
2017-02-22 01:53:15 +01:00
currentPaletteIndex = EEPROM . read ( 8 ) ;
2017-02-18 20:48:33 +01:00
if ( currentPaletteIndex < 0 )
currentPaletteIndex = 0 ;
else if ( currentPaletteIndex > = paletteCount )
currentPaletteIndex = paletteCount - 1 ;
2016-03-10 14:57:02 +01:00
}
2016-12-18 23:02:44 +01:00
void setPower ( uint8_t value )
2016-03-10 14:57:02 +01:00
{
2016-12-18 23:02:44 +01:00
power = value = = 0 ? 0 : 1 ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
EEPROM . write ( 5 , power ) ;
EEPROM . commit ( ) ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
broadcastInt ( " power " , power ) ;
}
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
void setAutoplay ( uint8_t value )
2017-07-13 15:46:28 +02:00
{
2016-12-18 23:02:44 +01:00
autoplay = value = = 0 ? 0 : 1 ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
EEPROM . write ( 6 , autoplay ) ;
EEPROM . commit ( ) ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
broadcastInt ( " autoplay " , autoplay ) ;
2016-03-10 14:57:02 +01:00
}
2016-12-18 23:02:44 +01:00
void setAutoplayDuration ( uint8_t value )
2016-03-10 14:57:02 +01:00
{
2016-12-18 23:02:44 +01:00
autoplayDuration = value ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
EEPROM . write ( 7 , autoplayDuration ) ;
EEPROM . commit ( ) ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
autoPlayTimeout = millis ( ) + ( autoplayDuration * 1000 ) ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
broadcastInt ( " autoplayDuration " , autoplayDuration ) ;
2016-03-10 14:57:02 +01:00
}
void setSolidColor ( CRGB color )
{
setSolidColor ( color . r , color . g , color . b ) ;
}
void setSolidColor ( uint8_t r , uint8_t g , uint8_t b )
{
solidColor = CRGB ( r , g , b ) ;
EEPROM . write ( 2 , r ) ;
2016-07-19 01:52:44 +02:00
EEPROM . write ( 3 , g ) ;
EEPROM . write ( 4 , b ) ;
2016-12-18 23:02:44 +01:00
EEPROM . commit ( ) ;
2016-03-10 14:57:02 +01:00
setPattern ( patternCount - 1 ) ;
2016-12-18 23:02:44 +01:00
broadcastString ( " color " , String ( solidColor . r ) + " , " + String ( solidColor . g ) + " , " + String ( solidColor . b ) ) ;
2016-03-10 14:57:02 +01:00
}
// increase or decrease the current pattern number, and wrap around at the ends
void adjustPattern ( bool up )
{
if ( up )
currentPatternIndex + + ;
else
currentPatternIndex - - ;
// wrap around at the ends
if ( currentPatternIndex < 0 )
currentPatternIndex = patternCount - 1 ;
if ( currentPatternIndex > = patternCount )
currentPatternIndex = 0 ;
2017-02-18 20:48:33 +01:00
if ( autoplay = = 0 ) {
EEPROM . write ( 1 , currentPatternIndex ) ;
EEPROM . commit ( ) ;
}
2016-12-18 23:02:44 +01:00
broadcastInt ( " pattern " , currentPatternIndex ) ;
2016-03-10 14:57:02 +01:00
}
2016-12-18 23:02:44 +01:00
void setPattern ( uint8_t value )
2016-03-10 14:57:02 +01:00
{
2016-12-18 23:02:44 +01:00
if ( value > = patternCount )
2016-03-10 14:57:02 +01:00
value = patternCount - 1 ;
currentPatternIndex = value ;
2017-02-18 20:48:33 +01:00
if ( autoplay = = 0 ) {
EEPROM . write ( 1 , currentPatternIndex ) ;
EEPROM . commit ( ) ;
}
2016-12-18 23:02:44 +01:00
broadcastInt ( " pattern " , currentPatternIndex ) ;
}
void setPatternName ( String name )
{
2017-07-13 15:46:28 +02:00
for ( uint8_t i = 0 ; i < patternCount ; i + + ) {
if ( patterns [ i ] . name = = name ) {
2016-12-18 23:02:44 +01:00
setPattern ( i ) ;
break ;
}
}
2016-03-10 14:57:02 +01:00
}
2017-02-18 20:48:33 +01:00
void setPalette ( uint8_t value )
{
if ( value > = paletteCount )
value = paletteCount - 1 ;
currentPaletteIndex = value ;
2017-02-22 01:53:15 +01:00
EEPROM . write ( 8 , currentPaletteIndex ) ;
2017-02-18 20:48:33 +01:00
EEPROM . commit ( ) ;
broadcastInt ( " palette " , currentPaletteIndex ) ;
}
void setPaletteName ( String name )
{
2017-07-13 15:46:28 +02:00
for ( uint8_t i = 0 ; i < paletteCount ; i + + ) {
if ( paletteNames [ i ] = = name ) {
2017-02-18 20:48:33 +01:00
setPalette ( i ) ;
break ;
}
}
}
2016-03-10 14:57:02 +01:00
void adjustBrightness ( bool up )
{
2016-12-18 23:02:44 +01:00
if ( up & & brightnessIndex < brightnessCount - 1 )
2016-03-10 14:57:02 +01:00
brightnessIndex + + ;
2016-12-18 23:02:44 +01:00
else if ( ! up & & brightnessIndex > 0 )
2016-03-10 14:57:02 +01:00
brightnessIndex - - ;
brightness = brightnessMap [ brightnessIndex ] ;
FastLED . setBrightness ( brightness ) ;
EEPROM . write ( 0 , brightness ) ;
EEPROM . commit ( ) ;
2016-12-18 23:02:44 +01:00
broadcastInt ( " brightness " , brightness ) ;
2016-03-10 14:57:02 +01:00
}
2016-12-18 23:02:44 +01:00
void setBrightness ( uint8_t value )
2016-03-10 14:57:02 +01:00
{
if ( value > 255 )
value = 255 ;
else if ( value < 0 ) value = 0 ;
brightness = value ;
FastLED . setBrightness ( brightness ) ;
EEPROM . write ( 0 , brightness ) ;
EEPROM . commit ( ) ;
2016-12-18 23:02:44 +01:00
broadcastInt ( " brightness " , brightness ) ;
}
void strandTest ( )
{
static uint8_t i = 0 ;
EVERY_N_SECONDS ( 1 )
{
i + + ;
if ( i > = NUM_LEDS )
i = 0 ;
}
fill_solid ( leds , NUM_LEDS , CRGB : : Black ) ;
leds [ i ] = solidColor ;
2016-03-10 14:57:02 +01:00
}
void showSolidColor ( )
{
fill_solid ( leds , NUM_LEDS , solidColor ) ;
}
2016-12-18 23:02:44 +01:00
// Patterns from FastLED example DemoReel100: https://github.com/FastLED/FastLED/blob/master/examples/DemoReel100/DemoReel100.ino
2016-03-10 14:57:02 +01:00
void rainbow ( )
{
// FastLED's built-in rainbow generator
2016-12-18 23:02:44 +01:00
fill_rainbow ( leds , NUM_LEDS , gHue , 255 / NUM_LEDS ) ;
2016-03-10 14:57:02 +01:00
}
void rainbowWithGlitter ( )
{
// built-in FastLED rainbow, plus some random sparkly glitter
rainbow ( ) ;
addGlitter ( 80 ) ;
}
2016-12-18 23:02:44 +01:00
void rainbowSolid ( )
2016-03-10 14:57:02 +01:00
{
2016-12-18 23:02:44 +01:00
fill_solid ( leds , NUM_LEDS , CHSV ( gHue , 255 , 255 ) ) ;
2016-03-10 14:57:02 +01:00
}
void confetti ( )
{
// random colored speckles that blink in and fade smoothly
fadeToBlackBy ( leds , NUM_LEDS , 10 ) ;
int pos = random16 ( NUM_LEDS ) ;
2017-02-18 20:48:33 +01:00
// leds[pos] += CHSV( gHue + random8(64), 200, 255);
leds [ pos ] + = ColorFromPalette ( palettes [ currentPaletteIndex ] , gHue + random8 ( 64 ) ) ;
2016-03-10 14:57:02 +01:00
}
void sinelon ( )
{
// a colored dot sweeping back and forth, with fading trails
fadeToBlackBy ( leds , NUM_LEDS , 20 ) ;
2016-12-18 23:02:44 +01:00
int pos = beatsin16 ( speed , 0 , NUM_LEDS ) ;
static int prevpos = 0 ;
2017-02-18 20:48:33 +01:00
CRGB color = ColorFromPalette ( palettes [ currentPaletteIndex ] , gHue , 255 ) ;
2017-07-13 15:46:28 +02:00
if ( pos < prevpos ) {
fill_solid ( leds + pos , ( prevpos - pos ) + 1 , color ) ;
2016-12-18 23:02:44 +01:00
} else {
2017-07-13 15:46:28 +02:00
fill_solid ( leds + prevpos , ( pos - prevpos ) + 1 , color ) ;
2016-12-18 23:02:44 +01:00
}
prevpos = pos ;
2016-03-10 14:57:02 +01:00
}
void bpm ( )
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
2016-12-18 23:02:44 +01:00
uint8_t beat = beatsin8 ( speed , 64 , 255 ) ;
2017-02-18 20:48:33 +01:00
CRGBPalette16 palette = palettes [ currentPaletteIndex ] ;
2016-12-18 23:02:44 +01:00
for ( int i = 0 ; i < NUM_LEDS ; i + + ) {
2017-02-18 20:48:33 +01:00
leds [ i ] = ColorFromPalette ( palette , gHue + ( i * 2 ) , beat - gHue + ( i * 10 ) ) ;
2016-03-10 14:57:02 +01:00
}
}
void juggle ( )
{
2016-12-18 23:02:44 +01:00
static uint8_t numdots = 4 ; // Number of dots in use.
static uint8_t faderate = 2 ; // How long should the trails be. Very low value = longer trails.
static uint8_t hueinc = 255 / numdots - 1 ; // Incremental change in hue between each dot.
static uint8_t thishue = 0 ; // Starting hue.
static uint8_t curhue = 0 ; // The current hue
static uint8_t thissat = 255 ; // Saturation of the colour.
static uint8_t thisbright = 255 ; // How bright should the LED/display be.
static uint8_t basebeat = 5 ; // Higher = faster movement.
static uint8_t lastSecond = 99 ; // Static variable, means it's only defined once. This is our 'debounce' variable.
uint8_t secondHand = ( millis ( ) / 1000 ) % 30 ; // IMPORTANT!!! Change '30' to a different value to change duration of the loop.
if ( lastSecond ! = secondHand ) { // Debounce to make sure we're not repeating an assignment.
lastSecond = secondHand ;
switch ( secondHand ) {
case 0 : numdots = 1 ; basebeat = 20 ; hueinc = 16 ; faderate = 2 ; thishue = 0 ; break ; // You can change values here, one at a time , or altogether.
case 10 : numdots = 4 ; basebeat = 10 ; hueinc = 16 ; faderate = 8 ; thishue = 128 ; break ;
case 20 : numdots = 8 ; basebeat = 3 ; hueinc = 0 ; faderate = 8 ; thishue = random8 ( ) ; break ; // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows.
case 30 : break ;
}
}
// Several colored dots, weaving in and out of sync with each other
curhue = thishue ; // Reset the hue values.
fadeToBlackBy ( leds , NUM_LEDS , faderate ) ;
for ( int i = 0 ; i < numdots ; i + + ) {
//beat16 is a FastLED 3.1 function
leds [ beatsin16 ( basebeat + i + numdots , 0 , NUM_LEDS ) ] + = CHSV ( gHue + curhue , thissat , thisbright ) ;
curhue + = hueinc ;
2016-03-10 14:57:02 +01:00
}
}
2016-12-18 23:02:44 +01:00
void fire ( )
{
heatMap ( HeatColors_p , true ) ;
}
void water ( )
2017-02-18 20:48:33 +01:00
{
2016-12-18 23:02:44 +01:00
heatMap ( IceColors_p , false ) ;
2017-02-18 20:48:33 +01:00
}
2016-12-18 23:02:44 +01:00
2016-03-10 14:57:02 +01:00
// Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5
// This function draws rainbows with an ever-changing,
// widely-varying set of parameters.
2016-12-18 23:02:44 +01:00
void pride ( )
{
2016-03-10 14:57:02 +01:00
static uint16_t sPseudotime = 0 ;
static uint16_t sLastMillis = 0 ;
static uint16_t sHue16 = 0 ;
uint8_t sat8 = beatsin88 ( 87 , 220 , 250 ) ;
uint8_t brightdepth = beatsin88 ( 341 , 96 , 224 ) ;
uint16_t brightnessthetainc16 = beatsin88 ( 203 , ( 25 * 256 ) , ( 40 * 256 ) ) ;
uint8_t msmultiplier = beatsin88 ( 147 , 23 , 60 ) ;
uint16_t hue16 = sHue16 ; //gHue * 256;
uint16_t hueinc16 = beatsin88 ( 113 , 1 , 3000 ) ;
uint16_t ms = millis ( ) ;
uint16_t deltams = ms - sLastMillis ;
sLastMillis = ms ;
sPseudotime + = deltams * msmultiplier ;
sHue16 + = deltams * beatsin88 ( 400 , 5 , 9 ) ;
uint16_t brightnesstheta16 = sPseudotime ;
for ( uint16_t i = 0 ; i < NUM_LEDS ; i + + ) {
hue16 + = hueinc16 ;
uint8_t hue8 = hue16 / 256 ;
brightnesstheta16 + = brightnessthetainc16 ;
uint16_t b16 = sin16 ( brightnesstheta16 ) + 32768 ;
uint16_t bri16 = ( uint32_t ) ( ( uint32_t ) b16 * ( uint32_t ) b16 ) / 65536 ;
uint8_t bri8 = ( uint32_t ) ( ( ( uint32_t ) bri16 ) * brightdepth ) / 65536 ;
bri8 + = ( 255 - brightdepth ) ;
CRGB newcolor = CHSV ( hue8 , sat8 , bri8 ) ;
2016-12-18 23:02:44 +01:00
uint16_t pixelnumber = i ;
pixelnumber = ( NUM_LEDS - 1 ) - pixelnumber ;
nblend ( leds [ pixelnumber ] , newcolor , 64 ) ;
}
}
void radialPaletteShift ( )
{
for ( uint8_t i = 0 ; i < NUM_LEDS ; i + + ) {
// leds[i] = ColorFromPalette( gCurrentPalette, gHue + sin8(i*16), brightness);
leds [ i ] = ColorFromPalette ( gCurrentPalette , i + gHue , 255 , LINEARBLEND ) ;
2016-03-10 14:57:02 +01:00
}
}
2016-12-18 23:02:44 +01:00
// based on FastLED example Fire2012WithPalette: https://github.com/FastLED/FastLED/blob/master/examples/Fire2012WithPalette/Fire2012WithPalette.ino
void heatMap ( CRGBPalette16 palette , bool up )
{
fill_solid ( leds , NUM_LEDS , CRGB : : Black ) ;
// Add entropy to random number generator; we use a lot of it.
random16_add_entropy ( random ( 256 ) ) ;
// Array of temperature readings at each simulation cell
static byte heat [ 256 ] ;
byte colorindex ;
// Step 1. Cool down every cell a little
for ( uint16_t i = 0 ; i < NUM_LEDS ; i + + ) {
heat [ i ] = qsub8 ( heat [ i ] , random8 ( 0 , ( ( cooling * 10 ) / NUM_LEDS ) + 2 ) ) ;
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for ( uint16_t k = NUM_LEDS - 1 ; k > = 2 ; k - - ) {
heat [ k ] = ( heat [ k - 1 ] + heat [ k - 2 ] + heat [ k - 2 ] ) / 3 ;
}
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
if ( random8 ( ) < sparking ) {
int y = random8 ( 7 ) ;
heat [ y ] = qadd8 ( heat [ y ] , random8 ( 160 , 255 ) ) ;
}
// Step 4. Map from heat cells to LED colors
for ( uint16_t j = 0 ; j < NUM_LEDS ; j + + ) {
// Scale the heat value from 0-255 down to 0-240
// for best results with color palettes.
colorindex = scale8 ( heat [ j ] , 190 ) ;
CRGB color = ColorFromPalette ( palette , colorindex ) ;
if ( up ) {
leds [ j ] = color ;
}
else {
leds [ ( NUM_LEDS - 1 ) - j ] = color ;
}
}
}
void addGlitter ( uint8_t chanceOfGlitter )
{
if ( random8 ( ) < chanceOfGlitter ) {
leds [ random16 ( NUM_LEDS ) ] + = CRGB : : White ;
}
}
///////////////////////////////////////////////////////////////////////
// Forward declarations of an array of cpt-city gradient palettes, and
// a count of how many there are. The actual color palette definitions
// are at the bottom of this file.
extern const TProgmemRGBGradientPalettePtr gGradientPalettes [ ] ;
extern const uint8_t gGradientPaletteCount ;
uint8_t beatsaw8 ( accum88 beats_per_minute , uint8_t lowest = 0 , uint8_t highest = 255 ,
uint32_t timebase = 0 , uint8_t phase_offset = 0 )
{
uint8_t beat = beat8 ( beats_per_minute , timebase ) ;
uint8_t beatsaw = beat + phase_offset ;
uint8_t rangewidth = highest - lowest ;
uint8_t scaledbeat = scale8 ( beatsaw , rangewidth ) ;
uint8_t result = lowest + scaledbeat ;
return result ;
}
void colorWaves ( )
{
colorwaves ( leds , NUM_LEDS , gCurrentPalette ) ;
}
2016-03-10 14:57:02 +01:00
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
// This function draws color waves with an ever-changing,
// widely-varying set of parameters, using a color palette.
2016-12-18 23:02:44 +01:00
void colorwaves ( CRGB * ledarray , uint16_t numleds , CRGBPalette16 & palette )
2016-03-10 14:57:02 +01:00
{
static uint16_t sPseudotime = 0 ;
static uint16_t sLastMillis = 0 ;
static uint16_t sHue16 = 0 ;
// uint8_t sat8 = beatsin88( 87, 220, 250);
uint8_t brightdepth = beatsin88 ( 341 , 96 , 224 ) ;
uint16_t brightnessthetainc16 = beatsin88 ( 203 , ( 25 * 256 ) , ( 40 * 256 ) ) ;
uint8_t msmultiplier = beatsin88 ( 147 , 23 , 60 ) ;
uint16_t hue16 = sHue16 ; //gHue * 256;
uint16_t hueinc16 = beatsin88 ( 113 , 300 , 1500 ) ;
uint16_t ms = millis ( ) ;
uint16_t deltams = ms - sLastMillis ;
sLastMillis = ms ;
sPseudotime + = deltams * msmultiplier ;
sHue16 + = deltams * beatsin88 ( 400 , 5 , 9 ) ;
uint16_t brightnesstheta16 = sPseudotime ;
2016-12-18 23:02:44 +01:00
for ( uint16_t i = 0 ; i < numleds ; i + + ) {
2016-03-10 14:57:02 +01:00
hue16 + = hueinc16 ;
uint8_t hue8 = hue16 / 256 ;
uint16_t h16_128 = hue16 > > 7 ;
if ( h16_128 & 0x100 ) {
hue8 = 255 - ( h16_128 > > 1 ) ;
} else {
hue8 = h16_128 > > 1 ;
}
brightnesstheta16 + = brightnessthetainc16 ;
uint16_t b16 = sin16 ( brightnesstheta16 ) + 32768 ;
uint16_t bri16 = ( uint32_t ) ( ( uint32_t ) b16 * ( uint32_t ) b16 ) / 65536 ;
uint8_t bri8 = ( uint32_t ) ( ( ( uint32_t ) bri16 ) * brightdepth ) / 65536 ;
bri8 + = ( 255 - brightdepth ) ;
uint8_t index = hue8 ;
//index = triwave8( index);
index = scale8 ( index , 240 ) ;
2016-12-18 23:02:44 +01:00
CRGB newcolor = ColorFromPalette ( palette , index , bri8 ) ;
uint16_t pixelnumber = i ;
pixelnumber = ( numleds - 1 ) - pixelnumber ;
2016-03-10 14:57:02 +01:00
2016-12-18 23:02:44 +01:00
nblend ( ledarray [ pixelnumber ] , newcolor , 128 ) ;
2016-03-10 14:57:02 +01:00
}
}
// Alternate rendering function just scrolls the current palette
// across the defined LED strip.
2016-12-18 23:02:44 +01:00
void palettetest ( CRGB * ledarray , uint16_t numleds , const CRGBPalette16 & gCurrentPalette )
2016-03-10 14:57:02 +01:00
{
static uint8_t startindex = 0 ;
startindex - - ;
2016-12-18 23:02:44 +01:00
fill_palette ( ledarray , numleds , startindex , ( 256 / NUM_LEDS ) + 1 , gCurrentPalette , 255 , LINEARBLEND ) ;
2016-03-10 14:57:02 +01:00
}