Lots of new effects!

This commit is contained in:
cschwinne 2020-06-06 00:57:34 +02:00
parent 7e01d113d8
commit 70c73d2e0e
7 changed files with 268 additions and 27 deletions

View File

@ -2,6 +2,13 @@
### Development versions after 0.10.0 release ### Development versions after 0.10.0 release
#### Build 2006060
- Added five effects by Andrew Tuline (Phased, Phased Noise, Sine, Noise Pal and Twinkleup)
- Added two new effects by Aircoookie (Sunrise and Flow)
- Added US-style sequence to traffic light effect
- Merged pull request #964 adding 9 key IR remote
#### Build 2005280 #### Build 2005280
- Added v2 usermod API - Added v2 usermod API

View File

@ -869,6 +869,7 @@ uint16_t WS2812FX::mode_traffic_light(void) {
if (now - SEGENV.step > mdelay) if (now - SEGENV.step > mdelay)
{ {
SEGENV.aux0++; SEGENV.aux0++;
if (SEGENV.aux0 == 1 && SEGMENT.intensity > 140) SEGENV.aux0 = 2; //skip Red + Amber, to get US-style sequence
if (SEGENV.aux0 > 3) SEGENV.aux0 = 0; if (SEGENV.aux0 > 3) SEGENV.aux0 = 0;
SEGENV.step = now; SEGENV.step = now;
} }
@ -3334,3 +3335,208 @@ uint16_t WS2812FX::mode_solid_glitter()
} }
return FRAMETIME; return FRAMETIME;
} }
/*
* Mode simulates a gradual sunrise
*/
uint16_t WS2812FX::mode_sunrise() {
//speed 0 - static sun
//speed 1 - 120: sunrise time in minutes
//speed 121 - 240 : sunset time in minutes - 120;
//speed above: "breathing" rise and set
if (SEGENV.call == 0 || SEGMENT.speed != SEGENV.aux0) {
SEGENV.step = millis(); //save starting time, millis() because now can change from sync
SEGENV.aux0 = SEGMENT.speed;
}
fill(0);
uint16_t stage = 0xFFFF;
uint32_t s10SinceStart = (millis() - SEGENV.step) /100; //tenths of seconds
if (SEGMENT.speed > 120) { //quick sunrise and sunset
uint16_t counter = (now >> 1) * (((SEGMENT.speed -120) >> 1) +1);
stage = triwave16(counter);
} else if (SEGMENT.speed) { //sunrise
uint8_t durMins = SEGMENT.speed;
if (durMins > 60) durMins -= 60;
uint32_t s10Target = durMins * 600;
if (s10SinceStart > s10Target) s10SinceStart = s10Target;
stage = map(s10SinceStart, 0, s10Target, 0, 0xFFFF);
if (SEGMENT.speed > 60) stage = 0xFFFF - stage; //sunset
}
for (uint16_t i = 0; i <= SEGLEN/2; i++)
{
//default palette is Fire
uint32_t c = color_from_palette(0, false, true, 255); //background
uint16_t wave = triwave16((i * stage) / SEGLEN);
wave = (wave >> 8) + ((wave * SEGMENT.intensity) >> 15);
if (wave > 240) { //clipped, full white sun
c = color_from_palette( 240, false, true, 255);
} else { //transition
c = color_from_palette(wave, false, true, 255);
}
setPixelColor(i, c);
setPixelColor(SEGLEN - i - 1, c);
}
return FRAMETIME;
}
/*
* Effects by Andrew Tuline
*/
uint16_t WS2812FX::phased_base(uint8_t moder) { // We're making sine waves here. By Andrew Tuline.
uint8_t allfreq = 16; // Base frequency.
//float* phasePtr = reinterpret_cast<float*>(SEGENV.step); // Phase change value gets calculated.
static float phase = 0;//phasePtr[0];
uint8_t cutOff = (255-SEGMENT.intensity); // You can change the number of pixels. AKA INTENSITY (was 192).
uint8_t modVal = 5;//SEGMENT.fft1/8+1; // You can change the modulus. AKA FFT1 (was 5).
uint8_t index = now/64; // Set color rotation speed
phase += SEGMENT.speed/32.0; // You can change the speed of the wave. AKA SPEED (was .4)
//phasePtr[0] = phase;
for (int i = 0; i < SEGLEN; i++) {
if (moder == 1) modVal = (inoise8(i*10 + i*10) /16); // Let's randomize our mod length with some Perlin noise.
uint16_t val = (i+1) * allfreq; // This sets the frequency of the waves. The +1 makes sure that leds[0] is used.
if (modVal == 0) modVal = 1;
val += phase * (i % modVal +1) /2; // This sets the varying phase change of the waves. By Andrew Tuline.
uint8_t b = cubicwave8(val); // Now we make an 8 bit sinewave.
b = (b > cutOff) ? (b - cutOff) : 0; // A ternary operator to cutoff the light.
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(index, false, false, 0), b));
index += 256 / SEGLEN;
}
return FRAMETIME;
}
uint16_t WS2812FX::mode_phased(void) {
return phased_base(0);
}
uint16_t WS2812FX::mode_phased_noise(void) {
return phased_base(1);
}
uint16_t WS2812FX::mode_twinkleup(void) { // A very short twinkle routine with fade-in and dual controls. By Andrew Tuline.
random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through.
for (int i = 0; i<SEGLEN; i++) {
uint8_t ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work.
uint8_t pixBri = sin8(ranstart + 16 * now/(256-SEGMENT.speed));
if (random8() > SEGMENT.intensity) pixBri = 0;
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i*20, false, PALETTE_SOLID_WRAP, 0), pixBri));
}
return FRAMETIME;
}
// Peaceful noise that's slow and with gradually changing palettes. Does not support WLED palettes or default colours or controls.
uint16_t WS2812FX::mode_noisepal(void) { // Slow noise palette by Andrew Tuline.
uint16_t scale = 15 + (SEGMENT.intensity >> 2); //default was 30
//#define scale 30
uint16_t dataSize = sizeof(CRGBPalette16) * 2; //allocate space for 2 Palettes
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
CRGBPalette16* palettes = reinterpret_cast<CRGBPalette16*>(SEGENV.data);
uint16_t changePaletteMs = 4000 + SEGMENT.speed *10; //between 4 - 6.5sec
if (millis() - SEGENV.step > changePaletteMs)
{
SEGENV.step = millis();
uint8_t baseI = random8();
palettes[1] = CRGBPalette16(CHSV(baseI+random8(64), 255, random8(128,255)), CHSV(baseI+128, 255, random8(128,255)), CHSV(baseI+random8(92), 192, random8(128,255)), CHSV(baseI+random8(92), 255, random8(128,255)));
}
CRGB color;
//EVERY_N_MILLIS(10) { //(don't have to time this, effect function is only called every 24ms)
nblendPaletteTowardPalette(palettes[0], palettes[1], 48); // Blend towards the target palette over 48 iterations.
if (SEGMENT.palette > 0) palettes[0] = currentPalette;
for(int i = 0; i < SEGLEN; i++) {
uint8_t index = inoise8(i*scale, SEGENV.aux0+i*scale); // Get a value from the noise function. I'm using both x and y axis.
color = ColorFromPalette(palettes[0], index, 255, LINEARBLEND); // Use the my own palette.
setPixelColor(i, color.red, color.green, color.blue);
}
SEGENV.aux0 += beatsin8(10,1,4); // Moving along the distance. Vary it a bit with a sine wave.
return FRAMETIME;
}
// Sine waves that have controllable phase change speed, frequency and cutoff. By Andrew Tuline.
// SEGMENT.speed ->Speed, SEGMENT.intensity -> Frequency (SEGMENT.fft1 -> Color change, SEGMENT.fft2 -> PWM cutoff)
//
uint16_t WS2812FX::mode_sinewave(void) { // Adjustable sinewave. By Andrew Tuline
//#define qsuba(x, b) ((x>b)?x-b:0) // Analog Unsigned subtraction macro. if result <0, then => 0
uint16_t colorIndex = now /32;//(256 - SEGMENT.fft1); // Amount of colour change.
SEGENV.step += SEGMENT.speed/16; // Speed of animation.
uint16_t freq = SEGMENT.intensity/4;//SEGMENT.fft2/8; // Frequency of the signal.
for (int i=0; i<SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows:
int pixBri = cubicwave8((i*freq)+SEGENV.step);//qsuba(cubicwave8((i*freq)+SEGENV.step), (255-SEGMENT.intensity)); // qsub sets a minimum value called thiscutoff. If < thiscutoff, then bright = 0. Otherwise, bright = 128 (as defined in qsub)..
//setPixCol(i, i*colorIndex/255, pixBri);
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i*colorIndex/255, false, PALETTE_SOLID_WRAP, 0), pixBri));
}
return FRAMETIME;
}
/*
* Best of both worlds from Palette and Spot effects. By Aircoookie
*/
uint16_t WS2812FX::mode_flow(void)
{
uint16_t counter = 0;
if (SEGMENT.speed != 0)
{
counter = now * ((SEGMENT.speed >> 2) +1);
counter = counter >> 8;
}
uint16_t maxZones = SEGLEN / 6; //only looks good if each zone has at least 6 LEDs
uint16_t zones = (SEGMENT.intensity * maxZones) >> 8;
if (zones & 0x01) zones++; //zones must be even
if (zones < 2) zones = 2;
uint16_t zoneLen = SEGLEN / zones;
uint16_t offset = (SEGLEN - zones * zoneLen) >> 1;
fill(color_from_palette(-counter, false, true, 255));
for (uint16_t z = 0; z < zones; z++)
{
uint16_t pos = offset + z * zoneLen;
for (uint16_t i = 0; i < zoneLen; i++)
{
uint8_t colorIndex = (i * 255 / zoneLen) - counter;
uint16_t led = (z & 0x01) ? i : (zoneLen -1) -i;
if (IS_REVERSE) led = (zoneLen -1) -led;
setPixelColor(pos + led, color_from_palette(colorIndex, false, true, 255));
}
}
return FRAMETIME;
}

