updated libraries
This commit is contained in:
parent
d5d5d000b3
commit
3b7e68065a
102 changed files with 3020 additions and 1624 deletions
|
|
@ -3,10 +3,31 @@
|
|||
/// @author Stefan Petrick
|
||||
/// @author Zach Vorhies (FastLED adaptation)
|
||||
///
|
||||
/// This sketch is fully compatible with the FastLED web compiler. To use it do the following:
|
||||
/// 1. Install Fastled: `pip install fastled`
|
||||
/// 2. cd into this examples page.
|
||||
/// 3. Run the FastLED web compiler at root: `fastled`
|
||||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
all the UI elements you see below.
|
||||
|
||||
|
||||
|
||||
OVERVIEW:
|
||||
This is the famouse Animartrix demo by Stefan Petrick. The effects are generated
|
||||
using polor polar coordinates. The effects are very complex and powerful.
|
||||
*/
|
||||
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Platform does not have enough memory
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -34,6 +55,10 @@ using namespace fl;
|
|||
|
||||
#define FIRST_ANIMATION POLAR_WAVES
|
||||
|
||||
// This is purely use for the web compiler to display the animartrix effects.
|
||||
// This small led was chosen because otherwise the bloom effect is too strong.
|
||||
#define LED_DIAMETER 0.15 // .15 cm or 1.5mm
|
||||
|
||||
|
||||
CRGB leds[NUM_LEDS];
|
||||
XYMap xyMap = XYMap::constructRectangularGrid(MATRIX_WIDTH, MATRIX_HEIGHT);
|
||||
|
|
@ -44,19 +69,33 @@ UIDescription description("Demo of the Animatrix effects. @author of fx is Stefa
|
|||
|
||||
UISlider brightness("Brightness", 255, 0, 255);
|
||||
UINumberField fxIndex("Animartrix - index", 0, 0, NUM_ANIMATIONS - 1);
|
||||
UINumberField colorOrder("Color Order", 0, 0, 5);
|
||||
UISlider timeSpeed("Time Speed", 1, -10, 10, .1);
|
||||
|
||||
Animartrix animartrix(xyMap, FIRST_ANIMATION);
|
||||
FxEngine fxEngine(NUM_LEDS);
|
||||
|
||||
|
||||
void setup() {
|
||||
auto screen_map = xyMap.toScreenMap();
|
||||
screen_map.setDiameter(.1);
|
||||
screen_map.setDiameter(LED_DIAMETER);
|
||||
FastLED.addLeds<WS2811, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS)
|
||||
.setCorrection(TypicalLEDStrip)
|
||||
.setScreenMap(screen_map);
|
||||
FastLED.setBrightness(brightness);
|
||||
fxEngine.addFx(animartrix);
|
||||
|
||||
colorOrder.onChanged([](int value) {
|
||||
switch(value) {
|
||||
case 0: value = RGB; break;
|
||||
case 1: value = RBG; break;
|
||||
case 2: value = GRB; break;
|
||||
case 3: value = GBR; break;
|
||||
case 4: value = BRG; break;
|
||||
case 5: value = BGR; break;
|
||||
}
|
||||
animartrix.setColorOrder(static_cast<EOrder>(value));
|
||||
});
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
@ -72,3 +111,4 @@ void loop() {
|
|||
}
|
||||
|
||||
|
||||
#endif // __AVR__
|
||||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
@ -11,6 +16,14 @@ all the UI elements you see below.
|
|||
#include <Arduino.h>
|
||||
#include <FastLED.h>
|
||||
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Platform does not have enough memory
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
|
||||
|
||||
#include "fl/audio.h"
|
||||
#include "fl/downscale.h"
|
||||
#include "fl/draw_visitor.h"
|
||||
|
|
@ -21,9 +34,11 @@ all the UI elements you see below.
|
|||
#include "fl/time_alpha.h"
|
||||
#include "fl/ui.h"
|
||||
#include "fl/xypath.h"
|
||||
#include "fx.h"
|
||||
#include "fl/unused.h"
|
||||
#include "fx_audio.h"
|
||||
#include "fx/time.h"
|
||||
|
||||
|
||||
// Sketch.
|
||||
#include "fl/function.h"
|
||||
|
||||
|
|
@ -34,6 +49,7 @@ using namespace fl;
|
|||
#define NUM_LEDS ((WIDTH) * (HEIGHT))
|
||||
#define IS_SERPINTINE false
|
||||
#define TIME_ANIMATION 1000 // ms
|
||||
#define PIN_DATA 3
|
||||
|
||||
UITitle title("Simple control of an xy path");
|
||||
UIDescription description("This is more of a test for new features.");
|
||||
|
|
@ -106,7 +122,7 @@ void setup() {
|
|||
audioFadeTracker.setOutputTime(value);
|
||||
FASTLED_WARN("Output time seconds: " << value);
|
||||
});
|
||||
FastLED.addLeds<NEOPIXEL, 2>(leds, ledsXY.getTotal())
|
||||
FastLED.addLeds<NEOPIXEL, PIN_DATA>(leds, ledsXY.getTotal())
|
||||
.setScreenMap(screenmap);
|
||||
}
|
||||
|
||||
|
|
@ -144,10 +160,6 @@ void loop() {
|
|||
if (triggered) {
|
||||
FASTLED_WARN("Triggered");
|
||||
}
|
||||
// fl::clear(framebuffer);
|
||||
// fl::clear(framebuffer);
|
||||
|
||||
static uint32_t frame = 0;
|
||||
|
||||
// x = pointX.as_int();
|
||||
y = HEIGHT / 2;
|
||||
|
|
@ -164,6 +176,7 @@ void loop() {
|
|||
soundLevelMeter.processBlock(sample.pcm());
|
||||
// FASTLED_WARN("")
|
||||
auto dbfs = soundLevelMeter.getDBFS();
|
||||
FASTLED_UNUSED(dbfs);
|
||||
// FASTLED_WARN("getDBFS: " << dbfs);
|
||||
int32_t max = 0;
|
||||
for (int i = 0; i < sample.pcm().size(); ++i) {
|
||||
|
|
@ -187,6 +200,7 @@ void loop() {
|
|||
|
||||
if (enableFFT) {
|
||||
auto max_x = fftOut.bins_raw.size() - 1;
|
||||
FASTLED_UNUSED(max_x);
|
||||
for (int i = 0; i < fftOut.bins_raw.size(); ++i) {
|
||||
auto x = i;
|
||||
auto v = fftOut.bins_db[i];
|
||||
|
|
@ -232,3 +246,5 @@ void loop() {
|
|||
|
||||
FastLED.show();
|
||||
}
|
||||
|
||||
#endif // __AVR__
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
#include "fl/time_alpha.h"
|
||||
#include "fl/math_macros.h"
|
||||
|
||||
/// Tracks a smoothed peak with attack, decay, and output-inertia time-constants.
|
||||
class MaxFadeTracker {
|
||||
|
|
@ -34,8 +32,8 @@ public:
|
|||
// 1) block peak
|
||||
float peak = 0.0f;
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
float v = std::abs(samples[i]) * (1.0f/32768.0f);
|
||||
peak = std::max(peak, v);
|
||||
float v = ABS(samples[i]) * (1.0f/32768.0f);
|
||||
peak = MAX(peak, v);
|
||||
}
|
||||
|
||||
// 2) time delta
|
||||
|
|
@ -43,15 +41,15 @@ public:
|
|||
|
||||
// 3) update currentLevel_ with attack/decay
|
||||
if (peak > currentLevel_) {
|
||||
float riseFactor = 1.0f - std::exp(-attackRate_ * dt);
|
||||
float riseFactor = 1.0f - exp(-attackRate_ * dt);
|
||||
currentLevel_ += (peak - currentLevel_) * riseFactor;
|
||||
} else {
|
||||
float decayFactor = std::exp(-decayRate_ * dt);
|
||||
float decayFactor = exp(-decayRate_ * dt);
|
||||
currentLevel_ *= decayFactor;
|
||||
}
|
||||
|
||||
// 4) output inertia: smooth smoothedOutput_ → currentLevel_
|
||||
float outFactor = 1.0f - std::exp(-outputRate_ * dt);
|
||||
float outFactor = 1.0f - exp(-outputRate_ * dt);
|
||||
smoothedOutput_ += (currentLevel_ - smoothedOutput_) * outFactor;
|
||||
|
||||
return smoothedOutput_;
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
|
||||
#if defined(__AVR__) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RP2350) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_TEENSYLC)
|
||||
// Avr is not powerful enough.
|
||||
// Platform does not have enough memory
|
||||
// Other platforms have weird issues. Will revisit this later.
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
|
|
|
|||
18
libraries/FastLED/examples/CompileTest/CompileTest.ino
Normal file
18
libraries/FastLED/examples/CompileTest/CompileTest.ino
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include "FastLED.h"
|
||||
|
||||
#if defined(__AVR__)
|
||||
#include "avr_test.h"
|
||||
#elif defined(ESP32)
|
||||
#include "esp_test.h"
|
||||
#endif
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Setup");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println("Loop");
|
||||
delay(100);
|
||||
}
|
||||
13
libraries/FastLED/examples/CompileTest/avr_test.h
Normal file
13
libraries/FastLED/examples/CompileTest/avr_test.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "FastLED.h"
|
||||
|
||||
void avr_tests() {
|
||||
#if FASTLED_USE_PROGMEM != 1
|
||||
#error "FASTLED_USE_PROGMEM is not 1 for AVR"
|
||||
#endif
|
||||
|
||||
#if SKETCH_HAS_LOTS_OF_MEMORY != 0
|
||||
#error "SKETCH_HAS_LOTS_OF_MEMORY is not 0 for AVR"
|
||||
#endif
|
||||
}
|
||||
13
libraries/FastLED/examples/CompileTest/esp_8266_test.h
Normal file
13
libraries/FastLED/examples/CompileTest/esp_8266_test.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "FastLED.h"
|
||||
|
||||
void esp_8266_tests() {
|
||||
#if FASTLED_USE_PROGMEM != 1
|
||||
#error "FASTLED_USE_PROGMEM is not 1 for AVR"
|
||||
#endif
|
||||
|
||||
#if SKETCH_HAS_LOTS_OF_MEMORY != 0
|
||||
#error "SKETCH_HAS_LOTS_OF_MEMORY is not 0 for AVR"
|
||||
#endif
|
||||
}
|
||||
13
libraries/FastLED/examples/CompileTest/esp_s3_test.h
Normal file
13
libraries/FastLED/examples/CompileTest/esp_s3_test.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "FastLED.h"
|
||||
|
||||
void esp32_s3_tests() {
|
||||
#if FASTLED_USE_PROGMEM != 0
|
||||
#error "FASTLED_USE_PROGMEM prog memory is turned on for esap32-s3"
|
||||
#endif
|
||||
|
||||
#if SKETCH_HAS_LOTS_OF_MEMORY == 0
|
||||
#error "SKETCH_HAS_LOTS_OF_MEMORY should have lots of memory for esp32-s3"
|
||||
#endif
|
||||
}
|
||||
10
libraries/FastLED/examples/CompileTest/esp_test.h
Normal file
10
libraries/FastLED/examples/CompileTest/esp_test.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include "esp_8266_test.h"
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#include "esp_s3_test.h"
|
||||
#endif
|
||||
134
libraries/FastLED/examples/Corkscrew/Corkscrew.h
Normal file
134
libraries/FastLED/examples/Corkscrew/Corkscrew.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
Basic cork screw test.
|
||||
|
||||
This test is forward mapping, in which we test that
|
||||
the corkscrew is mapped to cylinder cartesian coordinates.
|
||||
|
||||
Most of the time, you'll want the reverse mapping, that is
|
||||
drawing to a rectangular grid, and then mapping that to a corkscrew.
|
||||
|
||||
However, to make sure the above mapping works correctly, we have
|
||||
to test that the forward mapping works correctly first.
|
||||
|
||||
*/
|
||||
|
||||
#include "fl/assert.h"
|
||||
#include "fl/corkscrew.h"
|
||||
#include "fl/grid.h"
|
||||
#include "fl/leds.h"
|
||||
#include "fl/screenmap.h"
|
||||
#include "fl/sstream.h"
|
||||
#include "fl/warn.h"
|
||||
#include "noise.h"
|
||||
#include <FastLED.h>
|
||||
// #include "vec3.h"
|
||||
|
||||
using namespace fl;
|
||||
|
||||
#define PIN_DATA 9
|
||||
|
||||
#define NUM_LEDS 288
|
||||
#define CORKSCREW_TOTAL_LENGTH 100
|
||||
#define CORKSCREW_TOTAL_HEIGHT 23.25 // when height = 0, it's a circle.
|
||||
// wrapped up over 19 turns
|
||||
#define CORKSCREW_TURNS 19 // Default to 19 turns
|
||||
|
||||
// #define CM_BETWEEN_LEDS 1.0 // 1cm between LEDs
|
||||
// #define CM_LED_DIAMETER 0.5 // 0.5cm LED diameter
|
||||
|
||||
UITitle festivalStickTitle("Corkscrew");
|
||||
UIDescription festivalStickDescription(
|
||||
"Tests the ability to map a cork screw onto a 2D cylindrical surface");
|
||||
|
||||
UISlider speed("Speed", 0.1f, 0.01f, 1.0f, 0.01f);
|
||||
|
||||
UICheckbox allWhite("All White", false);
|
||||
UICheckbox splatRendering("Splat Rendering", true);
|
||||
|
||||
// CRGB leds[NUM_LEDS];
|
||||
|
||||
// Tested on a 288 led (2x 144 max density led strip) with 19 turns
|
||||
// with 23.25cm height, 19 turns, and ~15.5 LEDs per turn.
|
||||
Corkscrew::Input corkscrewInput(CORKSCREW_TOTAL_LENGTH, CORKSCREW_TOTAL_HEIGHT,
|
||||
CORKSCREW_TURNS, // Default to 19 turns
|
||||
NUM_LEDS, // Default to dense 144 leds.
|
||||
0 // offset to account for gaps between segments
|
||||
);
|
||||
|
||||
// Corkscrew::State corkscrewMap = fl::Corkscrew::generateMap(corkscrewInput);
|
||||
Corkscrew corkscrew(corkscrewInput);
|
||||
|
||||
// Create a corkscrew with:
|
||||
// - 30cm total length (300mm)
|
||||
// - 5cm width (50mm)
|
||||
// - 2mm LED inner diameter
|
||||
// - 24 LEDs per turn
|
||||
// fl::ScreenMap screenMap = makeCorkScrew(NUM_LEDS,
|
||||
// 300.0f, 50.0f, 2.0f, 24.0f);
|
||||
|
||||
// fl::vector<vec3f> mapCorkScrew = makeCorkScrew(args);
|
||||
fl::ScreenMap screenMap;
|
||||
fl::Grid<CRGB> frameBuffer;
|
||||
|
||||
void setup() {
|
||||
int width = corkscrew.cylinder_width();
|
||||
int height = corkscrew.cylinder_height();
|
||||
|
||||
frameBuffer.reset(width, height);
|
||||
XYMap xyMap = XYMap::constructRectangularGrid(width, height, 0);
|
||||
|
||||
CRGB *leds = frameBuffer.data();
|
||||
size_t num_leds = frameBuffer.size();
|
||||
|
||||
CLEDController *controller =
|
||||
&FastLED.addLeds<WS2812, 3, BGR>(leds, num_leds);
|
||||
|
||||
fl::ScreenMap screenMap = xyMap.toScreenMap();
|
||||
screenMap.setDiameter(.2f);
|
||||
|
||||
// Set the screen map for the controller
|
||||
controller->setScreenMap(screenMap);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
fl::clear(frameBuffer);
|
||||
static float pos = 0;
|
||||
pos += speed.value();
|
||||
if (pos > corkscrew.size() - 1) {
|
||||
pos = 0; // Reset to the beginning
|
||||
}
|
||||
|
||||
if (allWhite) {
|
||||
for (size_t i = 0; i < frameBuffer.size(); ++i) {
|
||||
frameBuffer.data()[i] = CRGB(8, 8, 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (splatRendering) {
|
||||
Tile2x2_u8_wrap pos_tile = corkscrew.at_wrap(pos);
|
||||
const CRGB color = CRGB::Blue;
|
||||
// Draw each pixel in the 2x2 tile using the new wrapping API
|
||||
for (int dx = 0; dx < 2; ++dx) {
|
||||
for (int dy = 0; dy < 2; ++dy) {
|
||||
auto data = pos_tile.at(dx, dy);
|
||||
vec2i16 wrapped_pos = data.first; // Already wrapped position
|
||||
uint8_t alpha = data.second; // Alpha value
|
||||
|
||||
if (alpha > 0) { // Only draw if there's some alpha
|
||||
CRGB c = color;
|
||||
c.nscale8(alpha); // Scale the color by the alpha value
|
||||
frameBuffer.at(wrapped_pos.x, wrapped_pos.y) = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// None splat rendering, looks aweful.
|
||||
vec2f pos_vec2f = corkscrew.at_exact(pos);
|
||||
vec2i16 pos_i16 = vec2i16(round(pos_vec2f.x), round(pos_vec2f.y));
|
||||
// Now map the cork screw position to the cylindrical buffer that we
|
||||
// will draw.
|
||||
frameBuffer.at(pos_i16.x, pos_i16.y) =
|
||||
CRGB::Blue; // Draw a blue pixel at (w, h)
|
||||
}
|
||||
FastLED.show();
|
||||
}
|
||||
11
libraries/FastLED/examples/Corkscrew/Corkscrew.ino
Normal file
11
libraries/FastLED/examples/Corkscrew/Corkscrew.ino
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#include <FastLED.h> // Main FastLED library for controlling LEDs
|
||||
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Don't compile this for AVR microcontrollers (like Arduino Uno) because they typically
|
||||
// don't have enough memory to handle this complex animation.
|
||||
// Instead, we provide empty setup/loop functions so the sketch will compile but do nothing.
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else // For all other platforms with more memory (ESP32, Teensy, etc.)
|
||||
#include "Corkscrew.h"
|
||||
#endif // End of the non-AVR code section
|
||||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
@ -11,6 +16,7 @@ all the UI elements you see below.
|
|||
#include <Arduino.h>
|
||||
#include <FastLED.h>
|
||||
|
||||
#include "fl/downscale.h"
|
||||
#include "fl/draw_visitor.h"
|
||||
#include "fl/math_macros.h"
|
||||
#include "fl/raster.h"
|
||||
|
|
@ -18,7 +24,6 @@ all the UI elements you see below.
|
|||
#include "fl/ui.h"
|
||||
#include "fl/xypath.h"
|
||||
#include "fx/time.h"
|
||||
#include "fl/bilinear_compression.h"
|
||||
|
||||
// Sketch.
|
||||
#include "src/wave.h"
|
||||
|
|
@ -32,10 +37,11 @@ using namespace fl;
|
|||
#define TIME_ANIMATION 1000 // ms
|
||||
|
||||
CRGB leds[NUM_LEDS];
|
||||
CRGB leds_downscaled[NUM_LEDS / 4]; // Downscaled buffer
|
||||
CRGB leds_downscaled[NUM_LEDS / 4]; // Downscaled buffer
|
||||
|
||||
XYMap xyMap(WIDTH, HEIGHT, false);
|
||||
XYMap xyMap_Dst(WIDTH / 2, HEIGHT / 2, false); // Framebuffer is regular rectangle LED matrix.
|
||||
XYMap xyMap_Dst(WIDTH / 2, HEIGHT / 2,
|
||||
false); // Framebuffer is regular rectangle LED matrix.
|
||||
// XYPathPtr shape = XYPath::NewRosePath(WIDTH, HEIGHT);
|
||||
|
||||
// Speed up writing to the super sampled waveFx by writing
|
||||
|
|
@ -44,7 +50,6 @@ XYMap xyMap_Dst(WIDTH / 2, HEIGHT / 2, false); // Framebuffer is regular rectang
|
|||
WaveEffect wave_fx; // init in setup().
|
||||
fl::vector<XYPathPtr> shapes = CreateXYPaths(WIDTH, HEIGHT);
|
||||
|
||||
|
||||
XYRaster raster(WIDTH, HEIGHT);
|
||||
TimeWarp time_warp;
|
||||
|
||||
|
|
@ -77,12 +82,12 @@ void setupUiCallbacks() {
|
|||
maxAnimation.onChanged(
|
||||
[](float value) { shapeProgress.set_max_clamp(maxAnimation.value()); });
|
||||
|
||||
trigger.onChanged([]() {
|
||||
trigger.onClicked([]() {
|
||||
// shapeProgress.trigger(millis());
|
||||
FASTLED_WARN("Trigger pressed");
|
||||
});
|
||||
useWaveFx.onChanged([](bool on) {
|
||||
if (on) {
|
||||
useWaveFx.onChanged([](fl::UICheckbox &checkbox) {
|
||||
if (checkbox.value()) {
|
||||
FASTLED_WARN("WaveFX enabled");
|
||||
} else {
|
||||
FASTLED_WARN("WaveFX disabled");
|
||||
|
|
@ -94,7 +99,8 @@ void setup() {
|
|||
Serial.begin(115200);
|
||||
auto screenmap = xyMap.toScreenMap();
|
||||
screenmap.setDiameter(.2);
|
||||
FastLED.addLeds<NEOPIXEL, 2>(leds, xyMap.getTotal()).setScreenMap(screenmap);
|
||||
FastLED.addLeds<NEOPIXEL, 2>(leds, xyMap.getTotal())
|
||||
.setScreenMap(screenmap);
|
||||
auto screenmap2 = xyMap_Dst.toScreenMap();
|
||||
screenmap.setDiameter(.5);
|
||||
screenmap2.addOffsetY(-HEIGHT / 2);
|
||||
|
|
@ -142,9 +148,6 @@ void loop() {
|
|||
s_prev_alpha = curr_alpha;
|
||||
}
|
||||
|
||||
const bool is_active =
|
||||
true || curr_alpha < maxAnimation.value() && curr_alpha > 0.0f;
|
||||
|
||||
static uint32_t frame = 0;
|
||||
frame++;
|
||||
clearLeds();
|
||||
|
|
@ -171,9 +174,6 @@ void loop() {
|
|||
}
|
||||
uint8_t alpha =
|
||||
fl::map_range<uint8_t>(i, 0.0f, number_of_steps - 1, 64, 255);
|
||||
if (!is_active) {
|
||||
alpha = 0;
|
||||
}
|
||||
Tile2x2_u8 subpixel = shape->at_subpixel(a);
|
||||
subpixel.scale(alpha);
|
||||
// subpixels.push_back(subpixel);
|
||||
|
|
@ -182,8 +182,7 @@ void loop() {
|
|||
|
||||
s_prev_alpha = curr_alpha;
|
||||
|
||||
|
||||
if (useWaveFx && is_active) {
|
||||
if (useWaveFx) {
|
||||
DrawRasterToWaveSimulator draw_wave_fx(&wave_fx);
|
||||
raster.draw(xyMap, draw_wave_fx);
|
||||
} else {
|
||||
14
libraries/FastLED/examples/Downscale/Downscale.ino
Normal file
14
libraries/FastLED/examples/Downscale/Downscale.ino
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include <FastLED.h>
|
||||
|
||||
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Platform does not have enough memory
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "Downscale.h"
|
||||
|
||||
#endif // SKETCH_HAS_LOTS_OF_MEMORY
|
||||
|
|
@ -22,7 +22,7 @@ struct WaveEffect {
|
|||
|
||||
struct DrawRasterToWaveSimulator {
|
||||
DrawRasterToWaveSimulator(WaveEffect* wave_fx) : mWaveFx(wave_fx) {}
|
||||
void draw(const vec2<int> &pt, uint32_t index, uint8_t value) {
|
||||
void draw(const vec2<int16_t> &pt, uint32_t index, uint8_t value) {
|
||||
float valuef = value / 255.0f;
|
||||
int xx = pt.x;
|
||||
int yy = pt.y;
|
||||
|
|
@ -3,60 +3,40 @@
|
|||
/// The Yves ESP32_S3 I2S driver is a driver that uses the I2S peripheral on the ESP32-S3 to drive leds.
|
||||
/// Originally from: https://github.com/hpwit/I2SClockLessLedDriveresp32s3
|
||||
///
|
||||
///
|
||||
/// This is an advanced driver. It has certain ramifications.
|
||||
/// - You probably aren't going to be able to use this in ArduinoIDE, because ArduinoIDE does not allow you to put in the necessary build flags.
|
||||
/// You will need to use PlatformIO to build this.
|
||||
/// - These flags enable PSRAM.
|
||||
/// - Once flashed, the ESP32-S3 might NOT want to be reprogrammed again. To get around
|
||||
/// this hold the reset button and release when the flash tool is looking for an
|
||||
/// an upload port.
|
||||
/// - Put a delay in the setup function. This is to make it easier to flash the device.
|
||||
/// - Put a delay in the setup function. This is to make it easier to flash the device during developement.
|
||||
/// - Serial output will mess up the DMA controller. I'm not sure why this is happening
|
||||
/// but just be aware of it. If your device suddenly stops works, remove the printfs and see if that fixes the problem.
|
||||
/// - You MUST use all the available PINS specified in this demo. Anything less than that will cause FastLED to crash.
|
||||
/// - Certain leds will turn white in debug mode. Probably has something to do with timing.
|
||||
/// but just be aware of it. If your device suddenly stops working, remove the printfs and see if that fixes the problem.
|
||||
///
|
||||
/// Is RGBW supported? Yes.
|
||||
///
|
||||
/// Is Overclocking supported? No.
|
||||
/// Is Overclocking supported? Yes. Use this to bend the timeings to support other WS281X variants. Fun fact, just overclock the
|
||||
/// chipset until the LED starts working.
|
||||
///
|
||||
/// What about the new WS2812-5VB leds? Kinda. We put in a hack to add the extra wait time of 300 uS.
|
||||
/// What about the new WS2812-5VB leds? Yes, they have 250us timing.
|
||||
///
|
||||
/// What are the advantages of using the FastLED bindings over the raw driver?
|
||||
/// - FastLED api is more user friendly since you don't have to combine all your leds into one rectangular block.
|
||||
/// - FastLED api allows you to have different sized strips which will be upscaled to the largest strip internally.
|
||||
///
|
||||
/// What are the advantages of using the raw driver over the FastLED bindings?
|
||||
/// - The raw driver uses less memory because it doesn't have a frame buffer copy.
|
||||
/// Why use this?
|
||||
/// Raw YVes driver needs a perfect parallel rectacngle buffer for operation. In this code we've provided FastLED
|
||||
/// type bindings.
|
||||
///
|
||||
// ArduinoIDE
|
||||
// Should already be enabled.
|
||||
//
|
||||
// PLATFORMIO BUILD FLAGS:
|
||||
// Define your platformio.ini like so:
|
||||
//
|
||||
// PlatformIO
|
||||
// [env:esp32s3]
|
||||
// platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip
|
||||
// platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip
|
||||
// framework = arduino
|
||||
// board = seeed_xiao_esp32s3
|
||||
// build_flags =
|
||||
// ${env:generic-esp.build_flags}
|
||||
// -DBOARD_HAS_PSRAM
|
||||
// -mfix-esp32-psram-cache-issue
|
||||
// -mfix-esp32-psram-cache-strategy=memw
|
||||
// board_build.partitions = huge_app.csv
|
||||
//
|
||||
// Then in your setup function you are going to want to call psramInit();
|
||||
//
|
||||
// Want to get a contributor badge for FastLED? This driver has only been lightly tested.
|
||||
// There are certain open questions:
|
||||
// - Can the pins order for the strips be changed? (the pins can be defined arbitrarily,Tested on esp32s3, esp32duino version 3.2.0)
|
||||
// - Are there some combination of pins that can be ommitted?
|
||||
// - What other caveats are there?
|
||||
//
|
||||
// If you know the answer to these questions then please submit a PR to the FastLED repo and
|
||||
// we will update the information for the community.
|
||||
|
||||
#include <esp_psram.h>
|
||||
|
||||
#define FASTLED_USES_ESP32S3_I2S
|
||||
#define FASTLED_USES_ESP32S3_I2S // Must define this before including FastLED.h
|
||||
|
||||
#include "FastLED.h"
|
||||
#include "fl/assert.h"
|
||||
|
|
@ -66,6 +46,8 @@
|
|||
#define NUM_LEDS_PER_STRIP 256
|
||||
#define NUM_LEDS (NUM_LEDS_PER_STRIP * NUMSTRIPS)
|
||||
|
||||
// Note that you can use less strips than this.
|
||||
|
||||
#define EXAMPLE_PIN_NUM_DATA0 19 // B0
|
||||
#define EXAMPLE_PIN_NUM_DATA1 45 // B1
|
||||
#define EXAMPLE_PIN_NUM_DATA2 21 // B2
|
||||
|
|
@ -84,8 +66,9 @@
|
|||
#define EXAMPLE_PIN_NUM_DATA15 18 // R4
|
||||
|
||||
|
||||
const bool gUseFastLEDApi = true; // Set this to false to use the raw driver.
|
||||
|
||||
// Users say you can use a lot less strips. Experiment around and find out!
|
||||
// Please comment at reddit.com/r/fastled and let us know if you have problems.
|
||||
// Or send us a picture of your Triumps!
|
||||
int PINS[] = {
|
||||
EXAMPLE_PIN_NUM_DATA0,
|
||||
EXAMPLE_PIN_NUM_DATA1,
|
||||
|
|
@ -105,10 +88,9 @@ int PINS[] = {
|
|||
EXAMPLE_PIN_NUM_DATA15
|
||||
};
|
||||
|
||||
fl::InternalI2SDriver *driver = nullptr;
|
||||
CRGB leds[NUM_LEDS];
|
||||
|
||||
void setup_i2s_using_fastled_api() {
|
||||
void setup_i2s() {
|
||||
// Note, in this case we are using contingious memory for the leds. But this is not required.
|
||||
// Each strip can be a different size and the FastLED api will upscale the smaller strips to the largest strip.
|
||||
FastLED.addLeds<WS2812, EXAMPLE_PIN_NUM_DATA0, GRB>(
|
||||
|
|
@ -159,15 +141,13 @@ void setup_i2s_using_fastled_api() {
|
|||
FastLED.addLeds<WS2812, EXAMPLE_PIN_NUM_DATA15, GRB>(
|
||||
leds + (15 * NUM_LEDS_PER_STRIP), NUM_LEDS_PER_STRIP
|
||||
);
|
||||
FastLED.setBrightness(32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
psramInit(); // IMPORTANT: This is required to enable PSRAM. If you don't do this, the driver will not work.
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
Serial.begin(57600);
|
||||
|
||||
// This is used so that you can see if PSRAM is enabled. If not, we will crash in setup() or in loop().
|
||||
log_d("Total heap: %d", ESP.getHeapSize());
|
||||
|
|
@ -175,15 +155,12 @@ void setup() {
|
|||
log_d("Total PSRAM: %d", ESP.getPsramSize()); // If this prints out 0, then PSRAM is not enabled.
|
||||
log_d("Free PSRAM: %d", ESP.getFreePsram());
|
||||
|
||||
log_d("waiting 6 second before startup");
|
||||
log_d("waiting 6 seconds before startup");
|
||||
delay(6000); // The long reset time here is to make it easier to flash the device during the development process.
|
||||
if (gUseFastLEDApi) {
|
||||
setup_i2s_using_fastled_api();
|
||||
} else {
|
||||
driver = fl::InternalI2SDriver::create();
|
||||
driver->initled((uint8_t *)leds, PINS, NUMSTRIPS, NUM_LEDS_PER_STRIP); // Skips extra frame buffer copy.
|
||||
driver->setBrightness(32);
|
||||
}
|
||||
|
||||
setup_i2s();
|
||||
FastLED.setBrightness(32);
|
||||
|
||||
}
|
||||
|
||||
void fill_rainbow(CRGB* all_leds) {
|
||||
|
|
@ -199,10 +176,6 @@ void fill_rainbow(CRGB* all_leds) {
|
|||
|
||||
void loop() {
|
||||
fill_rainbow(leds);
|
||||
if (gUseFastLEDApi) {
|
||||
FastLED.show();
|
||||
} else {
|
||||
FASTLED_ASSERT(driver != nullptr, "Did not expect driver to be null");
|
||||
driver->show();
|
||||
}
|
||||
FastLED.show();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,11 @@
|
|||
#include "old.h"
|
||||
#include "FastLED.h"
|
||||
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Platform does not have enough memory
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "curr.h"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,112 +1,64 @@
|
|||
/*
|
||||
Festival Stick is a dense corkscrew of LEDs that is wrapped around one end of
|
||||
a wooden walking stick commonly found on amazon.A0
|
||||
Basic cork screw test.
|
||||
|
||||
The UI screenmap projects this cork screw into polar coordinates, so that the
|
||||
LEDs are mapped to a sprial, with the inner portion of the spiral being the top,
|
||||
the outer most portion being the bottom.
|
||||
This test is forward mapping, in which we test that
|
||||
the corkscrew is mapped to cylinder cartesian coordinates.
|
||||
|
||||
Most of the time, you'll want the reverse mapping, that is
|
||||
drawing to a rectangular grid, and then mapping that to a corkscrew.
|
||||
|
||||
However, to make sure the above mapping works correctly, we have
|
||||
to test that the forward mapping works correctly first.
|
||||
|
||||
*/
|
||||
|
||||
#include "fl/assert.h"
|
||||
#include "fl/corkscrew.h"
|
||||
#include "fl/screenmap.h"
|
||||
#include "fl/warn.h"
|
||||
#include "fl/sstream.h"
|
||||
#include "fl/grid.h"
|
||||
#include "fl/leds.h"
|
||||
#include "fl/screenmap.h"
|
||||
#include "fl/sstream.h"
|
||||
#include "fl/warn.h"
|
||||
#include "noise.h"
|
||||
#include <FastLED.h>
|
||||
// #include "vec3.h"
|
||||
|
||||
using namespace fl;
|
||||
|
||||
// Power management settings
|
||||
#define VOLTS 5
|
||||
#define MAX_AMPS 1
|
||||
|
||||
#define PIN_DATA 9
|
||||
#define PIN_CLOCK 7
|
||||
#define PIN_DATA 3
|
||||
#define PIN_CLOCK 4
|
||||
|
||||
// Pin could have been tied to ground, instead it's tied to another pin.
|
||||
#define PIN_BUTTON 1
|
||||
#define PIN_GRND 2
|
||||
|
||||
#define NUM_LEDS 288
|
||||
#define CORKSCREW_TOTAL_LENGTH 100 // 100 cm
|
||||
#define CORKSCREW_TOTAL_HEIGHT \
|
||||
23.25f // Total height of the corkscrew in centimeters for 144 densly
|
||||
// wrapped up over 19 turns
|
||||
#define CORKSCREW_TURNS 19 // Default to 19 turns
|
||||
23.25 // when height = 0, it's a circle.
|
||||
// wrapped up over 19 turns
|
||||
#define CORKSCREW_TURNS 20.5 // Default to 19 turns
|
||||
|
||||
// #define CM_BETWEEN_LEDS 1.0 // 1cm between LEDs
|
||||
// #define CM_LED_DIAMETER 0.5 // 0.5cm LED diameter
|
||||
|
||||
#define CORKSCREW_WIDTH 16
|
||||
#define CORKSCREW_HEIGHT 19
|
||||
|
||||
|
||||
UITitle festivalStickTitle("Festival Stick");
|
||||
UITitle festivalStickTitle("Corkscrew");
|
||||
UIDescription festivalStickDescription(
|
||||
"Take a wooden walking stick, wrap dense LEDs around it like a corkscrew. "
|
||||
"Super simple but very awesome looking."
|
||||
"This assumes the dense 144 LEDs / meter.");
|
||||
"Tests the ability to map a cork screw onto a 2D cylindrical surface");
|
||||
|
||||
UISlider ledsScale("Leds scale", 0.1f, 0.1f, 1.0f, 0.01f);
|
||||
UIButton button("Button");
|
||||
UISlider speed("Speed", 0.1f, 0.01f, 1.0f, 0.01f);
|
||||
|
||||
CRGB leds[NUM_LEDS];
|
||||
UICheckbox allWhite("All White", false);
|
||||
UICheckbox splatRendering("Splat Rendering", true);
|
||||
|
||||
// CRGB leds[NUM_LEDS];
|
||||
|
||||
// Tested on a 288 led (2x 144 max density led strip) with 19 turns
|
||||
// with 23.25cm height, 19 turns, and ~15.5 LEDs per turn.
|
||||
Corkscrew::Input
|
||||
corkscrewInput(CORKSCREW_TOTAL_HEIGHT,
|
||||
CORKSCREW_TURNS * 2.0f * PI, // Default to 19 turns
|
||||
0, // offset to account for gaps between segments
|
||||
NUM_LEDS, // Default to dense 144 leds.
|
||||
);
|
||||
Corkscrew::Input corkscrewInput(CORKSCREW_TOTAL_LENGTH, CORKSCREW_TOTAL_HEIGHT,
|
||||
CORKSCREW_TURNS, NUM_LEDS, 0);
|
||||
|
||||
// Corkscrew::Output corkscrewMap = fl::Corkscrew::generateMap(corkscrewInput);
|
||||
// Corkscrew::State corkscrewMap = fl::Corkscrew::generateMap(corkscrewInput);
|
||||
Corkscrew corkscrew(corkscrewInput);
|
||||
|
||||
// Used only for the fl::ScreenMap generation.
|
||||
struct corkscrew_args {
|
||||
int num_leds = NUM_LEDS;
|
||||
float leds_per_turn = 15.5;
|
||||
float width_cm = 1.0;
|
||||
};
|
||||
|
||||
fl::ScreenMap makeScreenMap(corkscrew_args args = corkscrew_args()) {
|
||||
// Create a ScreenMap for the corkscrew
|
||||
fl::vector<vec2f> points(args.num_leds);
|
||||
|
||||
int num_leds = args.num_leds;
|
||||
float leds_per_turn = args.leds_per_turn;
|
||||
float width_cm = args.width_cm;
|
||||
|
||||
const float circumference = leds_per_turn;
|
||||
const float radius = circumference / (2.0 * PI); // radius in mm
|
||||
const float angle_per_led = 2.0 * PI / leds_per_turn; // degrees per LED
|
||||
const float height_per_turn_cm = width_cm; // 10cm height per turn
|
||||
const float height_per_led = height_per_turn_cm / leds_per_turn *
|
||||
1.3; // this is the changing height per led.
|
||||
|
||||
for (int i = 0; i < num_leds; i++) {
|
||||
float angle = i * angle_per_led; // angle in radians
|
||||
float r = radius + 10 + i * height_per_led; // height in cm
|
||||
|
||||
// Calculate the x, y coordinates for the corkscrew
|
||||
float x = r * cos(angle); // x coordinate
|
||||
float y = r * sin(angle); // y coordinate
|
||||
|
||||
// Store the 2D coordinates in the vector
|
||||
points[i] = vec2f(x, y);
|
||||
}
|
||||
|
||||
FASTLED_WARN("Creating ScreenMap with:\n" << points);
|
||||
|
||||
// Create a ScreenMap from the points
|
||||
fl::ScreenMap screenMap(points.data(), num_leds, .5);
|
||||
return screenMap;
|
||||
}
|
||||
|
||||
// Create a corkscrew with:
|
||||
// - 30cm total length (300mm)
|
||||
// - 5cm width (50mm)
|
||||
|
|
@ -117,96 +69,77 @@ fl::ScreenMap makeScreenMap(corkscrew_args args = corkscrew_args()) {
|
|||
|
||||
// fl::vector<vec3f> mapCorkScrew = makeCorkScrew(args);
|
||||
fl::ScreenMap screenMap;
|
||||
fl::Grid<CRGB> frameBuffer;
|
||||
|
||||
|
||||
CLEDController *addController() {
|
||||
CLEDController *controller =
|
||||
&FastLED.addLeds<APA102HD, PIN_DATA, PIN_CLOCK, BGR>(leds, NUM_LEDS);
|
||||
return controller;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(PIN_GRND, OUTPUT);
|
||||
digitalWrite(PIN_GRND, LOW); // Set ground pin to low
|
||||
button.addRealButton(Button(PIN_BUTTON));
|
||||
corkscrew_args args = corkscrew_args();
|
||||
screenMap = makeScreenMap(args);
|
||||
// screenMap = ScreenMap::Circle(NUM_LEDS, 1.5f, 0.5f, 1.0f);
|
||||
auto controller = addController();
|
||||
int width = corkscrew.cylinder_width();
|
||||
int height = corkscrew.cylinder_height();
|
||||
|
||||
frameBuffer.reset(width, height);
|
||||
XYMap xyMap = XYMap::constructRectangularGrid(width, height, 0);
|
||||
|
||||
CRGB *leds = frameBuffer.data();
|
||||
size_t num_leds = frameBuffer.size();
|
||||
|
||||
CLEDController* controller = &FastLED.addLeds<APA102HD, PIN_DATA, PIN_CLOCK, BGR>(leds, NUM_LEDS);
|
||||
|
||||
// CLEDController *controller =
|
||||
// &FastLED.addLeds<WS2812, 3, BGR>(leds, num_leds);
|
||||
|
||||
fl::ScreenMap screenMap = xyMap.toScreenMap();
|
||||
screenMap.setDiameter(.2f);
|
||||
|
||||
// Set the screen map for the controller
|
||||
controller->setScreenMap(screenMap);
|
||||
|
||||
// Set power management. This allows this festival stick to conformatable
|
||||
// run on any USB battery that can output at least 1A at 5V.
|
||||
// Keep in mind that this sketch is designed to use APA102HD mode, which
|
||||
// will result in even lowwer run power consumption, since the power mode
|
||||
// does not take into account the APA102HD gamma correction. However it is
|
||||
// still a correct upper bound that will match the ledset exactly when the
|
||||
// display tries to go full white.
|
||||
FastLED.setMaxPowerInVoltsAndMilliamps(VOLTS, MAX_AMPS * 1000);
|
||||
button.onChanged([](UIButton &but) {
|
||||
// This function is called when the button is pressed
|
||||
// If the button is pressed, show the generative pattern
|
||||
if (but.isPressed()) {
|
||||
FASTLED_WARN("Button pressed");
|
||||
} else {
|
||||
FASTLED_WARN("NOT Button pressed");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void printOutput(const Corkscrew::Output& output) {
|
||||
fl::sstream stream;
|
||||
stream << "Corkscrew Output:\n";
|
||||
stream << "Width: " << output.width << "\n";
|
||||
stream << "Height: " << output.height << "\n";
|
||||
// stream << "Mapping: \n";
|
||||
// for (const auto &point : output.mapping) {
|
||||
// stream << point << "\n";
|
||||
// }
|
||||
FASTLED_WARN(stream.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
LedsXY<CORKSCREW_WIDTH, CORKSCREW_HEIGHT> frameBuffer;
|
||||
|
||||
void loop() {
|
||||
uint32_t now = millis();
|
||||
fl::clear(leds);
|
||||
// fl::clear(lesdds);
|
||||
fl::clear(frameBuffer);
|
||||
|
||||
static int w = 0;
|
||||
static float pos = 0;
|
||||
|
||||
EVERY_N_MILLIS(300) {
|
||||
// Update the corkscrew mapping every second
|
||||
w = (w + 1) % CORKSCREW_WIDTH;
|
||||
// Update the corkscrew mapping every second
|
||||
// w = (w + 1) % CORKSCREW_WIDTH;
|
||||
// frameBuffer.
|
||||
pos += speed.value();
|
||||
if (pos > corkscrew.size() - 1) {
|
||||
pos = 0; // Reset to the beginning
|
||||
}
|
||||
|
||||
|
||||
// draw a blue line down the middle
|
||||
for (int i = 0; i < CORKSCREW_HEIGHT; ++i) {
|
||||
frameBuffer.at(w % CORKSCREW_WIDTH, i) = CRGB::Blue;
|
||||
frameBuffer.at((w + 1) % CORKSCREW_WIDTH, i) = CRGB::Blue;
|
||||
frameBuffer.at((w - 1 + CORKSCREW_WIDTH) % CORKSCREW_WIDTH, i) = CRGB::Blue;
|
||||
frameBuffer.at((w + 2) % CORKSCREW_WIDTH, i) = CRGB::Blue;
|
||||
frameBuffer.at((w - 2 + CORKSCREW_WIDTH) % CORKSCREW_WIDTH, i) = CRGB::Blue;
|
||||
if (allWhite) {
|
||||
for (size_t i = 0; i < frameBuffer.size(); ++i) {
|
||||
frameBuffer.data()[i] = CRGB(8, 8, 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (splatRendering) {
|
||||
Tile2x2_u8_wrap pos_tile = corkscrew.at_wrap(pos);
|
||||
const CRGB color = CRGB::Blue;
|
||||
// Draw each pixel in the 2x2 tile using the new wrapping API
|
||||
for (int dx = 0; dx < 2; ++dx) {
|
||||
for (int dy = 0; dy < 2; ++dy) {
|
||||
auto data = pos_tile.at(dx, dy);
|
||||
vec2i16 wrapped_pos = data.first; // Already wrapped position
|
||||
uint8_t alpha = data.second; // Alpha value
|
||||
|
||||
|
||||
// printOutput(corkscrewMap);
|
||||
|
||||
for (int i = 0; i < NUM_LEDS; ++i) {
|
||||
// Get the position in the frame buffer
|
||||
vec2<int16_t> pos = corkscrew.at(i);
|
||||
// Draw the tile to the frame buffer
|
||||
CRGB c = frameBuffer.at(pos.x, pos.y);
|
||||
leds[i] = c;
|
||||
|
||||
FASTLED_WARN_IF(i < 16, "LED " << i << " at position: "
|
||||
<< pos.x << ", " << pos.y
|
||||
<< " with color: " << c);
|
||||
|
||||
if (alpha > 0) { // Only draw if there's some alpha
|
||||
CRGB c = color;
|
||||
c.nscale8(alpha); // Scale the color by the alpha value
|
||||
frameBuffer.at(wrapped_pos.x, wrapped_pos.y) = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// None splat rendering, looks aweful.
|
||||
vec2f pos_vec2f = corkscrew.at_exact(pos);
|
||||
vec2i16 pos_i16 = vec2i16(round(pos_vec2f.x), round(pos_vec2f.y));
|
||||
// Now map the cork screw position to the cylindrical buffer that we
|
||||
// will draw.
|
||||
frameBuffer.at(pos_i16.x, pos_i16.y) =
|
||||
CRGB::Blue; // Draw a blue pixel at (w, h)
|
||||
}
|
||||
|
||||
FastLED.show();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,11 +40,11 @@ UIDescription festivalStickDescription(
|
|||
"Take a wooden walking stick, wrap dense LEDs around it like a corkscrew. Super simple but very awesome looking."
|
||||
"This assumes the dense 144 LEDs / meter.");
|
||||
|
||||
|
||||
|
||||
UISlider ledsScale("Leds scale", 0.1f, 0.1f, 1.0f, 0.01f);
|
||||
UIButton button("Button");
|
||||
|
||||
// Adding a brightness slider
|
||||
UISlider brightness("Brightness", 16, 0, 255, 1); // Brightness from 0 to 255
|
||||
|
||||
CRGB leds[NUM_LEDS];
|
||||
|
||||
|
|
@ -166,6 +166,8 @@ void setup() {
|
|||
// into account the APA102HD gamma correction. However it is still a correct upper bound
|
||||
// that will match the ledset exactly when the display tries to go full white.
|
||||
FastLED.setMaxPowerInVoltsAndMilliamps(VOLTS, MAX_AMPS * 1000);
|
||||
// set brightness 8
|
||||
FastLED.setBrightness(brightness.as_int());
|
||||
button.onChanged([](UIButton& but) {
|
||||
// This function is called when the button is pressed
|
||||
// If the button is pressed, show the generative pattern
|
||||
|
|
|
|||
214
libraries/FastLED/examples/FireCylinder/FireCylinder.h
Normal file
214
libraries/FastLED/examples/FireCylinder/FireCylinder.h
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
all the UI elements you see below.
|
||||
|
||||
OVERVIEW:
|
||||
This sketch creates a fire effect on a cylindrical LED display using Perlin noise.
|
||||
Unlike a flat matrix, this cylinder connects the left and right edges (x=0 and x=width-1),
|
||||
creating a seamless wrap-around effect. The fire appears to rise from the bottom,
|
||||
with colors transitioning from black to red/yellow/white (or other palettes).
|
||||
*/
|
||||
|
||||
// Perlin noise fire procedure
|
||||
// 16x16 rgb led cylinder demo
|
||||
// Exactly the same as the FireMatrix example, but with a cylinder, meaning that the x=0
|
||||
// and x = len-1 are connected.
|
||||
// This also showcases the inoise16(x,y,z,t) function which handles 3D+time noise effects.
|
||||
// Keep in mind that a cylinder is embedded in a 3D space with time being used to add
|
||||
// additional noise to the effect.
|
||||
|
||||
// HOW THE CYLINDRICAL FIRE EFFECT WORKS:
|
||||
// 1. We use sine and cosine to map the x-coordinate to a circle in 3D space
|
||||
// 2. This creates a cylindrical mapping where the left and right edges connect seamlessly
|
||||
// 3. We use 4D Perlin noise (x,y,z,t) to generate natural-looking fire patterns
|
||||
// 4. The height coordinate controls color fade-out to create the rising fire effect
|
||||
// 5. The time dimension adds continuous variation to make the fire look dynamic
|
||||
|
||||
#include "FastLED.h" // Main FastLED library for controlling LEDs
|
||||
#include "fl/ui.h" // UI components for the FastLED web compiler (sliders, buttons, etc.)
|
||||
#include "fl/xymap.h" // Mapping between 1D LED array and 2D coordinates
|
||||
#include "fx/time.h" // Time manipulation utilities for animations
|
||||
|
||||
using namespace fl; // Use the FastLED namespace for convenience
|
||||
|
||||
// Cylinder dimensions - this defines the size of our virtual LED grid
|
||||
#define HEIGHT 100 // Number of rows in the cylinder (vertical dimension)
|
||||
#define WIDTH 100 // Number of columns in the cylinder (circumference)
|
||||
#define SERPENTINE true // Whether the LED strip zigzags back and forth (common in matrix layouts)
|
||||
#define BRIGHTNESS 255 // Maximum brightness level (0-255)
|
||||
|
||||
// UI elements that appear in the FastLED web compiler interface:
|
||||
UITitle title("FireCylinder Demo"); // Title displayed in the UI
|
||||
UIDescription description("This Fire demo wraps around the cylinder. It uses Perlin noise to create a fire effect.");
|
||||
|
||||
// TimeWarp helps control animation speed - it tracks time and allows speed adjustments
|
||||
TimeWarp timeScale(0, 1.0f); // Initialize with 0 starting time and 1.0 speed multiplier
|
||||
|
||||
// UI Controls for adjusting the fire effect:
|
||||
UISlider scaleXY("Scale", 8, 1, 100, 1); // Controls the overall size of the fire pattern
|
||||
UISlider speedY("SpeedY", 1.3, 1, 6, .1); // Controls how fast the fire moves upward
|
||||
UISlider scaleX("ScaleX", .3, 0.1, 3, .01); // Controls the horizontal scale (affects the wrap-around)
|
||||
UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1); // Controls how fast the fire pattern changes over time (higher = slower)
|
||||
UISlider brightness("Brightness", 255, 0, 255, 1); // Controls overall brightness
|
||||
UINumberField palette("Palette", 0, 0, 2); // Selects which color palette to use (0=fire, 1=green, 2=blue)
|
||||
|
||||
// Array to hold all LED color values - one CRGB struct per LED
|
||||
CRGB leds[HEIGHT * WIDTH];
|
||||
|
||||
// Color palettes define the gradient of colors used for the fire effect
|
||||
// Each entry has the format: position (0-255), R, G, B
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(firepal){
|
||||
// Traditional fire palette - transitions from black to red to yellow to white
|
||||
0, 0, 0, 0, // black (bottom of fire)
|
||||
32, 255, 0, 0, // red (base of flames)
|
||||
190, 255, 255, 0, // yellow (middle of flames)
|
||||
255, 255, 255, 255 // white (hottest part/tips of flames)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricGreenFirePal){
|
||||
// Green fire palette - for a toxic/alien look
|
||||
0, 0, 0, 0, // black (bottom)
|
||||
32, 0, 70, 0, // dark green (base)
|
||||
190, 57, 255, 20, // electric neon green (middle)
|
||||
255, 255, 255, 255 // white (hottest part)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricBlueFirePal){
|
||||
// Blue fire palette - for a cold/ice fire look
|
||||
0, 0, 0, 0, // Black (bottom)
|
||||
32, 0, 0, 70, // Dark blue (base)
|
||||
128, 20, 57, 255, // Electric blue (middle)
|
||||
255, 255, 255, 255 // White (hottest part)
|
||||
};
|
||||
|
||||
// Create a mapping between 1D array positions and 2D x,y coordinates
|
||||
XYMap xyMap(WIDTH, HEIGHT, SERPENTINE);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); // Initialize serial communication for debugging
|
||||
|
||||
// Initialize the LED strip:
|
||||
// - NEOPIXEL is the LED type
|
||||
// - 3 is the data pin number (for real hardware)
|
||||
// - setScreenMap connects our 2D coordinate system to the 1D LED array
|
||||
fl::ScreenMap screen_map = xyMap.toScreenMap();
|
||||
screen_map.setDiameter(0.1f); // Set the diameter for the cylinder (0.2 cm per LED)
|
||||
FastLED.addLeds<NEOPIXEL, 3>(leds, HEIGHT * WIDTH).setScreenMap(screen_map);
|
||||
|
||||
// Apply color correction for more accurate colors on LED strips
|
||||
FastLED.setCorrection(TypicalLEDStrip);
|
||||
}
|
||||
|
||||
uint8_t getPaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height,
|
||||
uint32_t y_speed) {
|
||||
// This function calculates which color to use from our palette for each LED
|
||||
|
||||
// Get the scale factor from the UI slider
|
||||
uint16_t scale = scaleXY.as<uint16_t>();
|
||||
|
||||
// Convert width position to an angle (0-255 represents 0-360 degrees)
|
||||
// This maps our flat coordinate to a position on a cylinder
|
||||
float xf = (float)width / (float)max_width; // Normalized position (0.0 to 1.0)
|
||||
uint8_t x = (uint8_t)(xf * 255); // Convert to 0-255 range for trig functions
|
||||
|
||||
// Calculate the sine and cosine of this angle to get 3D coordinates on the cylinder
|
||||
uint32_t cosx = cos8(x); // cos8 returns a value 0-255 representing cosine
|
||||
uint32_t sinx = sin8(x); // sin8 returns a value 0-255 representing sine
|
||||
|
||||
// Apply scaling to the sine/cosine values
|
||||
// This controls how "wide" the noise pattern is around the cylinder
|
||||
float trig_scale = scale * scaleX.value();
|
||||
cosx *= trig_scale;
|
||||
sinx *= trig_scale;
|
||||
|
||||
// Calculate Y coordinate (vertical position) with speed offset for movement
|
||||
uint32_t y = height * scale + y_speed;
|
||||
|
||||
// Calculate Z coordinate (time dimension) - controls how the pattern changes over time
|
||||
uint16_t z = millis32 / invSpeedZ.as<uint16_t>();
|
||||
|
||||
// Generate 16-bit Perlin noise using our 4D coordinates (x,y,z,t)
|
||||
// The << 8 shifts values left by 8 bits (multiplies by 256) to use the full 16-bit range
|
||||
// The last parameter (0) could be replaced with another time variable for more variation
|
||||
uint16_t noise16 = inoise16(cosx << 8, sinx << 8, y << 8, 0);
|
||||
|
||||
// Convert 16-bit noise to 8-bit by taking the high byte
|
||||
uint8_t noise_val = noise16 >> 8;
|
||||
|
||||
// Calculate how much to subtract based on vertical position (height)
|
||||
// This creates the fade-out effect from bottom to top
|
||||
// The formula maps height from 0 to max_height-1 to a value from 255 to 0
|
||||
int8_t subtraction_factor = abs8(height - (max_height - 1)) * 255 /
|
||||
(max_height - 1);
|
||||
|
||||
// Subtract the factor from the noise value (with underflow protection)
|
||||
// qsub8 is a "saturating subtraction" - it won't go below 0
|
||||
return qsub8(noise_val, subtraction_factor);
|
||||
}
|
||||
CRGBPalette16 getPalette() {
|
||||
// This function returns the appropriate color palette based on the UI selection
|
||||
switch (palette) {
|
||||
case 0:
|
||||
return firepal; // Traditional orange/red fire
|
||||
case 1:
|
||||
return electricGreenFirePal; // Green "toxic" fire
|
||||
case 2:
|
||||
return electricBlueFirePal; // Blue "cold" fire
|
||||
default:
|
||||
return firepal; // Default to traditional fire if invalid value
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// The main program loop that runs continuously
|
||||
|
||||
// Set the overall brightness from the UI slider
|
||||
FastLED.setBrightness(brightness);
|
||||
|
||||
// Get the selected color palette
|
||||
CRGBPalette16 myPal = getPalette();
|
||||
|
||||
// Get the current time in milliseconds
|
||||
uint32_t now = millis();
|
||||
|
||||
// Update the animation speed from the UI slider
|
||||
timeScale.setSpeed(speedY);
|
||||
|
||||
// Calculate the current y-offset for animation (makes the fire move)
|
||||
uint32_t y_speed = timeScale.update(now);
|
||||
|
||||
// Loop through every LED in our cylindrical matrix
|
||||
for (int width = 0; width < WIDTH; width++) {
|
||||
for (int height = 0; height < HEIGHT; height++) {
|
||||
// Calculate which color to use from our palette for this LED
|
||||
// This function handles the cylindrical mapping using sine/cosine
|
||||
uint8_t palette_index =
|
||||
getPaletteIndex(now, width, WIDTH, height, HEIGHT, y_speed);
|
||||
|
||||
// Get the actual RGB color from the palette
|
||||
// BRIGHTNESS ensures we use the full brightness range
|
||||
CRGB c = ColorFromPalette(myPal, palette_index, BRIGHTNESS);
|
||||
|
||||
// Convert our 2D coordinates to the 1D array index
|
||||
// We use (WIDTH-1)-width and (HEIGHT-1)-height to flip the coordinates
|
||||
// This makes the fire appear to rise from the bottom
|
||||
int index = xyMap((WIDTH - 1) - width, (HEIGHT - 1) - height);
|
||||
|
||||
// Set the LED color in our array
|
||||
leds[index] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the color data to the actual LEDs
|
||||
FastLED.show();
|
||||
}
|
||||
|
|
@ -1,207 +1,9 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
all the UI elements you see below.
|
||||
|
||||
OVERVIEW:
|
||||
This sketch creates a fire effect on a cylindrical LED display using Perlin noise.
|
||||
Unlike a flat matrix, this cylinder connects the left and right edges (x=0 and x=width-1),
|
||||
creating a seamless wrap-around effect. The fire appears to rise from the bottom,
|
||||
with colors transitioning from black to red/yellow/white (or other palettes).
|
||||
*/
|
||||
|
||||
// Perlin noise fire procedure
|
||||
// 16x16 rgb led cylinder demo
|
||||
// Exactly the same as the FireMatrix example, but with a cylinder, meaning that the x=0
|
||||
// and x = len-1 are connected.
|
||||
// This also showcases the inoise16(x,y,z,t) function which handles 3D+time noise effects.
|
||||
// Keep in mind that a cylinder is embedded in a 3D space with time being used to add
|
||||
// additional noise to the effect.
|
||||
|
||||
// HOW THE CYLINDRICAL FIRE EFFECT WORKS:
|
||||
// 1. We use sine and cosine to map the x-coordinate to a circle in 3D space
|
||||
// 2. This creates a cylindrical mapping where the left and right edges connect seamlessly
|
||||
// 3. We use 4D Perlin noise (x,y,z,t) to generate natural-looking fire patterns
|
||||
// 4. The height coordinate controls color fade-out to create the rising fire effect
|
||||
// 5. The time dimension adds continuous variation to make the fire look dynamic
|
||||
|
||||
#include "FastLED.h" // Main FastLED library for controlling LEDs
|
||||
#include "fl/ui.h" // UI components for the FastLED web compiler (sliders, buttons, etc.)
|
||||
#include "fl/xymap.h" // Mapping between 1D LED array and 2D coordinates
|
||||
#include "fx/time.h" // Time manipulation utilities for animations
|
||||
|
||||
using namespace fl; // Use the FastLED namespace for convenience
|
||||
|
||||
// Cylinder dimensions - this defines the size of our virtual LED grid
|
||||
#define HEIGHT 100 // Number of rows in the cylinder (vertical dimension)
|
||||
#define WIDTH 100 // Number of columns in the cylinder (circumference)
|
||||
#define SERPENTINE true // Whether the LED strip zigzags back and forth (common in matrix layouts)
|
||||
#define BRIGHTNESS 255 // Maximum brightness level (0-255)
|
||||
|
||||
// UI elements that appear in the FastLED web compiler interface:
|
||||
UITitle title("FireCylinder Demo"); // Title displayed in the UI
|
||||
UIDescription description("This Fire demo wraps around the cylinder. It uses Perlin noise to create a fire effect.");
|
||||
|
||||
// TimeWarp helps control animation speed - it tracks time and allows speed adjustments
|
||||
TimeWarp timeScale(0, 1.0f); // Initialize with 0 starting time and 1.0 speed multiplier
|
||||
|
||||
// UI Controls for adjusting the fire effect:
|
||||
UISlider scaleXY("Scale", 8, 1, 100, 1); // Controls the overall size of the fire pattern
|
||||
UISlider speedY("SpeedY", 1.3, 1, 6, .1); // Controls how fast the fire moves upward
|
||||
UISlider scaleX("ScaleX", .3, 0.1, 3, .01); // Controls the horizontal scale (affects the wrap-around)
|
||||
UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1); // Controls how fast the fire pattern changes over time (higher = slower)
|
||||
UISlider brightness("Brightness", 255, 0, 255, 1); // Controls overall brightness
|
||||
UINumberField palette("Palette", 0, 0, 2); // Selects which color palette to use (0=fire, 1=green, 2=blue)
|
||||
|
||||
// Array to hold all LED color values - one CRGB struct per LED
|
||||
CRGB leds[HEIGHT * WIDTH];
|
||||
|
||||
// Color palettes define the gradient of colors used for the fire effect
|
||||
// Each entry has the format: position (0-255), R, G, B
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(firepal){
|
||||
// Traditional fire palette - transitions from black to red to yellow to white
|
||||
0, 0, 0, 0, // black (bottom of fire)
|
||||
32, 255, 0, 0, // red (base of flames)
|
||||
190, 255, 255, 0, // yellow (middle of flames)
|
||||
255, 255, 255, 255 // white (hottest part/tips of flames)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricGreenFirePal){
|
||||
// Green fire palette - for a toxic/alien look
|
||||
0, 0, 0, 0, // black (bottom)
|
||||
32, 0, 70, 0, // dark green (base)
|
||||
190, 57, 255, 20, // electric neon green (middle)
|
||||
255, 255, 255, 255 // white (hottest part)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricBlueFirePal){
|
||||
// Blue fire palette - for a cold/ice fire look
|
||||
0, 0, 0, 0, // Black (bottom)
|
||||
32, 0, 0, 70, // Dark blue (base)
|
||||
128, 20, 57, 255, // Electric blue (middle)
|
||||
255, 255, 255, 255 // White (hottest part)
|
||||
};
|
||||
|
||||
// Create a mapping between 1D array positions and 2D x,y coordinates
|
||||
XYMap xyMap(HEIGHT, WIDTH, SERPENTINE);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); // Initialize serial communication for debugging
|
||||
|
||||
// Initialize the LED strip:
|
||||
// - NEOPIXEL is the LED type
|
||||
// - 3 is the data pin number (for real hardware)
|
||||
// - setScreenMap connects our 2D coordinate system to the 1D LED array
|
||||
FastLED.addLeds<NEOPIXEL, 3>(leds, HEIGHT * WIDTH).setScreenMap(xyMap);
|
||||
|
||||
// Apply color correction for more accurate colors on LED strips
|
||||
FastLED.setCorrection(TypicalLEDStrip);
|
||||
}
|
||||
|
||||
uint8_t getPaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height,
|
||||
uint32_t y_speed) {
|
||||
// This function calculates which color to use from our palette for each LED
|
||||
|
||||
// Get the scale factor from the UI slider
|
||||
uint16_t scale = scaleXY.as<uint16_t>();
|
||||
|
||||
// Convert width position to an angle (0-255 represents 0-360 degrees)
|
||||
// This maps our flat coordinate to a position on a cylinder
|
||||
float xf = (float)width / (float)max_width; // Normalized position (0.0 to 1.0)
|
||||
uint8_t x = (uint8_t)(xf * 255); // Convert to 0-255 range for trig functions
|
||||
|
||||
// Calculate the sine and cosine of this angle to get 3D coordinates on the cylinder
|
||||
uint32_t cosx = cos8(x); // cos8 returns a value 0-255 representing cosine
|
||||
uint32_t sinx = sin8(x); // sin8 returns a value 0-255 representing sine
|
||||
|
||||
// Apply scaling to the sine/cosine values
|
||||
// This controls how "wide" the noise pattern is around the cylinder
|
||||
float trig_scale = scale * scaleX.value();
|
||||
cosx *= trig_scale;
|
||||
sinx *= trig_scale;
|
||||
|
||||
// Calculate Y coordinate (vertical position) with speed offset for movement
|
||||
uint32_t y = height * scale + y_speed;
|
||||
|
||||
// Calculate Z coordinate (time dimension) - controls how the pattern changes over time
|
||||
uint16_t z = millis32 / invSpeedZ.as<uint16_t>();
|
||||
|
||||
// Generate 16-bit Perlin noise using our 4D coordinates (x,y,z,t)
|
||||
// The << 8 shifts values left by 8 bits (multiplies by 256) to use the full 16-bit range
|
||||
// The last parameter (0) could be replaced with another time variable for more variation
|
||||
uint16_t noise16 = inoise16(cosx << 8, sinx << 8, y << 8, 0);
|
||||
|
||||
// Convert 16-bit noise to 8-bit by taking the high byte
|
||||
uint8_t noise_val = noise16 >> 8;
|
||||
|
||||
// Calculate how much to subtract based on vertical position (height)
|
||||
// This creates the fade-out effect from bottom to top
|
||||
// The formula maps height from 0 to max_height-1 to a value from 255 to 0
|
||||
int8_t subtraction_factor = abs8(height - (max_height - 1)) * 255 /
|
||||
(max_height - 1);
|
||||
|
||||
// Subtract the factor from the noise value (with underflow protection)
|
||||
// qsub8 is a "saturating subtraction" - it won't go below 0
|
||||
return qsub8(noise_val, subtraction_factor);
|
||||
}
|
||||
CRGBPalette16 getPalette() {
|
||||
// This function returns the appropriate color palette based on the UI selection
|
||||
switch (palette) {
|
||||
case 0:
|
||||
return firepal; // Traditional orange/red fire
|
||||
case 1:
|
||||
return electricGreenFirePal; // Green "toxic" fire
|
||||
case 2:
|
||||
return electricBlueFirePal; // Blue "cold" fire
|
||||
default:
|
||||
return firepal; // Default to traditional fire if invalid value
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// The main program loop that runs continuously
|
||||
|
||||
// Set the overall brightness from the UI slider
|
||||
FastLED.setBrightness(brightness);
|
||||
|
||||
// Get the selected color palette
|
||||
CRGBPalette16 myPal = getPalette();
|
||||
|
||||
// Get the current time in milliseconds
|
||||
uint32_t now = millis();
|
||||
|
||||
// Update the animation speed from the UI slider
|
||||
timeScale.setSpeed(speedY);
|
||||
|
||||
// Calculate the current y-offset for animation (makes the fire move)
|
||||
uint32_t y_speed = timeScale.update(now);
|
||||
|
||||
// Loop through every LED in our cylindrical matrix
|
||||
for (int width = 0; width < WIDTH; width++) {
|
||||
for (int height = 0; height < HEIGHT; height++) {
|
||||
// Calculate which color to use from our palette for this LED
|
||||
// This function handles the cylindrical mapping using sine/cosine
|
||||
uint8_t palette_index =
|
||||
getPaletteIndex(now, width, WIDTH, height, HEIGHT, y_speed);
|
||||
|
||||
// Get the actual RGB color from the palette
|
||||
// BRIGHTNESS ensures we use the full brightness range
|
||||
CRGB c = ColorFromPalette(myPal, palette_index, BRIGHTNESS);
|
||||
|
||||
// Convert our 2D coordinates to the 1D array index
|
||||
// We use (WIDTH-1)-width and (HEIGHT-1)-height to flip the coordinates
|
||||
// This makes the fire appear to rise from the bottom
|
||||
int index = xyMap((WIDTH - 1) - width, (HEIGHT - 1) - height);
|
||||
|
||||
// Set the LED color in our array
|
||||
leds[index] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the color data to the actual LEDs
|
||||
FastLED.show();
|
||||
}
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Platform does not have enough memory
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "FireCylinder.h"
|
||||
#endif
|
||||
|
|
|
|||
200
libraries/FastLED/examples/FireMatrix/FireMatrix.h
Normal file
200
libraries/FastLED/examples/FireMatrix/FireMatrix.h
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
|
||||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
all the UI elements you see below.
|
||||
|
||||
OVERVIEW:
|
||||
This sketch creates a fire effect using Perlin noise on a matrix of LEDs.
|
||||
The fire appears to move upward with colors transitioning from black at the bottom
|
||||
to white at the top, with red and yellow in between (for the default palette).
|
||||
*/
|
||||
|
||||
// Perlin noise fire procedure
|
||||
// 16x16 rgb led matrix demo
|
||||
// Yaroslaw Turbin, 22.06.2020
|
||||
// https://vk.com/ldirko
|
||||
// https://www.reddit.com/user/ldirko/
|
||||
// https://www.reddit.com/r/FastLED/comments/hgu16i/my_fire_effect_implementation_based_on_perlin/
|
||||
// Based on the code found at: https://editor.soulmatelights.com/gallery/1229-
|
||||
|
||||
// HOW THE FIRE EFFECT WORKS:
|
||||
// 1. We use Perlin noise with time offset for X and Z coordinates
|
||||
// to create a naturally scrolling fire pattern that changes over time
|
||||
// 2. We distort the fire noise to make it look more realistic
|
||||
// 3. We subtract a value based on Y coordinate to shift the fire color in the palette
|
||||
// (not just brightness). This creates a fade-out effect from the bottom of the matrix to the top
|
||||
// 4. The palette is carefully designed to give realistic fire colors
|
||||
|
||||
#if defined(__AVR__)
|
||||
// Platform does not have enough memory
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "FastLED.h" // Main FastLED library for controlling LEDs
|
||||
#include "fl/ui.h" // UI components for the FastLED web compiler (sliders, etc.)
|
||||
#include "fl/xymap.h" // Mapping between 1D LED array and 2D coordinates
|
||||
#include "fx/time.h" // Time manipulation utilities
|
||||
|
||||
using namespace fl; // Use the FastLED namespace for convenience
|
||||
|
||||
// Matrix dimensions - this defines the size of our virtual LED grid
|
||||
#define HEIGHT 100 // Number of rows in the matrix
|
||||
#define WIDTH 100 // Number of columns in the matrix
|
||||
#define SERPENTINE true // Whether the LED strip zigzags back and forth (common in matrix layouts)
|
||||
#define BRIGHTNESS 255 // Maximum brightness level (0-255)
|
||||
|
||||
// TimeWarp helps control animation speed - it tracks time and allows speed adjustments
|
||||
TimeWarp timeScale(0, 1.0f); // Initialize with 0 starting time and 1.0 speed multiplier
|
||||
|
||||
// UI Controls that appear in the FastLED web compiler interface:
|
||||
UISlider scaleXY("Scale", 20, 1, 100, 1); // Controls the size of the fire pattern
|
||||
UISlider speedY("SpeedY", 1, 1, 6, .1); // Controls how fast the fire moves upward
|
||||
UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1); // Controls how fast the fire pattern changes over time (higher = slower)
|
||||
UISlider brightness("Brightness", 255, 0, 255, 1); // Controls overall brightness
|
||||
UINumberField palette("Palette", 0, 0, 2); // Selects which color palette to use (0=fire, 1=green, 2=blue)
|
||||
|
||||
// Array to hold all LED color values - one CRGB struct per LED
|
||||
CRGB leds[HEIGHT * WIDTH];
|
||||
|
||||
// Color palettes define the gradient of colors used for the fire effect
|
||||
// Each entry has the format: position (0-255), R, G, B
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(firepal){
|
||||
// Traditional fire palette - transitions from black to red to yellow to white
|
||||
0, 0, 0, 0, // black (bottom of fire)
|
||||
32, 255, 0, 0, // red (base of flames)
|
||||
190, 255, 255, 0, // yellow (middle of flames)
|
||||
255, 255, 255, 255 // white (hottest part/tips of flames)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricGreenFirePal){
|
||||
// Green fire palette - for a toxic/alien look
|
||||
0, 0, 0, 0, // black (bottom)
|
||||
32, 0, 70, 0, // dark green (base)
|
||||
190, 57, 255, 20, // electric neon green (middle)
|
||||
255, 255, 255, 255 // white (hottest part)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricBlueFirePal) {
|
||||
// Blue fire palette - for a cold/ice fire look
|
||||
0, 0, 0, 0, // Black (bottom)
|
||||
32, 0, 0, 70, // Dark blue (base)
|
||||
128, 20, 57, 255, // Electric blue (middle)
|
||||
255, 255, 255, 255 // White (hottest part)
|
||||
};
|
||||
|
||||
// Create a mapping between 1D array positions and 2D x,y coordinates
|
||||
XYMap xyMap(WIDTH, HEIGHT, SERPENTINE);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); // Initialize serial communication for debugging
|
||||
|
||||
// Initialize the LED strip:
|
||||
// - NEOPIXEL is the LED type
|
||||
// - 3 is the data pin number (for real hardware)
|
||||
// - setScreenMap connects our 2D coordinate system to the 1D LED array
|
||||
|
||||
fl::ScreenMap screen_map = xyMap.toScreenMap();
|
||||
screen_map.setDiameter(0.1f); // Set the diameter for the cylinder (0.2 cm per LED)
|
||||
FastLED.addLeds<NEOPIXEL, 3>(leds, HEIGHT * WIDTH).setScreenMap(screen_map);
|
||||
|
||||
// Apply color correction for more accurate colors on LED strips
|
||||
FastLED.setCorrection(TypicalLEDStrip);
|
||||
}
|
||||
|
||||
uint8_t getPaletteIndex(uint32_t millis32, int i, int j, uint32_t y_speed) {
|
||||
// This function calculates which color to use from our palette for each LED
|
||||
|
||||
// Get the scale factor from the UI slider (controls the "size" of the fire)
|
||||
uint16_t scale = scaleXY.as<uint16_t>();
|
||||
|
||||
// Calculate 3D coordinates for the Perlin noise function:
|
||||
uint16_t x = i * scale; // X position (horizontal in matrix)
|
||||
uint32_t y = j * scale + y_speed; // Y position (vertical) + movement offset
|
||||
uint16_t z = millis32 / invSpeedZ.as<uint16_t>(); // Z position (time dimension)
|
||||
|
||||
// Generate 16-bit Perlin noise value using these coordinates
|
||||
// The << 8 shifts values left by 8 bits (multiplies by 256) to use the full 16-bit range
|
||||
uint16_t noise16 = inoise16(x << 8, y << 8, z << 8);
|
||||
|
||||
// Convert 16-bit noise to 8-bit by taking the high byte (>> 8 shifts right by 8 bits)
|
||||
uint8_t noise_val = noise16 >> 8;
|
||||
|
||||
// Calculate how much to subtract based on vertical position (j)
|
||||
// This creates the fade-out effect from bottom to top
|
||||
// abs8() ensures we get a positive value
|
||||
// The formula maps j from 0 to HEIGHT-1 to a value from 255 to 0
|
||||
int8_t subtraction_factor = abs8(j - (HEIGHT - 1)) * 255 / (HEIGHT - 1);
|
||||
|
||||
// Subtract the factor from the noise value (with underflow protection)
|
||||
// qsub8 is a "saturating subtraction" - it won't go below 0
|
||||
return qsub8(noise_val, subtraction_factor);
|
||||
}
|
||||
|
||||
CRGBPalette16 getPalette() {
|
||||
// This function returns the appropriate color palette based on the UI selection
|
||||
switch (palette) {
|
||||
case 0:
|
||||
return firepal; // Traditional orange/red fire
|
||||
case 1:
|
||||
return electricGreenFirePal; // Green "toxic" fire
|
||||
case 2:
|
||||
return electricBlueFirePal; // Blue "cold" fire
|
||||
default:
|
||||
return firepal; // Default to traditional fire if invalid value
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// The main program loop that runs continuously
|
||||
|
||||
// Set the overall brightness from the UI slider
|
||||
FastLED.setBrightness(brightness);
|
||||
|
||||
// Get the selected color palette
|
||||
CRGBPalette16 myPal = getPalette();
|
||||
|
||||
// Get the current time in milliseconds
|
||||
uint32_t now = millis();
|
||||
|
||||
// Update the animation speed from the UI slider
|
||||
timeScale.setSpeed(speedY);
|
||||
|
||||
// Calculate the current y-offset for animation (makes the fire move)
|
||||
uint32_t y_speed = timeScale.update(now);
|
||||
|
||||
// Loop through every LED in our matrix
|
||||
for (int i = 0; i < WIDTH; i++) {
|
||||
for (int j = 0; j < HEIGHT; j++) {
|
||||
// Calculate which color to use from our palette for this LED
|
||||
uint8_t palette_index = getPaletteIndex(now, i, j, y_speed);
|
||||
|
||||
// Get the actual RGB color from the palette
|
||||
// BRIGHTNESS ensures we use the full brightness range
|
||||
CRGB c = ColorFromPalette(myPal, palette_index, BRIGHTNESS);
|
||||
|
||||
// Convert our 2D coordinates (i,j) to the 1D array index
|
||||
// We use (WIDTH-1)-i and (HEIGHT-1)-j to flip the coordinates
|
||||
// This makes the fire appear to rise from the bottom
|
||||
int index = xyMap((WIDTH - 1) - i, (HEIGHT - 1) - j);
|
||||
|
||||
// Set the LED color in our array
|
||||
leds[index] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the color data to the actual LEDs
|
||||
FastLED.show();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,184 +1,9 @@
|
|||
|
||||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
all the UI elements you see below.
|
||||
|
||||
OVERVIEW:
|
||||
This sketch creates a fire effect using Perlin noise on a matrix of LEDs.
|
||||
The fire appears to move upward with colors transitioning from black at the bottom
|
||||
to white at the top, with red and yellow in between (for the default palette).
|
||||
*/
|
||||
|
||||
// Perlin noise fire procedure
|
||||
// 16x16 rgb led matrix demo
|
||||
// Yaroslaw Turbin, 22.06.2020
|
||||
// https://vk.com/ldirko
|
||||
// https://www.reddit.com/user/ldirko/
|
||||
// https://www.reddit.com/r/FastLED/comments/hgu16i/my_fire_effect_implementation_based_on_perlin/
|
||||
// Based on the code found at: https://editor.soulmatelights.com/gallery/1229-
|
||||
|
||||
// HOW THE FIRE EFFECT WORKS:
|
||||
// 1. We use Perlin noise with time offset for X and Z coordinates
|
||||
// to create a naturally scrolling fire pattern that changes over time
|
||||
// 2. We distort the fire noise to make it look more realistic
|
||||
// 3. We subtract a value based on Y coordinate to shift the fire color in the palette
|
||||
// (not just brightness). This creates a fade-out effect from the bottom of the matrix to the top
|
||||
// 4. The palette is carefully designed to give realistic fire colors
|
||||
|
||||
#include "FastLED.h" // Main FastLED library for controlling LEDs
|
||||
#include "fl/ui.h" // UI components for the FastLED web compiler (sliders, etc.)
|
||||
#include "fl/xymap.h" // Mapping between 1D LED array and 2D coordinates
|
||||
#include "fx/time.h" // Time manipulation utilities
|
||||
|
||||
using namespace fl; // Use the FastLED namespace for convenience
|
||||
|
||||
// Matrix dimensions - this defines the size of our virtual LED grid
|
||||
#define HEIGHT 100 // Number of rows in the matrix
|
||||
#define WIDTH 100 // Number of columns in the matrix
|
||||
#define SERPENTINE true // Whether the LED strip zigzags back and forth (common in matrix layouts)
|
||||
#define BRIGHTNESS 255 // Maximum brightness level (0-255)
|
||||
|
||||
// TimeWarp helps control animation speed - it tracks time and allows speed adjustments
|
||||
TimeWarp timeScale(0, 1.0f); // Initialize with 0 starting time and 1.0 speed multiplier
|
||||
|
||||
// UI Controls that appear in the FastLED web compiler interface:
|
||||
UISlider scaleXY("Scale", 20, 1, 100, 1); // Controls the size of the fire pattern
|
||||
UISlider speedY("SpeedY", 1, 1, 6, .1); // Controls how fast the fire moves upward
|
||||
UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1); // Controls how fast the fire pattern changes over time (higher = slower)
|
||||
UISlider brightness("Brightness", 255, 0, 255, 1); // Controls overall brightness
|
||||
UINumberField palette("Palette", 0, 0, 2); // Selects which color palette to use (0=fire, 1=green, 2=blue)
|
||||
|
||||
// Array to hold all LED color values - one CRGB struct per LED
|
||||
CRGB leds[HEIGHT * WIDTH];
|
||||
|
||||
// Color palettes define the gradient of colors used for the fire effect
|
||||
// Each entry has the format: position (0-255), R, G, B
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(firepal){
|
||||
// Traditional fire palette - transitions from black to red to yellow to white
|
||||
0, 0, 0, 0, // black (bottom of fire)
|
||||
32, 255, 0, 0, // red (base of flames)
|
||||
190, 255, 255, 0, // yellow (middle of flames)
|
||||
255, 255, 255, 255 // white (hottest part/tips of flames)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricGreenFirePal){
|
||||
// Green fire palette - for a toxic/alien look
|
||||
0, 0, 0, 0, // black (bottom)
|
||||
32, 0, 70, 0, // dark green (base)
|
||||
190, 57, 255, 20, // electric neon green (middle)
|
||||
255, 255, 255, 255 // white (hottest part)
|
||||
};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE(electricBlueFirePal) {
|
||||
// Blue fire palette - for a cold/ice fire look
|
||||
0, 0, 0, 0, // Black (bottom)
|
||||
32, 0, 0, 70, // Dark blue (base)
|
||||
128, 20, 57, 255, // Electric blue (middle)
|
||||
255, 255, 255, 255 // White (hottest part)
|
||||
};
|
||||
|
||||
// Create a mapping between 1D array positions and 2D x,y coordinates
|
||||
XYMap xyMap(HEIGHT, WIDTH, SERPENTINE);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); // Initialize serial communication for debugging
|
||||
|
||||
// Initialize the LED strip:
|
||||
// - NEOPIXEL is the LED type
|
||||
// - 3 is the data pin number (for real hardware)
|
||||
// - setScreenMap connects our 2D coordinate system to the 1D LED array
|
||||
FastLED.addLeds<NEOPIXEL, 3>(leds, HEIGHT * WIDTH).setScreenMap(xyMap);
|
||||
|
||||
// Apply color correction for more accurate colors on LED strips
|
||||
FastLED.setCorrection(TypicalLEDStrip);
|
||||
}
|
||||
|
||||
uint8_t getPaletteIndex(uint32_t millis32, int i, int j, uint32_t y_speed) {
|
||||
// This function calculates which color to use from our palette for each LED
|
||||
|
||||
// Get the scale factor from the UI slider (controls the "size" of the fire)
|
||||
uint16_t scale = scaleXY.as<uint16_t>();
|
||||
|
||||
// Calculate 3D coordinates for the Perlin noise function:
|
||||
uint16_t x = i * scale; // X position (horizontal in matrix)
|
||||
uint32_t y = j * scale + y_speed; // Y position (vertical) + movement offset
|
||||
uint16_t z = millis32 / invSpeedZ.as<uint16_t>(); // Z position (time dimension)
|
||||
|
||||
// Generate 16-bit Perlin noise value using these coordinates
|
||||
// The << 8 shifts values left by 8 bits (multiplies by 256) to use the full 16-bit range
|
||||
uint16_t noise16 = inoise16(x << 8, y << 8, z << 8);
|
||||
|
||||
// Convert 16-bit noise to 8-bit by taking the high byte (>> 8 shifts right by 8 bits)
|
||||
uint8_t noise_val = noise16 >> 8;
|
||||
|
||||
// Calculate how much to subtract based on vertical position (j)
|
||||
// This creates the fade-out effect from bottom to top
|
||||
// abs8() ensures we get a positive value
|
||||
// The formula maps j from 0 to WIDTH-1 to a value from 255 to 0
|
||||
int8_t subtraction_factor = abs8(j - (WIDTH - 1)) * 255 / (WIDTH - 1);
|
||||
|
||||
// Subtract the factor from the noise value (with underflow protection)
|
||||
// qsub8 is a "saturating subtraction" - it won't go below 0
|
||||
return qsub8(noise_val, subtraction_factor);
|
||||
}
|
||||
|
||||
CRGBPalette16 getPalette() {
|
||||
// This function returns the appropriate color palette based on the UI selection
|
||||
switch (palette) {
|
||||
case 0:
|
||||
return firepal; // Traditional orange/red fire
|
||||
case 1:
|
||||
return electricGreenFirePal; // Green "toxic" fire
|
||||
case 2:
|
||||
return electricBlueFirePal; // Blue "cold" fire
|
||||
default:
|
||||
return firepal; // Default to traditional fire if invalid value
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// The main program loop that runs continuously
|
||||
|
||||
// Set the overall brightness from the UI slider
|
||||
FastLED.setBrightness(brightness);
|
||||
|
||||
// Get the selected color palette
|
||||
CRGBPalette16 myPal = getPalette();
|
||||
|
||||
// Get the current time in milliseconds
|
||||
uint32_t now = millis();
|
||||
|
||||
// Update the animation speed from the UI slider
|
||||
timeScale.setSpeed(speedY);
|
||||
|
||||
// Calculate the current y-offset for animation (makes the fire move)
|
||||
uint32_t y_speed = timeScale.update(now);
|
||||
|
||||
// Loop through every LED in our matrix
|
||||
for (int i = 0; i < HEIGHT; i++) {
|
||||
for (int j = 0; j < WIDTH; j++) {
|
||||
// Calculate which color to use from our palette for this LED
|
||||
uint8_t palette_index = getPaletteIndex(now, i, j, y_speed);
|
||||
|
||||
// Get the actual RGB color from the palette
|
||||
// BRIGHTNESS ensures we use the full brightness range
|
||||
CRGB c = ColorFromPalette(myPal, palette_index, BRIGHTNESS);
|
||||
|
||||
// Convert our 2D coordinates (i,j) to the 1D array index
|
||||
// We use (HEIGHT-1)-i and (WIDTH-1)-j to flip the coordinates
|
||||
// This makes the fire appear to rise from the bottom
|
||||
int index = xyMap((HEIGHT - 1) - i, (WIDTH - 1) - j);
|
||||
|
||||
// Set the LED color in our array
|
||||
leds[index] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the color data to the actual LEDs
|
||||
FastLED.show();
|
||||
}
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Platform does not have enough memory
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "FireMatrix.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
/// 3. Run the FastLED web compiler at root: `fastled`
|
||||
/// 4. When the compiler is done a web page will open.
|
||||
|
||||
#include "FastLED.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
@ -40,6 +40,7 @@ CRGB leds[NUM_LEDS];
|
|||
UITitle title("FxWave2D Demo");
|
||||
UIDescription description("Advanced layered and blended wave effects.");
|
||||
|
||||
UICheckbox xCyclical("X Is Cyclical", false); // If true, waves wrap around the x-axis (like a loop)
|
||||
// Main control UI elements:
|
||||
UIButton button("Trigger"); // Button to trigger a single ripple
|
||||
UIButton buttonFancy("Trigger Fancy"); // Button to trigger a fancy cross-shaped effect
|
||||
|
|
@ -50,7 +51,7 @@ UISlider blurAmount("Global Blur Amount", 0, 0, 172, 1); // Controls overall
|
|||
UISlider blurPasses("Global Blur Passes", 1, 1, 10, 1); // Controls how many times blur is applied (more = smoother but slower)
|
||||
UISlider superSample("SuperSampleExponent", 1.f, 0.f, 3.f, 1.f); // Controls anti-aliasing quality (higher = better quality but more CPU)
|
||||
|
||||
UICheckbox xCyclical("X Is Cyclical", false); // If true, waves wrap around the x-axis (like a loop)
|
||||
|
||||
|
||||
// Upper wave layer controls:
|
||||
UISlider speedUpper("Wave Upper: Speed", 0.12f, 0.0f, 1.0f); // How fast the upper wave propagates
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
|
|||
83
libraries/FastLED/examples/NoisePlayground/NoisePlayground.h
Normal file
83
libraries/FastLED/examples/NoisePlayground/NoisePlayground.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
|
||||
|
||||
|
||||
/// @file NoisePlayground.ino
|
||||
/// @brief Demonstrates how to use noise generation on a 2D LED matrix
|
||||
/// @example NoisePlayground.ino
|
||||
|
||||
#include <FastLED.h>
|
||||
|
||||
|
||||
// Params for width and height
|
||||
const uint8_t kMatrixWidth = 16;
|
||||
const uint8_t kMatrixHeight = 16;
|
||||
|
||||
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
|
||||
|
||||
// Param for different pixel layouts
|
||||
#define kMatrixSerpentineLayout true
|
||||
|
||||
// led array
|
||||
CRGB leds[kMatrixWidth * kMatrixHeight];
|
||||
|
||||
// x,y, & time values
|
||||
uint32_t x,y,v_time,hue_time,hxy;
|
||||
|
||||
// Play with the values of the variables below and see what kinds of effects they
|
||||
// have! More octaves will make things slower.
|
||||
|
||||
// how many octaves to use for the brightness and hue functions
|
||||
uint8_t octaves=1;
|
||||
uint8_t hue_octaves=3;
|
||||
|
||||
// the 'distance' between points on the x and y axis
|
||||
int xscale=57771;
|
||||
int yscale=57771;
|
||||
|
||||
// the 'distance' between x/y points for the hue noise
|
||||
int hue_scale=1;
|
||||
|
||||
// how fast we move through time & hue noise
|
||||
int time_speed=1111;
|
||||
int hue_speed=31;
|
||||
|
||||
// adjust these values to move along the x or y axis between frames
|
||||
int x_speed=331;
|
||||
int y_speed=1111;
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
// initialize the x/y and time values
|
||||
random16_set_seed(8934);
|
||||
random16_add_entropy(analogRead(3));
|
||||
|
||||
Serial.begin(57600);
|
||||
Serial.println("resetting!");
|
||||
|
||||
delay(3000);
|
||||
FastLED.addLeds<WS2811,2,GRB>(leds,NUM_LEDS);
|
||||
FastLED.setBrightness(96);
|
||||
|
||||
hxy = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
x = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
y = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
v_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
hue_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// fill the led array 2/16-bit noise values
|
||||
fill_2dnoise16(leds, kMatrixWidth, kMatrixHeight, kMatrixSerpentineLayout,
|
||||
octaves,x,xscale,y,yscale,v_time,
|
||||
hue_octaves,hxy,hue_scale,hxy,hue_scale,hue_time, false);
|
||||
|
||||
FastLED.show();
|
||||
|
||||
// adjust the intra-frame time values
|
||||
x += x_speed;
|
||||
y += y_speed;
|
||||
v_time += time_speed;
|
||||
hue_time += hue_speed;
|
||||
// delay(50);
|
||||
}
|
||||
|
|
@ -1,90 +1,11 @@
|
|||
#include <FastLED.h> // Main FastLED library for controlling LEDs
|
||||
|
||||
|
||||
|
||||
/// @file NoisePlayground.ino
|
||||
/// @brief Demonstrates how to use noise generation on a 2D LED matrix
|
||||
/// @example NoisePlayground.ino
|
||||
|
||||
#include <FastLED.h>
|
||||
|
||||
#if defined(__AVR__)
|
||||
// too large for ATtiny85, attiny88, etc.. Just disable it for all avr boards.
|
||||
void setup() {};
|
||||
void loop() {};
|
||||
#else
|
||||
|
||||
// Params for width and height
|
||||
const uint8_t kMatrixWidth = 16;
|
||||
const uint8_t kMatrixHeight = 16;
|
||||
|
||||
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
|
||||
|
||||
// Param for different pixel layouts
|
||||
#define kMatrixSerpentineLayout true
|
||||
|
||||
// led array
|
||||
CRGB leds[kMatrixWidth * kMatrixHeight];
|
||||
|
||||
// x,y, & time values
|
||||
uint32_t x,y,v_time,hue_time,hxy;
|
||||
|
||||
// Play with the values of the variables below and see what kinds of effects they
|
||||
// have! More octaves will make things slower.
|
||||
|
||||
// how many octaves to use for the brightness and hue functions
|
||||
uint8_t octaves=1;
|
||||
uint8_t hue_octaves=3;
|
||||
|
||||
// the 'distance' between points on the x and y axis
|
||||
int xscale=57771;
|
||||
int yscale=57771;
|
||||
|
||||
// the 'distance' between x/y points for the hue noise
|
||||
int hue_scale=1;
|
||||
|
||||
// how fast we move through time & hue noise
|
||||
int time_speed=1111;
|
||||
int hue_speed=31;
|
||||
|
||||
// adjust these values to move along the x or y axis between frames
|
||||
int x_speed=331;
|
||||
int y_speed=1111;
|
||||
|
||||
void loop() {
|
||||
// fill the led array 2/16-bit noise values
|
||||
fill_2dnoise16(leds, kMatrixWidth, kMatrixHeight, kMatrixSerpentineLayout,
|
||||
octaves,x,xscale,y,yscale,v_time,
|
||||
hue_octaves,hxy,hue_scale,hxy,hue_scale,hue_time, false);
|
||||
|
||||
FastLED.show();
|
||||
|
||||
// adjust the intra-frame time values
|
||||
x += x_speed;
|
||||
y += y_speed;
|
||||
v_time += time_speed;
|
||||
hue_time += hue_speed;
|
||||
// delay(50);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
// initialize the x/y and time values
|
||||
random16_set_seed(8934);
|
||||
random16_add_entropy(analogRead(3));
|
||||
|
||||
Serial.begin(57600);
|
||||
Serial.println("resetting!");
|
||||
|
||||
delay(3000);
|
||||
FastLED.addLeds<WS2811,2,GRB>(leds,NUM_LEDS);
|
||||
FastLED.setBrightness(96);
|
||||
|
||||
hxy = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
x = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
y = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
v_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
hue_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Don't compile this for AVR microcontrollers (like Arduino Uno) because they typically
|
||||
// don't have enough memory to handle this complex animation.
|
||||
// Instead, we provide empty setup/loop functions so the sketch will compile but do nothing.
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else // For all other platforms with more memory (ESP32, Teensy, etc.)
|
||||
#include "NoisePlayground.h"
|
||||
#endif // End of the non-AVR code section
|
||||
|
|
|
|||
407
libraries/FastLED/examples/NoisePlusPalette/NoisePlusPalette.h
Normal file
407
libraries/FastLED/examples/NoisePlusPalette/NoisePlusPalette.h
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
/// @file NoisePlusPalette.ino
|
||||
/// @brief Demonstrates how to mix noise generation with color palettes on a 2D LED matrix
|
||||
/// @example NoisePlusPalette.ino
|
||||
///
|
||||
/// OVERVIEW:
|
||||
/// This sketch demonstrates combining Perlin noise with color palettes to create
|
||||
/// dynamic, flowing color patterns on an LED matrix. The noise function creates
|
||||
/// natural-looking patterns that change over time, while the color palettes
|
||||
/// determine which colors are used to visualize the noise values.
|
||||
|
||||
#include <FastLED.h> // Main FastLED library for controlling LEDs
|
||||
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Don't compile this for AVR microcontrollers (like Arduino Uno) because they typically
|
||||
// don't have enough memory to handle this complex animation.
|
||||
// Instead, we provide empty setup/loop functions so the sketch will compile but do nothing.
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else // For all other platforms with more memory (ESP32, Teensy, etc.)
|
||||
|
||||
// LED hardware configuration
|
||||
#define LED_PIN 3 // Data pin connected to the LED strip
|
||||
#define BRIGHTNESS 96 // Default brightness level (0-255)
|
||||
#define LED_TYPE WS2811 // Type of LED strip being used
|
||||
#define COLOR_ORDER GRB // Color order of the LEDs (varies by strip type)
|
||||
|
||||
// Matrix dimensions - defines the size of our virtual LED grid
|
||||
const uint8_t kMatrixWidth = 16; // Number of columns in the matrix
|
||||
const uint8_t kMatrixHeight = 16; // Number of rows in the matrix
|
||||
|
||||
// LED strip layout configuration
|
||||
const bool kMatrixSerpentineLayout = true; // If true, every other row runs backwards
|
||||
// This is common in matrix setups to allow
|
||||
// for easier wiring
|
||||
|
||||
|
||||
// HOW THIS EXAMPLE WORKS:
|
||||
//
|
||||
// This example combines two features of FastLED to produce a remarkable range of
|
||||
// effects from a relatively small amount of code. This example combines FastLED's
|
||||
// color palette lookup functions with FastLED's Perlin noise generator, and
|
||||
// the combination is extremely powerful.
|
||||
//
|
||||
// You might want to look at the "ColorPalette" and "Noise" examples separately
|
||||
// if this example code seems daunting.
|
||||
//
|
||||
//
|
||||
// The basic setup here is that for each frame, we generate a new array of
|
||||
// 'noise' data, and then map it onto the LED matrix through a color palette.
|
||||
//
|
||||
// Periodically, the color palette is changed, and new noise-generation parameters
|
||||
// are chosen at the same time. In this example, specific noise-generation
|
||||
// values have been selected to match the given color palettes; some are faster,
|
||||
// or slower, or larger, or smaller than others, but there's no reason these
|
||||
// parameters can't be freely mixed-and-matched.
|
||||
//
|
||||
// In addition, this example includes some fast automatic 'data smoothing' at
|
||||
// lower noise speeds to help produce smoother animations in those cases.
|
||||
//
|
||||
// The FastLED built-in color palettes (Forest, Clouds, Lava, Ocean, Party) are
|
||||
// used, as well as some 'hand-defined' ones, and some procedurally generated
|
||||
// palettes.
|
||||
|
||||
|
||||
// Calculate the total number of LEDs in our matrix
|
||||
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
|
||||
|
||||
// Find the larger dimension (width or height) for our noise array size
|
||||
#define MAX_DIMENSION ((kMatrixWidth>kMatrixHeight) ? kMatrixWidth : kMatrixHeight)
|
||||
|
||||
// Array to hold all LED color values - one CRGB struct per LED
|
||||
CRGB leds[kMatrixWidth * kMatrixHeight];
|
||||
|
||||
// The 16-bit version of our coordinates for the noise function
|
||||
// Using 16 bits gives us more resolution and smoother animations
|
||||
static uint16_t x; // x-coordinate in the noise space
|
||||
static uint16_t y; // y-coordinate in the noise space
|
||||
static uint16_t z; // z-coordinate (time dimension) in the noise space
|
||||
|
||||
// ANIMATION PARAMETERS:
|
||||
|
||||
// We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll
|
||||
// use the z-axis for "time". speed determines how fast time moves forward. Try
|
||||
// 1 for a very slow moving effect, or 60 for something that ends up looking like
|
||||
// water.
|
||||
uint16_t speed = 20; // Speed is set dynamically once we've started up
|
||||
// Higher values = faster animation
|
||||
|
||||
// Scale determines how far apart the pixels in our noise matrix are. Try
|
||||
// changing these values around to see how it affects the motion of the display. The
|
||||
// higher the value of scale, the more "zoomed out" the noise will be. A value
|
||||
// of 1 will be so zoomed in, you'll mostly see solid colors.
|
||||
uint16_t scale = 30; // Scale is set dynamically once we've started up
|
||||
// Higher values = more "zoomed out" pattern
|
||||
|
||||
// This is the array that we keep our computed noise values in
|
||||
// Each position stores an 8-bit (0-255) noise value
|
||||
uint8_t noise[MAX_DIMENSION][MAX_DIMENSION];
|
||||
|
||||
// The current color palette we're using to map noise values to colors
|
||||
CRGBPalette16 currentPalette( PartyColors_p ); // Start with party colors
|
||||
|
||||
// If colorLoop is set to 1, we'll cycle through the colors in the palette
|
||||
// This creates an additional animation effect on top of the noise movement
|
||||
uint8_t colorLoop = 1; // 0 = no color cycling, 1 = cycle colors
|
||||
|
||||
|
||||
// Forward declare our functions so that we have maximum compatibility
|
||||
// with other build tools outside of ArduinoIDE. The *.ino files are
|
||||
// special in that Arduino will generate function prototypes for you.
|
||||
// For non-Arduino environments, we need these declarations.
|
||||
void SetupRandomPalette(); // Creates a random color palette
|
||||
void SetupPurpleAndGreenPalette(); // Creates a purple and green striped palette
|
||||
void SetupBlackAndWhiteStripedPalette(); // Creates a black and white striped palette
|
||||
void ChangePaletteAndSettingsPeriodically(); // Changes palettes and settings over time
|
||||
void mapNoiseToLEDsUsingPalette(); // Maps noise data to LED colors using the palette
|
||||
uint16_t XY( uint8_t x, uint8_t y); // Converts x,y coordinates to LED array index
|
||||
|
||||
void setup() {
|
||||
delay(3000); // 3 second delay for recovery and to give time for the serial monitor to open
|
||||
|
||||
// Initialize the LED strip:
|
||||
// - LED_TYPE specifies the chipset (WS2811, WS2812B, etc.)
|
||||
// - LED_PIN is the data pin number
|
||||
// - COLOR_ORDER specifies the RGB color ordering for your strip
|
||||
FastLED.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,NUM_LEDS);
|
||||
// NOTE - This does NOT have a ScreenMap (because it's a legacy sketch)
|
||||
// so it won't look that good on the web-compiler. But adding it is ONE LINE!
|
||||
|
||||
// Set the overall brightness level (0-255)
|
||||
FastLED.setBrightness(BRIGHTNESS);
|
||||
|
||||
// Initialize our noise coordinates to random values
|
||||
// This ensures the pattern starts from a different position each time
|
||||
x = random16(); // Random x starting position
|
||||
y = random16(); // Random y starting position
|
||||
z = random16(); // Random time starting position
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Fill the x/y array of 8-bit noise values using the inoise8 function.
|
||||
void fillnoise8() {
|
||||
// If we're running at a low "speed", some 8-bit artifacts become visible
|
||||
// from frame-to-frame. In order to reduce this, we can do some fast data-smoothing.
|
||||
// The amount of data smoothing we're doing depends on "speed".
|
||||
uint8_t dataSmoothing = 0;
|
||||
if( speed < 50) {
|
||||
// At lower speeds, apply more smoothing
|
||||
// This formula creates more smoothing at lower speeds:
|
||||
// speed=10 → smoothing=160, speed=30 → smoothing=80
|
||||
dataSmoothing = 200 - (speed * 4);
|
||||
}
|
||||
|
||||
// Loop through each pixel in our noise array
|
||||
for(int i = 0; i < MAX_DIMENSION; i++) {
|
||||
// Calculate the offset for this pixel in the x dimension
|
||||
int ioffset = scale * i;
|
||||
|
||||
for(int j = 0; j < MAX_DIMENSION; j++) {
|
||||
// Calculate the offset for this pixel in the y dimension
|
||||
int joffset = scale * j;
|
||||
|
||||
// Generate the noise value for this pixel using 3D Perlin noise
|
||||
// The noise function takes x, y, and z (time) coordinates
|
||||
uint8_t data = inoise8(x + ioffset, y + joffset, z);
|
||||
|
||||
// The range of the inoise8 function is roughly 16-238.
|
||||
// These two operations expand those values out to roughly 0..255
|
||||
// You can comment them out if you want the raw noise data.
|
||||
data = qsub8(data, 16); // Subtract 16 (with underflow protection)
|
||||
data = qadd8(data, scale8(data, 39)); // Add a scaled version of the data to itself
|
||||
|
||||
// Apply data smoothing if enabled
|
||||
if( dataSmoothing ) {
|
||||
uint8_t olddata = noise[i][j]; // Get the previous frame's value
|
||||
|
||||
// Blend between old and new data based on smoothing amount
|
||||
// Higher dataSmoothing = more of the old value is kept
|
||||
uint8_t newdata = scale8(olddata, dataSmoothing) +
|
||||
scale8(data, 256 - dataSmoothing);
|
||||
data = newdata;
|
||||
}
|
||||
|
||||
// Store the final noise value in our array
|
||||
noise[i][j] = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment z to move through the noise space over time
|
||||
z += speed;
|
||||
|
||||
// Apply slow drift to X and Y, just for visual variation
|
||||
// This creates a gentle shifting of the entire pattern
|
||||
x += speed / 8; // X drifts at 1/8 the speed of z
|
||||
y -= speed / 16; // Y drifts at 1/16 the speed of z in the opposite direction
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Map the noise data to LED colors using the current color palette
|
||||
void mapNoiseToLEDsUsingPalette()
|
||||
{
|
||||
// Static variable that slowly increases to cycle through colors when colorLoop is enabled
|
||||
static uint8_t ihue=0;
|
||||
|
||||
// Loop through each pixel in our LED matrix
|
||||
for(int i = 0; i < kMatrixWidth; i++) {
|
||||
for(int j = 0; j < kMatrixHeight; j++) {
|
||||
// We use the value at the (i,j) coordinate in the noise
|
||||
// array for our brightness, and the flipped value from (j,i)
|
||||
// for our pixel's index into the color palette.
|
||||
// This creates interesting patterns with two different noise mappings.
|
||||
|
||||
uint8_t index = noise[j][i]; // Color index from the flipped coordinate
|
||||
uint8_t bri = noise[i][j]; // Brightness from the normal coordinate
|
||||
|
||||
// If color cycling is enabled, add a slowly-changing base value to the index
|
||||
// This makes the colors shift/rotate through the palette over time
|
||||
if( colorLoop) {
|
||||
index += ihue; // Add the slowly increasing hue offset
|
||||
}
|
||||
|
||||
// Brighten up the colors, as the color palette itself often contains the
|
||||
// light/dark dynamic range desired
|
||||
if( bri > 127 ) {
|
||||
// If brightness is in the upper half, make it full brightness
|
||||
bri = 255;
|
||||
} else {
|
||||
// Otherwise, scale it to the full range (0-127 becomes 0-254)
|
||||
bri = dim8_raw( bri * 2);
|
||||
}
|
||||
|
||||
// Get the final color by looking up the palette color at our index
|
||||
// and applying the brightness value
|
||||
CRGB color = ColorFromPalette( currentPalette, index, bri);
|
||||
|
||||
// Set the LED color in our array, using the XY mapping function
|
||||
// to convert from x,y coordinates to the 1D array index
|
||||
leds[XY(i,j)] = color;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the hue value for the next frame (for color cycling)
|
||||
ihue+=1;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// The main program loop that runs continuously
|
||||
|
||||
// Periodically choose a new palette, speed, and scale
|
||||
// This creates variety in the animation over time
|
||||
ChangePaletteAndSettingsPeriodically();
|
||||
|
||||
// Generate new noise data for this frame
|
||||
fillnoise8();
|
||||
|
||||
// Convert the noise data to colors in the LED array
|
||||
// using the current palette
|
||||
mapNoiseToLEDsUsingPalette();
|
||||
|
||||
// Send the color data to the actual LEDs
|
||||
FastLED.show();
|
||||
|
||||
// No delay is needed here as the calculations already take some time
|
||||
// Adding a delay would slow down the animation
|
||||
// delay(10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PALETTE MANAGEMENT:
|
||||
//
|
||||
// There are several different palettes of colors demonstrated here.
|
||||
//
|
||||
// FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
|
||||
// OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
|
||||
//
|
||||
// Additionally, you can manually define your own color palettes, or you can write
|
||||
// code that creates color palettes on the fly.
|
||||
|
||||
// This controls how long each palette is displayed before changing
|
||||
// 1 = 5 sec per palette
|
||||
// 2 = 10 sec per palette
|
||||
// etc.
|
||||
#define HOLD_PALETTES_X_TIMES_AS_LONG 1 // Multiplier for palette duration
|
||||
|
||||
// Periodically change the palette, speed, and scale settings
|
||||
void ChangePaletteAndSettingsPeriodically()
|
||||
{
|
||||
// Calculate which "second hand" we're on (0-59) based on elapsed time
|
||||
// We divide by HOLD_PALETTES_X_TIMES_AS_LONG to slow down the changes
|
||||
uint8_t secondHand = ((millis() / 1000) / HOLD_PALETTES_X_TIMES_AS_LONG) % 60;
|
||||
static uint8_t lastSecond = 99; // Track the last second to detect changes
|
||||
|
||||
// Only update when the second hand changes
|
||||
if( lastSecond != secondHand) {
|
||||
lastSecond = secondHand;
|
||||
|
||||
// Every 5 seconds, change to a different palette and settings
|
||||
// Each palette has specific speed and scale settings that work well with it
|
||||
|
||||
if( secondHand == 0) { currentPalette = RainbowColors_p; speed = 20; scale = 30; colorLoop = 1; }
|
||||
if( secondHand == 5) { SetupPurpleAndGreenPalette(); speed = 10; scale = 50; colorLoop = 1; }
|
||||
if( secondHand == 10) { SetupBlackAndWhiteStripedPalette(); speed = 20; scale = 30; colorLoop = 1; }
|
||||
if( secondHand == 15) { currentPalette = ForestColors_p; speed = 8; scale =120; colorLoop = 0; }
|
||||
if( secondHand == 20) { currentPalette = CloudColors_p; speed = 4; scale = 30; colorLoop = 0; }
|
||||
if( secondHand == 25) { currentPalette = LavaColors_p; speed = 8; scale = 50; colorLoop = 0; }
|
||||
if( secondHand == 30) { currentPalette = OceanColors_p; speed = 20; scale = 90; colorLoop = 0; }
|
||||
if( secondHand == 35) { currentPalette = PartyColors_p; speed = 20; scale = 30; colorLoop = 1; }
|
||||
if( secondHand == 40) { SetupRandomPalette(); speed = 20; scale = 20; colorLoop = 1; }
|
||||
if( secondHand == 45) { SetupRandomPalette(); speed = 50; scale = 50; colorLoop = 1; }
|
||||
if( secondHand == 50) { SetupRandomPalette(); speed = 90; scale = 90; colorLoop = 1; }
|
||||
if( secondHand == 55) { currentPalette = RainbowStripeColors_p; speed = 30; scale = 20; colorLoop = 1; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This function generates a random palette that's a gradient
|
||||
// between four different colors. The first is a dim hue, the second is
|
||||
// a bright hue, the third is a bright pastel, and the last is
|
||||
// another bright hue. This gives some visual bright/dark variation
|
||||
// which is more interesting than just a gradient of different hues.
|
||||
void SetupRandomPalette()
|
||||
{
|
||||
// Create a new palette with 4 random colors that blend together
|
||||
currentPalette = CRGBPalette16(
|
||||
CHSV( random8(), 255, 32), // Random dim hue (low value)
|
||||
CHSV( random8(), 255, 255), // Random bright hue (full saturation & value)
|
||||
CHSV( random8(), 128, 255), // Random pastel (medium saturation, full value)
|
||||
CHSV( random8(), 255, 255)); // Another random bright hue
|
||||
|
||||
// The CRGBPalette16 constructor automatically creates a 16-color gradient
|
||||
// between these four colors, evenly distributed
|
||||
}
|
||||
|
||||
|
||||
// This function sets up a palette of black and white stripes,
|
||||
// using code. Since the palette is effectively an array of
|
||||
// sixteen CRGB colors, the various fill_* functions can be used
|
||||
// to set them up.
|
||||
void SetupBlackAndWhiteStripedPalette()
|
||||
{
|
||||
// 'black out' all 16 palette entries...
|
||||
fill_solid( currentPalette, 16, CRGB::Black);
|
||||
|
||||
// and set every fourth one to white to create stripes
|
||||
// Positions 0, 4, 8, and 12 in the 16-color palette
|
||||
currentPalette[0] = CRGB::White;
|
||||
currentPalette[4] = CRGB::White;
|
||||
currentPalette[8] = CRGB::White;
|
||||
currentPalette[12] = CRGB::White;
|
||||
|
||||
// The palette interpolation will create smooth transitions between these colors
|
||||
}
|
||||
|
||||
// This function sets up a palette of purple and green stripes.
|
||||
void SetupPurpleAndGreenPalette()
|
||||
{
|
||||
// Define our colors using HSV color space for consistency
|
||||
CRGB purple = CHSV( HUE_PURPLE, 255, 255); // Bright purple
|
||||
CRGB green = CHSV( HUE_GREEN, 255, 255); // Bright green
|
||||
CRGB black = CRGB::Black; // Black
|
||||
|
||||
// Create a 16-color palette with a specific pattern:
|
||||
// green-green-black-black-purple-purple-black-black, repeated twice
|
||||
// This creates alternating green and purple stripes with black in between
|
||||
currentPalette = CRGBPalette16(
|
||||
green, green, black, black, // First 4 colors
|
||||
purple, purple, black, black, // Next 4 colors
|
||||
green, green, black, black, // Repeat the pattern
|
||||
purple, purple, black, black ); // Last 4 colors
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Mark's xy coordinate mapping code. See the XYMatrix for more information on it.
|
||||
//
|
||||
// This function converts x,y coordinates to a single array index
|
||||
// It handles both regular and serpentine matrix layouts
|
||||
uint16_t XY( uint8_t x, uint8_t y)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
// For a regular/sequential layout, it's just y * width + x
|
||||
if( kMatrixSerpentineLayout == false) {
|
||||
i = (y * kMatrixWidth) + x;
|
||||
}
|
||||
|
||||
// For a serpentine layout (zigzag), odd rows run backwards
|
||||
if( kMatrixSerpentineLayout == true) {
|
||||
if( y & 0x01) { // Check if y is odd (bitwise AND with 1)
|
||||
// Odd rows run backwards
|
||||
uint8_t reverseX = (kMatrixWidth - 1) - x;
|
||||
i = (y * kMatrixWidth) + reverseX;
|
||||
} else {
|
||||
// Even rows run forwards
|
||||
i = (y * kMatrixWidth) + x;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
#endif // End of the non-AVR code section
|
||||
|
|
@ -1,407 +1,11 @@
|
|||
/// @file NoisePlusPalette.ino
|
||||
/// @brief Demonstrates how to mix noise generation with color palettes on a 2D LED matrix
|
||||
/// @example NoisePlusPalette.ino
|
||||
///
|
||||
/// OVERVIEW:
|
||||
/// This sketch demonstrates combining Perlin noise with color palettes to create
|
||||
/// dynamic, flowing color patterns on an LED matrix. The noise function creates
|
||||
/// natural-looking patterns that change over time, while the color palettes
|
||||
/// determine which colors are used to visualize the noise values.
|
||||
|
||||
#include <FastLED.h> // Main FastLED library for controlling LEDs
|
||||
|
||||
#ifdef __AVR__
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Don't compile this for AVR microcontrollers (like Arduino Uno) because they typically
|
||||
// don't have enough memory to handle this complex animation.
|
||||
// Instead, we provide empty setup/loop functions so the sketch will compile but do nothing.
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else // For all other platforms with more memory (ESP32, Teensy, etc.)
|
||||
|
||||
// LED hardware configuration
|
||||
#define LED_PIN 3 // Data pin connected to the LED strip
|
||||
#define BRIGHTNESS 96 // Default brightness level (0-255)
|
||||
#define LED_TYPE WS2811 // Type of LED strip being used
|
||||
#define COLOR_ORDER GRB // Color order of the LEDs (varies by strip type)
|
||||
|
||||
// Matrix dimensions - defines the size of our virtual LED grid
|
||||
const uint8_t kMatrixWidth = 16; // Number of columns in the matrix
|
||||
const uint8_t kMatrixHeight = 16; // Number of rows in the matrix
|
||||
|
||||
// LED strip layout configuration
|
||||
const bool kMatrixSerpentineLayout = true; // If true, every other row runs backwards
|
||||
// This is common in matrix setups to allow
|
||||
// for easier wiring
|
||||
|
||||
|
||||
// HOW THIS EXAMPLE WORKS:
|
||||
//
|
||||
// This example combines two features of FastLED to produce a remarkable range of
|
||||
// effects from a relatively small amount of code. This example combines FastLED's
|
||||
// color palette lookup functions with FastLED's Perlin noise generator, and
|
||||
// the combination is extremely powerful.
|
||||
//
|
||||
// You might want to look at the "ColorPalette" and "Noise" examples separately
|
||||
// if this example code seems daunting.
|
||||
//
|
||||
//
|
||||
// The basic setup here is that for each frame, we generate a new array of
|
||||
// 'noise' data, and then map it onto the LED matrix through a color palette.
|
||||
//
|
||||
// Periodically, the color palette is changed, and new noise-generation parameters
|
||||
// are chosen at the same time. In this example, specific noise-generation
|
||||
// values have been selected to match the given color palettes; some are faster,
|
||||
// or slower, or larger, or smaller than others, but there's no reason these
|
||||
// parameters can't be freely mixed-and-matched.
|
||||
//
|
||||
// In addition, this example includes some fast automatic 'data smoothing' at
|
||||
// lower noise speeds to help produce smoother animations in those cases.
|
||||
//
|
||||
// The FastLED built-in color palettes (Forest, Clouds, Lava, Ocean, Party) are
|
||||
// used, as well as some 'hand-defined' ones, and some procedurally generated
|
||||
// palettes.
|
||||
|
||||
|
||||
// Calculate the total number of LEDs in our matrix
|
||||
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
|
||||
|
||||
// Find the larger dimension (width or height) for our noise array size
|
||||
#define MAX_DIMENSION ((kMatrixWidth>kMatrixHeight) ? kMatrixWidth : kMatrixHeight)
|
||||
|
||||
// Array to hold all LED color values - one CRGB struct per LED
|
||||
CRGB leds[kMatrixWidth * kMatrixHeight];
|
||||
|
||||
// The 16-bit version of our coordinates for the noise function
|
||||
// Using 16 bits gives us more resolution and smoother animations
|
||||
static uint16_t x; // x-coordinate in the noise space
|
||||
static uint16_t y; // y-coordinate in the noise space
|
||||
static uint16_t z; // z-coordinate (time dimension) in the noise space
|
||||
|
||||
// ANIMATION PARAMETERS:
|
||||
|
||||
// We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll
|
||||
// use the z-axis for "time". speed determines how fast time moves forward. Try
|
||||
// 1 for a very slow moving effect, or 60 for something that ends up looking like
|
||||
// water.
|
||||
uint16_t speed = 20; // Speed is set dynamically once we've started up
|
||||
// Higher values = faster animation
|
||||
|
||||
// Scale determines how far apart the pixels in our noise matrix are. Try
|
||||
// changing these values around to see how it affects the motion of the display. The
|
||||
// higher the value of scale, the more "zoomed out" the noise will be. A value
|
||||
// of 1 will be so zoomed in, you'll mostly see solid colors.
|
||||
uint16_t scale = 30; // Scale is set dynamically once we've started up
|
||||
// Higher values = more "zoomed out" pattern
|
||||
|
||||
// This is the array that we keep our computed noise values in
|
||||
// Each position stores an 8-bit (0-255) noise value
|
||||
uint8_t noise[MAX_DIMENSION][MAX_DIMENSION];
|
||||
|
||||
// The current color palette we're using to map noise values to colors
|
||||
CRGBPalette16 currentPalette( PartyColors_p ); // Start with party colors
|
||||
|
||||
// If colorLoop is set to 1, we'll cycle through the colors in the palette
|
||||
// This creates an additional animation effect on top of the noise movement
|
||||
uint8_t colorLoop = 1; // 0 = no color cycling, 1 = cycle colors
|
||||
|
||||
|
||||
// Forward declare our functions so that we have maximum compatibility
|
||||
// with other build tools outside of ArduinoIDE. The *.ino files are
|
||||
// special in that Arduino will generate function prototypes for you.
|
||||
// For non-Arduino environments, we need these declarations.
|
||||
void SetupRandomPalette(); // Creates a random color palette
|
||||
void SetupPurpleAndGreenPalette(); // Creates a purple and green striped palette
|
||||
void SetupBlackAndWhiteStripedPalette(); // Creates a black and white striped palette
|
||||
void ChangePaletteAndSettingsPeriodically(); // Changes palettes and settings over time
|
||||
void mapNoiseToLEDsUsingPalette(); // Maps noise data to LED colors using the palette
|
||||
uint16_t XY( uint8_t x, uint8_t y); // Converts x,y coordinates to LED array index
|
||||
|
||||
void setup() {
|
||||
delay(3000); // 3 second delay for recovery and to give time for the serial monitor to open
|
||||
|
||||
// Initialize the LED strip:
|
||||
// - LED_TYPE specifies the chipset (WS2811, WS2812B, etc.)
|
||||
// - LED_PIN is the data pin number
|
||||
// - COLOR_ORDER specifies the RGB color ordering for your strip
|
||||
FastLED.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,NUM_LEDS);
|
||||
// NOTE - This does NOT have a ScreenMap (because it's a legacy sketch)
|
||||
// so it won't look that good on the web-compiler. But adding it is ONE LINE!
|
||||
|
||||
// Set the overall brightness level (0-255)
|
||||
FastLED.setBrightness(BRIGHTNESS);
|
||||
|
||||
// Initialize our noise coordinates to random values
|
||||
// This ensures the pattern starts from a different position each time
|
||||
x = random16(); // Random x starting position
|
||||
y = random16(); // Random y starting position
|
||||
z = random16(); // Random time starting position
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Fill the x/y array of 8-bit noise values using the inoise8 function.
|
||||
void fillnoise8() {
|
||||
// If we're running at a low "speed", some 8-bit artifacts become visible
|
||||
// from frame-to-frame. In order to reduce this, we can do some fast data-smoothing.
|
||||
// The amount of data smoothing we're doing depends on "speed".
|
||||
uint8_t dataSmoothing = 0;
|
||||
if( speed < 50) {
|
||||
// At lower speeds, apply more smoothing
|
||||
// This formula creates more smoothing at lower speeds:
|
||||
// speed=10 → smoothing=160, speed=30 → smoothing=80
|
||||
dataSmoothing = 200 - (speed * 4);
|
||||
}
|
||||
|
||||
// Loop through each pixel in our noise array
|
||||
for(int i = 0; i < MAX_DIMENSION; i++) {
|
||||
// Calculate the offset for this pixel in the x dimension
|
||||
int ioffset = scale * i;
|
||||
|
||||
for(int j = 0; j < MAX_DIMENSION; j++) {
|
||||
// Calculate the offset for this pixel in the y dimension
|
||||
int joffset = scale * j;
|
||||
|
||||
// Generate the noise value for this pixel using 3D Perlin noise
|
||||
// The noise function takes x, y, and z (time) coordinates
|
||||
uint8_t data = inoise8(x + ioffset, y + joffset, z);
|
||||
|
||||
// The range of the inoise8 function is roughly 16-238.
|
||||
// These two operations expand those values out to roughly 0..255
|
||||
// You can comment them out if you want the raw noise data.
|
||||
data = qsub8(data, 16); // Subtract 16 (with underflow protection)
|
||||
data = qadd8(data, scale8(data, 39)); // Add a scaled version of the data to itself
|
||||
|
||||
// Apply data smoothing if enabled
|
||||
if( dataSmoothing ) {
|
||||
uint8_t olddata = noise[i][j]; // Get the previous frame's value
|
||||
|
||||
// Blend between old and new data based on smoothing amount
|
||||
// Higher dataSmoothing = more of the old value is kept
|
||||
uint8_t newdata = scale8(olddata, dataSmoothing) +
|
||||
scale8(data, 256 - dataSmoothing);
|
||||
data = newdata;
|
||||
}
|
||||
|
||||
// Store the final noise value in our array
|
||||
noise[i][j] = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment z to move through the noise space over time
|
||||
z += speed;
|
||||
|
||||
// Apply slow drift to X and Y, just for visual variation
|
||||
// This creates a gentle shifting of the entire pattern
|
||||
x += speed / 8; // X drifts at 1/8 the speed of z
|
||||
y -= speed / 16; // Y drifts at 1/16 the speed of z in the opposite direction
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Map the noise data to LED colors using the current color palette
|
||||
void mapNoiseToLEDsUsingPalette()
|
||||
{
|
||||
// Static variable that slowly increases to cycle through colors when colorLoop is enabled
|
||||
static uint8_t ihue=0;
|
||||
|
||||
// Loop through each pixel in our LED matrix
|
||||
for(int i = 0; i < kMatrixWidth; i++) {
|
||||
for(int j = 0; j < kMatrixHeight; j++) {
|
||||
// We use the value at the (i,j) coordinate in the noise
|
||||
// array for our brightness, and the flipped value from (j,i)
|
||||
// for our pixel's index into the color palette.
|
||||
// This creates interesting patterns with two different noise mappings.
|
||||
|
||||
uint8_t index = noise[j][i]; // Color index from the flipped coordinate
|
||||
uint8_t bri = noise[i][j]; // Brightness from the normal coordinate
|
||||
|
||||
// If color cycling is enabled, add a slowly-changing base value to the index
|
||||
// This makes the colors shift/rotate through the palette over time
|
||||
if( colorLoop) {
|
||||
index += ihue; // Add the slowly increasing hue offset
|
||||
}
|
||||
|
||||
// Brighten up the colors, as the color palette itself often contains the
|
||||
// light/dark dynamic range desired
|
||||
if( bri > 127 ) {
|
||||
// If brightness is in the upper half, make it full brightness
|
||||
bri = 255;
|
||||
} else {
|
||||
// Otherwise, scale it to the full range (0-127 becomes 0-254)
|
||||
bri = dim8_raw( bri * 2);
|
||||
}
|
||||
|
||||
// Get the final color by looking up the palette color at our index
|
||||
// and applying the brightness value
|
||||
CRGB color = ColorFromPalette( currentPalette, index, bri);
|
||||
|
||||
// Set the LED color in our array, using the XY mapping function
|
||||
// to convert from x,y coordinates to the 1D array index
|
||||
leds[XY(i,j)] = color;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the hue value for the next frame (for color cycling)
|
||||
ihue+=1;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// The main program loop that runs continuously
|
||||
|
||||
// Periodically choose a new palette, speed, and scale
|
||||
// This creates variety in the animation over time
|
||||
ChangePaletteAndSettingsPeriodically();
|
||||
|
||||
// Generate new noise data for this frame
|
||||
fillnoise8();
|
||||
|
||||
// Convert the noise data to colors in the LED array
|
||||
// using the current palette
|
||||
mapNoiseToLEDsUsingPalette();
|
||||
|
||||
// Send the color data to the actual LEDs
|
||||
FastLED.show();
|
||||
|
||||
// No delay is needed here as the calculations already take some time
|
||||
// Adding a delay would slow down the animation
|
||||
// delay(10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PALETTE MANAGEMENT:
|
||||
//
|
||||
// There are several different palettes of colors demonstrated here.
|
||||
//
|
||||
// FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
|
||||
// OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
|
||||
//
|
||||
// Additionally, you can manually define your own color palettes, or you can write
|
||||
// code that creates color palettes on the fly.
|
||||
|
||||
// This controls how long each palette is displayed before changing
|
||||
// 1 = 5 sec per palette
|
||||
// 2 = 10 sec per palette
|
||||
// etc.
|
||||
#define HOLD_PALETTES_X_TIMES_AS_LONG 1 // Multiplier for palette duration
|
||||
|
||||
// Periodically change the palette, speed, and scale settings
|
||||
void ChangePaletteAndSettingsPeriodically()
|
||||
{
|
||||
// Calculate which "second hand" we're on (0-59) based on elapsed time
|
||||
// We divide by HOLD_PALETTES_X_TIMES_AS_LONG to slow down the changes
|
||||
uint8_t secondHand = ((millis() / 1000) / HOLD_PALETTES_X_TIMES_AS_LONG) % 60;
|
||||
static uint8_t lastSecond = 99; // Track the last second to detect changes
|
||||
|
||||
// Only update when the second hand changes
|
||||
if( lastSecond != secondHand) {
|
||||
lastSecond = secondHand;
|
||||
|
||||
// Every 5 seconds, change to a different palette and settings
|
||||
// Each palette has specific speed and scale settings that work well with it
|
||||
|
||||
if( secondHand == 0) { currentPalette = RainbowColors_p; speed = 20; scale = 30; colorLoop = 1; }
|
||||
if( secondHand == 5) { SetupPurpleAndGreenPalette(); speed = 10; scale = 50; colorLoop = 1; }
|
||||
if( secondHand == 10) { SetupBlackAndWhiteStripedPalette(); speed = 20; scale = 30; colorLoop = 1; }
|
||||
if( secondHand == 15) { currentPalette = ForestColors_p; speed = 8; scale =120; colorLoop = 0; }
|
||||
if( secondHand == 20) { currentPalette = CloudColors_p; speed = 4; scale = 30; colorLoop = 0; }
|
||||
if( secondHand == 25) { currentPalette = LavaColors_p; speed = 8; scale = 50; colorLoop = 0; }
|
||||
if( secondHand == 30) { currentPalette = OceanColors_p; speed = 20; scale = 90; colorLoop = 0; }
|
||||
if( secondHand == 35) { currentPalette = PartyColors_p; speed = 20; scale = 30; colorLoop = 1; }
|
||||
if( secondHand == 40) { SetupRandomPalette(); speed = 20; scale = 20; colorLoop = 1; }
|
||||
if( secondHand == 45) { SetupRandomPalette(); speed = 50; scale = 50; colorLoop = 1; }
|
||||
if( secondHand == 50) { SetupRandomPalette(); speed = 90; scale = 90; colorLoop = 1; }
|
||||
if( secondHand == 55) { currentPalette = RainbowStripeColors_p; speed = 30; scale = 20; colorLoop = 1; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This function generates a random palette that's a gradient
|
||||
// between four different colors. The first is a dim hue, the second is
|
||||
// a bright hue, the third is a bright pastel, and the last is
|
||||
// another bright hue. This gives some visual bright/dark variation
|
||||
// which is more interesting than just a gradient of different hues.
|
||||
void SetupRandomPalette()
|
||||
{
|
||||
// Create a new palette with 4 random colors that blend together
|
||||
currentPalette = CRGBPalette16(
|
||||
CHSV( random8(), 255, 32), // Random dim hue (low value)
|
||||
CHSV( random8(), 255, 255), // Random bright hue (full saturation & value)
|
||||
CHSV( random8(), 128, 255), // Random pastel (medium saturation, full value)
|
||||
CHSV( random8(), 255, 255)); // Another random bright hue
|
||||
|
||||
// The CRGBPalette16 constructor automatically creates a 16-color gradient
|
||||
// between these four colors, evenly distributed
|
||||
}
|
||||
|
||||
|
||||
// This function sets up a palette of black and white stripes,
|
||||
// using code. Since the palette is effectively an array of
|
||||
// sixteen CRGB colors, the various fill_* functions can be used
|
||||
// to set them up.
|
||||
void SetupBlackAndWhiteStripedPalette()
|
||||
{
|
||||
// 'black out' all 16 palette entries...
|
||||
fill_solid( currentPalette, 16, CRGB::Black);
|
||||
|
||||
// and set every fourth one to white to create stripes
|
||||
// Positions 0, 4, 8, and 12 in the 16-color palette
|
||||
currentPalette[0] = CRGB::White;
|
||||
currentPalette[4] = CRGB::White;
|
||||
currentPalette[8] = CRGB::White;
|
||||
currentPalette[12] = CRGB::White;
|
||||
|
||||
// The palette interpolation will create smooth transitions between these colors
|
||||
}
|
||||
|
||||
// This function sets up a palette of purple and green stripes.
|
||||
void SetupPurpleAndGreenPalette()
|
||||
{
|
||||
// Define our colors using HSV color space for consistency
|
||||
CRGB purple = CHSV( HUE_PURPLE, 255, 255); // Bright purple
|
||||
CRGB green = CHSV( HUE_GREEN, 255, 255); // Bright green
|
||||
CRGB black = CRGB::Black; // Black
|
||||
|
||||
// Create a 16-color palette with a specific pattern:
|
||||
// green-green-black-black-purple-purple-black-black, repeated twice
|
||||
// This creates alternating green and purple stripes with black in between
|
||||
currentPalette = CRGBPalette16(
|
||||
green, green, black, black, // First 4 colors
|
||||
purple, purple, black, black, // Next 4 colors
|
||||
green, green, black, black, // Repeat the pattern
|
||||
purple, purple, black, black ); // Last 4 colors
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Mark's xy coordinate mapping code. See the XYMatrix for more information on it.
|
||||
//
|
||||
// This function converts x,y coordinates to a single array index
|
||||
// It handles both regular and serpentine matrix layouts
|
||||
uint16_t XY( uint8_t x, uint8_t y)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
// For a regular/sequential layout, it's just y * width + x
|
||||
if( kMatrixSerpentineLayout == false) {
|
||||
i = (y * kMatrixWidth) + x;
|
||||
}
|
||||
|
||||
// For a serpentine layout (zigzag), odd rows run backwards
|
||||
if( kMatrixSerpentineLayout == true) {
|
||||
if( y & 0x01) { // Check if y is odd (bitwise AND with 1)
|
||||
// Odd rows run backwards
|
||||
uint8_t reverseX = (kMatrixWidth - 1) - x;
|
||||
i = (y * kMatrixWidth) + reverseX;
|
||||
} else {
|
||||
// Even rows run forwards
|
||||
i = (y * kMatrixWidth) + x;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
#include "NoisePlusPalette.h"
|
||||
#endif // End of the non-AVR code section
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
/// @file Overclock.ino
|
||||
/// @brief Demonstrates how to overclock a FastLED setup
|
||||
|
||||
#include "FastLED.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// To effectively test the overclock feature we need
|
||||
// a large enough dataset to test against. Unfortunately
|
||||
// the avr platforms don't have enough memory so this example
|
||||
|
|
|
|||
|
|
@ -8,9 +8,6 @@
|
|||
// Animated, ever-changing rainbows.
|
||||
// by Mark Kriegsman
|
||||
|
||||
#if FASTLED_VERSION < 3001000
|
||||
#error "Requires FastLED 3.1 or later; check github for latest code."
|
||||
#endif
|
||||
|
||||
#define DATA_PIN 3
|
||||
//#define CLK_PIN 4
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
This is a 1D wave simluation!
|
||||
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
@ -27,7 +32,6 @@ all the UI elements you see below.
|
|||
#include "src/xypaths.h"
|
||||
#include "fl/function.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace fl;
|
||||
|
||||
|
|
@ -37,8 +41,6 @@ using namespace fl;
|
|||
#define IS_SERPINTINE true
|
||||
#define TIME_ANIMATION 1000 // ms
|
||||
|
||||
// CRGB leds[NUM_LEDS];
|
||||
|
||||
LedsXY<WIDTH, HEIGHT> leds;
|
||||
XYMap xyMap(WIDTH, HEIGHT, IS_SERPINTINE);
|
||||
UITitle title("Simple control of an xy path");
|
||||
|
|
@ -49,31 +51,21 @@ UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f);
|
|||
UISlider steps("Steps", 100.0f, 1.0f, 200.0f, 1.0f);
|
||||
UISlider length("Length", 1.0f, 0.0f, 1.0f, 0.01f);
|
||||
|
||||
|
||||
XYPathPtr heartPath = XYPath::NewHeartPath(WIDTH, HEIGHT);
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
auto screenmap = xyMap.toScreenMap();
|
||||
screenmap.setDiameter(.2);
|
||||
FastLED.addLeds<NEOPIXEL, 2>(leds, NUM_LEDS).setScreenMap(screenmap);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
fl::clear(leds);
|
||||
|
||||
// FASTLED_ASSERT(false, "This is a test");
|
||||
|
||||
// leds(x,y) = CRGB(255, 0, 0);
|
||||
float from = offset;
|
||||
float to = length.value() + offset.value();
|
||||
|
||||
heartPath->drawColor(CRGB(255, 0, 0), from, to, &leds, steps.as_int());
|
||||
|
||||
|
||||
FastLED.show();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
/*
|
||||
This demo is best viewed using the FastLED compiler.
|
||||
|
||||
Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
|
||||
|
||||
Python
|
||||
|
||||
Install: pip install fastled
|
||||
Run: fastled <this sketch directory>
|
||||
This will compile and preview the sketch in the browser, and enable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue