Provavelmente, essa pergunta "como funciona" parece tola para muitos. A resposta é quase óbvia: uma faixa de LED endereçável consiste em uma pluralidade de "LEDs inteligentes" conectados em série. Isso pode ser visto simplesmente olhando para o dispositivo de fita. Você pode ver microcircuitos individuais soldados em um loop flexível, você pode ver as conexões: os microcircuitos são conectados em série com apenas três fios e dois deles são de potência e terra. Apenas um fio transmite dados de cores de pixel. Como é isso? O que é um LED inteligente?A seguir, falarei sobre o protocolo de transferência de dados usado na faixa de LEDs com base no WS2812B e, além disso, quase criarei meu próprio “chip de faixa de LED” no chip FPGA.Portanto, a fita usa transmissão serial através de um único sinal de dados.O bit zero é transmitido como um impulso positivo curto e uma pausa aproximadamente duas vezes maior que o impulso. A unidade de bit é transmitida como um amplo pulso positivo e uma curta pausa:
se não houver transmissão superior a 50 microssegundos, a fita retornará ao seu estado original, pronta para aceitar pixels a partir do primeiro.A cada 24 bits em uma sequência são 3 bytes para três cores RGB. E, de fato, a sequência será GRB. A parte alta do G7 vem em primeiro lugar.A sequência dos primeiros 24 bits é de um pixel, que receberá o primeiro LED da fita. Até o primeiro LED ficar saturado, ele não transfere mais os dados para o próximo LED. Depois que o primeiro LED recebe sua porção de 24x bits RGB, ele abre a transmissão para o próximo. Primitivamente, pode-se imaginar uma sequência de LEDs como uma cascata de jarros que são sucessivamente enchidos com água: o
primeiro, o segundo, o terceiro e assim por diante serão preenchidos.Assim, acredito que o protocolo de transferência foi resolvido.É possível tentar projetar um "LED inteligente" você mesmo? Obviamente, isso faz pouco sentido prático, mas para a autoeducação e a ampliação dos horizontes, essa é uma tarefa interessante. Vamos tentar descrever a lógica do chip na linguagem de programação Verilog HDL. Claro, isso não será um design de chip real, haverá limitações. Uma das limitações mais importantes - vou precisar de um relógio externo para o meu microcircuito. Em um LED inteligente real, esse gerador também existe, mas já está integrado ao chip.Vamos começar o módulo Verilog assim:module WS2812B(
input wire clk,
input wire in,
output wire out,
output reg r,
output reg g,
output reg b
);
Acho que tudo está claro aqui: a frequência do relógio clk, os sinais de entrada e saída do "LED inteligente" entrando e saindo e, é claro, os sinais de saída r, g, b através dos quais controlarei os LEDs externos reais em vermelho, verde e azul.Capturarei o sinal de entrada em um registro de deslocamento de dois bits e, a partir do estado atual desses bits capturados, posso determinar o início da borda positiva do sinal em: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);
Além disso, é importante determinar o status da redefinição da fita quando o controlador de controle faz uma pausa antes de iniciar uma nova transmissão: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);
Além disso, a partir de uma margem positiva em_pos_edge, é necessário suportar uma pausa para obter o momento de corrigir um novo bit: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);
O número de bits já recebidos no chip é considerado da seguinte maneira: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;
Um sinal de passagem importante é introduzido aqui, que apenas determina o redirecionamento do fluxo de entrada para a saída. Depois de aceitar o bit de 24x pixels, o sinal de passagem é definido como um: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;
A saída de entrada é multiplexada para a saída de saída quando o sinal pass_final é um.Bem, é claro, precisamos de um registro de deslocamento, no qual os 24 bits recebidos do pixel são acumulados: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] };
Após o recebimento de todos os 24 bits, eles também são copiados para o registro final de 24 bits.Agora o assunto permanece pequeno. É necessário implementar um sinal PWM (Latitudinal Pulse Modulation) para transmitir brilho aos LEDs externos reais de acordo com os bytes RGB recebidos: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
Isso parece ser tudo.Um pequeno detalhe permanece - como experimentar tudo isso?Peguei algumas placas-mãe simples com o FPGA MAX II (estas são as placas da série Mars rover) e mostrei todas elas com o projeto com este código Verilog. Já havia 8 LEDs nas placas, mas todos eram amarelos. Em cada uma das placas, substituí 3 LEDs por R, G, B. Conectei as placas em série e, além disso, as conectei a uma faixa de LED real. Assim, ampliei a fita real com meus LEDs caseiros.Essa conexão acabou assim:
Na realidade, é assim:
Agora, aplicando uma certa imagem à fita, vejo que meus "LEDs inteligentes" se comportam exatamente da mesma forma que os reais da fita:Acontece que a lógica que eu implementei no FPGA é totalmente funcional! Como primeira aproximação, eu pude fazer algo semelhante a um chip de LED inteligente real.Na verdade, eu gosto de tiras de LED. Basicamente, todos podem inventar algo próprio: iluminação inteligente, telas, efeitos ambilight. Uma vez eu implementei música colorida em uma fita LED executando FPGA. Mas isso é outra história .