View File

@ -98,7 +98,7 @@
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
#define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED ) #define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED )
#define MODE_COUNT 104 #define MODE_COUNT 111
#define FX_MODE_STATIC 0 #define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1 #define FX_MODE_BLINK 1
@ -204,6 +204,13 @@
#define FX_MODE_PACIFICA 101 #define FX_MODE_PACIFICA 101
#define FX_MODE_CANDLE_MULTI 102 #define FX_MODE_CANDLE_MULTI 102
#define FX_MODE_SOLID_GLITTER 103 #define FX_MODE_SOLID_GLITTER 103
#define FX_MODE_SUNRISE 104
#define FX_MODE_PHASED 105
#define FX_MODE_TWINKLEUP 106
#define FX_MODE_NOISEPAL 107
#define FX_MODE_SINEWAVE 108
#define FX_MODE_PHASEDNOISE 109
#define FX_MODE_FLOW 110
class WS2812FX { class WS2812FX {
typedef uint16_t (WS2812FX::*mode_ptr)(void); typedef uint16_t (WS2812FX::*mode_ptr)(void);
@ -396,6 +403,13 @@ class WS2812FX {
_mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica; _mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica;
_mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi; _mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi;
_mode[FX_MODE_SOLID_GLITTER] = &WS2812FX::mode_solid_glitter; _mode[FX_MODE_SOLID_GLITTER] = &WS2812FX::mode_solid_glitter;
_mode[FX_MODE_SUNRISE] = &WS2812FX::mode_sunrise;
_mode[FX_MODE_PHASED] = &WS2812FX::mode_phased;
_mode[FX_MODE_TWINKLEUP] = &WS2812FX::mode_twinkleup;
_mode[FX_MODE_NOISEPAL] = &WS2812FX::mode_noisepal;
_mode[FX_MODE_SINEWAVE] = &WS2812FX::mode_sinewave;
_mode[FX_MODE_PHASEDNOISE] = &WS2812FX::mode_phased_noise;
_mode[FX_MODE_FLOW] = &WS2812FX::mode_flow;
_brightness = DEFAULT_BRIGHTNESS; _brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black); currentPalette = CRGBPalette16(CRGB::Black);
@ -461,7 +475,7 @@ class WS2812FX {
uint32_t uint32_t
timebase, timebase,
color_wheel(uint8_t), color_wheel(uint8_t),
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255), color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255),
color_blend(uint32_t,uint32_t,uint8_t), color_blend(uint32_t,uint32_t,uint8_t),
gamma32(uint32_t), gamma32(uint32_t),
getLastShow(void), getLastShow(void),
@ -583,7 +597,14 @@ class WS2812FX {
mode_heartbeat(void), mode_heartbeat(void),
mode_pacifica(void), mode_pacifica(void),
mode_candle_multi(void), mode_candle_multi(void),
mode_solid_glitter(void); mode_solid_glitter(void),
mode_sunrise(void),
mode_phased(void),
mode_twinkleup(void),
mode_noisepal(void),
mode_sinewave(void),
mode_phased_noise(void),
mode_flow(void);
private: private:
NeoPixelWrapper *bus; NeoPixelWrapper *bus;
@ -630,7 +651,8 @@ class WS2812FX {
running(uint32_t, uint32_t), running(uint32_t, uint32_t),
tricolor_chase(uint32_t, uint32_t), tricolor_chase(uint32_t, uint32_t),
twinklefox_base(bool), twinklefox_base(bool),
spots_base(uint16_t); spots_base(uint16_t),
phased_base(uint8_t);
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat); CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff); CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff);
@ -669,7 +691,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst", "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow", "Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow",
"Heartbeat","Pacifica","Candle Multi", "Solid Glitter" "Heartbeat","Pacifica","Candle Multi", "Solid Glitter","Sunrise","Phased","Twinkleup","Noise Pal", "Sine","Phased Noise","Flow"
])====="; ])=====";

