Руководства · 10 мин чтения

Ёлочная гирлянда на Arduino: снег и радуга на WS2812B

Сделай гирлянду для новогодней ёлки на Arduino: лента WS2812B, эффекты снегопада, радуги и мерцания, переключение режимов кнопкой, расчёт питания 5 V и готовый код.

Arduino и светодиодная лента WS2812B для новогодней ёлки — самый весёлый способ выйти за рамки нескольких фиксированных режимов готовых гирлянд. Цвет и яркость каждого светодиода управляются по отдельности, поэтому на ёлку можно добавить снежинки, падающие с макушки вниз, радугу, бегущую вокруг веток, или красные, зелёные и золотые звёзды, мерцающие в случайном порядке. Для всего этого нужны лишь один провод данных, кнопка и правильно подобранный блок питания на 5 V.

В этом руководстве мы начнём со списка деталей и пошагово соберём всё остальное: расчёт питания под длину ленты, правильное подключение блока питания, платы и ленты, полную программу для Arduino Uno (FastLED) с переключением эффектов кнопкой, а также версии того же проекта для ESP32 (Adafruit NeoPixel) и Raspberry Pi Pico (MicroPython). В конце ты узнаешь, как обмотать лентой ёлку, на что обратить внимание в плане безопасности и как решить самые частые проблемы.

Адресный RGB-светодиод WS2812B NeoPixel
Адресный RGB-светодиод WS2812B NeoPixel

Почему для ёлки стоит взять ленту WS2812B?

В классических гирляндах все лампочки загораются одновременно или работают по очереди несколькими группами. А в WS2812B внутри каждого светодиода есть крошечная микросхема-драйвер. Arduino отправляет по линии данных информацию о цвете одну за другой; первый светодиод забирает свою 24-битную долю, а остальное передаёт следующему. Так лентой из 100 или 300 светодиодов можно управлять одним пином и задавать каждому светодиоду свой цвет. Именно поэтому подвижные эффекты вроде снегопада выглядят так живо, как невозможно с обычными гирляндами. Если хочется глубже разобраться, как работают адресные светодиоды, загляни в статью Светодиоды WS2812B NeoPixel.

ХарактеристикаЗначение
Корпус5050 SMD, микросхема-драйвер внутри светодиода
Питание5 V (примерно 3,5–5,3 V)
ТокОколо 20 mA на цвет, около 60 mA на полном белом
ДанныеОдна линия, 800 kHz, 24 бита на светодиод (порядок G-R-B)
Время передачи30 µs на светодиод; 100 светодиодов — около 3 мс
Порог входа данныхНе менее 0,7 × VDD для логической 1 (3,5 V при 5 V)
Цвет256 уровней на канал, всего 16,7 млн цветов
Плотность ленты30, 60 и 144 светодиода/м
РезкаМожно резать посередине медных площадок между светодиодами

Список деталей

  • Светодиодная лента WS2812B: для ёлки высотой 1,5–1,8 м хорошо начать с 2,5 м ленты плотностью 60 светодиодов/м или 5 м ленты на 30 светодиодов/м. Версии в силиконе IP65 лучше выдерживают развешивание по веткам и пыль.
  • Управляющая плата: Arduino Uno, Nano, ESP32 или Raspberry Pi Pico.
  • Блок питания 5 V: ток выбирай по таблице ниже; для 100 светодиодов 5 V 4 A — комфортный вариант.
  • Гнездо питания DC «мама» (с винтовыми клеммами): чтобы подключить штекер блока питания к проводам без пайки.
  • Электролитический конденсатор 1000 µF / 10 V: сглаживает резкие скачки тока на входе ленты.
  • Резистор 330 Ω: ставится последовательно в линию данных; гасит отражения сигнала и ограничивает входной ток первого светодиода.
  • Тактовая кнопка: для переключения эффектов.
  • Толстый провод: сечением не меньше 0,75–1,5 мм² для линий 5V и GND.
  • По желанию 74AHCT125 или 74HCT245: чтобы поднять 3,3-вольтовый сигнал данных ESP32 и Pico до 5 V.

Расчёт питания: на сколько ампер нужен блок?

