#include <FastLED.h>
#include "shapes.h" // has animations[], totalAnimations
// ------------------ Pin definitions ---------------------
#define LED_PIN_STRIP_1 4
#define LED_PIN_STRIP_2 5
#define LED_PIN_STRIP_3 6
// ------------------ LED counts --------------------------
#define SMALL_RING_LEDS 28
#define BASE_RING_LEDS 42
#define LARGE_RING_LEDS 51
#define LED_GROUPS 7
// How many LEDs are in each group:
const uint16_t ledsInGroup = SMALL_RING_LEDS + BASE_RING_LEDS + LARGE_RING_LEDS;
// Arrays for each of the 7 LED groups:
CRGB leds_1[121];
CRGB leds_2[121];
CRGB leds_3[121];
// Pointer array for convenience:
CRGB* ledGroups[LED_GROUPS] = {
leds_1, leds_2, leds_3
};
// --------------------------------------------------------
// Global Variables
// --------------------------------------------------------
uint8_t currentAnim = 0; // which animation are we showing now
uint8_t currentFrame = 0; // which frame in that animation
bool reverseAnimatione = false;
// --------------------------------------------------------
// Function Declarations
// --------------------------------------------------------
CRGB getColorInAnimationFrame(uint8_t animIndex, uint8_t frameIndex,
uint8_t group, uint16_t led);
void morphAnimationFrames(uint8_t animIndex, uint8_t frameFrom,
uint8_t frameTo, uint16_t durationMs);
// --------------------------------------------------------
// Setup
// --------------------------------------------------------
void setup() {
Serial.begin(9600);
// Initialize LED strips
FastLED.addLeds<WS2812, LED_PIN_STRIP_1, GRB>(leds_1, ledsInGroup);
FastLED.addLeds<WS2812, LED_PIN_STRIP_2, GRB>(leds_2, ledsInGroup);
FastLED.addLeds<WS2812, LED_PIN_STRIP_3, GRB>(leds_3, ledsInGroup);
}
// --------------------------------------------------------
// Loop
// --------------------------------------------------------
void loop() {
int blowVal1 = analogRead(A0);
int blowVal2 = analogRead(A1);
int diff = abs(blowVal1 - blowVal2);
// 1) If difference is small, morph to the next frame
if (diff < 50) {
uint8_t nextFrame;
nextFrame = (currentFrame + 1) % animations[currentAnim].numFrames;
morphAnimationFrames(currentAnim, currentFrame, nextFrame, 2);
currentFrame = nextFrame;
/* if (currentFrame == animations[currentAnim].numFrames - 1) {
currentAnim = (currentAnim + 1) % totalAnimations;
} */
}
FastLED.show();
delay(20);
}
// --------------------------------------------------------
// getColorInAnimationFrame(animIndex, frameIndex, group, led)
// --------------------------------------------------------
CRGB getColorInAnimationFrame(uint8_t animIndex, uint8_t frameIndex,
uint8_t group, uint16_t led)
{
// Safety checks
if (animIndex >= totalAnimations) return CRGB::Black;
const Animation &anim = animations[animIndex];
if (frameIndex >= anim.numFrames) return CRGB::Black;
// Grab the shape for that frame
const Shape &shape = anim.frames[frameIndex];
// Check each segment in the shape
for (uint8_t i = 0; i < shape.numSegments; i++) {
const LedSegment &seg = shape.segments[i];
if (seg.group == group && led >= seg.startIndex && led <= seg.endIndex) {
// Convert CHSV to CRGB
CRGB rgb;
hsv2rgb_rainbow(seg.color, rgb);
return rgb;
}
}
// Not in any segment -> black
return CRGB::Black;
}
// --------------------------------------------------------
// morphAnimationFrames(animIndex, fromFrame, toFrame, durationMs)
// --------------------------------------------------------
void morphAnimationFrames(uint8_t animIndex, uint8_t frameFrom,
uint8_t frameTo, uint16_t durationMs)
{
// Safety checks
if (animIndex >= totalAnimations) return;
const Animation &anim = animations[animIndex];
if (frameFrom >= anim.numFrames || frameTo >= anim.numFrames) return;
// Increase `steps` for a smoother, more fluid fade
const uint16_t steps = 10;
float stepDelay = (float)durationMs / (float)steps;
for (uint16_t s = 0; s <= steps; s++) {
float alpha = (float)s / (float)steps;
for (uint8_t g = 0; g < LED_GROUPS; g++) {
for (uint16_t led = 0; led < ledsInGroup; led++) {
CRGB colorA = getColorInAnimationFrame(animIndex, frameFrom, g, led);
CRGB colorB = getColorInAnimationFrame(animIndex, frameTo, g, led);
// Blend between colors
uint8_t blendAmount = (uint8_t)(alpha * 255);
CRGB crossFaded = blend(colorA, colorB, blendAmount);
ledGroups[g][led] = crossFaded;
}
}
FastLED.show();
delay(stepDelay);
}
}