View File

@ -707,26 +707,28 @@ void WS2812FX::handle_palette(void)
_segment_index_palette_last = _segment_index; _segment_index_palette_last = _segment_index;
byte paletteIndex = SEGMENT.palette; byte paletteIndex = SEGMENT.palette;
if (SEGMENT.mode == FX_MODE_GLITTER && paletteIndex == 0) paletteIndex = 11; if (paletteIndex == 0) //default palette. Differs depending on effect
{
switch (SEGMENT.mode)
{
case FX_MODE_FIRE_2012 : paletteIndex = 35; break; //heat palette
case FX_MODE_COLORWAVES : paletteIndex = 26; break; //landscape 33
case FX_MODE_FILLNOISE8 : paletteIndex = 9; break; //ocean colors
case FX_MODE_NOISE16_1 : paletteIndex = 20; break; //Drywet
case FX_MODE_NOISE16_2 : paletteIndex = 43; break; //Blue cyan yellow
case FX_MODE_NOISE16_3 : paletteIndex = 35; break; //heat palette
case FX_MODE_NOISE16_4 : paletteIndex = 26; break; //landscape 33
case FX_MODE_GLITTER : paletteIndex = 11; break; //rainbow colors
case FX_MODE_SUNRISE : paletteIndex = 35; break; //heat palette
case FX_MODE_FLOW : paletteIndex = 6; break; //party
}
}
if (SEGMENT.mode >= FX_MODE_METEOR && paletteIndex == 0) paletteIndex = 4; if (SEGMENT.mode >= FX_MODE_METEOR && paletteIndex == 0) paletteIndex = 4;
switch (paletteIndex) switch (paletteIndex)
{ {
case 0: {//default palette. Differs depending on effect case 0: //default palette. Exceptions for specific effects above
switch (SEGMENT.mode) targetPalette = PartyColors_p; break;
{
case FX_MODE_FIRE_2012 : load_gradient_palette(22); break;//heat palette
case FX_MODE_COLORWAVES : load_gradient_palette(13); break;//landscape 33
case FX_MODE_FILLNOISE8 : targetPalette = OceanColors_p; break;
case FX_MODE_NOISE16_1 : load_gradient_palette(17); break;//Drywet
case FX_MODE_NOISE16_2 : load_gradient_palette(30); break;//Blue cyan yellow
case FX_MODE_NOISE16_3 : load_gradient_palette(22); break;//heat palette
case FX_MODE_NOISE16_4 : load_gradient_palette(13); break;//landscape 33
//case FX_MODE_GLITTER : targetPalette = RainbowColors_p; break;
default: targetPalette = PartyColors_p; break;//palette, bpm
}
break;}
case 1: {//periodically replace palette with a random one. Doesn't work with multiple FastLED segments case 1: {//periodically replace palette with a random one. Doesn't work with multiple FastLED segments
if (!singleSegmentMode) if (!singleSegmentMode)
{ {
@ -778,7 +780,7 @@ void WS2812FX::handle_palette(void)
case 12: //Rainbow stripe colors case 12: //Rainbow stripe colors
targetPalette = RainbowStripeColors_p; break; targetPalette = RainbowStripeColors_p; break;
default: //progmem palettes default: //progmem palettes
load_gradient_palette(SEGMENT.palette -13); load_gradient_palette(paletteIndex -13);
} }
if (singleSegmentMode && paletteFade) //only blend if just one segment uses FastLED mode if (singleSegmentMode && paletteFade) //only blend if just one segment uses FastLED mode

View File

@ -1,9 +1,11 @@
#include "wled.h" #include "wled.h"
/* /*
* This file allows you to add own functionality to WLED more easily * This v1 usermod file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h) * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
* bytes 2400+ are currently ununsed, but might be used for future wled features * If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
*
* Consider the v2 usermod API if you need a more advanced feature set!
*/ */
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) //Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2005280 #define VERSION 2006060
// ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS). // ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).

View File

@ -583,8 +583,10 @@ void loadSettingsFromEEPROM(bool first)
EEPROM.write(2550, DMXStartLED); EEPROM.write(2550, DMXStartLED);
#endif #endif
//user MOD memory //Usermod memory
//2944 - 3071 reserved //2551 - 2559 reserved for Usermods, usable by default
//2560 - 2943 usable, NOT reserved (need to increase EEPSIZE accordingly, new WLED core features may override this section)
//2944 - 3071 reserved for Usermods (need to increase EEPSIZE to 3072 in const.h)
overlayCurrent = overlayDefault; overlayCurrent = overlayDefault;