Каждый из красного, зелёного и синего кристаллов внутри WS2812B на полной яркости потребляет около 20 mA, то есть один светодиод на полном белом берёт около 60 mA. Ток в худшем случае считается по формуле I = число светодиодов × 60 mA. Лента из 100 светодиодов потребляет 6 A, когда все светодиоды горят чисто белым на полной яркости, а это P = 5 V × 6 A = 30 W. В эффектах радуги, снега и мерцания большинство светодиодов светятся одним цветом или приглушены, поэтому на практике ток держится около трети от худшего случая. Для надёжного выбора умножь этот типичный ток на 2 и округли вверх до ближайшего номинала блока питания, а программное ограничение тока поставь примерно на 80% от возможностей блока. Связь тока, напряжения и мощности легко проверить с помощью калькулятора закона Ома.

Число светодиодовХудший случай (полный белый)Типичный ток эффектовРекомендуемый блок питанияПрограммный предел (MAX_MA)
301,8 Aоколо 0,6 A5 V 2 A1600 mA
603,6 Aоколо 1,2 A5 V 3 A2400 mA
1006 Aоколо 2 A5 V 4 A3200 mA
1509 Aоколо 3 A5 V 6 A4800 mA
300 (5 м, 60 светодиодов/м)18 Aоколо 6 A5 V 12 A9600 mA

На длинных лентах вторая проблема — падение напряжения. Тонкие медные дорожки ленты имеют сопротивление, поэтому в конце 5-метровой ленты напряжение может опуститься ниже 4 V; тогда синие и зелёные кристаллы слабеют, а белый выглядит желтоватым и тусклым. Решение — подавать 5V и GND не только в начало ленты, но и каждые 1–1,5 метра (или каждые 100–150 светодиодов) отдельными проводами от блока питания. Это называется подпиткой ленты (power injection). Для этих проводов используй сечение не меньше 0,75 мм² при 5 амперах и 1,5 мм² при 10 амперах; линию данных подключай только к началу ленты.

Никогда не пытайся питать ленту от пина 5V на Arduino. Пин 5V у Uno с питанием от USB отдаёт максимум 400–500 mA, а этого хватит лишь на несколько светодиодов на малой яркости. При большей нагрузке плата перезагружается, срабатывает защитный предохранитель USB или нагреваются тонкие дорожки на плате. Всегда питай ленту напрямую от блока питания.

Схема подключения: блок питания 5 V, лента и плата

ПодключениеArduino UnoESP32Raspberry Pi Pico
DIN ленты (данные)D6 (через 330 Ω)GPIO 13 (через 330 Ω)GP0 (через 330 Ω)
5V ленты+5 V блока питания+5 V блока питания+5 V блока питания
GND лентыGND блока питания + GND UnoGND блока питания + GND ESP32GND блока питания + GND Pico
КнопкаD2 и GNDGPIO 4 и GNDGP15 и GND
Конденсатор 1000 µF5V–GND на входе ленты5V–GND на входе ленты5V–GND на входе ленты
Питание платы (готовый вариант)Пин 5V или USBПин 5V (VIN) или USBVSYS (через диод Шоттки) или USB
  1. Найди стрелки на ленте и припаяй провод к тому концу, с которого начинается стрелка (DIN). Если подавать данные с противоположного конца, то есть с DOUT, ни один светодиод не загорится.
  2. Подключи выход +5 V блока питания к контакту 5V ленты (на некоторых лентах он подписан +5V или VCC), а GND блока питания — к контакту GND ленты.
  3. Подключи конденсатор 1000 µF между 5V и GND на входе ленты; длинная ножка (плюс) идёт к 5V, а ножка с полосой на корпусе (минус) — к GND.
  4. Соедини пин GND платы с GND блока питания. Без общей земли у сигнала данных нет опорного уровня.
  5. Подключи пин данных платы (на Uno это D6) к DIN ленты через резистор 330 Ω; лучше ставить резистор ближе к ленте.
  6. Одну ножку кнопки подключи к D2, другую — к GND; встроенный подтягивающий резистор включится в коде.
  7. Если светодиодов больше 150, протяни от блока питания отдельные провода 5V и GND ещё и к середине и концу ленты.
  8. Во время разработки питай плату от USB, а ленту — от блока питания. Когда проект закончен, можно подать 5 V от блока на пин 5V у Uno; в этом случае не подключай одновременно USB-кабель.
Самая частая ошибка — забыть соединить GND платы с GND блока питания; тогда светодиоды мигают случайными цветами или вообще не реагируют. Подробности — в статье про общую землю (GND). Вторая частая проблема — 3,3-вольтовый сигнал данных у ESP32 и Pico: при питании 5 V для уверенного распознавания логической 1 WS2812B нужно не меньше 3,5 V. Большинство лент работают и с 3,3 V, но если первые светодиоды мерцают, поставь между ними преобразователь уровней (74AHCT125).

