Реклама ⓘ
Главная » Световые эффекты
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Реклама ⓘ

Новогодняя елка на умных светодиодах

"Как Новый год встретишь - так его и проведешь" - давно ставшая крылатой фраза, в какой-то степени заставляющая заранее готовиться к самому любимому празднику. И если такие традиционные атрибуты, как оливье и мандарины, незаменимы, то выбор различных инсталляций и украшений ежегодно заставляет ломать голову, радиолюбителям и электронщикам - в особенности.

Просмотренные в Интернете видео с поделками на "умных" светодиодах WS2812B сразу породили множество идей их применения. В конце ноября мне наконец-то пришла долгожданная, заказанная на eBay лента из 200 диодов. Доставка бесплатна, стоимость одного диода - около шести рублей. И так как до Нового года оставался всего месяц, я решил совместить приятное с полезным - и с подключением диодов разобраться, и к празднику подготовиться.

WS2812B - трехцветный светодиод с интегрированным драйвером и схемой, реализующей протокол управления. Имеет 4 вывода, как и "обычный" RGB-диод, однако их назначение отличается: два вывода отведены под питание схемы, один вывод под вход данных, и один - под выход (диоды можно соединять последовательно). Нет необходимости придумывать сложные алгоритмы для регулировки яркости и цвета каждого диода - разработчику достаточно передать в цепочку диодов последовательность байт и выдержать необходимые временные интервалы - после чего цепочка будет гореть заданным цветом либо до подачи другой последовательности, либо до отключения питания. При этом расходуется всего один вывод МК или ПЛИС!

В даташите на диоды (прикреплен в конце статьи) подробно расписаны все характеристики, здесь же приведу наиболее важные параметры:

  • размер одного диода 5х5 мм, корпус - для поверхностного монтажа;
  • напряжение питания - 3,5...5,3В;
  • максимальное количество диодов в одной цепочке - 1024, при частоте обновления 30 кадров в секунду. Стоит заметить, что подключить такое число диодов возможно при идеальном следовании таймингам протокола, что бывает проблематично;
  • светодиоды реализуют RGB-модель: каждый цвет кодируется одним байтом - теоретически возможно получить более 16 млн цветов. Однако на глаз разница между даже не столь близкими цветами незаметна.

Схема подключения диодов выглядит следующим образом:

При подаче питания диоды не инициализированы и горят синим цветом. Для инициализации цепочки диодов требуется выполнить следующие действия:

  1. Передать 8 бит G7..G0 для установки зеленого цвета первого диода;
  2. Передать биты R7..R0 для установки красного цвета;
  3. Передать биты B7..B0 для установки синего цвета;
  4. Повторить пункты 1-3 для второго, третьего и др. диодов. То есть, после инициализации первого диода, данные начинают проходить через него на следующий диод;
  5. Установить на входе логический "0" как минимум на 50 мкс, после чего все инициализированные диоды примут заданный цвет.

Передача единиц и нулей осуществляется не непосредственно, но выдержкой определенных временных интервалов; суммарное время передачи одного бита - 1,25 мкс, настройки одного светодиода - 30 мкс. На практике требуется соблюсти лишь длительность высокого уровня, длительность низкого может выходить из пределов в большую сторону.

Далее я подробно прокомментирую программу, которая инициализирует диоды, отвечает за управление и смену эффектов. Программа написана на языке ассемблера, проект в среде ATmelStudio 6.2 прикреплен в конце статьи. Будет рассмотрена только логика загрузки и переключения эффектов; очевидные вещи, вроде инициализации стека и настройки прерываний и портов, опущены. Также подразумевается, что цепочка диодов подключена к порту PD7 контроллера, рабочая частота - 8 МГц.

Идея программы заключается в следующем. Имеется некий набор эффектов, которые поочередно требуется выводит на светодиоды. Эффект характеризуется:

  • частотой кадров;
  • временем работы;
  • "интеллектуальностью". "Умным" называется эффект, который проще запрограммировать (например, плавные переливы цветов, одинаковые для многих эффектов); "глупый" же эффект описывается покадрово, массивом.

Перед объяснением логики работы следует пояснить, для чего нужны следующие регистры и константы:

.def temp = r16		                    ;для всего, своего рода регистр-помойка
.def counter = r17  	                ;регистр-счетчик светодиодов
.def curFn = r18	                    ;счетчик кадров, прошедших с момента начала текущего эффекта
.def curEf = r19	                    ;7..4 - число эффектов всего, 3..0 - номер текущего

.equ LED_COUNT = 17						;константа-общее число светодиодов
.equ BUFFER_SIZE = LED_COUNT*12+1		;размер буфера (будет пояснено позднее)
.equ XTAL = 8000000						;тактовая частота
.equ DIV = 256							;значение предделителя таймера
.equ TPS = XTAL / DIV					;число тиков таймера за секунду
.equ END = 0xFE							;маркер конца

Учитывая приведенные выше характеристики эффекта, он выглядит примерно следующим образом:

EffectName:
.db high(TPS/15),low(TPS/15), 15*16,1
.db 7,7,9,7,7,9,7,7,9,7,7,9
.db 7,7,9,7,7,9,7,7,9,7,7,9
.db 7,7,9,7,7,9,7,7,9,7,7,9
.db 7,7,9,7,7,9,7,7,9,7,7,9
.db 7,7,9,END

В первой строке находятся 4 байта характеристик:

  • два байта настройки прерывания таймера, определяющие частоты смены кадров. В данном случае частота - 15 кадров/сек;
  • байт длительности эффекта (в кадрах). Данный эффект продлится 16 секунд;
  • байт "умности" эффекта. Так как данный эффект (перелив) проще запрограммировать, байт равен единице.

Далее в массиве следуют:

  • 51 байт цветовых характеристик каждого диода (в случае покадрового описания их было бы на порядок больше);
  • маркер конца массива.

Под хранение буфера и некоторых констант в ОЗУ выделено следующее количество места:

.dseg
BytesBuffer:	.byte BUFFER_SIZE           ;массив байт, который будет загружаться в диоды (пояснено ниже)
ColorsTable:	.byte LED_COUNT*3+1			;3 - число цветоканалов(R,G,B), 1 байт под маркер конца
MaxFrame:		.byte 1						;число кадров, которое необходимо проиграть, для конкретного эффекта
CurEffectAddr:	.byte 2						;хранит в себе адрес текущего эффекта

.equ CEA_H = CurEffectAddr + 1
.equ CEA_L = CurEffectAddr + 0

Хочется подробнее пояснить "программируемость" эффектов. Дело в том, что в массиве должны быть перечислены интенсивности каждого цвета (от 0 до 16). В свою очередь, данные значения умножаются на значения следующий регистров (заодно приведены константы-помощники в реализации перелива):

.def R = r20	;динамическая интенсивность красного
.def G = r21	;зеленого
.def B = r22	;и синего
.def F = r23	;флаг для автомата переключения состояний

;флаги состояний
.equ G_HIGH = 1
.equ R_DOWN = 2
.equ B_HIGH = 3
.equ G_DOWN = 4
.equ R_HIGH = 5
.equ B_DOWN = 6
.equ MAX_FLAG = 7

Произведение констант из массива и соответствующих регистров формируют таблицу цветов (ColorsTable) для каждого из диодов. В случае, если эффект программируется, значения регистров R,G,B можно динамически менять. Описание всех кадров такого эффекта нецелесообразно (требует слишком много памяти контроллера).

В случае, если эффект не программируемый, все кадры перечислены в массиве, а интенсивности вместо значений регистров умножаются на 15.

После получения таблицы цветов необходимо получить последовательность байт, которая будет загружаться непосредственно в диоды. Это выполняет следующая функция:

ColorToBytes:
	ldi temp,0x88
	sbrc R0,7                         ;используется регистр R0 как стандартный аргумент команды lpm
	subi temp,-(1<<6)          ;сложения в AVR нет, поэтому так извращенно
	sbrc R0,6
	subi temp,-(1<<2)
	st Y+,temp

	ldi temp,0x88
	sbrc R0,5
	subi temp,-(1<<6)
	sbrc R0,4
	subi temp,-(1<<2)
	st Y+,temp

	ldi temp,0x88
	sbrc R0,3
	subi temp,-(1<<6)
	sbrc R0,2
	subi temp,-(1<<2)
	st Y+,temp

	ldi temp,0x88
	sbrc R0,1
	subi temp,-(1<<6)
	sbrc R0,0
	subi temp,-(1<<2)
	st Y+,temp	
ret

То есть, данная функция преобразует один байт в четыре, которые будут загружаться в диоды.

LoadData:
cli				;цикл загрузки битов в диоды. Очень быстрый, и дабы тут ничего не сломалось, на всякий случай запрещаю прер-ия.
LoadData2:
ld temp,Y+
cpi temp,END
breq FromBegin  ;все диоды инициализированы, прыгаем в бесконечный цикл
Out1:
out PortD,temp
lsl temp
nop
out PortD,temp
lsl temp
nop
out PortD,temp
lsl temp
nop
out PortD,temp
lsl temp
nop
out PortD,temp
lsl temp
nop
out PortD,temp
lsl temp
nop
cbi PortD,7
rjmp PC+1		;выполняется 2 такта, но занимает 2 байта, в отличие от 2*nop, которые выполняются столько же,
rjmp PC+1		;но занимает 4 байта
rjmp PC+1
rjmp PC+1
rjmp PC+1
rjmp PC+1
rjmp LoadData2

FromBegin:
sei
cbi PortD,7
Loop: 
              ;пока что цикл абсолютно пуст, то есть можно разместить еще какие-либо действия/обработчики
rjmp Loop

Откуда взялась волшебная константа 0х88? Нужная длительность низких и высоких уровней формируется путем выдерживания определенного значения на выходе порта. Команды lsl - nop - out выполняются за три такта, то есть за 375 нс, что укладывается в допустимую погрешность. Таким образом, передача нуля сводится к загрузке последовательности 1000, а единицы - 1100. То есть, в одном байте передаются два бита, а в двенадцати байтах - настройки одного диода (24 бита = 3 байта G,R,B), что сразу делает понятной данную строку:

.equ BUFFER_SIZE = LED_COUNT*12+1  ;размер буфера (будет пояснено позднее)

Именно поэтому в начале байт равен 0x88, функция ColorToBytes попросту выставляет единицы на позициях 6 и 2, если это необходимо, и загружает байт в выходной буфер.

В упомянутом выше прерывании таймера реализовано следующее:

  • загрузка следующего кадра эффекта;
  • если же эффект дошел "до конца", то следующим кадром будет являться начало эффекта;
  • если эффект отыграл установленное время, следующим кадром будет начало следующего эффекта;
  • если эффект "умный", будут изменены значения интенсивностей в регистрах.

Общий алгоритм работы представлен следующей блок-схемой:

Также в конце статьи прикреплен шаблон проекта, незначительная правка которого позволит очень быстро работать с WS2812B.

Осталось продемонстрировать готовое устройство на "умных" светодиодах - новогоднюю елку. Схема елки достаточно проста и приведена ниже:

Основной компонент схемы - микроконтроллер ATmega8A в TQFP-корпусе. Также я оставил две кнопки для будущей доработки елки. Остальные компоненты почти полностью представлены резисторами и конденсаторами типоразмера 0805. Питается елка от 5 Вольт через разъем micro-USB, что позволяет разместить елку где угодно при подключении к внешнему ЗУ типа PowerBank. Файл с ПП елки находится в архиве (плата двусторонняя).

