FastLED 3.9.15
Loading...
Searching...
No Matches
Animartrix.ino
Go to the documentation of this file.
1// @filter: (memory is large)
2
16
17/*
18This demo is best viewed using the FastLED compiler.
19
20Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
21
22Python
23
24Install: pip install fastled
25Run: fastled <this sketch directory>
26This will compile and preview the sketch in the browser, and enable
27all the UI elements you see below.
28
29
30
31OVERVIEW:
32This is the famouse Animartrix demo by Stefan Petrick. The effects are generated
33using polor polar coordinates. The effects are very complex and powerful.
34*/
35
36#define FL_ANIMARTRIX_USES_FAST_MATH 1
37
38/*
39Performence notes @64x64:
40 * ESP32-S3:
41 * FL_ANIMARTRIX_USES_FAST_MATH 0: 143ms
42 * FL_ANIMARTRIX_USES_FAST_MATH 1: 90ms
43*/
44
45#include "FastLED.h"
46
47#if defined(FL_IS_TEENSY)
48// Keep fbuild's library scanner aware of PJRC Audio sources for Teensy.
49#include <Audio.h>
50#endif
51
52// DRAW TIME: 7ms
53
54
55#include <FastLED.h>
56#include "fl/stl/json.h"
57#include "fl/stl/span.h"
58#include "fl/fx/fx_engine.h"
59
61#include "fl/ui/ui.h"
64
65#ifndef PIN_DATA
66#define PIN_DATA 3
67#endif // PIN_DATA
68
69#ifndef LED_PIN
70#define LED_PIN PIN_DATA
71#endif // LED_PIN
72
73#define BRIGHTNESS 32
74#define COLOR_ORDER GRB
75
76#define MATRIX_WIDTH 64
77#define MATRIX_HEIGHT 64
78
79#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
80
81#define FIRST_ANIMATION fl::AnimartrixAnim::POLAR_WAVES
82
83// This is purely use for the web compiler to display the animartrix effects.
84// This small led was chosen because otherwise the bloom effect is too strong.
85#define LED_DIAMETER 0.15 // .15 cm or 1.5mm
86
87
88#define POWER_LIMITER_ACTIVE
89#define POWER_VOLTS 5
90#define POWER_MILLIAMPS 2000
91
92
95
96
97fl::UITitle title("Animartrix");
98fl::UIDescription description("Demo of the Animatrix effects. @author of fx is StefanPetrick");
99
100fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255);
101fl::UIDropdown fxIndex("Animartrix - index", {
102 "RGB_BLOBS5", "RGB_BLOBS4", "RGB_BLOBS3", "RGB_BLOBS2", "RGB_BLOBS",
103 "POLAR_WAVES", "SLOW_FADE", "ZOOM2", "ZOOM", "HOT_BLOB",
104 "SPIRALUS2", "SPIRALUS", "YVES", "SCALEDEMO1", "LAVA1",
105 "CALEIDO3", "CALEIDO2", "CALEIDO1", "DISTANCE_EXPERIMENT", "CENTER_FIELD",
106 "WAVES", "CHASING_SPIRALS", "ROTATING_BLOB", "RINGS", "COMPLEX_KALEIDO",
107 "COMPLEX_KALEIDO_2", "COMPLEX_KALEIDO_3", "COMPLEX_KALEIDO_4", "COMPLEX_KALEIDO_5", "COMPLEX_KALEIDO_6",
108 "WATER", "PARAMETRIC_WATER", "MODULE_EXPERIMENT1", "MODULE_EXPERIMENT2", "MODULE_EXPERIMENT3",
109 "MODULE_EXPERIMENT4", "MODULE_EXPERIMENT5", "MODULE_EXPERIMENT6", "MODULE_EXPERIMENT7", "MODULE_EXPERIMENT8",
110 "MODULE_EXPERIMENT9", "MODULE_EXPERIMENT10", "MODULE_EXPERIMENT_SM1", "MODULE_EXPERIMENT_SM2", "MODULE_EXPERIMENT_SM3",
111 "MODULE_EXPERIMENT_SM4", "MODULE_EXPERIMENT_SM5", "MODULE_EXPERIMENT_SM6", "MODULE_EXPERIMENT_SM8", "MODULE_EXPERIMENT_SM9",
112 "MODULE_EXPERIMENT_SM10", "FLUFFY_BLOBS"
113});
114fl::UIDropdown colorOrder("Color Order", {"RGB", "RBG", "GRB", "GBR", "BRG", "BGR"});
115fl::UISlider timeSpeed("Time Speed", 1, -10, 10, .1);
116
117// Audio UI controls
118fl::UIAudio audio("Audio Input");
119fl::UICheckbox enableVibeReactive("Enable Vibe Reactive", false);
120fl::UISlider vibeSpeedMultiplier("Vibe Speed Multiplier", 3.0, 0.0, 10.0, 0.1);
121fl::UISlider vibeBaseSpeed("Vibe Base Speed", 1.0, 0.0, 5.0, 0.1);
122
123// Processor with Vibe
125
128
129const bool kPowerLimiterActive = false;
130
133 FastLED.setMaxPowerInVoltsAndMilliamps(POWER_VOLTS, POWER_MILLIAMPS); // Set max power to 2 amps
134 }
135}
136
137
138void setup() {
139 Serial.begin(115200);
140 FL_WARN("*** SETUP ***");
141
142 auto screen_map = xyMap.toScreenMap();
143 screen_map.setDiameter(LED_DIAMETER);
144 FastLED.addLeds<WS2811, PIN_DATA, COLOR_ORDER>(leds, NUM_LEDS)
145 .setCorrection(TypicalLEDStrip)
146 .setScreenMap(screen_map);
147 FastLED.setBrightness(brightness);
149 fxEngine.addFx(animartrix);
150
151 colorOrder.onChanged([](fl::UIDropdown &dropdown) {
152 int value = dropdown.as_int();
153 switch(value) {
154 case 0: value = static_cast<int>(RGB); break;
155 case 1: value = static_cast<int>(RBG); break;
156 case 2: value = static_cast<int>(GRB); break;
157 case 3: value = static_cast<int>(GBR); break;
158 case 4: value = static_cast<int>(BRG); break;
159 case 5: value = static_cast<int>(BGR); break;
160 }
161 animartrix.setColorOrder(static_cast<fl::EOrder>(value));
162 });
163
164 // Hook Vibe bass level to FxEngine timewarp.
165 // onVibeLevels fires every frame with self-normalizing levels:
166 // bass ~1.0 = average, >1.0 = louder than normal, <1.0 = quieter
167 // We map bass level directly to animation speed so beats accelerate
168 // the animation.
169 audioProcessor.onVibeLevels([](const fl::audio::detector::VibeLevels &vibe) {
170 if (!enableVibeReactive.value()) {
171 return;
172 }
173 // Print beat/mid/treble levels and spike flags each frame
174 FL_WARN("Vibe: bass=" << vibe.bass << " mid=" << vibe.mid << " treb=" << vibe.treb
175 << " | spikes: bass=" << vibe.bassSpike << " mid=" << vibe.midSpike << " treb=" << vibe.trebSpike);
176
177 float bassBoost = (vibe.bass - 1.0f) * vibeSpeedMultiplier.value();
178 float speed = vibeBaseSpeed.value() + bassBoost;
179 speed *= timeSpeed.value();
180 fxEngine.setSpeed(speed);
181 });
182
183 // Log spike events
184 audioProcessor.onVibeBassSpike([]() {
185 FL_WARN(">>> BASS SPIKE!");
186 });
187 audioProcessor.onVibeMidSpike([]() {
188 FL_WARN(">>> MID SPIKE!");
189 });
190 audioProcessor.onVibeTrebSpike([]() {
191 FL_WARN(">>> TREB SPIKE!");
192 });
193}
194
195void loop() {
196 FL_WARN("*** LOOP ***");
197 uint32_t start = fl::millis();
198 FastLED.setBrightness(brightness);
199
200 // Always drain audio samples from the ring buffer to prevent overflow,
201 // and process them when vibe reactive is enabled.
202 {
203 fl::audio::Sample sample = audio.next();
204 if (sample.isValid()) {
205 static uint32_t sAudioSamples = 0;
206 sAudioSamples++;
207 if (sAudioSamples == 1) {
208 FL_WARN("Animartrix: First audio sample received! enableVibeReactive=" << (int)enableVibeReactive.value());
209 } else if (sAudioSamples % 172 == 0) {
210 FL_WARN("Animartrix: " << sAudioSamples << " audio samples processed, enableVibeReactive=" << (int)enableVibeReactive.value());
211 }
212 if (enableVibeReactive.value()) {
213 audioProcessor.update(sample);
214 }
215 }
216 if (!enableVibeReactive.value()) {
217 fxEngine.setSpeed(timeSpeed);
218 }
219 }
220
221 static int lastFxIndex = -1;
222 if (fxIndex.as_int() != lastFxIndex) {
223 lastFxIndex = fxIndex.as_int();
224 animartrix.fxSet(fxIndex.as_int());
225 }
226 fxEngine.draw(fl::millis(), leds);
227 uint32_t end = fl::millis();
228 FL_WARN("*** DRAW TIME: " << int(end - start) << "ms");
229 FastLED.show();
230 uint32_t end2 = fl::millis();
231 FL_WARN("*** SHOW + DRAW TIME: " << int(end2 - start) << "ms");
232}
#define COLOR_ORDER
fl::UIAudio audio("Audio Input")
#define MATRIX_HEIGHT
fl::UISlider vibeSpeedMultiplier("Vibe Speed Multiplier", 3.0, 0.0, 10.0, 0.1)
fl::XYMap xyMap
fl::audio::Processor audioProcessor
fl::UICheckbox enableVibeReactive("Enable Vibe Reactive", false)
fl::FxEngine fxEngine(NUM_LEDS)
#define NUM_LEDS
void setup()
fl::UIDescription description("Demo of the Animatrix effects. @author of fx is StefanPetrick")
fl::Animartrix animartrix(xyMap, FIRST_ANIMATION)
#define PIN_DATA
fl::UITitle title("Animartrix")
#define LED_DIAMETER
#define POWER_MILLIAMPS
#define POWER_VOLTS
fl::CRGB leds[NUM_LEDS]
const bool kPowerLimiterActive
fl::UIDropdown fxIndex("Animartrix - index", { "RGB_BLOBS5", "RGB_BLOBS4", "RGB_BLOBS3", "RGB_BLOBS2", "RGB_BLOBS", "POLAR_WAVES", "SLOW_FADE", "ZOOM2", "ZOOM", "HOT_BLOB", "SPIRALUS2", "SPIRALUS", "YVES", "SCALEDEMO1", "LAVA1", "CALEIDO3", "CALEIDO2", "CALEIDO1", "DISTANCE_EXPERIMENT", "CENTER_FIELD", "WAVES", "CHASING_SPIRALS", "ROTATING_BLOB", "RINGS", "COMPLEX_KALEIDO", "COMPLEX_KALEIDO_2", "COMPLEX_KALEIDO_3", "COMPLEX_KALEIDO_4", "COMPLEX_KALEIDO_5", "COMPLEX_KALEIDO_6", "WATER", "PARAMETRIC_WATER", "MODULE_EXPERIMENT1", "MODULE_EXPERIMENT2", "MODULE_EXPERIMENT3", "MODULE_EXPERIMENT4", "MODULE_EXPERIMENT5", "MODULE_EXPERIMENT6", "MODULE_EXPERIMENT7", "MODULE_EXPERIMENT8", "MODULE_EXPERIMENT9", "MODULE_EXPERIMENT10", "MODULE_EXPERIMENT_SM1", "MODULE_EXPERIMENT_SM2", "MODULE_EXPERIMENT_SM3", "MODULE_EXPERIMENT_SM4", "MODULE_EXPERIMENT_SM5", "MODULE_EXPERIMENT_SM6", "MODULE_EXPERIMENT_SM8", "MODULE_EXPERIMENT_SM9", "MODULE_EXPERIMENT_SM10", "FLUFFY_BLOBS" })
fl::UISlider timeSpeed("Time Speed", 1, -10, 10,.1)
fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255)
fl::UIDropdown colorOrder("Color Order", {"RGB", "RBG", "GRB", "GBR", "BRG", "BGR"})
#define BRIGHTNESS
#define FIRST_ANIMATION
void setup_max_power()
#define MATRIX_WIDTH
fl::UISlider vibeBaseSpeed("Vibe Base Speed", 1.0, 0.0, 5.0, 0.1)
void loop()
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
uint16_t speed
Definition Noise.ino:66
Manages and renders multiple visual effects (Fx) for LED strips.
Definition fx_engine.h:33
int as_int() const FL_NOEXCEPT
Definition dropdown.h:127
static XYMap constructRectangularGrid(u16 width, u16 height, u16 offset=0) FL_NOEXCEPT
Definition xymap.cpp.hpp:35
constexpr EOrder BGR
Definition eorder.h:22
constexpr EOrder RBG
Definition eorder.h:18
constexpr EOrder BRG
Definition eorder.h:21
constexpr EOrder GRB
Definition eorder.h:19
constexpr EOrder RGB
Definition eorder.h:17
constexpr EOrder GBR
Definition eorder.h:20
@ TypicalLEDStrip
Typical values for SMD5050 LEDs.
Definition color.h:15
FastLED's Elegant JSON Library: fl::json
#define FL_WARN(X)
Definition log.h:276
fl::u32 millis()
Universal millisecond timer - returns milliseconds since system startup.
EOrder
RGB color channel orderings, used when instantiating controllers to determine what order the controll...
Definition eorder.h:13
Representation of an 8-bit RGB pixel (Red, Green, Blue)
Definition crgb.h:38
#define Serial
Definition serial.h:304
Aggregator header for the fl/ui/ family of per-element UI types.