Há algum tempo, ensinamos aqui no blog a como utilizar fitas de LED RGB com o Arduino. Essas fitas são extremamente simples de se programar e possuem a limitação de apenas uma cor ao longo de toda a sua extensão. Hoje você conhecerá os LEDs WS2812B que compõem as fitas RGB endereçáveis e apresentam diversas vantagens em relação à anterior, pois permitem a programação de cada LED individualmente e isso amplia a gama de cores e efeitos que podemos adicionar ao longo de toda a fita. Acompanhe:
Conforme falado anteriormente, os LEDs endereçáveis nos permitem programar a cor, intensidade e até mesmo qual LED (também chamado de pixel) irá acender ao longo do circuito.
Na imagem abaixo você pode conferir em detalhes como o componente é por dentro.
LED endereçável visto no microscópio. Repare os detalhes do chip interno e as conexões com cada setor.
Também montamos um gif mostrando como ocorre a troca de cor em detalhes. Observe abaixo:
Troca de cores em detalhes
Abaixo você pode analisar o pinout do chip:
Pinout WS2812B – Fonte: Datasheet
Observe que existem 4 pinos: VCC, GND, Din e Dout. Os pinos de VCC e GND já são conhecidos por todos, certo? São os pinos de alimentação do LED, que trabalha em 5V. Já os pinos Din e Dout são responsáveis pela programação. Como esses LEDs são programados em cascata (primeiro um, depois o outro), é necessário que haja uma “passagem” dos dados para os demais LEDs do circuito e quem faz essa função é o pino Dout. Ao longo do post você entenderá melhor como funciona essa parte, mas, a grosso modo, os dados “entram” pelo pino Din, o chip interno processa os dados referentes àquele LED (cor, intensidade e posição (caso haja mais de um no circuito), basicamente) e dispensa os demais pelo pino Dout (que vai conectado ao Din do segundo LED, segundo a configuração de cascata). A parte mais legal disso tudo é que através de um único fio de sinal é possível programar todos os parâmetros da sequência de LEDs, conforme citado. Abaixo você pode observar um diagrama com a conexão de mais de um LED, ilustrando essa configuração em cascata:
Ligação em Cascata. Fonte: Datasheet
Agora que você conhece todas as conexões de um LED endereçável, vamos iniciar a montagem de um circuito bem simples contendo 4 LEDs WS2812B. Acompanhe:
Vamos começar separando os materiais que serão usados nesse projeto. Você vai precisar de:
No diagrama abaixo você pode observar a montagem do circuito. Reproduza fielmente as conexões e vamos partir para a parte mais legal: a programação!
A programação do nosso circuito de exemplo é bem simples. Vamos começar instalando a biblioteca “Adafruit NeoPixel”. Você pode instalá-la pelo próprio Gerenciador de Bibliotecas da Arduino IDE, mas também deixarei o link de referência para o repositório no GitHub.
Feito isso, vamos iniciar a programação dos LEDs. Acompanhe o raciocínio:
O primeiro passo é adicionar a biblioteca usando o comando #include. Em seguida, usando o comando #define, vamos atribuir nomes a alguns parâmetros que utilizaremos ao longo do código, como o pino do Arduino responsável por enviar o sinal ao circuito e o número de LEDs que compõem nossa sequência. Feito isso, crie um objeto que referencie a biblioteca e informe dois parâmetros: a quantidade de LEDs e o pino do Arduino a ser utilizado. Aqui você pode usar o nome atribuído anteriormente sem problema algum, beleza?
#include <Adafruit_NeoPixel.h> #define D_in 6 #define qtdeLeds 4 Adafruit_NeoPixel pixels(qtdeLeds, D_in);
O próximo passo é configurar o setup do nosso código, que é bem simples. Aqui você só precisa aplicar o comando pixels.begin(). Esse comando inicia a “comunicação” entre os parâmetros presentes na biblioteca e os LEDs. Lembre-se apenas de trocar o termo “pixels” pelo nome que você atribuiu ao objeto que criou anteriormente sempre que for se referir à biblioteca, ok? Estamos utilizando “pixels.begin()” pois “pixels” foi o nome que escolhemos para o objeto, portanto você deve alterá-lo caso não seguir esse mesmo exemplo. A sintaxe ficaria: “nomeDoObjeto.begin()”.
void setup() { pixels.begin(); }
Por fim, vamos configurar o loop, que é onde toda a nossa lógica será desenvolvida. Começamos aplicando o comando pixels.clear() para que todos os LEDs sejam desligados ao fim do ciclo e, em seguida, iniciamos um laço for para conter a lógica de funcionamento, que é bem simples: a variável i incrementará seu valor até igualar ao número de LEDs que configuramos, tornando a condição falsa. Enquanto for verdadeira, os LEDs serão acionados conforme os comandos dados. São eles:
pixels.setPixelColor(i, pixels.Color(255, 0, 0)) -> O comando setPixelColor é responsável por configurar os parâmetros referentes ao número do LED na cascata e também a cor, onde i representa o número do LED (de 0 a 3, no nosso exemplo) e o comando pixels.Color(255, 0, 0) se encarrega de configurar as cores (lembre-se que pixels é o nome do objeto, beleza?). Aqui, informamos a intensidade de 0 a 255 para cada canal do padrão RGB, onde zero mantém a cor desligada e 255 completamente ligada. No exemplo acima, o LED está configurado para ligar a cor vermelha pois setamos o canal R como 255 e os demais, G e B, como zero.
pixels.show() -> Executa a linha de configuração anterior. Lembre-se de adicioná-lo sempre que trocar algum parâmetro do comando setPixelColor e não se esqueça de trocar o nome do objeto aqui também, ok?
delay -> aguarda um tempo em milissegundos entre a execução dos parâmetros configurados.
void loop() { pixels.clear(); for(int i=0; i<qtdeLeds; i++){ pixels.setPixelColor(i, pixels.Color(255, 0, 0)); pixels.show(); delay(500); pixels.setPixelColor(i, pixels.Color(0, 255, 0)); pixels.show(); delay(500); pixels.setPixelColor(i, pixels.Color(0, 0, 255)); pixels.show(); delay(500); } }
Aqui você tem o código completo para esse exemplo, devidamente comentado caso tenha ficado alguma dúvida.
#include <Adafruit_NeoPixel.h> //Adiciona a biblioteca Adafruit NeoPixel #define D_in 6 //Nomeia o pino 6 do Arduino #define qtdeLeds 4 //Informa a quantidade de LEDs que serão ligados em cascata Adafruit_NeoPixel pixels(qtdeLeds, D_in); //Instancia o objeto "pixels", informando a quantidade e o pino de sinal void setup() { pinMode(D_in, OUTPUT); //Configura o pino 6 como saída pixels.begin(); //Inicia o objeto "pixels" } void loop() { pixels.clear(); //desliga todos os LEDs for(int i=0; i<qtdeLeds; i++){ //para i = 0, se i menor que a quantidade de leds, incremente 1 em i pixels.setPixelColor(i, pixels.Color(255, 0, 0)); //liga o led correspondente ao número da variável i na cor vermelha pixels.show(); //executa os parâmetros do comando acima delay(500); //Aguarda 500 milissegundos pixels.setPixelColor(i, pixels.Color(0, 255, 0)); //liga o led correspondente ao número da variável i na cor verde pixels.show(); //executa os parâmetros do comando acima delay(500); //Aguarda 500 milissegundos pixels.setPixelColor(i, pixels.Color(0, 0, 255)); //liga o led correspondente ao número da variável i na cor azul pixels.show(); //executa os parâmetros do comando acima delay(500); //Aguarda 500 milissegundos } }
Após carregar o código no Arduino, espera-se obter o resultado mostrado no vídeo a seguir:
No próximo exemplo, vamos te mostrar como misturar as cores e acender os leds de forma aleatória. O circuito é o mesmo, vamos apenas implementar uma nova função do Arduino: a random().
A função random é a responsável por gerar números pseudoaleatórios em um intervalo pré-definido. Sua sintaxe é bem simples:
random(max) -> Nessa sintaxe, informamos apenas o valor máximo (que no nosso caso será 255) e a função irá retornar um número entre zero – que é o número inicial quando não informamos nenhum outro valor, e o número que foi estipulado como limite máximo.
random(min, max) -> Nessa outra opção de sintaxe, podemos usar um valor mínimo diferente de zero, definindo o range que desejamos. Vale ressaltar que ambas estão corretas, cabe a você decidir qual se encaixa melhor em sua lógica.
O código novamente é bem simples. Desta vez vamos deixar toda a explicação nos comentários, ok? Basta carregar no Arduino e ligar o circuito:
#include <Adafruit_NeoPixel.h> //Adiciona a biblioteca Adafruit NeoPixel #define D_in 6 //Nomeia o pino 6 do Arduino int qtdeLeds = 4; //Informa a quantidade de LEDs que serão ligados em cascata Adafruit_NeoPixel pixels(qtdeLeds, D_in); //Instancia o objeto "pixels", informando a quantidade e o pino de sinal void setup() { pinMode(D_in, OUTPUT); //Configura o pino 6 como saída pixels.begin(); //Inicia o objeto "pixels" pixels.clear(); //desliga todos os LEDs } void loop() { // número de LEDs, vermelho, verde, azul pixels.setPixelColor(random(qtdeLeds), random(255), random(255), random(255)); //escolhe, de maneira pseudoaleatória, o número do LED e a intensidade de cada cor do canal RGB pixels.show(); //executa os parâmetros do comando acima delay(500); //Aguarda 500 milissegundos }
Novamente o resultado esperado você pode observar no vídeo abaixo:
Para você que ficou curioso para entender como esses LEDs recebem os parâmetros, vamos tentar explicar de maneira bem didática com o apoio de um osciloscópio. Veja só:
O primeiro passo para entender como funciona a programação e a transmissão de dados para um LED endereçável é conhecer um pouquinho de eletrônica digital. Sabemos que só podemos ter dois estados: 0 (desligado) e 1 (ligado), certo? Os pulsos de sinal são enviados para os LEDs através de um pino digital do Arduino, logo se beneficia dessa característica. Com isso em mente, concluímos que os dados são transmitidos apenas quando o pino está “ligado”, em nível lógico 1, e isso faz com que seja necessário recorrer a outras táticas para ligar e desligar os LEDs: é necessário variar a largura do pulso, ou seja, o tempo (normalmente em microssegundos) em que o pino fica em nível lógico alto ou baixo, afim de obter outros dois estados lógicos, mas dessa vez, esses estados serão referentes ao LED, não ao Arduino.
Conforme você pode observar no datasheet do LED WS2812B e na tabela a seguir, para ser considerado nível lógico 1, o pulso deve durar 0,8 microssegundo em high e 0,4 microssegundo em low, enquanto que, para ser considerado nível lógico zero, a duração deverá ser de 0,4 microssegundo em high e 0,8 microssegundo em low, totalizando um período total de, aproximadamente, 1,2 microssegundo.
Com o auxílio do osciloscópio podemos ver essa diferença de tempo na prática. Duplicamos a forma de onda obtida e mapeamos os limites de cada período para facilitar o entendimento. Veja só:
Tendo entendido como o Arduino consegue transmitir os pulsos para um LED, vamos entender como a transmissão é feita para os demais LEDs da cascata.
Como dito anteriormente, a configuração cascata recebe esse nome pois são ligados em uma espécie de circuito série, estando a entrada de dados do LED y conectado à saída de dados do LED x. Dessa forma, os circuitos integrados que controlam cada LED processam apenas os bits referentes à sua posição na fita e “descartam” os demais, para serem processados adiante.
Na imagem abaixo temos a representação gráfica desses bits, graças ao osciloscópio. Acompanhe:
Note que existem 24 bits nessa sequência. São 24 pois cada canal trabalha com até 256 valores (8 bits) de brilho diferentes (lembra do PWM?) e, como temos 3 canais, R, G e B, o total é de 24 bits.
Nesse exemplo, programei o circuito para ligar somente a cor azul do primeiro LED, logo, levando em consideração o que explicamos logo acima sobre como o chip WS2812B interpreta os níveis lógicos, você pode notar que os primeiros 16 bits da fita estão em zero e os 8 últimos estão em 1, ou seja, temos o número binário 000000000000000011111111, na qual as primeiras 8 posições são referentes à cor verde, o segundo conjunto refere-se à cor vermelha e, o último, à cor azul.
Mapa de Bits
Você pode observar melhor esse conceito na imagem abaixo, onde mapeamos essa fita de bits para o LED desligado, ligado na cor vermelha, verde, azul e também na cor branca, que é a soma de todas as 3 cores do padrão RGB quando ligadas, respectivamente:
Entendido isso fica muito simples compreender como os demais LEDs são programados e também como o Arduino é capaz de ligar qualquer LED ao longo da cascata sem alterar o estado dos LEDs anteriores. Observe o print a seguir:
Na imagem acima, programamos o circuito de modo a ligar dois LEDs: O primeiro 100% azul e, o segundo, 100% verde. Você pode observar que, na onda amarela, ao invés de 24, temos 48 bits, enquanto que na onda verde, temos apenas 24 e essa é a chave do funcionamento! O Arduino envia uma fita de bits contendo o número de LEDs do circuito multiplicado por 24, enquanto que, na cascata, a fita de bits é processada/interpretada da seguinte forma: o primeiro conjunto de 24 bits recebidos são atribuídos ao primeiro LED – que os divide e distribui para cada cor. Os demais bits que não foram interpretados são passados adiante e esse processo se repete até que todos os LEDs recebam seu conjunto de 24 bits (para os LEDs que forem ficar desligados, os mesmos 24 bits são enviados, porém todos em zero). Ao final da fita de bits, é dado um tempo de 50 microssegundos entre o fim da primeira e o início da segunda, que é interpretado como reset, indicando o fim daquela instrução, e isso libera o primeiro LED para receber novamente os primeiros 24 bits da próxima sequência.
Concluímos aqui a apresentação do chip WS2812B, seu funcionamento e programação básica, utilizando a biblioteca Adafruit NeoPixel. Nos próximos posts sobre LEDs endereçáveis traremos dois projetos muito legais: uma fita de LEDs que reage a sons e um autorama de luzes para dois jogadores. Não deixe de conferir!
Conheça a Metodologia Eletrogate e ofereça aulas de robótica em sua escola!
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Tenha a Metodologia Eletrogate dentro da sua Escola! Conheça nosso Programa de Robótica nas Escolas!