Код для Arduino Uno (FastLED): три эффекта и переключение режимов кнопкой

Открой в Arduino IDE «Менеджер библиотек» (Library Manager), найди FastLED и установи библиотеку; подробная инструкция — в статье Как добавить библиотеку в Arduino. Программа ниже содержит эффекты радуги, снегопада и мерцания звёзд; каждое нажатие кнопки переключает на следующий эффект. Так как в коде вместо delay() используется millis(), кнопка распознаётся в любой момент, пока работает эффект. Логику этого способа можно найти в статье millis и delay: в чём разница.

C++ (Arduino IDE)
1#include <FastLED.h>
2
3#define LED_PIN     6      // şeridin DIN girişi (330 ohm üzerinden) / strip DIN input (via 330 ohm)
4#define BUTTON_PIN  2      // buton, diğer bacak GND / button, other leg to GND
5#define NUM_LEDS    100    // şeritteki LED sayısı / number of LEDs on the strip
6#define BRIGHTNESS  120    // genel parlaklık 0-255 / global brightness 0-255
7#define MAX_MA      3200   // 4 A adaptörün %80'i / 80% of a 4 A supply
8
9CRGB leds[NUM_LEDS];
10
11const uint8_t MODE_COUNT = 3;                          // 0 gökkuşağı, 1 kar, 2 yıldız / 0 rainbow, 1 snow, 2 twinkle
12const uint16_t FRAME_MS[MODE_COUNT] = {20, 60, 30};    // kare süreleri (ms) / frame times (ms)
13const CRGB XMAS[4] = {CRGB::Red, CRGB::Green, CRGB::Gold, CRGB::White};
14
15uint8_t mode = 0;
16uint8_t hue = 0;
17
18void setup() {
19  pinMode(BUTTON_PIN, INPUT_PULLUP);
20  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
21  FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_MA);  // akım sınırı / current limit
22  FastLED.setBrightness(BRIGHTNESS);
23  FastLED.clear(true);                                // açılışta hepsini söndür / all off at start
24}
25
26void checkButton() {
27  static bool lastState = HIGH;
28  static unsigned long lastChange = 0;
29  bool state = digitalRead(BUTTON_PIN);
30  if (state != lastState && millis() - lastChange > 50) {  // 50 ms zıplama filtresi / 50 ms debounce
31    lastChange = millis();
32    lastState = state;
33    if (state == LOW) {                                     // basıldı / pressed
34      mode = (mode + 1) % MODE_COUNT;
35      FastLED.clear();
36    }
37  }
38}
39
40void rainbow() {
41  fill_rainbow(leds, NUM_LEDS, hue, 3);   // her LED'de ton 3 artar / hue +3 per LED
42  hue += 2;                               // renkler döner / colours rotate
43}
44
45void snowfall() {
46  for (int i = 0; i < NUM_LEDS - 1; i++) {
47    leds[i] = leds[i + 1];                // bir LED aşağı kaydır / shift one LED down
48  }
49  if (random8() < 38) {
50    leds[NUM_LEDS - 1] = CRGB::White;     // tepede yeni kar tanesi / new flake at the top
51  } else {
52    leds[NUM_LEDS - 1] = CRGB(0, 0, 24);  // koyu mavi gece / dark blue night
53  }
54}
55
56void twinkle() {
57  fadeToBlackBy(leds, NUM_LEDS, 20);      // hepsini biraz kıs / dim everything a little
58  if (random8() < 80) {
59    leds[random16(NUM_LEDS)] = XMAS[random8(4)];  // rastgele yıldız / random star
60  }
61}
62
63void loop() {
64  checkButton();
65  static unsigned long lastFrame = 0;
66  if (millis() - lastFrame >= FRAME_MS[mode]) {
67    lastFrame = millis();
68    if (mode == 0) rainbow();
69    else if (mode == 1) snowfall();
70    else twinkle();
71    FastLED.show();                       // renkleri şeride gönder / push colours to the strip
72  }
73}
Строка / настройкаЧто делает
NUM_LEDS (число светодиодов)Количество светодиодов на ленте; если указать неверно, часть ленты не загорится или эффекты сместятся.
BRIGHTNESS (яркость)Общая яркость (0–255). Около 120 достаточно ярко для ёлки и безопасно по току и нагреву.
setMaxPowerInVoltsAndMilliamps(5, MAX_MA) (ограничение тока)FastLED оценивает ток в каждом кадре и автоматически снижает яркость, если предел будет превышен.
addLeds<WS2812B, LED_PIN, GRB> (тип ленты)Задаёт тип ленты, пин данных и порядок цветов; у WS2812B порядок GRB.
FRAME_MS (время кадра)Время кадра для каждого эффекта (мс); чем меньше значение, тем быстрее анимация.
checkButton() (опрос кнопки)Считывает кнопку с фильтром антидребезга 50 мс и при каждом нажатии увеличивает номер режима на один.
FastLED.show() (вывод на ленту)Отправляет цвета из памяти на ленту; если не вызвать, никаких изменений видно не будет.

