Загрузка данных
#include <FastLED.h>
#define LED_PIN 25 // Пин управления светодиодами (GPIO 25)
#define BUTTON_PIN 4 // Пин кнопки (на GND)
#define NUM_LEDS 10 // Всего 10 светодиодов
#define BRIGHTNESS 130 // Комфортная яркость
CRGB leds[NUM_LEDS];
CRGB realLeds[NUM_LEDS];
// --- НАСЫЩЕННАЯ И СБАЛАНСИРОВАННАЯ ПАЛИТРА (для статики и цветовых модов) ---
const CRGB balancedColors[] = {
CRGB(255, 30, 30), // 0. Насыщенный красный
CRGB(0, 220, 50), // 1. Сочный зеленый
CRGB(0, 100, 255), // 2. Глубокий синий
CRGB(255, 255, 255), // 3. Чистый белый
CRGB(255, 180, 0), // 4. Теплый янтарно-желтый
CRGB(0, 220, 220), // 5. Бирюзовый
CRGB(255, 50, 150), // 6. Малиново-розовый
CRGB(255, 100, 0), // 7. Насыщенный оранжевый
CRGB(140, 50, 255) // 8. Благородный фиолетовый
};
const int totalColors = 9;
int currentColorIndex = 0;
int currentMode = 0;
const int totalModes = 7; // Всего 7 крутых плавных модов анимации!
// --- ПЕРЕМЕННЫЕ ДЛЯ АНТИДРЕБЕЗГА КНОПКИ ---
bool lastButtonState = HIGH;
bool buttonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
unsigned long pressStartTime = 0;
bool waitingForRelease = false;
bool longPressTriggered = false;
const unsigned long longPressTime = 600; // 0.6 сек для долгого удержания
void setup() {
Serial.begin(115200);
Serial.println("System initialized with smooth animations & gradient.");
FastLED.addLeds<WS2812B, LED_PIN, GRB>(realLeds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
handleButtonWithDebounce();
// Выполнение текущего анимационного режима
runCurrentAnimation();
// Перенос в физический порядок под вашу плату
for (int i = 0; i < NUM_LEDS; i++) {
realLeds[getPhysicalIndex(i)] = leds[i];
}
FastLED.show();
FastLED.delay(15); // Плавный фреймрейт (~66 FPS)
}
int getPhysicalIndex(int logicalIndex) {
const int mapTable[10] = {3, 2, 1, 0, 4, 5, 6, 7, 8, 9};
return mapTable[logicalIndex];
}
// --- УПРАВЛЕНИЕ КНОПКОЙ ---
void handleButtonWithDebounce() {
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) {
pressStartTime = millis();
longPressTriggered = false;
waitingForRelease = true;
}
else if (buttonState == HIGH && waitingForRelease) {
waitingForRelease = false;
if (!longPressTriggered) {
// Короткое нажатие -> меняет цвет (для модов, зависящих от цвета)
currentColorIndex = (currentColorIndex + 1) % totalColors;
Serial.print("Цвет изменен на индекс: ");
Serial.println(currentColorIndex);
}
}
}
}
// Долгое нажатие -> переключает режим анимации
if (waitingForRelease && !longPressTriggered) {
if (millis() - pressStartTime >= longPressTime) {
currentMode = (currentMode + 1) % totalModes;
longPressTriggered = true;
Serial.print("Режим анимации изменен на: ");
Serial.println(currentMode);
}
}
lastButtonState = reading;
}
// --- 7 ПЛАВНЫХ И КРАСИВЫХ АНИМАЦИОННЫХ МОДОВ ---
void runCurrentAnimation() {
CRGB baseColor = balancedColors[currentColorIndex];
switch (currentMode) {
case 0:
// МОД 0: Плавный переливающийся РАДУЖНЫЙ ГРАДИЕНТ (меняется сам, цвет кнопки не нужен)
{
uint8_t startIndex = millis() / 20;
fill_rainbow(leds, NUM_LEDS, startIndex, 15); // Плавная бегущая радуга по всей плате
}
break;
case 1:
// МОД 1: Статичное свечение выбранным цветом
fill_solid(leds, NUM_LEDS, baseColor);
break;
case 2:
// МОД 2: Мягкое «дыхание» выбранным цветом (плавное затухание и розжиг)
{
float breath = (sin(millis() / 400.0) + 1.0) / 2.0; // от 0.0 до 1.0
CRGB breathColor = baseColor;
breathColor.nscale8(breath * 255);
fill_solid(leds, NUM_LEDS, breathColor);
}
break;
case 3:
// МОД 3: Плавная бегущая волна выбранного цвета слева направо
{
for (int i = 0; i < NUM_LEDS; i++) {
float wave = (sin(millis() / 200.0 - i * 0.5) + 1.0) / 2.0;
CRGB waveColor = baseColor;
waveColor.nscale8(wave * 255);
leds[i] = waveColor;
}
}
break;
case 4:
// МОД 4: Двухсторонняя волна (перелив от центра к краям)
{
float t = millis() / 250.0;
for (int i = 0; i < NUM_LEDS; i++) {
float dist = abs(i - 4.5); // центр платы
float wave = (sin(t - dist * 0.6) + 1.0) / 2.0;
CRGB waveColor = baseColor;
waveColor.nscale8(wave * 255);
leds[i] = waveColor;
}
}
break;
case 5:
// МОД 5: Плавный перелив цвета в цвет (индивидуальный цветовой градиент для выбранного тона)
{
for (int i = 0; i < NUM_LEDS; i++) {
// Смешиваем базовый цвет с соседним оттенком по кругу палитры
CRGB nextColor = balancedColors[(currentColorIndex + 1) % totalColors];
float mix = (sin(millis() / 300.0 + i * 0.4) + 1.0) / 2.0;
leds[i] = blend(baseColor, nextColor, mix * 255);
}
}
break;
case 6:
// МОД 6: Мягкое мерцание / перелив «живые искорки» на выбранном цвете
{
fadeToBlackBy(leds, NUM_LEDS, 15); // Очень плавное угасание
if (random8() < 30) {
int idx = random8(NUM_LEDS);
leds[idx] = baseColor;
leds[idx].maximizeBrightness(); // Делаем искорку чуть ярче и сочнее
}
}
break;
}
}