Загрузка данных
#include <FastLED.h>
// --- НАСТРОЙКИ ---
#define LED_PIN 25 // Пин управления светодиодами (GPIO 25)
#define BUTTON_PIN 4 // Пин кнопки (замыкается на GND)
#define NUM_LEDS 10 // Всего ровно 10 светодиодов
#define BRIGHTNESS 140 // Комфортная яркость
CRGB leds[NUM_LEDS];
CRGB realLeds[NUM_LEDS]; // Буфер для реального порядка физического подключения
// --- ПАЛИТРА ИЗ 12 ПРИЯТНЫХ СТАТИЧНЫХ ЦВЕТОВ ---
const CRGB pleasantColors[12] = {
CRGB(255, 120, 50), // 0. Теплый янтарный
CRGB(255, 150, 100), // 1. Пастельный персиковый
CRGB(255, 100, 150), // 2. Нежно-розовый
CRGB(180, 100, 255), // 3. Мягкий лавандовый
CRGB(100, 130, 255), // 4. Спокойный васильковый
CRGB(50, 180, 255), // 5. Небесно-голубой
CRGB(50, 220, 180), // 6. Бирюзово-мятный
CRGB(80, 240, 120), // 7. Светло-салатовый
CRGB(220, 220, 100), // 8. Теплый золотистый
CRGB(255, 180, 50), // 9. Медовый
CRGB(200, 150, 220), // 10. Сиреневая дымка
CRGB(230, 230, 230) // 11. Мягкий белый (теплый)
};
// --- СОСТОЯНИЯ ---
int currentHueIndex = 0;
int currentMode = 0;
const int totalModes = 6;
// Переменные кнопки
unsigned long buttonPressStartTime = 0;
bool buttonIsPressed = false;
bool longPressHandled = false;
const unsigned long longPressTime = 500;
void setup() {
Serial.begin(115200);
FastLED.addLeds<WS2812B, LED_PIN, GRB>(realLeds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
handleButton();
runCurrentMode();
// Маппинг (перенос красивого логического порядка в реальный физический порядок пайким)
// Распределяем 10 диодов слева направо по платам
// Допустим, логические индексы 0..3 — левая плата, 4..9 — правая плата
for (int i = 0; i < NUM_LEDS; i++) {
realLeds[getPhysicalIndex(i)] = leds[i];
}
FastLED.show();
FastLED.delay(20);
}
// Функция перевода логического порядка в физический (под вашу пайку на фото)
int getPhysicalIndex(int logicalIndex) {
// Настроено так, чтобы волна шла плавно слева направо по обеим платам:
const int mapTable[10] = {3, 2, 1, 0, 4, 5, 6, 7, 8, 9};
return mapTable[logicalIndex];
}
// --- ЛОГИКА КНОПКИ ---
void handleButton() {
bool reading = (digitalRead(BUTTON_PIN) == LOW);
if (reading && !buttonIsPressed) {
buttonIsPressed = true;
buttonPressStartTime = millis();
longPressHandled = false;
}
else if (reading && buttonIsPressed) {
if (!longPressHandled && (millis() - buttonPressStartTime >= longPressTime)) {
currentMode = (currentMode + 1) % totalModes;
longPressHandled = true;
}
}
else if (!reading && buttonIsPressed) {
buttonIsPressed = false;
if (!longPressHandled) {
currentHueIndex = (currentHueIndex + 1) % 12;
}
}
}
// --- МОДЫ АНИМАЦИИ (РАБОТАЮТ С 10 ВИРТУАЛЬНЫМИ СВЕТОДИОДАМИ) ---
void runCurrentMode() {
CRGB baseColor = pleasantColors[currentHueIndex];
switch (currentMode) {
case 0:
// 0: Статика выбранным цветом
fill_solid(leds, NUM_LEDS, baseColor);
break;
case 1:
// 1: Плавное «дыхание»
{
float breath = (sin(millis() / 350.0) + 1.0) / 2.0;
CRGB breathColor = baseColor;
breathColor.nscale8(breath * 255);
fill_solid(leds, NUM_LEDS, breathColor);
}
break;
case 2:
// 2: Красивая бегущая волна слева направо по всем 10 кнопкам
for (int i = 0; i < NUM_LEDS; i++) {
float wave = (sin(millis() / 150.0 - i * 0.6) + 1.0) / 2.0;
CRGB waveColor = baseColor;
waveColor.nscale8(wave * 255);
leds[i] = waveColor;
}
break;
case 3:
// 3: Бегающая искра на приглушенном фоне
{
fadeToBlackBy(leds, NUM_LEDS, 50);
int pos = (millis() / 120) % NUM_LEDS;
leds[pos] = CRGB::White;
for(int i = 0; i < NUM_LEDS; i++) {
if(i != pos) {
CRGB dimColor = baseColor;
dimColor.nscale8(80);
leds[i] = dimColor;
}
}
}
break;
case 4:
// 4: Плавный переливающийся градиент по всей длине
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = blend(baseColor, CHSV(currentHueIndex * 21 + i * 15, 150, 255), 128);
}
break;
case 5:
// 5: Мягкое мерцание огоньков
{
fadeToBlackBy(leds, NUM_LEDS, 30);
if (random8() < 50) {
int idx = random8(NUM_LEDS);
leds[idx] = baseColor;
}
}
break;
}
}