Как работает адресная светодиодная лента?

от автора


Наверное этот вопрос «как работает» очень многим покажется глупым. Ответ почти очевиден: адресная светодиодная лента состоит из множества последовательно соединенных «умных светодиодов». Это можно увидеть просто рассматривая устройство ленты. Видны отдельные микросхемы, припаянные к гибкому шлейфу, видны соединения: микросхемы соединены последовательно всего тремя проводами, при этом два из них это питание и земля. Только один провод передает данные о цвете пикселей. Как же это? Что такое «умный светодиод»?

Дальше я расскажу о протоколе передачи данных, используемом в светодиодной ленте на базе WS2812B, и, более того, я почти создам свою «микросхему светодиодной ленты» в микросхеме ПЛИС.

Итак, в ленте используется последовательная передача через один единственный сигнал данных.

Бит ноль передается, как короткий положительный импульс и пауза, которая примерно в два раза шире импульса. Бит единица передается как широкий положительный импульс и короткая пауза:

При отсутствии передачи более 50 микросекунд лента переходит в исходное состояние, готова принимать пиксели начиная с первого.

Каждые 24 бита в последовательности — это 3 байта для трех цветов RGB. Причем на самом деле последовательность будет G-R-B. Старший бит G7 идет первым.

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

Заполнится первый, потом второй, потом третий и так все по очереди.

Таким образом, я считаю, что с протоколом передачи разобрались.

Можно ли попробовать самому спроектировать такой «умный светодиод»? Практического смысла в этом конечно мало, но для самообразования и расширения кругозора — задача интересная. Попробуем описать логику чипа на языке проектирования аппраратуры Verilog HDL. Конечно, это будет не настоящий дизайн микросхемы, будут ограничения. Одно из самых важных ограничений — мне для моей микросхемы будет нужен внешний тактовый генератор. В настоящем умном светодиоде такой генератор тоже есть, но он встроен уже в чип.

Модуль на Verilog начнем вот так:

module WS2812B( 	input wire clk, 	input wire in, 	output wire out, 	output reg r, 	output reg g, 	output reg b );

Здесь думаю все понятно: тактовая частота clk, входной и выходной сигналы «умного светодиода» in и out, ну и, конечно, выходные сигналы r, g, b через которые я буду управлять реальными внешними светодиодами красным, зеленым и синим.

Входной сигнал я буду захватывать в двухббитный сдвиговый регистр и по текущему состоянию в этих захваченных битах смогу определить начало положительного фронта сигнала in:

reg [1:0]r_in = 0; always @( posedge clk ) 	r_in <= { r_in[0],in };  wire in_pos_edge; assign in_pos_edge = (r_in==2'b01);

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

localparam reset_level = 3000; reg [15:0]reset_counter = 0; always @( posedge clk ) 	if( r_in[0] ) 		reset_counter <= 0; 	else 	if( reset_counter<reset_level ) 		reset_counter <= reset_counter+1;  wire reset; assign reset = (reset_counter==reset_level);

Дальше, от положительного фронта in_pos_edge нужно выдержать некоторую паузу, чтобы получить момент фиксации нового бита:

localparam fix_level   = 50; reg [7:0]bit_length_cnt; always @( posedge clk ) 	if( in_pos_edge ) 		bit_length_cnt <= 0; 	else 	if( bit_length_cnt<(fix_level+1) && !pass ) 		bit_length_cnt <= bit_length_cnt + 1;  wire bit_fix; assign bit_fix = (bit_length_cnt==fix_level); 

Количество уже принятых бит в чипе считаем так:

reg pass = 0; reg [5:0]bits_captured = 0;  always @( posedge clk ) 	if( reset ) 		bits_captured <= 1'b0; 	else 	if( ~pass && bit_fix ) 		bits_captured <= bits_captured+1'b1;

Здесь вводится еще важный сигнал pass, который как раз и определяет перенаправление входного потока на выход. После принятия 24х бит пикселя сигнал pass устанавливается в единицу:

always @( posedge clk ) 	if( reset ) 		pass <= 1'b0; 	else 	if( bits_captured==23 && bit_fix ) 		pass <= 1'b1; 		 reg pass_final; always @( posedge clk ) 	if( reset ) 		pass_final <= 1'b0; 	else 	if( r_in!=2'b11 ) 		pass_final <= pass; 		 assign out = pass_final ? in : 1'b0;

На выход out мультиплексируются входные данные, когда сигнал pass_final в единице.

Ну и, конечно, нужен сдвиговый регистр, где накапливаются принятые 24 бита пикселя:

reg [23:0]shift_rgb; always @( posedge clk ) 	if( bit_fix ) 		shift_rgb <= { in, shift_rgb[23:1] };  reg [23:0]fix_rgb; always @( posedge clk ) 	if( bits_captured==23 && bit_fix ) 		fix_rgb <= { in, shift_rgb[23:1] };

По приему всех 24х бит они переписываются в итоговый так же 24х битный регистр.

Теперь остается дело за малым. Нужно реализовать ШИМ (Широтно Импульсную Модуляцию) сигнала для передачи яркости реальным внешним светодиодам согласно принятым байтам RGB:

wire [7:0]wgreen; assign wgreen = { fix_rgb[0 ], fix_rgb[1 ], fix_rgb[2 ], fix_rgb[3 ], fix_rgb[4 ], fix_rgb[5 ], fix_rgb[6 ], fix_rgb[7 ] }; wire [7:0]wred;   assign wred   = { fix_rgb[8 ], fix_rgb[9 ], fix_rgb[10], fix_rgb[11], fix_rgb[12], fix_rgb[13], fix_rgb[14], fix_rgb[15] }; wire [7:0]wblue;  assign wblue  = { fix_rgb[16], fix_rgb[17], fix_rgb[18], fix_rgb[19], fix_rgb[20], fix_rgb[21], fix_rgb[22], fix_rgb[23] };  reg [7:0]pwm_cnt;  always @( posedge clk ) begin 	pwm_cnt <= pwm_cnt+1; 	r <= pwm_cnt<wred; 	g <= pwm_cnt<wgreen; 	b <= pwm_cnt<wblue; end

Вот кажется и все.

Остается маленькая деталь — как это все испытать?

Я взял несколько простых плат с ПЛИС MAX II (это платы серии Марсоход) и прошил их все проектом с вот этим Verilog кодом. На платах уже было 8 светодиодов, но они были все желтые. На каждой из плат я заменил 3 светодиода на R, G, B. Платы соединил последовательно и более того подключил их к настоящей светодиодной ленте. Таким образом, я удлинил настоящую ленту своими самодельными светодиодами.

Получилось вот такое соединение:

В реальности это выглядит вот так:

Теперь, подавая на ленту некоторое изображение я вижу, что мои «умные светодиоды» ведут себе точно так же, как и настоящие из ленты:

Получается, что реализованная мною в ПЛИС логика вполне работоспособна! Я смог в первом приближении сделать нечто похожее на реальный чип «умного светодиода».

Вообще, мне нравятся светодиодные ленты. На их основе каждый может изобрести что-то свое: интеллектуальное освещение, экраны, амбилайт эффекты. Однажды я даже реализовал цветомузыку на светодионой ленте под управлением FPGA. Но это уже другая история.

ссылка на оригинал статьи https://habr.com/ru/post/502712/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *