ESP32 підключення 12 RGB LED WS2812
У цій статті підключимо до моєї улюбленої *сороконіжки* ESP32 S2 mini адресні свтлодіоди у вигляді кільця NeoPixel 12 RGB LED WS2812 та керуватимемо 10 простими світлодіодними ефектами. Цей приклад коду був використаний у проекті інтернет-радіо на esp32 у корпусі, надрукованому на 3D-принтері.
Компоненти:
- ESP32-S2 Mini
- Світлодіодне кільце на 12 RGB LED WS2812 (NeoPixel)
- 3 кнопки (або тактові кнопки)
- Резистори 10к (опціонально для підтягування кнопок)
- Дроти
- Живлення 5В (наприклад, від USB)
- Arduino IDE
| Призначення | Пін ESP32-S2 Mini |
|---|---|
| LED кільце (DIN) | GPIO16 |
| Кнопка «Наступний» | GPIO18 |
| Кнопка «Попередній» | GPIO35 |
| Кнопка «Вкл/Вимк» | GPIO33 |
| Живлення кільця (5V) | 5V |
| GND кільця та кнопок | GND |
Передбачається, що у вас встановлено Arduino IDE (я використовую версію 2.3.3). Додайте у менеджері бібліотек FastLED для керування адресними світлодіодами. Якщо немає:
Скетч → Підключити бібліотеку → Керування бібліотеками
Знайдіть та встановіть FastLED
Як це працюватиме:
- Світлодіоди підключені до піна 16 і керуються через бібліотеку FastLED.
- Кнопка на піні 18 перемикає ефект вперед.
- Кнопка на піні 35 перемикає назад.
- Кнопка на піні 33 вмикає та вимикає анімацію.
#include <fastled.h>
#define LED_PIN 16
#define NUM_LEDS 12
#define BRIGHTNESS 100
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
// Кнопки
#define BTN_NEXT 18
#define BTN_PREV 35
#define BTN_TOGGLE 33
bool effectOn = true;
int currentEffect = 0;
const int totalEffects = 10;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 200; // защита от дребезга
void setup() {
FastLED.addLeds<led_type, led_pin,="" color_order="">(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
pinMode(BTN_NEXT, INPUT_PULLUP);
pinMode(BTN_PREV, INPUT_PULLUP);
pinMode(BTN_TOGGLE, INPUT_PULLUP);
// Показать зелёный при старте
fill_solid(leds, NUM_LEDS, CRGB::Green);
FastLED.show();
delay(2000);
FastLED.clear();
FastLED.show();
}
void loop() {
handleButtons();
if (effectOn) {
switch (currentEffect) {
case 0: rainbowCycle(); break;
case 1: colorWipe(CRGB::Red); break;
case 2: theaterChase(CRGB::Blue); break;
case 3: setSolidColor(CRGB::White); break;
case 4: setSolidColor(CRGB::Blue); break;
case 5: setSolidColor(CRGB::Green); break;
case 6: setSolidColor(CRGB::Red); break;
case 7: fireEffect(); break;
case 8: rainbowFill(); break;
case 9: strobeEffect(); break;
}
FastLED.show();
delay(30);
} else {
FastLED.clear();
FastLED.show();
delay(100);
}
}
// === ЭФФЕКТЫ ===
void setSolidColor(CRGB color) {
fill_solid(leds, NUM_LEDS, color);
}
void rainbowFill() {
static uint8_t hue = 0;
fill_rainbow(leds, NUM_LEDS, hue, 7); // шаг изменения цвета
hue++;
}
void strobeEffect() {
static uint32_t lastBlinkTime = 0;
static bool ledOn = false;
if (millis() - lastBlinkTime >= 100) {
lastBlinkTime = millis();
ledOn = !ledOn;
setSolidColor(ledOn ? CRGB::White : CRGB::Black);
}
}
void fireEffect() {
static uint8_t heat[NUM_LEDS];
for (int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8(heat[i], random(0, 50));
}
for (int i = NUM_LEDS - 1; i >= 2; i--) {
heat[i] = (heat[i - 1] + heat[i - 2] + heat[i - 2]) / 3;
}
if (random(0, 10) > 7) {
int sparkIndex = random(0, 3);
heat[sparkIndex] = qadd8(heat[sparkIndex], random(160, 255));
}
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = HeatColor(heat[i]);
}
}
void rainbowCycle() {
static uint8_t hue = 0;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV((hue + (i * 256 / NUM_LEDS)) % 256, 255, 255);
}
hue++;
}
void colorWipe(CRGB color) {
static int pos = 0;
leds[pos] = color;
pos = (pos + 1) % NUM_LEDS;
}
void theaterChase(CRGB color) {
static int step = 0;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ((i + step) % 3 == 0) ? color : CRGB::Black;
}
step = (step + 1) % 3;
}
// === ОБРАБОТКА КНОПОК ===
void handleButtons() {
static bool lastStateNext = HIGH;
static bool lastStatePrev = HIGH;
static bool lastStateToggle = HIGH;
bool currentStateNext = digitalRead(BTN_NEXT);
bool currentStatePrev = digitalRead(BTN_PREV);
bool currentStateToggle = digitalRead(BTN_TOGGLE);
unsigned long currentTime = millis();
// Обработка кнопки "Следующий эффект"
if (currentStateNext == LOW && lastStateNext == HIGH && (currentTime - lastDebounceTime > debounceDelay)) {
currentEffect = (currentEffect + 1) % totalEffects;
lastDebounceTime = currentTime;
}
// Обработка кнопки "Предыдущий эффект"
if (currentStatePrev == LOW && lastStatePrev == HIGH && (currentTime - lastDebounceTime > debounceDelay)) {
currentEffect = (currentEffect - 1 + totalEffects) % totalEffects;
lastDebounceTime = currentTime;
}
// Обработка кнопки "Вкл/Выкл"
if (currentStateToggle == LOW && lastStateToggle == HIGH && (currentTime - lastDebounceTime > debounceDelay)) {
effectOn = !effectOn;
lastDebounceTime = currentTime;
}
// Обновляем предыдущее состояние
lastStateNext = currentStateNext;
lastStatePrev = currentStatePrev;
lastStateToggle = currentStateToggle;
}
