Перейти к содержанию

Сколько светодиодов WS2812B потянет Arduino Uno?

Обновлено Редакция GAW

У Arduino Uno на ATmega328P два узких места для адресной ленты — память и время. Третье, питание, к микроконтроллеру не относится, но о нём забывают чаще всего.

Память

По даташиту Worldsemi каждый WS2812B получает 24 бита — по байту на зелёный, красный и синий. Программа держит цвета всех светодиодов в массиве, то есть 3 байта на светодиод, а ОЗУ у ATmega328P всего 2048 байт.

Время

На 800 кбит/с бит длится 1,25 мкс, светодиод — 24 бита, а между кадрами нужна пауза не меньше 280 мкс. Наш расчёт:

СветодиодовОЗУ под цветаДоля из 2048 байтВывод кадраПредел кадров в секунду
100300 байт15 %3,0 мс304
300900 байт44 %9,0 мс107
5001500 байт73 %15,0 мс65
6001800 байт88 %18,0 мс54

Кадровая частота — предел для одного вывода без расчёта эффектов; любой расчёт цвета её снижает. Время для другого числа светодиодов и частоты кадров считает калькулятор WS2812B.

Что из этого следует

  • До 200–300 светодиодов Uno справляется: остаётся память для логики и кнопок.
  • 500 и больше — массив занимает почти всё ОЗУ, а стек и глобальные переменные начинают затирать друг друга.
  • Часы и прерывания. Если вывод на ленту идёт при запрещённых прерываниях, millis() отстаёт: Timer0 переполняется каждые 1024 мкс, а пропущенные переполнения не накапливаются.

Как раздать несколько лент по каналам и вывести их аппаратно — в ответе «Сколько лент WS2812 можно подключить к ESP32 одновременно?». Почему ленту нельзя питать от USB платы — в ответе «Сколько светодиодов WS2812B можно питать от USB?», а предельные режимы светодиода — в карточке WS2812B.

Похожие вопросы

Почему при длинной ленте отстаёт millis()?

Если вывод на ленту идёт с запрещёнными прерываниями, переполнения Timer0, которые случаются каждые 1024 мкс, за это время не обрабатываются: флаг запоминает только одно. Вывод 300 светодиодов длится около 9 мс, и при каждом кадре часы теряют несколько миллисекунд.

Как обойти нехватку ОЗУ?

Хранить не все пиксели, а вычислять цвет на лету при выводе, повторять одинаковые фрагменты или перейти на плату с большей памятью. ESP32 или RP2040 к тому же выводят данные на ленту аппаратно — через RMT или PIO, не останавливая программу.

Хватит ли питания платы для 500 светодиодов?

Нет, это отдельный вопрос, и он важнее памяти: 500 светодиодов на белом полной яркости — около 18 А при 5 В по нашему расчёту. Ленту питают от своего блока с предохранителями на питающих проводах, а с Arduino соединяют только землю и линию данных.

Источники

  1. Worldsemi. WS2812B-V5/W Intelligent control LED integrated light source, datasheet V6.1 (2022-09-08) — передача данных на 800 кбит/с; 24 бита данных на светодиод в порядке G, R, B, старшим битом вперёд; T0H 220–380 нс, T1H, T0L и T1L 580 нс–1 мкс; сброс — низкий уровень дольше 280 мкс; ток каждого цвета 12 мА
  2. Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet, DS40002061B, 2020 — 8.3 — 2048 байт SRAM у ATmega328P; 7.7 — флаг прерывания запоминается, пока прерывания запрещены, и обработчик выполняется после их разрешения; флаг на каждое событие один, поэтому повторные события за это время не накапливаются (наш вывод)
  3. Arduino. ArduinoCore-avr, коммит 11b9130: cores/arduino/wiring.c — Timer0 тикает каждые 64 такта, обработчик переполнения вызывается каждые 256 тиков: MICROSECONDS_PER_TIMER0_OVERFLOW = 64 · 256 тактов — 1024 мкс при 16 МГц; millis() считается в этом обработчике

Нашли ошибку?