Содержание:
- Назначение и принцип работ
- Разновидности
- Технические характеристики WS2812B
- Подключение к Ардуин
- Примеры использования
- Недостатки и ограничения
- Выводы
- FAQ
Назначение и принцип работы
Спасибо тебе, трехцветный светодиод! Тебе было достаточно всего три пина Ардуино с ШИМ, чтобы светить нам любым цветом, в рамках своих технических характеристик, разумеется. Ты славно служил нам еще с доцифровой эпохи, но теперь твое время, кажется, уходит...
Хотя нет, останься, ты еще пригодишься в качестве равноправного компонента светодиода адресного. А в боевые товарищи дадим тебе чип WS2811!
Итак, что изменилось и какое преимущество дает присвоение каждому RGB-светодиоду индивидуального контроллера? Во-первых, контроллер главный (в нашем случае Ардуино), освобождается от недостойной его задачи формировать по три ШИМ-сигнала для каждого светодиода, теперь этим займется WS2811. Прежде чем озвучить “во-вторых”, давайте, для примера, представим что нам необходимо сделать игрушечный светофор из трех светодиодов с плавным переключением сигналов. Потребуется 9 пинов, из которых на UNO ШИМом обладает всего 6. То есть для такой простой задачи уже готовим целую MEGA. Если же нам захочется чуть большего, то проблемы вырастут до размеров, недоступных для решения одним контроллером. Давайте теперь представим минимальный цветной светодиодный куб 4х4х4. 64 светодиода, 192 управляющих сигнала, не считая питания, жгут из проводов толщиной в два пальца, дополнительные генераторы ШИМ или, что еще страшнее, ЦАПы, охапка резисторов, горсть прочих радиодеталей, невероятная программа, чтобы этим всем управлять и так далее. Такой куб больше будет похож на ворох проводов, сквозь которые едва пробивается свет. Вот теперь скажу “во-вторых”. В-вторых, адресные светодиоды могут подключаться “паровозиком” один к другому и всего тремя проводами, включая питание. Собираться в цепочки до нескольких сотен штук, при этом каждый будет самостоятельно светить своим собственным цветом, который ему, между прочими делами, назначит Ардуино. И в-третьих, для передачи команд всей этой цепочке от Ардуино потребуется всего один пин. Причем, любой, а не только из шести генерирующих широтно-импульсную модуляцию. К другому пину может подключаться следующая цепочка и так далее, один контроллер, при необходимости, может одновременно управлять несколькими независимыми лентами. Такие возможности позволяют легко использовать светодиоды в качестве пикселей и формировать цветную картинку, переливающуюся гирлянду, создавать художественную подсветку и LED-экраны любого размера. Применений можно придумать тысячи.
Хорошим подспорьем в расширении возможностей является высокая скорость обновления информации. Цепочка из 100 адресных светодиодов получает данные всего за 3 мс, то есть, в теории, может работать с частотой до 300 кадров в секунду. Это позволяет не только формировать любые цветные изображения, но и запросто анимировать их.
Адресные светодиоды бывают разные, о чем вкратце расскажу чуть позже, но принцип работы у них схожий. Рассмотрим самый распространенный вариант - WS2812b.
Две ножки питания, вход и выход. Команда приходит на входную ножку в виде последовательности 24 битов, по 8 на каждый цвет. Так как синхроимпульс отсутствует, ноль и единица отличаются длительностью: 0,4 мкс - ноль, 0,85 - единица. На один бит тратится 1,25 мкс, на один светодиод команда передается, соответственно, за 30 мкс. Скорость передачи, таким образом, составляет 800 кбит/с. В каждом чипе, в качестве конкретно ему адресованной команды, остается последние перед завершением передачи 24 бита, все предыдущие он транслирует на выход, передавая информацию по цепочке дальше. Окончанием пакета данных является пауза на низком уровне в течение 50 мкс, после чего каждый чип формирует сигналы на своих светодиодных ножках согласно “замершей” в нем информации. Цвет установлен и будет сохраняться до приема следующей команды.
Вот так в реальности выглядит передача данных на один светодиод:
24 бита и пауза. Данные можно расшифровать даже невооруженным глазом: 010110.. и так далее. Вот так все просто.
Разновидности
Разновидностей адресных светодиодов существует довольно много, более двух десятков, и их число продолжает расти. Не будем подробно останавливаться на каждой из них, перечислим основные отличия и рассмотрим самые популярные.
По типу:
WS2811 - отдельный чип без собственно светодиода в корпусе soic-8. К нему можно припаять старый добрый трехцветный светодиод или что-нибудь другое, что управляется ШИМ сигналом. Редко используется любителями ввиду сложности сборки на его основе.
WS2812B - пожалуй, самый популярный адресник на данный момент. Именно о нем мы будем говорить в этой статье и на нем работать с примерами. Размер 5х5 мм, частота ШИМ 400Гц. Подробнее в следующем разделе.
WS2812S - отличается от предыдущего раздельным питанием чипа и светодиода. Рекомендуется для особо длинных цепочек, так как напряжение на чипе не снижается так сильно от расстояния и не зависит от яркости свечения цепочки.
WS2812B-Mini - уменьшенная до размера 3,5х3,5 мм и менее яркая версия WS2812B.
WS2813 - улучшенная версия 2812, отличается повышенной до 2кГц частотой ШИМ и возможностью передавать сигналы по цепочке дальше даже через вышедший из строя чип. Рекомендуется для труднодоступных мест и изделий с повышенной надежностью.
SK6812-RGBW - светодиод состоит не из 3-х, а из 4-х компонентов, к красному, синему и зеленому добавлен белый. Такому светодиоду в сигнале требуется не 24, а 32 бита данных. Отличается более ярким свечением за счет мощного белого излучателя. Рекомендуется для освещения и подсветки больших объектов.
По исполнению:
- В виде лент, плотностью от 30 до 144 светодиодов на метр и в разном защитном исполнении: IP30, IP65, IP67, IP68. Все, кроме первого, могут использоваться на улице почти в любых погодных условиях.
Ленты особенно удобны для создания подсветки, габаритных форм и угловатых фигур. Например, часов любого размера и формы.
- В виде отдельных “пикселей”, что нужно для различных тонких художественных применений, так как не ограничивают творца прямыми линиями.
- В виде стандартных, привычных глазу светодиодов диаметром 5 мм. Они излучают равномерно во все стороны, что особо ценится любителями праздничных гирлянд, 3Д-кубов и прочих объемных предметов.
Технические характеристики WS2812B
- Размер - 5х5 мм
- Частота ШИМ - 400Гц
- Напряжение питания - 5В
- Потребление при нулевой яркости - 1 мА на светодиод
- Потребление при максимальной яркости - 60 мА на светодиод
- Цветность: RGB, 256 оттенков на канал, 16 миллионов цветов
- Размер данных - 24 бита на светодиод
- Скорость передачи данных - 800 кГц
Подключение WS2812B к Arduino
Схема проста до скуки. Важно лишь знать и соблюдать следующие правила:
- Адресники довольно энергоемкие, блок питания должен быть рассчитан на максимальную мощность и даже чуть превышать ее. Один светодиод, напомню, потребляет до 60 мА. Для примера, лента со 100 диодами потребует 6 А, а лучше 8 А и более.
- Ленты, длиннее пары десятков светодиодов, рекомендуется запитывать с двух сторон, а еще лучше в нескольких точках по всей длине, чтобы избежать падения напряжения с расстоянием и перегрева дорожек.
- Ардуино и лента могут быть запитаны из разных источников, но “земля” у них должна быть едина.
- Резистор на управляющем пине не обязателен, но очень желателен для защиты контроллера, иначе в случае даже кратковременного обрыва питания ленты пин моментально выгорит.
Примеры использования
Задача вывода информации на светодиоды непростая, требуется отправить одним пакетом много данных на большой скорости и с большой точностью. Даже при отключенных таймерах и прерываниях с этой частью работы успешно справляется лишь программа, написанная на ассемблере, то есть максимально близкая к машинному уровню. Поэтому без готовых библиотек любителю обойтись довольно сложно. Библиотек существует несколько, самыми известными из которых являются NeoPixel и FastLed. Споры о том, какая из них лучше ведутся давно, выбирайте на свой вкус. Мне больше нравится NeoPixel, она ощутимо компактнее во флеше и занимает гораздо меньше динамической памяти контроллера. В примерах будем пользоваться именно ей.
Вообще, в каждой библиотеке уже есть несколько готовых примеров, наглядно демонстрирующих почти все возможности. Достаточно лишь подключить ленту, по схеме выше и указать в настройках правильные параметры: управляющий пин, тип ленты, количество светодиодов.
#define PIXEL_PIN 6 // номер управляющего пина #define PIXEL_COUNT 16 // количество пикселей (светодиодов) в ленте // объявление объекта: Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800); // Argument 1 = количество пикселей (светодиодов) // Argument 2 = номер управляющего пина // Argument 3 = тип светодиода по порядку и количеству цветов, а также скорости передачи данных: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Первая строка - номер пина, вторая - количество светодиодов, третья - установка этих данных плюс выбор типа ленты и скорости передачи. По умолчанию назначена лента с цветностью RGB и скоростью 800 кГц, это подходит для WS2812B. Для SK6812 выбираем NEO_RGBW. Загружаем стандартный пример от библиотеки simple или strandtest_wheel, проверяем настройки, запускаем, любуемся.
А теперь попробуем сделать что-то простое, но своё. Для этого изучим несколько простейших функций данной библиотеки с примерами и посмотрим на результаты. Поможет там в этом кольцо из 24-х светодиодов WS2812B. Итак, первый пример. Выводим на кольцо три основных цвета RGB.
#include <Adafruit_NeoPixel.h> #define PIN 6 Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, PIN, NEO_GRB + NEO_KHZ800); void setup() { strip.begin(); // начинаем strip.setBrightness(50); // делаем яркость 50 (максимум 254) strip.show(); // ощищаем экран (рекомендуется при запуске для отключения случайных пикселей strip.setPixelColor(0, 0xFF0000); // красный strip.setPixelColor(1, 0x00FF00); // зеленый strip.setPixelColor(2, 0x0000FF); // синий strip.show(); // выводим } void loop() { }
Результат:
Немного комментариев.
Команда setBrightness(50); устанавливает, можно так сказать, масштаб шкалы яркости. Максимальная яркость любого цвета (0xFF), используемая после этой команды, будет ограничена данным параметром, промежуточные значения уменьшаются пропорционально. Можно ей не пользоваться вовсе, но иногда это удобно, например, если требуется приглушить цвета оптом, не выискивая и меняя их во всей программе. В примере я установил яркость 50, чтобы цвета хорошо отображались, не ослепляя камеру.
Команда setPixelColor(i, 0x00RRGGBB); также может принимать вид setPixelColor(i, R, G, B), где i - номер светодиода в ленте (начиная с 0), R, G, B - соответственно, яркость красного, зеленого и синего цвета по шкале от 0 до 254 в десятичном виде или от 0x00 до 0xFF в шестнадцатиричном. Примечание: первый вариант записи допускает только шестнадцатиричный вид, это 32-битное число (uint32_t), первые незначащие нули для лент RGB можно опустить. В примере я написал эту команду трижды с разными параметрами, тем самым присвоил каждому пикселю один из основных цветов.
Команда show(); служит для отправки данных на ленту. Все, что делается до выполнения этой команды, является лишь подготовкой массива к отправке. На время вывода данных, как я уже говорил ранее, отключаются все прерывания и таймеры, это может повлиять на отсчет времени в контроллере, его реакцию на события и так далее, обязательно имейте это в виду.
По большому счету, описанных команд достаточно для выполнения почти любых задач, все остальное - вопрос подготовки и обработки данных стандартными средствами Си. Надо лишь дать контроллеру понять, где и какой цвет мы хотим видеть.
Следующий пример. Построим шкалу яркости, поднимая накал по десятке на каждый следующий светодиод.
#include <Adafruit_NeoPixel.h> #define PIN 6 Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, PIN, NEO_GRB + NEO_KHZ800); void setup() { strip.begin(); // начинаем strip.setBrightness(50); // делаем яркость 50 (максимум 254) strip.show(); // очищаем экран (рекомендуется при запуске для отключения случайных пикселей for (byte i = 0; i < 24; i++) { strip.setPixelColor(i, i * 10, 0, 0); // увеличиваем яркость каждого следующего светодиода на 10 } strip.show(); // выводим } void loop() { }
Как видим, все прекрасно работает, разница заметна. Первый светодиод не горит, на нем 0, на последнем 230. Кстати, снимок не передает цветность полностью, в реальности разница еще заметнее.
Заменяем строку внутри цикла на такую:
strip.setPixelColor(i, i * 10, 240 - i * 10, 0); // плавно переливаемся от зеленого в красный
Результат:
Начиная с чисто зеленого, постепенно убавляя его добавляя красный, получаем плавный переход через смешивание цветов.
Наконец, простейшая анимация - бегущая по кругу точка.
#include <Adafruit_NeoPixel.h> #define PIN 6 Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, PIN, NEO_GRB + NEO_KHZ800); void setup() { strip.begin(); // начинаем strip.setBrightness(50); // делаем яркость 50 (максимум 254) strip.show(); // ощищаем экран (рекомендуется при запуске для отключения случайных пикселей } void loop() { static byte i = 0; // адрес "бегущей" точки static byte old_i = 23; // предыдущий адрес "бегущей" точки strip.setPixelColor(i, 0xFF, 0, 0xFF); // выводим новую точку strip.setPixelColor(old_i, 0, 0, 0); // стираем старую точку strip.show(); i < 23 ? i++ : i = 0; // сдвигаем положение точки i == 0 ? old_i = 23 : old_i = i - 1; delay(100); // задержка между кадрами }
Немного поколдовав с кодом можно сделать эффект интереснее:
Из кусочков ленты собрать модные очки.
Добавив акселерометр, изготовить динамическую подсветку для колеса.
И даже имитацию открытого огня.
Как видим, области применения в DIY адресных светодиодов ограничивается лишь некоторыми техническими особенностями и фантазией.
Недостатки и ограничения
К сожалению или к счастью, в мире нет ничего идеального и адресные светодиоды не исключение. Какие проблемы могут возникнуть при работе с ними и можно ли с этим жить? Попробуем разобраться.
Помехоустойчивость. Высокая скорость передачи данных без синхронизации и обратной связи проста, но имеет оборотную сторону - любая микроскопическая помеха портит весь пакет данных, превращая изображение в случайный набор пятен. При длине проводов от Ардуино до первого светодиода и между светодиодами более 10 см помехи начинают появляться просто “из воздуха” от наводок, статики и прочего электромагнитного шума. Частично этот эффект можно уменьшить, экранируя провода или просто скрутив в жгут сигнал и “землю”, но вероятность сбоев останется и будет расти с каждым лишним сантиметром. Совет: размещать пиксели как можно ближе.
Температура. Зимой, при морозе от -15 градусов и ниже чипы WS2811 начинают “сходить с ума” и вовсе перестают работать, вероятно, из-за замерзания тактового генератора. Совет: при использовании на открытом воздухе заранее позаботиться о подогреве.
Глубина цвета. Разница между максимально ярким и максимально тусклым светодиодом не так велика, как этого хотелось бы. Кроме того, светиться диоды начинают примерно с уровня 6-8 и сразу довольно ярко, то есть получить глубоких оттенков темных цветов на адресниках не получится. Совет: не ожидать качественного полноцвета и применять там, где этого не требуется.
Цветопередача. Проблема, родственная предыдущей - не всегда получаемый цвет полностью соответствует ожидаемому. Особенно это заметно при попытках вывести на экран из адресников реальные фотографии. Смешение цветов при небольшой глубине цвета происходит не всегда корректно, да и “чистые” цвета могут плавать от модели к модели и даже от партии к партии. Совет тот же.
Однако нужно понимать, что прогресс не стоит на месте, наверняка скоро мы увидим новые, более совершенные варианты этого устройства.
Выводы
В целом, адресные светодиоды - это гениальное изобретение с широчайшими возможностями и бездонными перспективами. Их появление развязало умелые руки и позволило отбросить от проектов множество костылей. Если учитывать и обходить ограничения, то процесс творчества и его результат будут приносить сплошное удовольствие.
FAQ
1. Можно ли управлять одним контроллером несколькими независимыми светодиодными лентами?Конечно, нужно лишь создать экземпляры класса Adafruit_NeoPixel, присвоив каждому свой индивидуальный пин. Рекомендую таким образом разбивать на части слишком длинные ленты.
Adafruit_NeoPixel strip_1 = Adafruit_NeoPixel(24, PIN_1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip_2 = Adafruit_NeoPixel(24, PIN_2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip_3 = Adafruit_NeoPixel(24, PIN_3, NEO_GRB + NEO_KHZ800);
2. Как управлять лентой с дополнительным белым цветом?Точно так же. Разница лишь в инициализации и дополнительном байте цвета.
Инициализация:
Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, PIN, NEO_GRBW + NEO_KHZ800);
Выставление цвета пикселя:
strip.setPixelColor(0, 0xRRGGBBWW);
3. Что означает класс защиты светодиодной ленты?Цитируем стандарт:
IP30. Защита от проникновения твердых объектов размером более 12 мм, пальцев рук или других предметов длиной не более 80 мм, или твердых предметов.
IP65: Полная защита от проникновения пыли и случайного проникновения. Защита от попадания струй воды, падающих под любым углом.
IP67: Полная защита от проникновения пыли и случайного проникновения. Защита от попадания воды при временном погружении в воду. Вода не вызывает порчи оборудования при определенной глубине и времени погружения.