Как работают эффекты?

Радуга: функция fill_rainbow начинает с оттенка (hue), заданного для первого светодиода, и на каждом следующем светодиоде увеличивает оттенок на 3 шага. В FastLED оттенок лежит в диапазоне 0–255; при 100 светодиодах оттенок продвигается в сумме на 300 шагов, поэтому на ленте видно чуть больше одного полного цветового круга. Так как в каждом кадре мы увеличиваем переменную hue на 2, цвета медленно вращаются вокруг ёлки. Если нужны более широкие цветовые полосы, используй 1 или 2 вместо 3.

Снегопад: когда лента обмотана вокруг ёлки снизу вверх, первый светодиод внизу, а последний — на макушке. В каждом кадре мы сдвигаем все цвета на один светодиод вниз и добавляем наверх либо белую снежинку, либо тёмно-синий «ночной» пиксель. Функция random8() выдаёт число от 0 до 255, поэтому вероятность получить меньше 38 — около 15%; увеличь это число, и снег станет гуще. При времени кадра 60 мс снежинка проходит 100 светодиодов за 6 секунд. Мерцание (звёзды): fadeToBlackBy в каждом кадре приглушает все светодиоды примерно на 8%; одновременно случайно выбранный светодиод вспыхивает на полной яркости красным, зелёным, золотым или белым. В итоге получается сверкание, напоминающее старые гирлянды, но гораздо живее.

Чтобы добавить новый эффект, напиши функцию, увеличь MODE_COUNT на один, добавь его скорость в массив FRAME_MS и вставь новую строку в выбор внутри loop. Например, чтобы покрасить всю ёлку в один цвет, достаточно fill_solid(leds, NUM_LEDS, CRGB::Red); если каждую секунду менять цвет между красным и зелёным, получится классический новогодний эффект.

Новогодняя ёлка на ESP32 (Adafruit NeoPixel)

FastLED работает и на ESP32, но здесь мы пишем тот же проект на библиотеке Adafruit NeoPixel — так получится познакомиться с обеими популярными библиотеками. Актуальная версия библиотеки компилируется одним и тем же кодом на версиях 2.x и 3.x ядра ESP32 для Arduino и формирует сигнал аппаратным блоком RMT. В Adafruit NeoPixel цвета, приглушённые через setBrightness, при обратном чтении могут искажаться, поэтому мы считаем эффекты в собственном массиве яркости (level) и в каждом кадре записываем их на ленту заново. Пин данных — GPIO 13, кнопка — GPIO 4. Если позже захочется управлять ёлкой с телефона, готовый интерфейс предлагает статья Установка WLED.

C++ (Arduino IDE)
1#include <Adafruit_NeoPixel.h>
2
3#define LED_PIN     13     // şeridin DIN girişi (330 ohm üzerinden) / strip DIN input (via 330 ohm)
4#define BUTTON_PIN  4      // buton, diğer bacak GND / button, other leg to GND
5#define NUM_LEDS    100    // şeritteki LED sayısı / number of LEDs on the strip
6
7Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
8
9const uint8_t MODE_COUNT = 3;                          // 0 gökkuşağı, 1 kar, 2 yıldız / 0 rainbow, 1 snow, 2 twinkle
10const uint16_t FRAME_MS[MODE_COUNT] = {20, 60, 30};    // kare süreleri (ms) / frame times (ms)
11const uint8_t PALETTE[4][3] = {{255, 0, 0}, {0, 255, 0}, {255, 160, 0}, {255, 255, 255}};
12
13uint8_t level[NUM_LEDS];      // LED başına parlaklık / per-LED level
14uint8_t colorIdx[NUM_LEDS];   // yıldız rengi / star colour index
15uint8_t mode = 0;
16uint16_t hue = 0;
17
18void setup() {
19  pinMode(BUTTON_PIN, INPUT_PULLUP);
20  strip.begin();
21  strip.setBrightness(110);   // genel parlaklık / global brightness
22  strip.clear();
23  strip.show();
24}
25
26void checkButton() {
27  static bool lastState = HIGH;
28  static unsigned long lastChange = 0;
29  bool state = digitalRead(BUTTON_PIN);
30  if (state != lastState && millis() - lastChange > 50) {  // 50 ms zıplama filtresi / 50 ms debounce
31    lastChange = millis();
32    lastState = state;
33    if (state == LOW) {                                     // basıldı / pressed
34      mode = (mode + 1) % MODE_COUNT;
35      memset(level, 0, sizeof(level));                      // efekt belleğini sıfırla / reset effect buffer
36      strip.clear();
37    }
38  }
39}
40
41void rainbow() {
42  for (int i = 0; i < NUM_LEDS; i++) {
43    uint16_t h = hue + (uint32_t)i * 65536UL / NUM_LEDS;   // LED'e göre ton / hue per LED
44    strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(h)));
45  }
46  hue += 256;                                              // renkler döner / colours rotate
47}
48
49void snowfall() {
50  for (int i = 0; i < NUM_LEDS - 1; i++) level[i] = level[i + 1];   // bir LED aşağı kaydır / shift one LED down
51  level[NUM_LEDS - 1] = (random(100) < 15) ? 255 : 0;               // tepede yeni kar / new flake on top
52  for (int i = 0; i < NUM_LEDS; i++) {
53    if (level[i]) strip.setPixelColor(i, 255, 255, 255);            // kar tanesi / snowflake
54    else strip.setPixelColor(i, 0, 0, 24);                          // koyu mavi gece / dark blue night
55  }
56}
57
58void twinkle() {
59  for (int i = 0; i < NUM_LEDS; i++) {
60    level[i] = (level[i] > 12) ? level[i] - 12 : 0;                 // yavaşça sön / fade out
61  }
62  if (random(100) < 30) {
63    int p = random(NUM_LEDS);
64    level[p] = 255;                                                 // yeni yıldız / new star
65    colorIdx[p] = random(4);
66  }
67  for (int i = 0; i < NUM_LEDS; i++) {
68    const uint8_t *c = PALETTE[colorIdx[i]];
69    strip.setPixelColor(i, c[0] * level[i] / 255, c[1] * level[i] / 255, c[2] * level[i] / 255);
70  }
71}
72
73void loop() {
74  checkButton();
75  static unsigned long lastFrame = 0;
76  if (millis() - lastFrame >= FRAME_MS[mode]) {
77    lastFrame = millis();
78    if (mode == 0) rainbow();
79    else if (mode == 1) snowfall();
80    else twinkle();
81    strip.show();                                                   // renkleri şeride gönder / push colours to the strip
82  }
83}

Новогодняя ёлка на Raspberry Pi Pico и MicroPython

В MicroPython для Raspberry Pi Pico модуль neopixel уже встроен; ничего дополнительно устанавливать не нужно. Модуль сам обеспечивает точные тайминги WS2812B, поэтому можно использовать любой пин GP; ниже данные подключены к GP0, а кнопка — к GP15. В MicroPython нет общей настройки яркости, поэтому мы приглушаем цвета вручную коэффициентом BRIGHT. Python работает медленнее, чем C++, поэтому при 100 светодиодах эффекты плавные, а при больше чем 300 светодиодах время кадра может вырасти. Если MicroPython в новинку, начни со статьи Основы MicroPython.

