Created
July 13, 2017 11:50
-
-
Save headphones81/d3474359f1b3744ce203b16905f93d5f to your computer and use it in GitHub Desktop.
ESP8266 + FASTLED
This file contains 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
int rgbarray[] = {100,150,200}; | |
int Rval = rgbarray[0]; | |
int Gval = rgbarray[1]; | |
int Bval = rgbarray[2]; | |
int Speed = 100; | |
int BRIGHTNESS = 255; | |
#define LED_DITHER 255 // try 0 to disable flickering | |
String Preset = "pnoise"; | |
String PresetArray = "AutoVu,AutoStat,Static,blur,pnoise,beatwave,cylon,ripple,rainbow1,ripple2,Twinkle,pattern2,juggle2,pattern3,bpm,fire,vu,vu2,Vu3,Vu4,Vu6,niko,vu7,vu8,vu9,vu10"; | |
String onoff = "ON"; | |
uint8_t qCurrentPatternNumber = 0; // Index number of which pattern is current | |
String vucheck = "false" ,statcheck = "false" ,autocheck = "false"; | |
#include <ESP8266WiFi.h> | |
#include <ESP8266WebServer.h> | |
#include <Wire.h> | |
//#include <SPI.h> | |
#include "./Javascript.h" | |
#include "./HTML.h" | |
#define ESP8266 | |
#include <Adafruit_NeoPixel.h> | |
//#include <NeoPixelBus.h> | |
//#include <NeoPixelAnimator.h> | |
#define FASTLED_ALLOW_INTERRUPTS 0 | |
#define INTERRUPT_THRESHOLD 1 | |
#define FASTLED_INTERRUPT_RETRY_COUNT 2 | |
#define FASTLED_DEBUG_COUNT_FRAME_RETRIES 2 | |
#include <FastLED.h> | |
#include "water_torture.h" | |
#define PIN D5 | |
#define N_PIXELS 300 | |
#define BG 0 | |
#define COLOR_ORDER GRB // Try mixing up the letters (RGB, GBR, BRG, etc) for a whole new world of color combinations | |
#define LED_TYPE WS2812B | |
#define MIC_PIN A0 // Microphone is attached to this analog pin | |
#define DC_OFFSET 0 // DC offset in mic signal - if unusure, leave 0 | |
#define NOISE 25 // Noise/hum/interference in mic signal | |
#define SAMPLES 40 // Length of buffer for dynamic level adjustment 60(default) | |
#define TOP (N_PIXELS + 2) // Allow dot to go slightly off scale | |
#define TOP2 (N_PIXELS + 1) // Allow dot to go slightly off scale | |
#define PEAK_FALL 5 // Rate of peak falling dot | |
#define N_PIXELS_HALF (N_PIXELS/2) | |
#define PEAK_FALL_MILLIS 10 // Rate of peak falling dot | |
#define GRAVITY -9.81 // Downward (negative) acceleration of gravity in m/s^2 | |
#define h0 1 // Starting height, in meters, of the ball (strip length) | |
#define SPEED .20 // Amount to increment RGB color by each cycle | |
#define SPARKING 60 | |
#define COOLING 85 | |
#define FRAMES_PER_SECOND 60 | |
#define LAST_PIXEL_OFFSET N_PIXELS-1 | |
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) | |
#define qsubd(x, b) ((x>b)?wavebright:0) // A digital unsigned subtraction macro. if result <0, then => 0. Otherwise, take on fixed value. | |
#define qsuba(x, b) ((x>b)?x-b:0) | |
#define SEGMENTS 7 // Number of segments to carve amplitude bar into | |
#define COLOR_WAIT_CYCLES 10 // Loop cycles to wait between advancing pixel origin | |
#define COLOR_MIN 0 | |
#define COLOR_MAX 255 | |
#define DRAW_MAX 100 | |
uint8_t BeatsPerMinute = 65; | |
uint8_t gHue = 0; | |
float | |
greenOffset = 30, | |
blueOffset = 150; | |
byte | |
peak = 0, // Used for falling dot | |
dotCount = 0, // Frame counter for delaying dot-falling speed | |
volCount = 0; // Frame counter for storing past volume data | |
int | |
reading, | |
vol[SAMPLES], // Collection of prior volume samples | |
lvl = 10, // Current "dampened" audio level | |
minLvlAvg = 0, // For dynamic adjustment of graph low & high | |
maxLvlAvg = 512; | |
//vu 8 variables | |
int | |
origin = 0, | |
color_wait_count = 0, | |
scroll_color = COLOR_MIN, | |
last_intensity = 0, | |
intensity_max = 0, | |
origin_at_flip = 0; | |
uint32_t | |
draw[DRAW_MAX]; | |
boolean | |
growing = false, | |
fall_from_left = true; | |
//NOISE VARS | |
static uint16_t dist = random16(1000); // A random number for our noise generator. | |
uint16_t scale = 30; | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, PIN, NEO_GRB + NEO_KHZ800); | |
//NeoPixelBus<NeoBrgFeature, Neo800KbpsMethod> strip(N_PIXELS, PIN); | |
// Water torture | |
WaterTorture water_torture = WaterTorture(&strip); | |
// Modes | |
enum | |
{ | |
} MODE; | |
bool test = true; | |
int BRIGHTNESS_MAX = 80; | |
int brightness = 20; | |
// cycle variables | |
int CYCLE_MIN_MILLIS = 2; | |
int CYCLE_MAX_MILLIS = 1000; | |
int cycleMillis = 20; | |
bool paused = false; | |
long lastTime = 0; | |
bool boring = true; | |
bool gReverseDirection = false; | |
// FOR SYLON ETC | |
uint8_t thisbeat = 23; | |
uint8_t thatbeat = 28; | |
uint8_t thisfade = 4; // How quickly does it fade? Lower = slower fade rate. | |
uint8_t thissat = 255; // The saturation, where 255 = brilliant colours. | |
uint8_t thisbri = 255; | |
//FOR JUGGLE | |
uint8_t numdots = 3; // Number of dots in use. | |
uint8_t faderate = 6; // How long should the trails be. Very low value = longer trails. | |
uint8_t hueinc = 16; // Incremental change in hue between each dot. | |
uint8_t thishue = 0; // Starting hue. | |
uint8_t curhue = 0; | |
uint8_t thisbright = 255; // How bright should the LED/display be. | |
uint8_t basebeat = 5; | |
uint8_t max_bright = 255; | |
// Twinkle | |
float redStates[N_PIXELS]; | |
float blueStates[N_PIXELS]; | |
float greenStates[N_PIXELS]; | |
float Fade = 0.96; | |
unsigned int sample; | |
//Samples | |
#define NSAMPLES 64 | |
unsigned int samplearray[NSAMPLES]; | |
unsigned long samplesum = 0; | |
unsigned int sampleavg = 0; | |
int samplecount = 0; | |
//unsigned int sample = 0; | |
unsigned long oldtime = 0; | |
unsigned long newtime = 0; | |
CRGB leds[N_PIXELS]; | |
int myhue = 0; | |
//Ripple variables | |
int color; | |
int center = 0; | |
int step = -1; | |
int maxSteps = 16; | |
float fadeRate = 0.80; | |
int diff; | |
//vu ripple | |
uint8_t colour; | |
uint8_t myfade = 255; // Starting brightness. | |
#define maxsteps 16 // Case statement wouldn't allow a variable. | |
int peakspersec = 0; | |
int peakcount = 0; | |
uint8_t bgcol = 0; | |
int thisdelay = 20; | |
//background color | |
uint32_t currentBg = random(256); | |
uint32_t nextBg = currentBg; | |
CRGBPalette16 currentPalette; | |
CRGBPalette16 targetPalette = CRGBPalette16(CHSV(random8(), 255, random8(128,255)), CHSV(random8(), 255, random8(128,255)), CHSV(random8(), 192, random8(128,255)), CHSV(random8(), 255, random8(128,255))); | |
TBlendType currentBlending; | |
const char* ssid = "Your-Wifi-SSID"; | |
const char* password = "Your-PASSWORD"; | |
ESP8266WebServer server(80); | |
unsigned long wait000 = 0UL, wait001 = 1000UL; | |
//SETUP | |
void setup() { | |
Serial.begin(115200); | |
Serial.setDebugOutput(true); | |
// ESP.wdtDisable(); // Postoqnno restartira !!! | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) delay(500); | |
WiFi.mode(WIFI_STA); | |
WiFi.setSleepMode(WIFI_NONE_SLEEP); | |
Serial.println(WiFi.localIP()); | |
server.on("/", handleWebsite); | |
server.on("/xml", handleXML); | |
server.on("/SetRGB", handleRGB); | |
server.on("/Fade", handleFade); | |
server.on("/Speed", handleSpeed); | |
server.on("/Preset", handlePreset); | |
server.on("/flip", handleFlip); | |
server.begin(); | |
delay( 100 ); // power-up safety delay | |
FastLED.addLeds<WS2812B, PIN, COLOR_ORDER>(leds, N_PIXELS).setCorrection( TypicalLEDStrip ); | |
FastLED.setBrightness( BRIGHTNESS ); | |
memset(vol, 0, sizeof(vol)); | |
LEDS.addLeds<LED_TYPE, PIN, COLOR_ORDER>(leds, N_PIXELS); | |
strip.begin(); | |
strip.show(); // Initialize all pixels to 'off' | |
} | |
void SimpleHandle() { | |
} | |
//LOOP | |
void loop() { | |
server.handleClient(); | |
if (millis() > wait000) { | |
buildXML(); | |
wait000 = millis() + 1000UL; | |
} | |
FastLED.setBrightness( BRIGHTNESS ); | |
FastLED.setDither(LED_DITHER); | |
strip.setBrightness(BRIGHTNESS); | |
//for mic | |
uint8_t i; | |
uint16_t minLvl, maxLvl; | |
int n, height; | |
// end mic | |
ESP.wdtFeed(); //Nahrani kucheto !!! Zasega biva :) | |
if ( onoff == "ON"){ | |
if ( Preset == "AutoVu"){ | |
All2();} | |
else if ( Preset == "AutoStat"){ | |
All();} | |
else if ( Preset == "blur"){ | |
blur();} | |
else if ( Preset == "pnoise"){ | |
pnoise();} | |
else if ( Preset == "beatwave"){ | |
beatwave();} | |
else if ( Preset == "Static"){ | |
colorWipe(strip.Color(Rval, Gval, Bval), 100);} | |
else if ( Preset == "cylon"){ | |
cylon();} | |
else if ( Preset == "ripple"){ | |
ripple();} | |
else if ( Preset == "rainbow1"){ | |
rainbow1();} | |
else if ( Preset == "ripple2"){ | |
ripple2();} | |
else if ( Preset == "Twinkle"){ | |
Twinkle();} | |
else if ( Preset == "pattern2"){ | |
pattern2();} | |
else if ( Preset == "juggle2"){ | |
juggle2();} | |
else if ( Preset == "pattern3"){ | |
pattern3();} | |
else if ( Preset == "bpm"){ | |
bpm();} | |
else if ( Preset == "fire"){ | |
fire();} | |
else if ( Preset == "vu"){ | |
vu();} | |
else if ( Preset == "vu2"){ | |
vu2();} | |
else if ( Preset == "Vu3"){ | |
Vu3();} | |
else if ( Preset == "Vu4"){ | |
Vu4();} | |
else if ( Preset == "Vu6"){ | |
Vu6();} | |
else if ( Preset == "niko"){ | |
niko();} | |
else if ( Preset == "vu7"){ | |
vu7();} | |
else if ( Preset == "vu8"){ | |
vu8();} | |
else if ( Preset == "vu9"){ | |
vu9();} | |
else if ( Preset == "vu10"){ | |
vu10();} | |
else if ( Preset == "Simple"){ | |
SimpleHandle();} | |
} | |
else colorWipe(strip.Color(0, 0, 0), 10); | |
//delayMicroseconds(500); | |
} | |
void handleWebsite() { | |
buildWebsite(); | |
server.send(200, "text/html", webSite); | |
} | |
void handleRGB() { | |
String Rstr = {server.arg("r")}; | |
String Gstr = {server.arg("g")}; | |
String Bstr = {server.arg("b")}; | |
Rval = constrain(Rstr.toInt(),0,255); | |
Gval = constrain(Gstr.toInt(),0,255); | |
Bval = constrain(Bstr.toInt(),0,255); | |
rgbarray[0] = Rval; | |
rgbarray[1] = Gval; | |
rgbarray[2] = Bval; | |
buildXML(); | |
String RGBStr = String(Rval) + "," + String(Gval) + "," + String(Bval); | |
Serial.println("RGB:" + RGBStr); | |
server.send(200, "text/xml", XML); | |
} | |
void handleFade() { | |
String fadestr = {server.arg("f")}; | |
BRIGHTNESS = constrain(fadestr.toInt(),0,255); | |
buildXML(); | |
Serial.println("Fade:" + fadestr); | |
server.send(200, "text/xml", XML); | |
} | |
void handleSpeed() { | |
String speedstr = {server.arg("s")}; | |
Speed = constrain(speedstr.toInt(),0,255); | |
buildXML(); | |
Serial.println("Speed:" + speedstr); | |
server.send(200, "text/xml", XML); | |
} | |
void handlePreset() { | |
String presetstr = {server.arg("p")}; | |
Preset = presetstr; | |
buildXML(); | |
if ( presetstr == "AutoVu") { autocheck = "false"; statcheck = "false"; vucheck = "true";} | |
else if ( presetstr == "Static") { autocheck = "false"; statcheck = "true"; vucheck = "false";} | |
else if ( presetstr == "AutoStat") { autocheck = "true"; statcheck = "false"; vucheck = "false";} | |
else { autocheck = "false"; statcheck = "false"; vucheck = "false";} | |
//Serial.println(autocheck + vucheck + statcheck); | |
Serial.println("Preset:" + Preset); | |
server.send(200, "text/xml", XML); | |
} | |
void handleFlip() { | |
String flipstr = {server.arg("o")}; | |
onoff = flipstr; | |
buildXML(); | |
Serial.println(onoff); | |
server.send(200, "text/xml", XML); | |
} | |
void handleXML() { | |
buildXML(); | |
server.send(200, "text/xml", XML); | |
} | |
void buildXML() { | |
XML = "<?xml version='1.0'?>"; | |
XML += "<xml>"; | |
XML += "<onoff>"; | |
XML += String(onoff); | |
XML += "</onoff>"; | |
XML += "<rgbarray>"; | |
for (int i = 0 ; i <3 ; i++) { | |
XML += "<rgbarray" + (String)i + ">"; | |
XML += String(rgbarray[i]); | |
XML += "</rgbarray" + (String)i + ">"; | |
} | |
XML += "</rgbarray>"; | |
XML += "<fade>"; | |
XML += String(BRIGHTNESS); | |
XML += "</fade>"; | |
XML += "<speed>"; | |
XML += String(Speed); | |
XML += "</speed>"; | |
XML += "<preset>"; | |
XML += Preset; | |
XML += "</preset>"; | |
XML += "</xml>"; | |
} | |
void colorWipe(uint32_t c, uint8_t wait) { | |
for(uint16_t i=0; i<strip.numPixels(); i++) { | |
strip.setPixelColor(i, c); | |
strip.show(); | |
} | |
} | |
void vu() { | |
uint8_t i; | |
uint16_t minLvl, maxLvl; | |
int n, height; | |
n = analogRead(MIC_PIN); // Raw reading from mic | |
n = abs(n - 474 - DC_OFFSET); | |
n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum | |
lvl = ((lvl * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) | |
Serial.print(lvl); | |
Serial.print(" "); | |
Serial.print(n); | |
Serial.println(" "); | |
// Calculate bar height based on dynamic min/max levels (fixed point): | |
height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg); | |
if(height < 0L) height = 0; // Clip output | |
else if(height > TOP) height = TOP; | |
if(height > peak) peak = height; // Keep 'peak' dot at top | |
// Serial.println(height); | |
// Color pixels based on rainbow gradient | |
for(i=0; i<=N_PIXELS/2; i++) { | |
if(i >= height) { | |
strip.setPixelColor(i, 0, 0, 0); | |
strip.setPixelColor(N_PIXELS-i, 0, 0, 0); | |
//strip.setPixelColor(N_PIXELS/2-1, 250, 0, 0); | |
} | |
else strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()/2-1,30,140))); //30 - 150 | |
strip.setPixelColor(N_PIXELS-i-1,Wheel(map(i,0,strip.numPixels()/2-1,30,140))); | |
} | |
// Draw peak dot | |
if(peak > 0 && peak <= N_PIXELS-1) | |
strip.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()/2-1,30,150))); | |
strip.setPixelColor(N_PIXELS-peak,Wheel(map(peak,0,strip.numPixels()/2-1,30,150))); | |
strip.show(); // Update strip | |
// Every few frames, make the peak pixel drop by 1: | |
if(++dotCount >= PEAK_FALL) { //fall rate | |
if(peak > 0) peak--; | |
dotCount = 0; | |
} | |
vol[volCount] = n; // Save sample for dynamic leveling | |
if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter | |
//else volCount++; | |
// Get volume range of prior frames | |
minLvl = maxLvl = vol[0]; | |
for(i=1; i<SAMPLES; i++) { | |
if(vol[i] < minLvl) minLvl = vol[i]; | |
else if(vol[i] > maxLvl) maxLvl = vol[i]; | |
} | |
// minLvl and maxLvl indicate the volume range over prior frames, used | |
// for vertically scaling the output graph (so it looks interesting | |
// regardless of volume level). If they're too close together though | |
// (e.g. at very low volume levels) the graph becomes super coarse | |
// and 'jumpy'...so keep some minimum distance between them (this | |
// also lets the graph go to zero when no sound is playing): | |
if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP; | |
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels | |
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average) | |
} | |
// Input a value 0 to 255 to get a color value. | |
// The colors are a transition r - g - b - back to r. | |
uint32_t Wheel(byte WheelPos) { | |
if(WheelPos < 85) { | |
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); | |
} else if(WheelPos < 170) { | |
WheelPos -= 85; | |
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); | |
} else { | |
WheelPos -= 170; | |
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); | |
} | |
} | |
void vu2() { | |
uint8_t i; | |
uint16_t minLvl, maxLvl; | |
int n, height; | |
n = analogRead(MIC_PIN); // Raw reading from mic | |
n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum | |
lvl = ((lvl * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) dobavil sym -8 na N | |
// Calculate bar height based on dynamic min/max levels (fixed point): | |
height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg); | |
if(height < 0L) height = 0; // Clip output | |
else if(height > TOP) height = TOP; | |
if(height > peak) peak = height; // Keep 'peak' dot at top | |
// Color pixels based on rainbow gradient | |
for(i=0; i<N_PIXELS_HALF; i++) { | |
if(i >= height) { | |
strip.setPixelColor(N_PIXELS_HALF-i-1, 0, 0, 0); | |
strip.setPixelColor(N_PIXELS_HALF+i, 0, 0, 0); | |
} | |
else { | |
uint32_t color = Wheel(map(i,0,N_PIXELS_HALF-1,30,150)); | |
strip.setPixelColor(N_PIXELS_HALF-i-1,color); | |
strip.setPixelColor(N_PIXELS_HALF+i,color); | |
} | |
} | |
// Draw peak dot | |
if(peak > 0 && peak <= N_PIXELS_HALF-1) { | |
uint32_t color = Wheel(map(peak,0,N_PIXELS_HALF-1,30,150)); | |
strip.setPixelColor(N_PIXELS_HALF-peak-1,color); | |
strip.setPixelColor(N_PIXELS_HALF+peak,color); | |
} | |
strip.show(); // Update strip | |
// Every few frames, make the peak pixel drop by 1: | |
if(++dotCount >= PEAK_FALL) { //fall rate | |
if(peak > 0) peak--; | |
dotCount = 0; | |
} | |
vol[volCount] = n; // Save sample for dynamic leveling | |
if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter | |
// Get volume range of prior frames | |
minLvl = maxLvl = vol[0]; | |
for(i=1; i<SAMPLES; i++) { | |
if(vol[i] < minLvl) minLvl = vol[i]; | |
else if(vol[i] > maxLvl) maxLvl = vol[i]; | |
} | |
// minLvl and maxLvl indicate the volume range over prior frames, used | |
// for vertically scaling the output graph (so it looks interesting | |
// regardless of volume level). If they're too close together though | |
// (e.g. at very low volume levels) the graph becomes super coarse | |
// and 'jumpy'...so keep some minimum distance between them (this | |
// also lets the graph go to zero when no sound is playing): | |
if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP; | |
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels | |
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average) | |
} | |
void Vu3() { | |
uint8_t i; | |
uint16_t minLvl, maxLvl; | |
int n, height; | |
n = analogRead(MIC_PIN); // Raw reading from mic | |
// n = abs(n - 512 - DC_OFFSET); // Center on zero | |
// n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum | |
lvl = ((lvl * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) Dobaveno -8 na N | |
// Calculate bar height based on dynamic min/max levels (fixed point): | |
height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg); | |
if (height < 0L) height = 0; // Clip output | |
else if (height > TOP) height = TOP; | |
if (height > peak) peak = height; // Keep 'peak' dot at top | |
greenOffset += SPEED; | |
blueOffset += SPEED; | |
if (greenOffset >= 255) greenOffset = 0; | |
if (blueOffset >= 255) blueOffset = 0; | |
// Color pixels based on rainbow gradient | |
for(i=0; i<N_PIXELS/2-2; i++) { | |
if(i >= height) { | |
strip.setPixelColor(i, 0, 0, 0); | |
strip.setPixelColor(N_PIXELS-i, 0, 0, 0); | |
strip.setPixelColor(height*2+i, 0, 0, 0); | |
} | |
else { | |
strip.setPixelColor(i, Wheel( map(i, 0, strip.numPixels()/2 - 1, (int)greenOffset, (int)blueOffset) )); | |
strip.setPixelColor(N_PIXELS-i-1, Wheel( map(i, 0, strip.numPixels()/2 - 1, (int)greenOffset, (int)blueOffset) )); | |
} | |
} | |
// Draw peak dot | |
if(peak > 0 && peak <= N_PIXELS-1) | |
strip.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()/2-1,30,150))); | |
strip.setPixelColor(N_PIXELS-peak,Wheel(map(peak,0,strip.numPixels()/2-1,30,150))); | |
strip.show(); // Update strip | |
// Every few frames, make the peak pixel drop by 1: | |
if(++dotCount >= PEAK_FALL) { //fall rate | |
if(peak > 0) peak--; | |
dotCount = 0; | |
} | |
strip.show(); // Update strip | |
vol[volCount] = n; | |
if (++volCount >= SAMPLES) { | |
volCount = 0; | |
} | |
// Get volume range of prior frames | |
minLvl = maxLvl = vol[0]; | |
for (i = 1; i < SAMPLES; i++) { | |
if (vol[i] < minLvl) { | |
minLvl = vol[i]; | |
} else if (vol[i] > maxLvl) { | |
maxLvl = vol[i]; | |
} | |
} | |
// minLvl and maxLvl indicate the volume range over prior frames, used | |
// for vertically scaling the output graph (so it looks interesting | |
// regardless of volume level). If they're too close together though | |
// (e.g. at very low volume levels) the graph becomes super coarse | |
// and 'jumpy'...so keep some minimum distance between them (this | |
// also lets the graph go to zero when no sound is playing): | |
if ((maxLvl - minLvl) < TOP) { | |
maxLvl = minLvl + TOP; | |
} | |
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels | |
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average) | |
} | |
void Vu4() { | |
uint8_t i; | |
uint16_t minLvl, maxLvl; | |
int n, height; | |
n = analogRead(MIC_PIN); // Raw reading from mic | |
// n = abs(n - 512 - DC_OFFSET); // Center on zero | |
n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum | |
lvl = ((lvl * 7) + n -8 ) >> 3; // "Dobaveno -8 na N | |
// Calculate bar height based on dynamic min/max levels (fixed point): | |
height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg); | |
if(height < 0L) height = 0; // Clip output | |
else if(height > TOP) height = TOP; | |
if(height > peak) peak = height; // Keep 'peak' dot at top | |
greenOffset += SPEED; | |
blueOffset += SPEED; | |
if (greenOffset >= 255) greenOffset = 0; | |
if (blueOffset >= 255) blueOffset = 0; | |
// Color pixels based on rainbow gradient | |
for(i=0; i<N_PIXELS_HALF; i++) { | |
if(i >= height) { | |
strip.setPixelColor(N_PIXELS_HALF-i-1, 0, 0, 0); | |
strip.setPixelColor(N_PIXELS_HALF+i, 0, 0, 0); | |
} | |
else { | |
uint32_t color = Wheel(map(i,0,N_PIXELS_HALF-1,(int)greenOffset, (int)blueOffset)); | |
strip.setPixelColor(N_PIXELS_HALF-i-1,color); | |
strip.setPixelColor(N_PIXELS_HALF+i,color); | |
} | |
} | |
// Draw peak dot | |
if(peak > 0 && peak <= N_PIXELS_HALF-1) { | |
uint32_t color = Wheel(map(peak,0,N_PIXELS_HALF-1,30,150)); | |
strip.setPixelColor(N_PIXELS_HALF-peak-1,color); | |
strip.setPixelColor(N_PIXELS_HALF+peak,color); | |
} | |
strip.show(); // Update strip | |
// Every few frames, make the peak pixel drop by 1: | |
if(++dotCount >= PEAK_FALL) { //fall rate | |
if(peak > 0) peak--; | |
dotCount = 0; | |
} | |
vol[volCount] = n; // Save sample for dynamic leveling | |
if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter | |
// Get volume range of prior frames | |
minLvl = maxLvl = vol[0]; | |
for(i=1; i<SAMPLES; i++) { | |
if(vol[i] < minLvl) minLvl = vol[i]; | |
else if(vol[i] > maxLvl) maxLvl = vol[i]; | |
} | |
// minLvl and maxLvl indicate the volume range over prior frames, used | |
// for vertically scaling the output graph (so it looks interesting | |
// regardless of volume level). If they're too close together though | |
// (e.g. at very low volume levels) the graph becomes super coarse | |
// and 'jumpy'...so keep some minimum distance between them (this | |
// also lets the graph go to zero when no sound is playing): | |
if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP; | |
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels | |
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average) | |
} | |
void Vu5() | |
{ | |
uint8_t i; | |
uint16_t minLvl, maxLvl; | |
int n, height; | |
n = analogRead(MIC_PIN); // Raw reading from mic | |
// n = abs(n - 512 - DC_OFFSET); // Center on zero | |
n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum | |
lvl = ((lvl * 7) + n ) >> 3; // "Dampened" reading -8 na N | |
// Calculate bar height based on dynamic min/max levels (fixed point): | |
height = TOP2 * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg); | |
if(height < 0L) height = 0; // Clip output | |
else if(height > TOP2) height = TOP2; | |
if(height > peak) peak = height; // Keep 'peak' dot at top | |
// Color pixels based on rainbow gradient | |
for(i=0; i<N_PIXELS/2; i++) { | |
if(i >= height) { | |
strip.setPixelColor(i, 0, 0, 0); | |
// strip.setPixelColor(N_PIXELS/2-i, 0, 0, 0); | |
strip.setPixelColor(N_PIXELS-i, 0, 0, 0); | |
} | |
else | |
{ | |
strip.setPixelColor(i,(35+i)/i,i,60/i); | |
strip.setPixelColor(N_PIXELS-i,(35+i)/i,i,60/i); | |
// strip.setPixelColor(N_PIXELS/2-i,(35+i)/i,i,60/i); | |
// strip.setPixelColor(N_PIXELS/2+i,(35+i)/i,i,60/i); | |
} | |
} | |
// Draw peak dot | |
if(peak > 0 && peak <= LAST_PIXEL_OFFSET) | |
{ | |
strip.setPixelColor(peak,Wheel(map(n,0,N_PIXELS/2,0,60))); //30 - 150 | |
strip.setPixelColor(N_PIXELS-peak,Wheel(map(n,0,N_PIXELS/2,0,60))); | |
strip.setPixelColor(peak+3,Wheel(map(n,0,N_PIXELS/2,60,80))); //30 - 150 | |
strip.setPixelColor(N_PIXELS-peak-3,Wheel(map(n,0,N_PIXELS/2,60,80))); | |
strip.setPixelColor(peak+6,Wheel(map(n,0,N_PIXELS/2,80,120))); //30 - 150 | |
strip.setPixelColor(N_PIXELS-peak-6,Wheel(map(n,0,N_PIXELS/2,80,120))); | |
strip.setPixelColor(peak+9,Wheel(map(n,0,N_PIXELS/2,200,80))); //30 - 150 | |
strip.setPixelColor(N_PIXELS-peak-9,Wheel(map(n,0,N_PIXELS/2,200,80))); | |
} | |
// Every few frames, make the peak pixel drop by 1: | |
if (millis() - lastTime >= 50) | |
{ | |
lastTime = millis(); | |
strip.show(); // Update strip | |
//fall rate | |
if(peak > 0) peak--; | |
} | |
vol[volCount] = n; // Save sample for dynamic leveling | |
if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter | |
// Get volume range of prior frames | |
minLvl = maxLvl = vol[0]; | |
for(i=1; i<SAMPLES; i++) | |
{ | |
if(vol[i] < minLvl) minLvl = vol[i]; | |
else if(vol[i] > maxLvl) maxLvl = vol[i]; | |
} | |
// minLvl and maxLvl indicate the volume range over prior frames, used | |
// for vertically scaling the output graph (so it looks interesting | |
// regardless of volume level). If they're too close together though | |
// (e.g. at very low volume levels) the graph becomes super coarse | |
// and 'jumpy'...so keep some minimum distance between them (this | |
// also lets the graph go to zero when no sound is playing): | |
if((maxLvl - minLvl) < TOP2) maxLvl = minLvl + TOP2; | |
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels | |
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average) | |
} | |
void Vu6() | |
{ | |
uint8_t i; | |
uint16_t minLvl, maxLvl; | |
int n, height; | |
n = analogRead(MIC_PIN); // Raw reading from mic | |
n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum | |
lvl = ((lvl * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) | |
// Calculate bar height based on dynamic min/max levels (fixed point): | |
height = TOP2 * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg); | |
if(height < 0L) height = 0; // Clip output | |
else if(height > TOP2) height = TOP2; | |
if(height > peak) peak = height; // Keep 'peak' dot at top | |
//#define CENTERED | |
#ifdef CENTERED | |
// Draw peak dot | |
if(peak > 0 && peak <= LAST_PIXEL_OFFSET) | |
{ | |
strip.setPixelColor(((N_PIXELS/2) + peak),0,0,0); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150))); | |
strip.setPixelColor(((N_PIXELS/2) - peak),0,0,0); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150))); | |
} | |
#else | |
// Color pixels based on rainbow gradient | |
for(i=0; i<N_PIXELS/2; i++) | |
{ | |
if(i >= height) | |
{ | |
strip.setPixelColor(i, 0, 0, 0); | |
strip.setPixelColor(N_PIXELS-i-1, 0, 0, 0); | |
//fadeToBlackBy( leds, N_PIXELS-i-1, 1); | |
//fadeToBlackBy( leds,i, 1); | |
} | |
else | |
{ | |
strip.setPixelColor(i,(255-i*15),0,constrain(height,0,205-peak)); | |
strip.setPixelColor(N_PIXELS-i,(255-i*15),0,constrain(height,0,205-peak)); | |
strip.setPixelColor(N_PIXELS_HALF,0,0,0); | |
} | |
} | |
// Draw peak dot | |
if(peak >0 && peak <= LAST_PIXEL_OFFSET) | |
{ | |
//show_at_max_brightness_for_power(); | |
strip.setPixelColor(peak+5,(int)sqrt(peak)*2,0+peak,200+(peak)); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150))); | |
strip.setPixelColor(N_PIXELS-peak-5,(int)sqrt(peak)*2,0+peak,200+(peak)); | |
strip.setPixelColor(peak+(int)log(2*peak)*10,2*(int)sqrt(peak),10+peak/2,2*peak); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150))); | |
strip.setPixelColor(N_PIXELS-peak-(int)log(2*peak)*10,2*(int)sqrt(peak),10+peak/2,2*peak); | |
if(peak >50 && peak <= LAST_PIXEL_OFFSET) | |
{ | |
strip.setPixelColor(N_PIXELS_HALF,110,peak,110); | |
strip.setPixelColor(N_PIXELS_HALF+2,110,peak,110);} //center | |
if(peak >55 && peak == LAST_PIXEL_OFFSET) | |
{ | |
strip.setPixelColor(N_PIXELS_HALF-14,255,peak,150); //corners | |
strip.setPixelColor(N_PIXELS_HALF+17,255,peak,150); | |
} | |
if(peak >40 && peak <= LAST_PIXEL_OFFSET) | |
{ | |
strip.setPixelColor(N_PIXELS_HALF-peak/3,200,i,200); //corners | |
strip.setPixelColor(N_PIXELS_HALF+peak/3,random(140,220),i,random(180,220));} | |
if(peak >50 && peak <= LAST_PIXEL_OFFSET) | |
{ | |
strip.setPixelColor(N_PIXELS_HALF-peak/4,250,i*2,250); //corners | |
strip.setPixelColor(N_PIXELS_HALF+peak/4,250,i*2,250);} | |
if(peak >=60 && peak <= LAST_PIXEL_OFFSET) | |
{ | |
strip.setPixelColor(N_PIXELS_HALF+1,255,255,255);} | |
} | |
#endif | |
// Every few frames, make the peak pixel drop by 1: | |
if (millis() - lastTime >= PEAK_FALL_MILLIS) | |
{ | |
lastTime = millis(); | |
strip.show(); // Update strip | |
//fall rate | |
if(peak > 0) peak--; | |
} | |
vol[volCount] = n; // Save sample for dynamic leveling | |
if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter | |
// Get volume range of prior frames | |
minLvl = maxLvl = vol[0]; | |
for(i=1; i<SAMPLES; i++) | |
{ | |
if(vol[i] < minLvl) minLvl = vol[i]; | |
else if(vol[i] > maxLvl) maxLvl = vol[i]; | |
} | |
// minLvl and maxLvl indicate the volume range over prior frames, used | |
// for vertically scaling the output graph (so it looks interesting | |
// regardless of volume level). If they're too close together though | |
// (e.g. at very low volume levels) the graph becomes super coarse | |
// and 'jumpy'...so keep some minimum distance between them (this | |
// also lets the graph go to zero when no sound is playing): | |
if((maxLvl - minLvl) < TOP2) maxLvl = minLvl + TOP2; | |
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels | |
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average) | |
} | |
void vu7() { | |
EVERY_N_MILLISECONDS(1000) { | |
peakspersec = peakcount; // Count the peaks per second. This value will become the foreground hue. | |
peakcount = 0; // Reset the counter every second. | |
} | |
soundmems(); | |
EVERY_N_MILLISECONDS(20) { | |
ripple3(); | |
} | |
//FastLED.show(); | |
show_at_max_brightness_for_power(); | |
} // loop() | |
void soundmems() { // Rolling average counter - means we don't have to go through an array each time. | |
newtime = millis(); | |
int tmp = analogRead(MIC_PIN); //- 512; | |
sample = abs(tmp); | |
int potin = map(Speed, 0, 255, 0, 60); | |
samplesum = samplesum + sample - samplearray[samplecount]; // Add the new sample and remove the oldest sample in the array | |
sampleavg = samplesum / NSAMPLES; // Get an average | |
samplearray[samplecount] = sample; // Update oldest sample in the array with new sample | |
samplecount = (samplecount + 1) % NSAMPLES; // Update the counter for the array | |
if (newtime > (oldtime + 200)) digitalWrite(13, LOW); // Turn the LED off 200ms after the last peak. | |
if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) { // Check for a peak, which is 30 > the average, but wait at least 60ms for another. | |
step = -1; | |
peakcount++; | |
digitalWrite(13, HIGH); | |
oldtime = newtime; | |
// Serial.println(potin); | |
} | |
} // soundmems() | |
void ripple3() { | |
for (int i = 0; i < N_PIXELS; i++) leds[i] = CHSV(bgcol, 255, sampleavg*2); // Set the background colour. | |
switch (step) { | |
case -1: // Initialize ripple variables. | |
center = random(N_PIXELS); | |
colour = (peakspersec*10) % 255; // More peaks/s = higher the hue colour. | |
step = 0; | |
bgcol = bgcol+8; | |
break; | |
case 0: | |
leds[center] = CHSV(colour, 255, 255); // Display the first pixel of the ripple. | |
step ++; | |
break; | |
case maxsteps: // At the end of the ripples. | |
// step = -1; | |
break; | |
default: // Middle of the ripples. | |
leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2); // Simple wrap from Marc Miller. | |
leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2); | |
step ++; // Next step. | |
break; | |
} // switch step | |
} // ripple() | |
//040216 | |
void vu8() { | |
int intensity = calculateIntensity(); | |
updateOrigin(intensity); | |
assignDrawValues(intensity); | |
writeSegmented(); | |
//uint32_t *segmented = segmentAndResize(draw); | |
//writeToStrip(segmented); | |
updateGlobals(); | |
} | |
int calculateIntensity() { | |
int intensity; | |
reading = analogRead(MIC_PIN); // Raw reading from mic | |
reading = (reading <= NOISE) ? 0 : (reading - NOISE); // Remove noise/hum | |
lvl = ((lvl * 7) + reading) >> 3; // "Dampened" reading (else looks twitchy) | |
// Calculate bar height based on dynamic min/max levels (fixed point): | |
intensity = DRAW_MAX * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg); | |
return constrain(intensity, 0, DRAW_MAX-1); | |
} | |
void updateOrigin(int intensity) { | |
// detect peak change and save origin at curve vertex | |
if (growing && intensity < last_intensity) { | |
growing = false; | |
intensity_max = last_intensity; | |
fall_from_left = !fall_from_left; | |
origin_at_flip = origin; | |
} else if (intensity > last_intensity) { | |
growing = true; | |
origin_at_flip = origin; | |
} | |
last_intensity = intensity; | |
// adjust origin if falling | |
if (!growing) { | |
if (fall_from_left) { | |
origin = origin_at_flip + ((intensity_max - intensity) / 2); | |
} else { | |
origin = origin_at_flip - ((intensity_max - intensity) / 2); | |
} | |
// correct for origin out of bounds | |
if (origin < 0) { | |
origin = DRAW_MAX - abs(origin); | |
} else if (origin > DRAW_MAX - 1) { | |
origin = origin - DRAW_MAX - 1; | |
} | |
} | |
} | |
void assignDrawValues(int intensity) { | |
// draw amplitue as 1/2 intensity both directions from origin | |
int min_lit = origin - (intensity / 2); | |
int max_lit = origin + (intensity / 2); | |
if (min_lit < 0) { | |
min_lit = min_lit + DRAW_MAX; | |
} | |
if (max_lit >= DRAW_MAX) { | |
max_lit = max_lit - DRAW_MAX; | |
} | |
for (int i=0; i < DRAW_MAX; i++) { | |
// if i is within origin +/- 1/2 intensity | |
if ( | |
(min_lit < max_lit && min_lit < i && i < max_lit) // range is within bounds and i is within range | |
|| (min_lit > max_lit && (i > min_lit || i < max_lit)) // range wraps out of bounds and i is within that wrap | |
) { | |
draw[i] = Wheel(scroll_color); | |
} else { | |
draw[i] = 0; | |
} | |
} | |
} | |
void writeSegmented() { | |
int seg_len = N_PIXELS / SEGMENTS; | |
for (int s = 0; s < SEGMENTS; s++) { | |
for (int i = 0; i < seg_len; i++) { | |
strip.setPixelColor(i + (s*seg_len), draw[map(i, 0, seg_len, 0, DRAW_MAX)]); | |
} | |
} | |
strip.show(); | |
} | |
uint32_t * segmentAndResize(uint32_t* draw) { | |
int seg_len = N_PIXELS / SEGMENTS; | |
uint32_t segmented[N_PIXELS]; | |
for (int s = 0; s < SEGMENTS; s++) { | |
for (int i = 0; i < seg_len; i++) { | |
segmented[i + (s * seg_len) ] = draw[map(i, 0, seg_len, 0, DRAW_MAX)]; | |
} | |
} | |
return segmented; | |
} | |
void writeToStrip(uint32_t* draw) { | |
for (int i = 0; i < N_PIXELS; i++) { | |
strip.setPixelColor(i, draw[i]); | |
} | |
strip.show(); | |
} | |
void updateGlobals() { | |
uint16_t minLvl, maxLvl; | |
//advance color wheel | |
color_wait_count++; | |
if (color_wait_count > COLOR_WAIT_CYCLES) { | |
color_wait_count = 0; | |
scroll_color++; | |
if (scroll_color > COLOR_MAX) { | |
scroll_color = COLOR_MIN; | |
} | |
} | |
vol[volCount] = reading; // Save sample for dynamic leveling | |
if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter | |
// Get volume range of prior frames | |
minLvl = maxLvl = vol[0]; | |
for(uint8_t i=1; i<SAMPLES; i++) { | |
if(vol[i] < minLvl) minLvl = vol[i]; | |
else if(vol[i] > maxLvl) maxLvl = vol[i]; | |
} | |
// minLvl and maxLvl indicate the volume range over prior frames, used | |
// for vertically scaling the output graph (so it looks interesting | |
// regardless of volume level). If they're too close together though | |
// (e.g. at very low volume levels) the graph becomes super coarse | |
// and 'jumpy'...so keep some minimum distance between them (this | |
// also lets the graph go to zero when no sound is playing): | |
if((maxLvl - minLvl) < N_PIXELS) maxLvl = minLvl + N_PIXELS; | |
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels | |
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average) | |
} | |
//monday | |
void vu9() { | |
currentBlending = LINEARBLEND; | |
EVERY_N_SECONDS(5) { // Change the target palette to a random one every 5 seconds. | |
static uint8_t baseC = random8(); // You can use this as a baseline colour if you want similar hues in the next line. | |
for (int i = 0; i < 16; i++) { | |
targetPalette[i] = CHSV(random8(), 255, 255); | |
} | |
} | |
EVERY_N_MILLISECONDS(100) { | |
uint8_t maxChanges = 24; | |
nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges); // AWESOME palette blending capability. | |
} | |
EVERY_N_MILLISECONDS(thisdelay) { // FastLED based non-blocking delay to update/display the sequence. | |
soundble(); | |
FastLED.show(); | |
} | |
} // loop() | |
void soundble() { | |
int n; | |
n = analogRead(MIC_PIN); // Raw reading from mic | |
n = qsuba(abs(n), 10); // Center on zero and get rid of low level noise | |
CRGB newcolour = ColorFromPalette(currentPalette, constrain(n,0,255), constrain(n,0,255), currentBlending); | |
nblend(leds[0], newcolour, 128); | |
for (int i = N_PIXELS-1; i>0; i--) { | |
leds[i] = leds[i-1]; | |
} | |
} // soundmems() | |
void vu10() { | |
EVERY_N_MILLISECONDS(1000) { | |
peakspersec = peakcount; // Count the peaks per second. This value will become the foreground hue. | |
peakcount = 0; // Reset the counter every second. | |
} | |
soundrip(); | |
EVERY_N_MILLISECONDS(20) { | |
rippled(); | |
} | |
FastLED.show(); | |
} // loop() | |
void soundrip() { // Rolling average counter - means we don't have to go through an array each time. | |
newtime = millis(); | |
int tmp = analogRead(MIC_PIN); | |
sample = abs(tmp); | |
int potin = map(Speed, 0, 255, 0, 60); | |
samplesum = samplesum + sample - samplearray[samplecount]; // Add the new sample and remove the oldest sample in the array | |
sampleavg = samplesum / NSAMPLES; // Get an average | |
// Serial.println(sampleavg); | |
samplearray[samplecount] = sample; // Update oldest sample in the array with new sample | |
samplecount = (samplecount + 1) % NSAMPLES; // Update the counter for the array | |
if (newtime > (oldtime + 200)) digitalWrite(13, LOW); // Turn the LED off 200ms after the last peak. | |
if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) { // Check for a peak, which is 30 > the average, but wait at least 60ms for another. | |
step = -1; | |
peakcount++; | |
oldtime = newtime; | |
} | |
} // soundmems() | |
void rippled() { | |
fadeToBlackBy(leds, N_PIXELS, 64); // 8 bit, 1 = slow, 255 = fast | |
switch (step) { | |
case -1: // Initialize ripple variables. | |
center = random(N_PIXELS); | |
colour = (peakspersec*10) % 255; // More peaks/s = higher the hue colour. | |
step = 0; | |
break; | |
case 0: | |
leds[center] = CHSV(colour, 255, 255); // Display the first pixel of the ripple. | |
step ++; | |
break; | |
case maxsteps: // At the end of the ripples. | |
// step = -1; | |
break; | |
default: // Middle of the ripples. | |
leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2); // Simple wrap from Marc Miller. | |
leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2); | |
step ++; // Next step. | |
break; | |
} // switch step | |
} // ripple() | |
// Slightly different, this makes the rainbow equally distributed throughout | |
void rainbowCycle(int wait) { | |
uint16_t i, j; | |
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel | |
for(i=0; i< strip.numPixels(); i++) { | |
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); | |
} | |
strip.show(); | |
} | |
} | |
void ripple() { | |
if (currentBg == nextBg) { | |
nextBg = random(256); | |
} | |
else if (nextBg > currentBg) { | |
currentBg++; | |
} else { | |
currentBg--; | |
} | |
for(uint16_t l = 0; l < N_PIXELS; l++) { | |
leds[l] = CHSV(currentBg, 255, 50); // strip.setPixelColor(l, Wheel(currentBg, 0.1)); | |
} | |
if (step == -1) { | |
center = random(N_PIXELS); | |
color = random(256); | |
step = 0; | |
} | |
if (step == 0) { | |
leds[center] = CHSV(color, 255, 255); // strip.setPixelColor(center, Wheel(color, 1)); | |
step ++; | |
} | |
else { | |
if (step < maxSteps) { | |
// Serial.println(pow(fadeRate,step)); | |
leds[wrap(center + step)] = CHSV(color, 255, pow(fadeRate, step)*255); // strip.setPixelColor(wrap(center + step), Wheel(color, pow(fadeRate, step))); | |
leds[wrap(center - step)] = CHSV(color, 255, pow(fadeRate, step)*255); // strip.setPixelColor(wrap(center - step), Wheel(color, pow(fadeRate, step))); | |
if (step > 3) { | |
leds[wrap(center + step - 3)] = CHSV(color, 255, pow(fadeRate, step - 2)*255); // strip.setPixelColor(wrap(center + step - 3), Wheel(color, pow(fadeRate, step - 2))); | |
leds[wrap(center - step + 3)] = CHSV(color, 255, pow(fadeRate, step - 2)*255); // strip.setPixelColor(wrap(center - step + 3), Wheel(color, pow(fadeRate, step - 2))); | |
} | |
step ++; | |
} | |
else { | |
step = -1; | |
} | |
} | |
LEDS.show(); | |
delay(50); | |
} | |
int wrap(int step) { | |
if(step < 0) return N_PIXELS + step; | |
if(step > N_PIXELS - 1) return step - N_PIXELS; | |
return step; | |
} | |
void one_color_allHSV(int ahue, int abright) { // SET ALL LEDS TO ONE COLOR (HSV) | |
for (int i = 0 ; i < N_PIXELS; i++ ) { | |
leds[i] = CHSV(ahue, 255, abright); | |
} | |
} | |
void ripple2() { | |
if (BG){ | |
if (currentBg == nextBg) { | |
nextBg = random(256); | |
} | |
else if (nextBg > currentBg) { | |
currentBg++; | |
} else { | |
currentBg--; | |
} | |
for(uint16_t l = 0; l < N_PIXELS; l++) { | |
strip.setPixelColor(l, Wheel(currentBg, 0.1)); | |
} | |
} else { | |
for(uint16_t l = 0; l < N_PIXELS; l++) { | |
strip.setPixelColor(l, 0, 0, 0); | |
} | |
} | |
if (step == -1) { | |
center = random(N_PIXELS); | |
color = random(256); | |
step = 0; | |
} | |
if (step == 0) { | |
strip.setPixelColor(center, Wheel(color, 1)); | |
step ++; | |
} | |
else { | |
if (step < maxSteps) { | |
strip.setPixelColor(wrap(center + step), Wheel(color, pow(fadeRate, step))); | |
strip.setPixelColor(wrap(center - step), Wheel(color, pow(fadeRate, step))); | |
if (step > 3) { | |
strip.setPixelColor(wrap(center + step - 3), Wheel(color, pow(fadeRate, step - 2))); | |
strip.setPixelColor(wrap(center - step + 3), Wheel(color, pow(fadeRate, step - 2))); | |
} | |
step ++; | |
} | |
else { | |
step = -1; | |
} | |
} | |
strip.show(); | |
delay(50); | |
} | |
void fire(){ | |
#define FRAMES_PER_SECOND 40 | |
//random16_add_entropy( random()); | |
// Array of temperature readings at each simulation cell | |
static byte heat[N_PIXELS]; | |
// Step 1. Cool down every cell a little | |
for( int i = 0; i < N_PIXELS; i++) { | |
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / N_PIXELS) + 2)); | |
} | |
// Step 2. Heat from each cell drifts 'up' and diffuses a little | |
for( int k= N_PIXELS - 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( int j = 0; j < N_PIXELS; j++) { | |
// Scale the heat value from 0-255 down to 0-240 | |
// for best results with color palettes. | |
byte colorindex = scale8( heat[j], 240); | |
CRGB color = ColorFromPalette( CRGBPalette16( CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White), colorindex); | |
int pixelnumber; | |
if( gReverseDirection ) { | |
pixelnumber = (N_PIXELS-1) - j; | |
} else { | |
pixelnumber = j; | |
} | |
leds[pixelnumber] = color; | |
} | |
FastLED.show(); | |
} | |
void bpm(){ | |
CRGBPalette16 palette = PartyColors_p; | |
uint8_t beat = beatsin8( map(Speed,0,100,20,150), 64, 255); | |
for( int i = 0; i < N_PIXELS; i++) { //9948 | |
fadeToBlackBy( leds, N_PIXELS, thisfade); | |
leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10)); | |
blur1d( leds, N_PIXELS, random(100,172)); | |
FastLED.show(); | |
//for( int k = 1; k < i; k++) { | |
// leds[k] = CRGB::Black; } | |
} | |
gHue = gHue+50; | |
} | |
void Drip() | |
{ | |
MODE_WATER_TORTURE: | |
if (cycle()) | |
{ | |
strip.setBrightness(BRIGHTNESS); // off limits | |
water_torture.animate(test); | |
strip.show(); | |
//strip.setBrightness(brightness); // back to limited | |
} | |
} | |
bool cycle() | |
{ | |
if (paused) | |
{ | |
return false; | |
} | |
if (millis() - lastTime >= cycleMillis) | |
{ | |
lastTime = millis(); | |
return true; | |
} | |
return false; | |
} | |
// Input a value 0 to 255 to get a color value. | |
// The colours are a transition r - g - b - back to r. | |
uint32_t Wheel(byte WheelPos, float opacity) { | |
if(WheelPos < 85) { | |
return strip.Color((WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity, 0); | |
} | |
else if(WheelPos < 170) { | |
WheelPos -= 85; | |
return strip.Color((255 - WheelPos * 3) * opacity, 0, (WheelPos * 3) * opacity); | |
} | |
else { | |
WheelPos -= 170; | |
return strip.Color(0, (WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity); | |
} | |
} | |
void pattern2() { | |
sinelon(); // Call our sequence. | |
show_at_max_brightness_for_power(); // Power managed display of LED's. | |
//FastLED.show(); | |
} // loop() | |
void rainbow1(){ | |
int raindelay = map(Speed,0,255,10,200); | |
rainbow(raindelay); | |
Serial.println(raindelay); | |
} | |
void sinelon() { | |
// a colored dot sweeping back and forth, with fading trails | |
fadeToBlackBy( leds, N_PIXELS, thisfade); | |
int pos1 = beatsin16(thisbeat,0,N_PIXELS); | |
int pos2 = beatsin16(thatbeat,0,N_PIXELS); | |
leds[(pos1+pos2)/2] += CHSV( myhue++/64, thissat, thisbri); | |
} | |
// Pattern 3 - JUGGLE | |
void pattern3() { | |
ChangeMe(); | |
juggle(); | |
//FastLED.show(); | |
show_at_max_brightness_for_power(); // Power managed display of LED's. | |
} // loop() | |
void juggle() { // Several colored dots, weaving in and out of sync with each other | |
curhue = thishue; // Reset the hue values. | |
fadeToBlackBy(leds, N_PIXELS, faderate); | |
for( int i = 0; i < numdots; i++) { | |
leds[beatsin16(basebeat+i+numdots,0,N_PIXELS)] += CHSV(curhue, thissat, thisbright); //beat16 is a FastLED 3.1 function | |
curhue += hueinc; | |
} | |
} // juggle() | |
void ChangeMe() { // A time (rather than loop) based demo sequencer. This gives us full control over the length of each sequence. | |
uint8_t secondHand = (millis() / 1000) % 60; // IMPORTANT!!! Change '30' to a different value to change duration of the loop. | |
static uint8_t lastSecond = 99; // Static variable, means it's only defined once. This is our 'debounce' variable. | |
if (lastSecond != secondHand) { // Debounce to make sure we're not repeating an assignment. | |
lastSecond = secondHand; | |
if (secondHand == 0) {numdots=1; faderate=2;} // You can change values here, one at a time , or altogether. | |
if (secondHand == 10) {numdots=4; thishue=128; faderate=8;} | |
if (secondHand == 20) {hueinc=48; thishue=random8();} // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows. | |
} | |
} // ChangeMe() | |
void juggle2() { // Several colored dots, weaving in and out of sync with each other | |
// eight colored dots, weaving in and out of sync with each other | |
fadeToBlackBy( leds, N_PIXELS, 20); | |
byte dothue = 0; | |
for( int i = 0; i < 8; i++) { | |
leds[beatsin16(i+7,0,N_PIXELS)] |= CHSV(dothue, 200, 255); | |
dothue += 32; | |
} | |
FastLED.show(); | |
} | |
void Twinkle () { | |
if (random(25) == 1) { | |
uint16_t i = random(N_PIXELS); | |
if (redStates[i] < 1 && greenStates[i] < 1 && blueStates[i] < 1) { | |
redStates[i] = random(256); | |
greenStates[i] = random(256); | |
blueStates[i] = random(256); | |
} | |
} | |
for(uint16_t l = 0; l < N_PIXELS; l++) { | |
if (redStates[l] > 1 || greenStates[l] > 1 || blueStates[l] > 1) { | |
strip.setPixelColor(l, redStates[l], greenStates[l], blueStates[l]); | |
if (redStates[l] > 1) { | |
redStates[l] = redStates[l] * Fade; | |
} else { | |
redStates[l] = 0; | |
} | |
if (greenStates[l] > 1) { | |
greenStates[l] = greenStates[l] * Fade; | |
} else { | |
greenStates[l] = 0; | |
} | |
if (blueStates[l] > 1) { | |
blueStates[l] = blueStates[l] * Fade; | |
} else { | |
blueStates[l] = 0; | |
} | |
} else { | |
strip.setPixelColor(l, 0, 0, 0); | |
} | |
} | |
strip.show(); | |
delay(10); | |
} | |
void blur() { | |
uint8_t blurAmount = dim8_raw( beatsin8(map(Speed,0,255,1,7),64, 172) ); // A sinewave at 3 Hz with values ranging from 64 to 192. | |
blur1d( leds, N_PIXELS, blurAmount); // Apply some blurring to whatever's already on the strip, which will eventually go black. | |
uint8_t i = beatsin8(map(Speed,0,255,6,38), N_PIXELS,0 ); | |
uint8_t j = beatsin8(map(Speed,0,255,4,34), 0, N_PIXELS); | |
uint8_t k = beatsin8(map(Speed,0,255,2,30), 0, N_PIXELS); | |
// The color of each point shifts over time, each at a different speed. | |
uint16_t ms = millis(); | |
leds[constrain(abs(i+j)/2,0,N_PIXELS)] = leds[N_PIXELS - constrain(abs(i+j)/2,0,N_PIXELS)] = CHSV( ms / 29, 200, 255); | |
leds[constrain(abs(j+k),0,N_PIXELS)] = leds[N_PIXELS - constrain(abs(j+k),0,N_PIXELS)] = CHSV( ms / 41, 200, 255); | |
leds[constrain(abs(k+i)/2,0,N_PIXELS)] = leds[N_PIXELS - constrain(abs(k+i)/2,0,N_PIXELS)] = CHSV( ms / 73, 200, 255); | |
leds[abs(k)] = leds[abs(N_PIXELS-k)] = CHSV( ms / 53, 200, 255); | |
//show_at_max_brightness_for_power(); | |
ESP.wdtFeed(); | |
FastLED.show(); | |
} | |
void rainbow(uint8_t wait) { | |
uint16_t i, j; | |
EVERY_N_MILLISECONDS(wait) { | |
for(j=0; j<256; j++) { | |
for(i=0; i<strip.numPixels(); i++) { | |
//strip.setPixelColor(i, Wheel((i+j) & 255)); | |
leds[i] = CHSV(j-i, 200 , 255); | |
} | |
yield(); | |
//strip.show(); | |
// check if a button pressed | |
} | |
ESP.wdtFeed(); | |
FastLED.show(); | |
// delay(wait); | |
} | |
} | |
// List of patterns to cycle through. Each is defined as a separate function below. | |
typedef void (*SimplePatternList[])(); | |
SimplePatternList gPatterns = {blur,pnoise,beatwave,cylon,ripple,rainbow1,ripple2,Twinkle,pattern2,juggle2,pattern3,bpm,fire}; | |
uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current | |
void nextPattern() | |
{ | |
// add one to the current pattern number, and wrap around at the end | |
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns); | |
} | |
void All() | |
{ | |
// Call the current pattern function once, updating the 'leds' array | |
gPatterns[gCurrentPatternNumber](); | |
EVERY_N_SECONDS( 30 ) { nextPattern(); } // change patterns periodically | |
} | |
// second list | |
// List of patterns to cycle through. Each is defined as a separate function below. | |
typedef void (*SimplePatternList[])(); | |
SimplePatternList qPatterns = {vu,vu2,Vu3,Vu4,Vu6,niko,vu7,vu8,vu9,vu10}; | |
//uint8_t qCurrentPatternNumber = 0; // Index number of which pattern is current | |
void nextPattern2() | |
{ | |
// add one to the current pattern number, and wrap around at the end | |
qCurrentPatternNumber = (qCurrentPatternNumber + 1) % ARRAY_SIZE( qPatterns); | |
} | |
void All2() | |
{ | |
// Call the current pattern function once, updating the 'leds' array | |
qPatterns[qCurrentPatternNumber](); | |
EVERY_N_SECONDS( 30 ) { nextPattern2(); } // change patterns periodically | |
} | |
//Niko | |
void fadeall() { for(int i = 0; i < N_PIXELS; i++) { leds[i].nscale8(250); } } | |
void cylon() { | |
static uint8_t hue = 0; | |
for(int i = 0; i < N_PIXELS; i++) { | |
leds[i] = CHSV(hue++, 255, 255); | |
fadeall(); | |
FastLED.delay(map(Speed,0,255,100,0)); | |
} | |
for(int i = (N_PIXELS)-1; i >= 0; i--) { | |
leds[i] = CHSV(hue++, 255, 255); | |
fadeall(); | |
FastLED.delay(map(Speed,0,255,100,0)); | |
} | |
ESP.wdtFeed(); | |
FastLED.show(); | |
} | |
void beatwave() { | |
EVERY_N_MILLISECONDS(map(Speed,0,255,100,25)) { | |
uint8_t maxChanges = 24; | |
nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges); // AWESOME palette blending capability. | |
} | |
EVERY_N_SECONDS(map(Speed,0,255,60,1)) { // Change the target palette to a random one every 5 seconds. | |
targetPalette = CRGBPalette16(CHSV(random8(), 255, random8(128,255)), CHSV(random8(), 255, random8(128,255)), CHSV(random8(), 192, random8(128,255)), CHSV(random8(), 255, random8(128,255))); | |
} | |
uint8_t wave1 = beatsin8(9, 0, 255); // That's the same as beatsin8(9); | |
uint8_t wave2 = beatsin8(8, 0, 255); | |
uint8_t wave3 = beatsin8(7, 0, 255); | |
uint8_t wave4 = beatsin8(6, 0, 255); | |
for (int i=0; i<N_PIXELS; i++) { | |
leds[i] = ColorFromPalette( currentPalette, i+wave1+wave2+wave3+wave4, 255, currentBlending); | |
} | |
FastLED.show(); | |
ESP.wdtFeed(); | |
} // beatwave() | |
void niko(){ | |
Vu4(); | |
vu(); | |
} // Niko()} | |
void pnoise(){ | |
uint8_t maxChanges = 48; | |
EVERY_N_MILLISECONDS(10) { | |
nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges); // Blend towards the target palette | |
fillnoise8(); // Update the LED array with noise at the new location | |
} | |
EVERY_N_SECONDS(map(Speed,0,255,300,5)) { // Change the target palette to a random one every N seconds. | |
targetPalette = CRGBPalette16(CHSV(random8(), 50, random8(20,255)), CHSV(random8(), 255, random8(5,128)), CHSV(random8(), 192, random8(50,100)), CHSV(random8(), 255, random8(128,255))); | |
dist = random16(1000); | |
} | |
LEDS.show(); // Display the LED's at every loop cycle. | |
ESP.wdtFeed(); | |
} // loop() | |
void fillnoise8() { | |
for(int i = 0; i < N_PIXELS; i++) { // Just ONE loop to fill up the LED array as all of the pixels change. | |
uint8_t index = inoise8(i*30, dist+i*30) % 255; // Get a value from the noise function. I'm using both x and y axis. | |
leds[i] = ColorFromPalette(currentPalette, index, 255, LINEARBLEND); // With that value, look up the 8 bit colour palette value and assign it to the current LED. | |
} | |
dist += beatsin8(3,1, 10); // Moving along the distance (that random number we started out with). Vary it a bit with a sine wave. | |
yield(); | |
} // fillnoise8() |
This file contains 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
//#include "./Javascript.h" | |
void buildWebsite() { | |
buildJavascript(); | |
//webSite = javaScript; | |
webSite = "<!DOCTYPE html>\n"; | |
webSite += "<html>\n"; | |
webSite += "<head>\n"; | |
webSite += "<meta charset='utf-8'>\n"; | |
webSite += "<meta name='viewport' content='width=device-width, initial-scale=1'>\n"; | |
webSite += "<title>LED CONTROL APP</title>\n"; | |
webSite += "<link rel='shortcut icon' href='http://forum.arduino.cc/favicon.ico'>\n"; | |
webSite += "<link rel='stylesheet' href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,700'>\n"; | |
webSite += "<link rel='stylesheet' href='http://demos.jquerymobile.com/1.4.5/css/themes/default/jquery.mobile-1.4.5.min.css'>\n"; | |
webSite += "<link rel='stylesheet' href='http://demos.jquerymobile.com/1.4.5/_assets/css/jqm-demos.css'>\n"; | |
webSite += "<script src='http://demos.jquerymobile.com/1.4.5/js/jquery.js'></script>\n"; | |
webSite += "<script src='http://demos.jquerymobile.com/1.4.5/_assets/js/index.js'></script>\n"; | |
webSite += "<script src='http://demos.jquerymobile.com/1.4.5/js/jquery.mobile-1.4.5.min.js'></script>\n"; | |
webSite += "</head>\n"; | |
webSite += "<style>\n"; | |
webSite += "#page {\n"; | |
webSite += "height: device-height;\n"; | |
webSite += "background: linear-gradient(to bottom , AliceBlue 0%,White 50%,Azure 100%);\n"; | |
webSite += "}\n"; | |
webSite += "input,select { background: linear-gradient(to bottom , Azure 0%,white 50%,AliceBlue 100%); }\n"; | |
webSite += "</style>\n"; | |
webSite += "<div data-role='page' id='page'>\n"; | |
webSite += "<body onload='process()'>\n"; | |
webSite += "<div class='ui-corner-all custom-corners style=text-align:center'>\n"; | |
webSite += "<div class='ui-bar ui-bar-a'>\n"; | |
webSite += "<h3>Led Control v.1.0b 20170609 (radiocheckboxes fixed ├┼─)</h3>\n"; | |
webSite += "</div>\n"; | |
webSite += "<select type='select' data-role='flipswitch' name='flip' id='flip' data-theme='a' data-inline='true' onchange='on1off()'>\n"; | |
webSite += "<option value='ON'>ON</option>\n"; | |
webSite += "<option value='OFF'>OFF</option>\n"; | |
webSite += "</select>\n"; | |
webSite += "<span id='udpvu'></span><br />\n"; | |
webSite += "<form action='#' method='get' id='modeform'>\n"; | |
webSite += "<div class='ui-field-contain'>\n"; | |
webSite += "<fieldset data-role='controlgroup' data-type='horizontal' content='width=device-width, initial-scale=1'>\n"; | |
webSite += "<input type='radio' name='radioName' id='VU' value='VU' onclick='VUselect()'>\n"; | |
webSite += "<label for='VU'>VU</label>\n"; | |
webSite += "<input type='radio' name='radioName' id='Static' value='Static' onclick='Statselect()'>\n"; | |
webSite += "<label for='Static'>Static</label>\n"; | |
webSite += "<input type='radio' name='radioName' id='Auto' value='Auto' onclick='Autoselect()'>\n"; | |
webSite += "<label for='Auto'>Auto</label>\n"; | |
webSite += "</fieldset>\n"; | |
webSite += "</div>\n"; | |
webSite += "<label for='select-choice' data-inline='true' >Preset:</label>\n"; | |
webSite += "<select name='select-choice' id='select-choice' data-mini='false' data-native-menu='true' data-inline='true' onchange='presetF()'>\n"; | |
webSite += "</select>\n"; | |
webSite += "</form>\n"; | |
webSite += "<script src='https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.min.js'></script>\n"; | |
webSite += "<div style='bold'>\n"; | |
webSite += "<input id=\"chcolor\" type=\"button\" class=\"jscolor {mode:'HVS',position:'bottom',onFineChange:'update(this)',width:300, height:150,borderColor:'#FFF', insetColor:'#FFF',backgroundColor:'#666'}\" data-type=\"inline\" data-theme=\"b\" value=\"Color\" style=\"border:10px solid gray;text-align:center\" />\n"; | |
webSite += "</div>\n"; | |
webSite += "<p id='rect' style='border:1px solid gray; width:device-width; height:100px;text-align:center'>\n"; | |
webSite += "<span id='rgbrect' ></span><br />\n"; | |
webSite += "RGB:<span id='rgbtext' ></span><br />\n"; | |
webSite += "<!-- toRGBString = <span id='rgb-str'></span><br />\n"; | |
webSite += "R, G, B = <span id='rgb'></span><br /> -->\n"; | |
webSite += "</p>\n"; | |
webSite += "<form id='sliderform'>\n"; | |
webSite += "<label for=\"slider-speed\">Speed:</label>\n"; | |
webSite += "<input type='range' data-type='range' data-highlight='true' id='slider-speed' min='0' max='255' step='1' value=" + String(Speed) + " ONINPUT='sliderS()' onchange='sliderS()'>\n"; | |
webSite += "<label for='slider-fade'>Fade:</label>\n"; | |
webSite += "<input type='range' data-type='range' data-highlight='true' id='slider-fade' min='0' max='255' step='1' value=" + String(BRIGHTNESS) + " ONINPUT='sliderF()' onchange='sliderF()'>\n"; | |
webSite += "</form>\n"; | |
webSite += javaScript; | |
webSite += "</div></div><!-- /page --></body></html>\n"; | |
// | |
} |
This file contains 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
String javaScript, XML, webSite; | |
void buildJavascript() { | |
javaScript = "<!-- AJAX ON CREATE -->\n"; | |
javaScript += "<script>\n"; | |
javaScript += "$( document ).on( \"pagecreate\", function() {\n"; | |
javaScript += "var rgbarray = [" + (String)rgbarray[0] + "," + (String)rgbarray[1] + "," + (String)rgbarray[2] + "];\n"; | |
javaScript += "var hexrgb = '#000080';\n"; | |
javaScript += "var flip1 = \"ON\";\n"; | |
//Select | |
javaScript += "var selectVU, fLen;\n"; | |
//javaScript += "var selectVU = \"Auto,vu, vu2, Vu3, Vu4, Vu5, Vu6, vu7, vu8, vu9, vu10,neshto drugo,Още Нещо\";\n"; | |
//javaScript += "var sVU = \"vu2\";\n"; | |
javaScript += "var selectVU = \"" + PresetArray + "\";\n"; | |
javaScript += "selectVU = selectVU.split(',');\n"; | |
javaScript += "fLen = selectVU.length;\n"; | |
javaScript += "text = \"\";\n"; | |
javaScript += "for (i = 0; i < fLen; i++) {\n"; | |
javaScript += "text += \"<option value='\" + selectVU[i] + \"'>\" + selectVU[i] + \"</option>\";\n"; | |
javaScript += "}\n"; | |
javaScript += "document.getElementById('select-choice').innerHTML = text;\n"; | |
javaScript += "$('#select-choice').val(\"" + Preset + "\");\n"; | |
javaScript += "$('#select-choice').selectmenu( \"refresh\" );\n"; | |
javaScript += "$('#flip').val(\"" + onoff + "\").flipswitch(\"refresh\");\n"; | |
javaScript += "$('#slider-speed').attr('value' ," + String(Speed) + ");\n"; | |
javaScript += "$('#slider-fade').attr('value' ," + String(BRIGHTNESS) + ").slider('refresh');\n"; | |
javaScript += "$('#rgbtext').text(\"" + (String)rgbarray[0] + "," + (String)rgbarray[1] + "," + (String)rgbarray[2] + "\");\n"; | |
javaScript += "$('#rect').css('background-color', 'rgb(" + String(Rval) + "," + String(Gval) + "," + String(Bval) + ")');\n"; | |
javaScript += "$('#udpvu').text(\"" + (String)Preset + "\");\n"; | |
javaScript += "$('#VU').prop('checked', " + String(vucheck) + ").checkboxradio(\"refresh\");\n"; | |
javaScript += "$('#Static').prop('checked', " + String(statcheck) + ").checkboxradio(\"refresh\");\n"; | |
javaScript += "$('#Auto').prop('checked', " + String(autocheck) + ").checkboxradio(\"refresh\");\n"; | |
javaScript += "});\n"; | |
javaScript += "</script>\n"; | |
javaScript += "<!-- AJAX ON CHANGE -->\n"; | |
javaScript += "<script>\n"; | |
javaScript += "$(\"#flip\").click(function() {\n"; | |
javaScript += "var flip1 = $(this).value\n"; | |
javaScript += "}); </script>\n"; | |
//COLOR PICKER | |
javaScript += "<script>\n"; | |
javaScript += "<!-- COLOR PICKER -->\n"; | |
javaScript += "function update(picker) {\n"; | |
javaScript += "var Rval = Math.round(picker.rgb[0]);\n"; | |
javaScript += "var Gval = Math.round(picker.rgb[1]);\n"; | |
javaScript += "var Bval = Math.round(picker.rgb[2]);\n"; | |
javaScript += "document.getElementById('rect').style.backgroundColor = '#' + picker;\n"; | |
javaScript += "var hexrgb = picker.toHEXString();\n"; | |
javaScript += "var rgbarray = [ Math.round(picker.rgb[0]) , Math.round(picker.rgb[1]) , Math.round(picker.rgb[2]) ];\n"; | |
javaScript += "document.getElementById('rgbtext').innerHTML = rgbarray;\n"; | |
//XMLHTTP COLORPICKER | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','SetRGB?r='+Rval+'&g='+Gval+'&b='+Bval,true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
javaScript += "</script>\n"; | |
//XMLHTTP | |
javaScript += "<SCRIPT>\n"; | |
javaScript += "xmlHttp=createXmlHttpObject();\n"; | |
javaScript += "function createXmlHttpObject(){\n"; | |
javaScript += " if(window.XMLHttpRequest){\n"; | |
javaScript += " xmlHttp=new XMLHttpRequest();\n"; | |
javaScript += " }else{\n"; | |
javaScript += " xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');\n"; | |
javaScript += " }\n"; | |
javaScript += " return xmlHttp;\n"; | |
javaScript += "}\n"; | |
javaScript += "function process(){\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.onreadystatechange=function(){\n"; | |
javaScript += " if(xmlHttp.readyState==4&&xmlHttp.status==200){\n"; | |
javaScript += " xmlDoc=xmlHttp.responseXML;\n"; | |
javaScript += " xmlmsg=xmlDoc.getElementsByTagName('rgbarray0')[0].firstChild.nodeValue;\n"; | |
javaScript += " xmlmsg+=\",\"\n"; | |
javaScript += " xmlmsg+=xmlDoc.getElementsByTagName('rgbarray1')[0].firstChild.nodeValue;\n"; | |
javaScript += " xmlmsg+=\",\"\n"; | |
javaScript += " xmlmsg+=xmlDoc.getElementsByTagName('rgbarray2')[0].firstChild.nodeValue;\n"; | |
javaScript += " document.getElementById('rgbtext').innerHTML=xmlmsg;\n"; | |
javaScript += " document.getElementById('rect').style.backgroundColor = 'rgb(xmlmsg)';\n"; | |
javaScript += " xmlmsg=xmlDoc.getElementsByTagName('fade')[0].firstChild.nodeValue;\n"; | |
javaScript += " document.getElementById('slider-fade').value=xmlmsg;\n"; | |
javaScript += " xmlmsg=xmlDoc.getElementsByTagName('speed')[0].firstChild.nodeValue;\n"; | |
javaScript += " document.getElementById('slider-speed').value=xmlmsg;\n"; | |
javaScript += " xmlmsg=xmlDoc.getElementsByTagName('preset')[0].firstChild.nodeValue;\n"; | |
javaScript += " document.getElementById('select-choice').value=xmlmsg;\n"; | |
javaScript += " xmlmsg=xmlDoc.getElementsByTagName('onoff')[0].firstChild.nodeValue;\n"; | |
javaScript += " document.getElementById('flip').value=xmlmsg;\n"; | |
//javaScript += " document.getElementById('rect').style.backgroundColor = 'rgb(" + String(Rval) + "," + String(Gval) + "," + String(Bval) + ")';\n"; | |
// javaScript += " for(i=0;i<" + (String)sliderMAX + ";i++){\n"; | |
// javaScript += " xmlmsg=xmlDoc.getElementsByTagName('rgbarray')[0].firstChild.nodeValue;\n"; | |
// javaScript += " document.getElementById('rgbarray').value=xmlmsg;\n"; | |
//javaScript += " document.getElementById('rgbarray').innerHTML=xmlmsg;\n"; | |
// javaScript += " xmlmsg=xmlDoc.getElementsByTagName('fade')[0].firstChild.nodeValue;\n"; | |
//javaScript += " document.getElementById('slider-fade').value=" + String(Fade)+ " ;\n"; | |
//javaScript += " }\n"; | |
javaScript += " }\n"; | |
javaScript += " }\n"; | |
javaScript += " xmlHttp.open('PUT','xml',true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += " setTimeout('process()',1000);\n"; | |
javaScript += "}\n"; | |
//FADE | |
javaScript += "function sliderF(){\n"; | |
javaScript += " sliderVal=document.getElementById('slider-fade').value;\n"; | |
javaScript += " document.getElementById('slider-fade').innerHTML=sliderVal;\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','Fade?f=' + sliderVal,true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
//SPEED | |
javaScript += "function sliderS(){\n"; | |
javaScript += " sliderVal=document.getElementById('slider-speed').value;\n"; | |
javaScript += " document.getElementById('slider-speed').innerHTML=sliderVal;\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','Speed?s=' + sliderVal,true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
//PRESET | |
javaScript += "function presetF(){\n"; | |
javaScript += " presetVal=document.getElementById('select-choice').value;\n"; | |
javaScript += " document.getElementById('select-choice').value=presetVal;\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','Preset?p=' + presetVal,true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
//ON1OFF | |
javaScript += "function on1off() {\n"; | |
javaScript += " onoff=document.getElementById('flip').value;\n"; | |
javaScript += " document.getElementById('select-choice').value=onoff;\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','flip?o=' + onoff,true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
//VUselect | |
javaScript += "function VUselect() {\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','Preset?p=AutoVu',true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
//Statselect | |
javaScript += "function Statselect() {\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','Preset?p=Static',true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
//Autoselect | |
javaScript += "function Autoselect() {\n"; | |
javaScript += " if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n"; | |
javaScript += " xmlHttp.open('PUT','Preset?p=AutoStat',true);\n"; | |
javaScript += " xmlHttp.send(null);\n"; | |
javaScript += " }\n"; | |
javaScript += "}\n"; | |
javaScript += "</SCRIPT>\n"; | |
} |
This file contains 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
#ifndef RGB_H_ | |
#define RGB_H_ | |
namespace ws2811 { | |
/** | |
* Type that holds RGB values. | |
* The in-memory order of this type is actually GRB, but the constructor takes | |
* its values in RGB order. | |
*/ | |
struct rgb | |
{ | |
rgb(uint8_t red, uint8_t green, uint8_t blue) | |
:green(green),red(red),blue(blue) | |
{} | |
rgb() | |
:green(0),red(0),blue(0) | |
{} | |
uint8_t green; | |
uint8_t red; | |
uint8_t blue; | |
}; | |
} | |
#endif /* RGB_H_ */ |
This file contains 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
#ifndef RGB_OPERATORS_HPP_ | |
#define RGB_OPERATORS_HPP_ | |
#include "rgb.h" | |
namespace ws2811 | |
{ | |
namespace detail { | |
inline uint8_t add_clipped( uint16_t left, uint16_t right) | |
{ | |
uint16_t result = left + right; | |
if (result > 255) result = 255; | |
return result; | |
} | |
} | |
inline void add_clipped( rgb &left, const rgb &right) | |
{ | |
using detail::add_clipped; | |
left = rgb( | |
add_clipped(left.red, right.red), | |
add_clipped( left.green, right.green), | |
add_clipped( left.blue, right.blue) | |
); | |
} | |
} | |
#endif /* RGB_OPERATORS_HPP_ */ |
This file contains 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
#ifndef WATER_TORTURE_HPP_ | |
#define WATER_TORTURE_HPP_ | |
#include "rgb_operators.h" | |
#include <Adafruit_NeoPixel.h> | |
#include <string.h> | |
namespace | |
{ | |
using ws2811::rgb; | |
uint8_t mult( uint8_t value, uint16_t multiplier) | |
{ | |
return (static_cast<uint16_t>( value) * multiplier) >> 8; | |
} | |
/// This class maintains the state and calculates the animations to render a falling water droplet | |
/// Objects of this class can have three states: | |
/// - inactive: this object does nothing | |
/// - swelling: the droplet is at the top of the led strip and swells in intensity | |
/// - falling: the droplet falls downwards and accelerates | |
/// - bouncing: the droplet has bounced of the ground. A smaller, less intensive droplet bounces up | |
/// while a part of the drop remains on the ground. | |
/// After going through the swelling, falling and bouncing phases, the droplet automatically returns to the | |
/// inactive state. | |
class droplet | |
{ | |
public: | |
droplet( const rgb &color, uint16_t gravity) | |
:color( color), position(0), speed(0), | |
gravity( gravity), state(swelling) | |
{} | |
droplet() | |
:color(0,0,0), position(0), speed(0), | |
gravity(0), state( inactive) | |
{ | |
} | |
/// calculate the next step in the animation for this droplet | |
void step( uint8_t maxpos) | |
{ | |
if (state == falling || state == bouncing) | |
{ | |
position += speed; | |
speed += gravity; | |
// if we hit the bottom... | |
const uint16_t maxpos16 = maxpos << 8; | |
if (position > maxpos16) | |
{ | |
if (state == bouncing) | |
{ | |
// this is the second collision, | |
// deactivate. | |
state = inactive; | |
} | |
else | |
{ | |
// reverse direction and dampen the speed | |
position = maxpos16 - (position - maxpos16); | |
speed = -speed/4; | |
color = scale( color, 10); | |
state = bouncing; | |
} | |
} | |
} | |
else if (state == swelling) | |
{ | |
++position; | |
if ( color.blue <= 10 || color.blue - position <= 10) | |
{ | |
state = falling; | |
position = 0; | |
} | |
} | |
} | |
/// perform one step and draw. | |
void step( rgb *leds, uint8_t ledcount, bool reverse) | |
{ | |
step( ledcount - 1); | |
draw( leds, ledcount - 1, reverse); | |
} | |
/// Draw the droplet on the led string | |
/// This will "smear" the light of this droplet between two leds. The closer | |
/// the droplets position is to that of a particular led, the brighter that | |
/// led will be | |
void draw( rgb *leds, uint8_t max_pos, bool reverse) | |
{ | |
if (state == falling || state == bouncing) | |
{ | |
uint8_t position8 = position >> 8; | |
uint8_t remainder = position; // get the lower bits | |
uint8_t last = max_pos; | |
uint8_t pos = position8; | |
uint8_t pos1 = position8+1; | |
if (reverse) | |
{ | |
last = 0; | |
pos = max_pos-position8; | |
pos1 = pos-1; | |
} | |
else | |
{ | |
last = max_pos; | |
pos = position8; | |
pos1 = pos+1; | |
} | |
add_clipped_to( leds[pos], scale( color, 256 - remainder )); | |
if (remainder) | |
{ | |
add_clipped_to( leds[pos1], scale( color, remainder)); | |
} | |
if (state == bouncing) | |
{ | |
add_clipped_to( leds[last], color); | |
} | |
} | |
else if (state == swelling) | |
{ | |
uint8_t first; | |
if (reverse) | |
{ | |
first = max_pos; | |
} | |
else | |
{ | |
first = 0; | |
} | |
add_clipped_to( leds[first], scale( color, position)); | |
} | |
} | |
bool is_active() const | |
{ | |
return state != inactive; | |
} | |
private: | |
/// Add two numbers and clip the result at 255. | |
static uint8_t add_clipped( uint16_t left, uint16_t right) | |
{ | |
uint16_t result = left + right; | |
if (result > 255) result = 255; | |
return result; | |
} | |
/// Add the right rgb value to the left one, clipping if necessary | |
static void add_clipped_to( rgb &left, const rgb &right) | |
{ | |
left.red = add_clipped(left.red, right.red); | |
left.green = add_clipped( left.green, right.green); | |
left.blue = add_clipped( left.blue, right.blue); | |
} | |
/// multiply an 8-bit value with an 8.8 bit fixed point number. | |
/// multiplier should not be higher than 1.00 (or 256). | |
static uint8_t mult( uint8_t value, uint16_t multiplier) | |
{ | |
return (static_cast<uint16_t>( value) * multiplier) >> 8; | |
} | |
/// scale an rgb value up or down. amplitude > 256 means scaling up, while | |
/// amplitude < 256 means scaling down. | |
static rgb scale(rgb value, uint16_t amplitude) | |
{ | |
return rgb( | |
mult( value.red, amplitude), | |
mult( value.green, amplitude), | |
mult( value.blue, amplitude) | |
); | |
} | |
// how much of a color is left when colliding with the floor, value | |
// between 0 and 256 where 256 means no loss. | |
static const uint16_t collision_scaling = 40; | |
rgb color; | |
uint16_t position; | |
int16_t speed; | |
uint16_t gravity; | |
enum stateval { | |
inactive, | |
swelling, | |
falling, | |
bouncing | |
}; | |
stateval state; | |
}; | |
uint8_t debugcount = 0; | |
volatile uint16_t random_scale() | |
{ | |
return (rand() % 256); | |
} | |
void create_random_droplet( droplet &d) | |
{ | |
d = droplet( | |
rgb( | |
mult( 100 ,random_scale()), | |
mult( 100, random_scale()), | |
mult(255, random_scale()) | |
), 5); | |
} | |
} | |
class WaterTorture | |
{ | |
public: | |
WaterTorture( Adafruit_NeoPixel *strip) | |
{ | |
this->strip = strip; | |
current_droplet = 0; // index of the next droplet to be created | |
droplet_pause = 1; // how long to wait for the next one | |
} | |
void animate (bool reverse) | |
{ | |
if (droplet_pause) | |
{ | |
--droplet_pause; | |
} | |
else | |
{ | |
if (!droplets[current_droplet].is_active()) | |
{ | |
create_random_droplet( droplets[current_droplet]); | |
++current_droplet; | |
if (current_droplet >= droplet_count) current_droplet = 0; | |
droplet_pause = 100 + rand() % 80; | |
} | |
} | |
rgb *leds = (rgb *)strip->getPixels(); | |
memset( leds, 0, strip->numPixels()*sizeof(rgb)); | |
for (uint8_t idx = 0; idx < droplet_count; ++idx) | |
{ | |
droplets[idx].step( leds, strip->numPixels(), reverse); | |
} | |
// for (uint8_t i = 0; i < strip->numPixels(); i++) | |
// { | |
// strip->setPixelColor(i, leds->red, leds->green, leds->blue); // overwrite with brightness | |
// leds++; | |
// } | |
} | |
private: | |
Adafruit_NeoPixel *strip; | |
static const uint8_t droplet_count = 4; | |
droplet droplets[droplet_count]; // droplets that can animate simultaneously. | |
uint8_t current_droplet; // index of the next droplet to be created | |
uint8_t droplet_pause; // how long to wait for the next one | |
}; | |
#endif /* WATER_TORTURE_HPP_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment