Светодиоды (пиксели) WS2812B и светодиодные ленты на базе этих пикселей довольно популярны и это оправдано по нескольким причинам:
— компактность — пиксель содержит в своем корпусе (размером всего 5х5 мм) 3 светодиода и драйвера для них
— простота управления – пиксель управляется посредством простого последовательного интерфейса, который легко реализовать как программно, так и используя аппаратные интерфейсы МК (такие как SPI и UART)
— управление всего по одной линии (не считая проводов питания)
— неограниченное количество включенных последовательно пикселей
— относительно небольшая стоимость (если посчитать стоимость отдельно 3х светодиодов и драйверов к ним выйдет гораздо дороже)
Эта статья попытка обобщить информацию (наверное, больше для себя) об умных светодиодах WS2812B в одном месте.
Начнем знакомство с серией WS
Первым идет WS2801
Фактически, это не светодиод а микросхема-драйвер для RGB-светодиода с последовательным интерфейсом SPI (есть линия данных и тактовая линия). Эти микросхемы используются во встраиваемых конструкциях пикселей:
Есть и ленты с использованием этих драйверов, но, наверное, их не найти уже.
WS2801.pdf (4760 Загрузок)
Дальше — WS2811
Это тоже микросхема для управления RGB-светодиодом, но она уже компактней (8 ног, в отличие от WS2801 — 14 ног) и имеет однолинейный последовательный интерфейс.
WS2811.pdf (3854 Загрузки)
Приближаемся — WS2812(S)
Это уже интегрированные в SMD корпусе 5050 и драйвер и сами светодиоды. Корпус 6-ти ножечный
Как и в предыдущем WS2811 интерфейс однолинейный, но тайминги протокола другие несовместимые.
WS2812.pdf (5865 Загрузок)
И, наконец, WS2812B
Это почти аналог предыдущего светодиода, но уже с 4-мя ножками и слегка измененными таймингами протокола (совместимы, при использовании компромиссных значений временных периодов сигналов)
WS2812B.pdf (9345 Загрузок)
Еще существует WS2812D (аналог PD9823)
Это полностью WS2812B но в корпусе обычного 8мм светодиода.
WS2812D.pdf (4395 Загрузок)
Нас, прежде всего, интересует именно WS2812B, так как он наиболее популярный и недорогой. Его чаще всего используют радиолюбители в своих конструкциях как отдельно, так и в лентах.
Принцип работы WS2812B — официальная информация из даташита.
Физически в WS2812B имеется 3 излучающих светодиода (красный, синий и зеленый) и ШИМ-драйвера управляющие их яркостью. ШИМ-драйвера 8-ми битные, то есть для каждого из цветов возможны 256 градаций яркости и, соответственно, для того чтобы установить яркости для каждого из 3-х светодиодов нужно передать пикселю 8х3=24 бит (3 байта) информации. Протокол передачи информации светодиоду однолинейный с фиксированной скоростью. Единички и нули информации о яркости кодируются длительностью высокого и низкого уровня сигнала в линии.
Время передачи одного бита составляет 0.8+0.45=1.25 мкС — это довольно быстро. Время передачи всего пакета из 24 бит для одного пикселя WS2812B составляет 24*1.25=30 мкС. Для 1000 штук — 1000*30=30 мС (что, например, позволяет обновлять по одной линии панно 30х30 пикселей с частотой 30 раз в секунду!).
Каждый из пикселей WS2812B имеет 2 вывода питания (VDD, VSS), вход (DIN) и выход (DOUT).
На вход DIN подается информация (24бита) для установки нового цвета. Информация о цвете передается побитно (начиная со старшего бита) последовательно для каждой из составляющей цветов G, R, B.
Пиксели соединяются в цепочку следующим образом:
Запись значений цвета цепочке пикселей происходит следующим способом:
Первые 24 бита поданные на DIN записывает себе во временную память (цвет пока остается неизменным с предыдущего раза) первый пиксель. Последующие биты первый пиксель пропускает через себя и выдает на выход DOUT. Второй пиксель повторяет действия первого (оставляя себе первые дошедшие до него 24 бита) и так по цепочке. Для того, чтобы значения цветов из временной памяти пикселей стали активными должна быть выдержана пауза в передаче (reset code) в течении 50мкС. После этой паузы цикл можно повторять снова.
Вот это основное, что нам говорит довольно скудный даташит.
Теперь более интересная часть –
Практические способы включения ленты и реализации протокола WS2812B.
То, о чем умалчивает даташит, я собрал из разных источников у людей имевший практический опыт работы с WS2812B. Конечно, это больше касается лент.
Для начала, общие советы (по большей части взятые с https://learn.adafruit.com):
— подключайте к ленте (между линиями питания) конденсатор побольше, вплоть до 1000 мкФ
— в разрыв линии данных (от МК к ленте) добавляйте резистор 300 — 500 Ом, устанавливая его ближе к ленте.
— по возможности, делайте короче провод данных к ленте
— при «горячем» подключении ленты, подключайте «землю» первой (отключайте последней)
— если лента запитана от отдельного источника питания, ее нужно запитать первой (после чего запитать схему управления)
— не допускайте статического электричества при монтаже ленты
— используйте преобразователь уровня, если лента и устройство управления запитаны от источников питания с разным напряжением
— напряжение питания пикселей, заявленное в даташите, лежит в пределах +3.5 ~ +5.3 вольт. Из чего видно, что предпочтительней подавать на ленту меньше 5ти вольт (этим правилом следует пользоваться при выборе количества элементов при батарейном питании)
— максимальный ток каждого пикселя составляет 60мА (при полной яркости белого цвета). Если Вы не планируете использовать ленту WS2812B как источник белого света (для этого лучше взять обычную светодиодную ленту с белыми светодиодами), то принято считать, что, усреднено, каждый пиксель потребляет 20мА.
Соответственно:
минимальный ток ИП = 20мА*количество_пикселей.
максимальный ток ИП = 60мА*количество_пикселей
— из последнего пункта вытекает следующее: если лента длинная, то недопустимо подавать на нее питание только с одной стороны. Для того чтобы исключить перегревание (или даже перегорание) токопроводящих дорожек ленты, питание ленты необходимо распределить по всей ее длине, подводя питание в нескольких местах отдельными проводами.
Теперь более ценные советы по реализации протокола
Есть несколько способов реализовать протокол умных светодиодов:
— аппаратный при помощи SPI-интерфейса
— аппаратный при помощи UART-интерфейса
— программный
Достоинство первых двух способов – это возможность освободить МК от части работы по передаче бит информации о цвете пикселю. Недостатки этих способов – во-первых, ограниченное количество линий управления пикселями (у МК редко бывает много незадействованных интерфейсных выходов), во-вторых, требуется дополнительное разбитие байтов информации о цвете на пачки битов (что частично съедает свободное время МК в моменты аппаратной передаче бит)
Реализация протокола WS2812B (NeoPixel) при помощи SPI
Прежде, чем приступить к реализации, следует акцентировать внимание, что у WS2812B кодирование нулей и единичек происходит по правилу 1/3 (смотрите даташит выше). То есть ноль передается как 1/3 времени высокий уровень и 2/3 низкий. Единица – это 2/3 высокий и 1/3 низкий. Из этого следует, что для передачи одного бита для WS2812B нам достаточно 3х бит переданных по SPI.
Как видно на картинке, чтобы сформировать нужную последовательность нулей и единиц, нам придется дробить первичную информацию о цвете на кусочки, кроме того, в байт, передаваемый по SPI, не вписывается триады и их придется дробить тоже, перенося часть информации о бите для пикселя в следующую посылку… выходит очень запутано и сложно.
Но есть решение этой проблемы! Забегая наперед, сообщу, что для пикселя важна длительность периода высокого уровня, а низкий уровень может быть с бОльшим отклонением, чем указано в даташите. Поэтому мы может удлинить наши цепочки бит SPI с трех до четырех:
Вот теперь алгоритм становится более простым и приемлемым к реализации.
Для выдачи информации на пиксели используется только один вывод SPI – MOSI. Выводы MISO и SCK остаются незадействованными. Частота SPI должна быть 1/0.4мкС = 2.5МГц
Реализация протокола WS2812B (NeoPixel) при помощи UART
Все, о чем я писал для SPI, подходит и для UART, но тут есть несколько моментов, которые усложнят реализацию:
— UART в паузах удерживает свою выходную линию (TXD) в высоком уровне, что для пикселей недопустимо, так как невозможно будет избежать неопределенностей в моменты начала и окончании передачи
— соответственно, нужно инвертировать сигнал перед подачей его на пиксели
— а, так как линия инвертируется, нужно инвертировать и передаваемые данные
— UART-пакет, в отличии от SPI, содержит служебные биты – это старт-бит и стоп-бит (бит четности нужно отключать в настройках UART — он не нужен). Дополнительные биты служебной информации нужно учитывать при формировании передаваемого байта, так как они тоже пойдут в пиксель
В итоге, если учесть все нюансы, получается идеальная реализация протокола. Устанавливаем скорость UART 2.5 МГц (это нестандартно), устанавливаем размер кадра 7 бит (вместо стандартных 8-ми), убираем бит четности, оставляем один стоп-бит и получаем следующую картинку:
Программная реализация протокола WS2812B (NeoPixel)
Переходим к тому разделу, ради которого я и писал эту статью (но, видимо, увлекся по ходу 🙂 ). Для меня интересней реализовать этот протокол программно, так как эта реализация дает мне произвольное количество линий у МК к которым можно подключить ленты и управлять ими независимо. Это плюс. Минусом является то, что протокол довольно быстрый и это накладывает ограничения на процедуру формирования сигналов и, конечно, в моменты вывода значений цвета все прерывания у МК должны быть запрещены.
Первая проблема, которую придется решать – это формирование малых временных интервалов.
Для примера. МК работает на частоте 16МГц. Время одного такта 0,0625 мкС
Для формирования интерфейса WS2812B нам нужно формировать 2 временных интервала: 0,4мкС (6 тактов) и 0,85мкС (14 тактов). Всего период бита составляет 20 тактов. Очевидно, язык высокого уровня не способен сформировать код с точной размерностью по тактам. Это возможно реализовать только на языке низкого уровня – придется использовать ассемблер (по крайней мере, только для этой процедуры).
Дальше возникает проблема с точностью формирования этих промежутков. Если мы говорим о передаче данных только для одного пикселя (3 байта), то периоды можно соблюсти очень точно, прописав отдельно буквально каждый бит. Другое дело если нам нужно передавать массив значений в одной посылке без пауз. Тут придется создавать алгоритм, который, кроме того что формирует сигнал (дрыгает ногой МК), еще и считывает данные с массива данных в SRAM (или Flash), возможно, осуществляет несложную обработку данных. В этом случае очень сложно будет уложиться в 20 тактов периода передачи бита и, неизбежно, будут возникать ситуации, где потраченное на обработку время превысит допустимые значения. Вот тут нам помогут исследования проведенные здесь:
Привожу итоговую таблицу того что допускает протокол в плане ухода от даташита.
Более детально читайте в статье по ссылке выше, но если кратко — протокол требует более жесткого формирования периодов сигнала с высоким уровнем, а периоды с низким уровнем могут быть значительно затянуты. Это дает нам простор для реализации «тяжелых» мест.
Далее, даташит нам дает время паузы после которой происходит защелкивание новых значений цвета – 50 мкС. По факту, защелкивание начинается уже после 10 мкС – нужно стараться не делать паузы больше 10 мкС во время передачи длинных пакетов данных.
И последнее, как видно из приведенных выше даташитов, у пикселей WS2812 и WS2812B разные временные периоды, формирующие нули и единички. Но используя допустимые отклонения по времени можно реализовать протокол, который сможет работать без проблем с обоими пикселями.
Нифига. А как же быть тогда с фьюзами? Что там выставлять, чтобы работало на 10 Мгц?
Ставлю фьюзы 0xCF, 0xD9, в atmel studio F_CPU 10000000, но частота точно неправильно задается, судя по blink’у.
Что-то я затупил. Можно же и на кварце 16 МГц все сделать. Надо просто в IDE указать частоту МК , допустим, 10 МГц и применить соответствующий предделитель.
Здравствуйте. С программной реализацией не могу сладить, так как не понимаю, как можно адекватно выдерживать такие задержки. Пытался выставлять высокий уровень на ножке, затем пропускать с помощью asm(«nop») требуемое количество тактов и «опускать» ножку. Подбирал это количество по показаниям китайского осциллографа(чтоб выходило 350-500 нс или 850-1000 нс). Но не взлетело.
Решил попытаться организовать передачу данных через SPI и сразу возникли вопросы. Как можно настроить частоту spi на 2,5 МГц? Получается, что единственным вариантом будет использование кварца с не кратной 2 частотой, допустим, 25 МГц?
В даташите меги8 есть табличка, описывающая зависимость частоты spi от частоты тактирования, но там всё кратно 2.
Вам нужно тогда поискать для вашего языка программирования примеры сдвига байта вправо, либо, просто подаваемые на вход библиотек (или снимаемые с их выхода) значения делить на 2. По идее это должно быть весьма просто. Я могу помочь лишь с Ассемблером. Языков или библиотек, указанных Вами, я не знаю.
Здравствуйте Vladimir я не знаком с программированием на Ассемблере и СИ не представляю как я реализую такой проект. Я прошивал только ардуинку для нее уже готовым скетчем можно ли в самом скетче что то прописать чтобы сдвинуть биты через те библиотеки в частности FastLED или как то там понизить минимальный порог яркости? Может можно с Prismatik что то сделать он же считывает всю информацию для отправки на ленту?
Здравствуйте Артем, Вы можете сдвинуть значения каждого из трёх отправляемых байт R, G, B вправо на 1 бит, или, это то же самое, разделить на 2. На Ассемблере это: LSR R16, 1. На СИ (возможно, не точно) R = R / 2; Для проверки пробуйте на числе 255 должно получиться 127, на числе 1 выйдет 0. Это уменьшит яркость в 2 раза, не только минимальную, а все возможные, и сделает её равной ЭКО-варианту.
Vladimir Добрый день. Могли бы вы подсказать как сделать из обычной ленты ЭКО сдвинув яркость на один бит? Я так понимаю это должно уменьшить минимальную яркость самой ленты сравняв его с ЭКО вариантом верно?
На очередной ленте обнаружилась неработоспособность на 1/256 яркости. Код один и тот же, многократно проверенный, подстройка кода ничего не дала. Оказалось — продавец подсунул WS2812B-ECO вместо настоящих. До этого с таким не сталкивался. Дальнейшее исследование выявило, что WS2812B-ECO используют просто сдвиг данных на 1 бит, что, разумеется приведёт к тому, что на полной программируемой яркости будет 50% ШИМ — что и подтвердилось. Указанное поведение даёт возможность сэкономить на светодиодных кристаллах и их монтаже без особого усложнения чипа (драйверы остаются 20 мА). Кристаллы СИД действительно оказались расположены на одной подложке, как и написано здесь. Будьте осторожны, возможно рынок ожидает наводнение очередным суррогатом. Спрашивайте продавца точную модель (не-ЭКО в явном виде). Из обычных пикселей при необходимости «ЭКО» делается сдвигом яркостей на 1 бит, но, к сожалению, из «ЭКО» обычных уже не сделать. Спасибо. P.S. Покупал здесь по причине того, что это одно из немногих мест, где доступен шаг пикселей 10 мм (это требовалось по ТЗ).
Пытался решить проблемы с ардуиной ( неправильно работал скетч),переодически подключал светодиодную ленту, думал починил, но нет, теперь при подключении питания к светодиодной ленте ( просто + и — ) горят светодиоды (они как-будто застыли и горят так, как нужно было бы). Что делать? Я подключал с резистором на 100 ом и конденсатором по цепи питания на 3300 мкф. Пытался сделать цветомузыку, и до сих пор не получается, при подключении питания к ардуине, у нее горит красный светодиод и все, при подключении другой ленты, она не горит.
Так легче понять
Я подключал с резистором на 100 ом и конденсатором по цепи питания на 3300 мкф
У самого теперь почему-то проблемы, пытался решить проблемы с ардуиной ( неправильно работал скетч), теперь при подключении питания ( просто + и — ) горят светодиоды (они как-будто застыли и горят так, как нужно было бы). Что делать?
Юрий
Конденсатор и резистор не помогли
to Юрий
При больших токах (и длинах ленты) обязательно подводящие линии питания нужно делать в нескольких местах по ленте, иначе лента будет перегреваться (вплоть до перегорания линий) и падение напряжения на конце ленты будут значительным.
попробуйте с конденсатором на 1000мкф и резистором от 100ом до 500ом
Без резистора и без конденсатора сама лента тоже без конденсаторов.
https://ru.aliexpress.…311.0.0.151733edmkT45K
WS2812B оснащена квадратным ШИМОМ красный и синий диод расположены на одной подложке а зеленый на другой все работает идеально.
WS2812B-ECO оснащена прямоугольным ШИМОМ все диоды расположены на одной подложке зависает в разных местах.
Ты подключал с резистором?
Привет кто нибудь знает почему некоторые светодиодные ленты WS2812B зависают во время работы. На одном и том же оборудовании в равных условиях как это можно объяснить?
Привет! Вот заказал я ленту, 4 метра 30 светодиодов на метр, посчитал, и получается лента потребляет 2.4 ампера, т.к. она у меня будет работать и в режиме подсветки (не на всю) он будет потреблять около 5 ампер, можно ли подключить питание ленты посередине (знаю, вопрос детский) или все-таки лучше подключить питание в начале и в середине? P.S. Огромное спасибо за информацию!
Да, пиксели работают каждый самостоятельно. Можно подключать каждый отдельно.
При изменении библиотеки и кода можно проверить каждый диод отдельно, все также не работают 6 и далее диоды. Эту ленту ведь можно резать каждый диод? Одна секция равна 1 диоду?
Не помогло, вырезал сгоревший-не помогло, горят все также 6 диодов. Резистор установил,330 ом
Да, сигнал данных проходит через каждый пиксель последовательно.
Почему згорело не могу сказать — подобного у меня не было.
Кстати, рекомендуется подключать линию данных через резистор до 1кОм
Тогда еще вопрос,это наверное уже больше к пониманию. Почему у меня сначала почти все горело, потом при контакте погасло? И еще вопрос, получается дорожка Di последовательная? То есть, если я просто соединю провод сигнала с Arduino nano с со следующим неработающим диодом после того треснутого, то остальная дорожка должна засветиться?