Фото вырезанной на ЧПУ-станке платы (одна сторона):

Впервые в жизни попробовал вырезать плату из тонкого (0.3мм) текстолита, так как планировал закрепить елку на листе бумаги формата А3. Для больших плат механическая прочность такого текстолита низка; советую брать текстолит от 1 мм толщиной. На фото даже видно просвечивающие дорожки другой стороны!

Пайка и прошивка схемы трудностей вызвать не должны, все необходимые файлы прикреплены в конце статьи. Фото елки в работе (эффект северного сияния, фрагменты гирлянд):

Далее осталось закрепить (или не закреплять) елку на какой-либо поверхности либо опоре, задекорировать мишурой... В общем, здесь простор для творчества еще больше.

Небольшое видео работы (пример эффекта перелива):

В конце статьи прикреплен архив, где находятся:

  • исходный проект новогодней елки в AtmelStudio 6.2;
  • шаблон проекта в этой же среде;
  • файл печатной платы елки;
  • файл схемы елки;
  • прошивка елки;
  • FUSE-биты контроллера;
  • схема подключения диодов;
  • даташит на WS2812B.

Теперь у Вас есть почти 9 месяцев, чтобы подготовиться к следующему Новому году! А также поделиться предложениями, идеями и замечаниями в комментариях и на форуме.

Список радиоэлементов

Обозначение Тип Номинал Количество ПримечаниеМагазинМой блокнот
U1 МК AVR 8-бит
ATmega8A-AU
1 TQFP32Поиск в магазине ОтронВ блокнот
D1-D17 СветодиодWS2812B17 Поиск в магазине ОтронВ блокнот
C1 Конденсатор47 мкФ1 TANT_AПоиск в магазине ОтронВ блокнот
C2 Конденсатор100 нФ1 0805Поиск в магазине ОтронВ блокнот
R1-R3 Резистор
10 кОм
3 0805Поиск в магазине ОтронВ блокнот
R4 Резистор
0.27 Ом
1 0805Поиск в магазине ОтронВ блокнот
S1-S2 Кнопка2 Без фикс.Поиск в магазине ОтронВ блокнот
J1 Разъем1 micro USBПоиск в магазине ОтронВ блокнот
Добавить все

Скачать список элементов (PDF)

Прикрепленные файлы:

Теги:

Опубликована: 0 0
Я собрал 0 1
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 5 Проголосовало: 1 чел.

Комментарии (5) | Я собрал (0) | Подписаться

0
Публикатор #
На форуме автоматически создана тема для обсуждения статьи.
Ответить
0
Vyacheslav #
Есть ощущение, что использовать обычные RGB все же проще
Ответить
0

[Автор]
elyspire #
Если диодов 1-2, то вполне возможно. А если их 100, и гореть должны независимо друг от друга...?
Ответить
0
favet #
Добрый день. А какое колличество светодиодов можно использовать? Имеется лента на 50 шт. светодиодов ws2812b или только ограничение как в статье17 штук. Я так понял фьзы поставлены на внутреннийгенератор на 8мГц?
Ответить
0

[Автор]
elyspire #
Здравствуйте.
Если говорить об оптимальной частоте обновления (в районе 30 кадров/с) - не более 900-1000 диодов.
Если о коде - то информация о диодах в совокупности занимает в ОЗУ N*15+2, где N - число диодов. В мега8 1 КБ ОЗУ, с учетом места на стек и прочие переменные зарезервируем хотя бы 150 байт. Получаем 58 диодов, что лично для меня было достаточно.
Фьюзы - да, на внутренний 8 МГц, но лучше использовать кварц на аналогичную частоту, будет стабильнее
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется напряжение?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Набор для сборки - LED лампа
Набор для сборки - LED лампа
Программатор Pickit3 DC-DC регулируемый преобразователь 1.5-37В 2А с индикатором
вверх