MicroPython
1from machine import Pin
2import neopixel, time, random
3
4NUM_LEDS = 100
5BRIGHT = 0.4                                   # 0-1 parlaklık / brightness
6np = neopixel.NeoPixel(Pin(0), NUM_LEDS)       # veri GP0 / data on GP0
7button = Pin(15, Pin.IN, Pin.PULL_UP)          # buton GP15-GND / button GP15-GND
8
9mode = 0
10MODE_COUNT = 3                                 # 0 gökkuşağı, 1 kar, 2 yıldız / 0 rainbow, 1 snow, 2 twinkle
11FRAME_MS = (20, 60, 30)                        # kare süreleri / frame times
12level = [0] * NUM_LEDS                         # LED başına parlaklık / per-LED level
13color_idx = [0] * NUM_LEDS                     # yıldız rengi / star colour index
14PALETTE = ((255, 0, 0), (0, 255, 0), (255, 160, 0), (255, 255, 255))
15hue = 0
16
17def scale(r, g, b):
18    return (int(r * BRIGHT), int(g * BRIGHT), int(b * BRIGHT))
19
20def wheel(pos):
21    # 0-255 -> gökkuşağı rengi / rainbow colour
22    pos = pos & 255
23    if pos < 85:
24        return (255 - pos * 3, pos * 3, 0)
25    if pos < 170:
26        pos -= 85
27        return (0, 255 - pos * 3, pos * 3)
28    pos -= 170
29    return (pos * 3, 0, 255 - pos * 3)
30
31def rainbow():
32    global hue
33    for i in range(NUM_LEDS):
34        np[i] = scale(*wheel(hue + i * 256 // NUM_LEDS))
35    hue = (hue + 2) & 255                      # renkler döner / colours rotate
36
37def snowfall():
38    for i in range(NUM_LEDS - 1):
39        level[i] = level[i + 1]                # bir LED aşağı kaydır / shift one LED down
40    level[-1] = 255 if random.randint(0, 99) < 15 else 0
41    for i in range(NUM_LEDS):
42        np[i] = scale(255, 255, 255) if level[i] else scale(0, 0, 24)
43
44def twinkle():
45    for i in range(NUM_LEDS):
46        level[i] = level[i] - 12 if level[i] > 12 else 0   # yavaşça sön / fade out
47    if random.randint(0, 99) < 30:
48        p = random.randint(0, NUM_LEDS - 1)
49        level[p] = 255                         # yeni yıldız / new star
50        color_idx[p] = random.randint(0, 3)
51    for i in range(NUM_LEDS):
52        r, g, b = PALETTE[color_idx[i]]
53        k = level[i] * BRIGHT / 255
54        np[i] = (int(r * k), int(g * k), int(b * k))
55
56effects = (rainbow, snowfall, twinkle)
57last_btn = 1
58last_change = time.ticks_ms()
59last_frame = time.ticks_ms()
60
61while True:
62    now = time.ticks_ms()
63    state = button.value()
64    if state != last_btn and time.ticks_diff(now, last_change) > 50:   # zıplama filtresi / debounce
65        last_change = now
66        last_btn = state
67        if state == 0:                         # basıldı / pressed
68            mode = (mode + 1) % MODE_COUNT
69            for i in range(NUM_LEDS):
70                level[i] = 0
71    if time.ticks_diff(now, last_frame) >= FRAME_MS[mode]:
72        last_frame = now
73        effects[mode]()
74        np.write()                             # şeride gönder / push to the strip

Размещение ленты на ёлке и безопасность

  • Начинай снизу: положи конец DIN ленты у основания ёлки рядом с блоком управления и обматывай ленту по спирали вверх. Так эффект снега потечёт сверху вниз, а провод данных останется коротким.
  • Шаг спирали: на ёлке высотой 1,8 м намотка с шагом 20–25 см равномерно распределяет 5-метровую ленту по веткам; к макушке диаметр витков уменьшается, поэтому шаг можно немного сократить.
  • Вертикальные полосы: ленту можно уложить и зигзагом — сверху вниз и снизу вверх. При такой раскладке направление эффекта снега на каждой второй полосе меняется на обратное, поэтому нужна небольшая доработка, которая вычисляет порядок светодиодов по номеру полосы.
  • Нагрев: лента WS2812B на высокой яркости нагревается; не прижимай её плотно к бумажным украшениям и сухим веткам. Яркость около 100–150 снижает и нагрев, и ток.
  • Безопасность блока питания: не собирай собственную схему на стороне 220 V; используй готовый блок питания 5 V в закрытом корпусе с маркировкой CE. Держи блок управления подальше от воды и полива цветов, а уходя из дома, выключай ёлку.
  • Предохранитель: в системах больше 5 A хорошая мера против возможного короткого замыкания — ножевой предохранитель подходящего номинала на выходе блока питания.

Идеи проектов для новогодней ёлки

  • Ёлка, реагирующая на музыку: зажигай огни в ритме песни с помощью микрофона; подробности — в статье Светодиоды, реагирующие на музыку.
  • Обратный отсчёт до Нового года: показывай на дисплее время до полуночи, а в 00:00 запускай на ёлке эффект фейерверка; загляни в статью Таймер обратного отсчёта до Нового года.
  • Ёлка, которая включается сама: автоматически зажигай огни, когда темнеет, с помощью датчика освещённости LDR.
  • Ёлка, которая ярче светит при приближении: повышай яркость с помощью PIR-датчика движения, когда кто-то входит в комнату, и приглушай, когда комната пуста.
  • Управление с телефона: подними веб-страницу на ESP32 и выбирай эффекты и цвета с телефона; статья Веб-сервер на ESP32 — хорошая отправная точка.
  • Звезда-дисплей на макушке: закрепи на верхушке ёлки небольшую светодиодную матрицу WS2812B и запусти анимацию звезды или снежинки.

Частые ошибки и их решение

СимптомВероятная причинаРешение
Не горит ни один светодиодДанные подключены к концу DOUT или нет общей GNDПроверь направление стрелки и подключи к DIN, соедини GND платы и блока питания
Первые светодиоды мерцают, случайные цветаСлабый сигнал данных, уровень 3,3 V, длинный провод данныхПеренеси резистор 330 Ω ближе к ленте, укороти провод данных, используй 74AHCT125
Неправильные цвета (зелёный вместо красного)Неверный порядок цветовИспользуй GRB в FastLED и NEO_GRB в NeoPixel; у некоторых лент порядок RGB
Конец ленты желтоватый и тусклыйПадение напряженияДобавь подпитку в середине и в конце, используй более толстый провод
Плата перезагружается при переходе на белыйСлабый блок питания, резкий бросок токаВозьми блок мощнее, снизь предел MAX_MA, добавь конденсатор 1000 µF
Кнопка за одно нажатие перескакивает два режимаДребезг контактов кнопкиУвеличь время антидребезга с 50 мс до 80 мс, держи провода кнопки короткими
На Pico эффекты идут медленноСлишком много светодиодов и вычислений на PythonУменьши NUM_LEDS, увеличь время кадра или перейди на C++ в Arduino IDE
Прежде чем вешать ленту на ёлку, погоняй её несколько минут на столе на высокой яркости и проверь рукой, не греются ли блок питания, клеммы и провода. Если провода нагреваются сильнее, чем до тёплого состояния, возьми провод толще или снизь значение MAX_MA. Если хочется освежить, как подключается кнопка, загляни в статью Как подключить кнопку.

С несколькими метрами светодиодной ленты, одной кнопкой и правильно подобранным блоком питания на 5 V твоя новогодняя ёлка превращается в программируемое световое шоу, которое каждый год можно обновлять новыми эффектами. Играя с цветовыми палитрами и временем кадра, можно придумывать собственные эффекты, а по любым вопросам питания и подключения можно вернуться к руководству по питанию Arduino. В приложении BlueGrays есть проекты с WS2812B — бегущие огни, эффект Knight Rider, полицейская мигалка и анимации, а также управление лентой NeoPixel на ESP32 — с пошаговыми схемами подключения и кодом.

Частые вопросы

Сколько светодиодов нужно для новогодней ёлки?

Для ёлки высотой 1,5–1,8 м 150–300 светодиодов, то есть 5 м ленты на 30 светодиодов/м или 2,5–5 м ленты на 60 светодиодов/м, дают насыщенный и живой вид. С меньшим числом светодиодов тоже работает, но эффекты выглядят редкими. С ростом числа светодиодов нужно учитывать и ток блока питания, и ОЗУ платы (3 байта на светодиод).

На сколько ампер нужен блок питания для ленты WS2812B?

Каждый светодиод на полном белом потребляет около 60 mA; для 100 светодиодов худший случай — 6 A. В цветных эффектах реальный ток держится около трети от этого, поэтому для 100 светодиодов хватит блока питания 5 V 4 A — при условии, что ток ограничен до 3200 mA функцией FastLED setMaxPowerInVoltsAndMilliamps. Если белый на полной яркости будет гореть долго, выбирай блок по худшему случаю.

Работает ли лента WS2812B от 12 V?

Нет, WS2812B — лента на 5 V, и подключение 12 V мгновенно выводит светодиоды из строя. Если нужна адресная лента на 12 V, выбирай тип WS2811 или WS2815. Если хочется использовать имеющийся блок питания на 12 V для небольшой ленты, 5 V можно получить понижающим преобразователем вроде LM2596, но такие модули ограничены примерно 2–3 A.

Что выбрать: FastLED или Adafruit NeoPixel?

Обе библиотеки без проблем управляют WS2812B. FastLED упрощает написание эффектов готовыми функциями радуги, цветовых палитр, приглушения и ограничения тока и обычно работает быстрее. Adafruit NeoPixel предлагает более простой API; если ты только начинаешь, хороший путь — начать с одной, а потом попробовать другую.

Сколько светодиодов WS2812B максимум может обслужить Arduino Uno?

Предел задают ОЗУ и скорость. В 2 КБ ОЗУ у Uno каждый светодиод занимает 3 байта, поэтому вместе с другими переменными на практике предел около 500 светодиодов. Кроме того, передача данных на каждый светодиод занимает 30 µs, так что при 1000 светодиодов один кадр доходит до 30 мс. На ESP32 и Pico ОЗУ много, и возможны тысячи светодиодов; настоящим ограничением становится источник питания.

Почему конец светодиодной ленты светится жёлтым или тускло?

Это признак падения напряжения. Тонкие медные дорожки ленты с ростом тока теряют напряжение; при напряжении ниже 4 V светодиоды в конце слабо выдают синий и зелёный, и белый уходит в жёлтый. Проблема решается отдельными проводами 5V и GND от блока питания к середине и концу ленты и небольшим снижением яркости.

Все проекты
Работа со светодиодной лентой WS2812B
#69Средний
Premium

Работа со светодиодной лентой WS2812B

Познакомься с умной светодиодной лентой, где каждому огоньку можно задать свой цвет. Arduino сначала зажигает первые пять светодиодов красным, через секунду остальные пять — синим, затем выключает все

4.8(54)
70
Полицейская мигалка на WS2812B
#70Средний
Premium

Полицейская мигалка на WS2812B

Ты переносишь красные и синие огни с крыши полицейской машины прямо на свой стол. Одна половина ленты WS2812B из десяти светодиодов три раза быстро вспыхивает красным, затем другая половина три раза в

4.8(67)
86
Бегущий огонь на WS2812B
#71Средний
Premium

Бегущий огонь на WS2812B

На ленте из десяти светодиодов зелёная светящаяся точка по одному светодиоду переходит от начала к концу, а затем перескакивает в начало; на каждом светодиоде она задерживается на треть секунды. На ле

4.8(58)
75
Бегущий огонь на WS2812B (эффект заполнения)
#72Средний
Premium

Бегущий огонь на WS2812B (эффект заполнения)

Световая лента, которая наполняется и пустеет, как стакан с водой. Arduino по одному зажигает десять цветных светодиодов оранжевым и оставляет их гореть; когда лента заполнена, выключает их по одному

4.7(50)
65
Эффект Knight Rider на WS2812B
#73Средний
Premium

Эффект Knight Rider на WS2812B

Красная светящаяся точка скользит от одного края умной светодиодной ленты к другому, затем возвращается и бегает туда-обратно без остановки. На каждом шаге Arduino зажигает только один светодиод, ждёт

4.9(73)
94
Анимация WS2812B 1
#75Средний
Premium

Анимация WS2812B 1

На ленте из 56 светодиодов все цвета радуги выстраиваются рядом и текут без остановки, будто по ленте скользит река света. Каждый светодиод светится чуть другим цветом, чем предыдущий, и пока цвета пл

4.9(69)
89
Анимация WS2812B 2
#76Средний
Premium

Анимация WS2812B 2

Устрой в комнате световое шоу, которое само меняет цвета. Arduino гонит цвета по ленте из 30 светодиодов и каждые несколько секунд переключается на новый набор: радуга, фиолетово-зелёные полосы, чёрно

4.8(65)
84
Управление лентой WS2812B NeoPixel на ESP32
#126Средний
Premium

Управление лентой WS2812B NeoPixel на ESP32

Адресуемые светодиоды WS2812B (NeoPixel) — умные RGB-светодиоды, которыми управляют цепочкой через один пин данных. В этом проекте лента WS2812B из 8 светодиодов управляется библиотекой Adafruit_NeoPixel и показывает плавную радужную анимацию. Логика 3,3V у ESP32 работает с большинством WS2812B, но на случай нестабильности показано решение с последовательным резистором 470Ω и конденсатором 1000µF. Анимация получается сдвигом значения оттенка.

4.9(19)
30