Os LEDs são RGB, mas esta imagem só usa verde. |
Existem vários tipos de "fita de LED". No caso mais simples, são apenas LEDs interconectados, que acendem todos juntos. A fita que estou examinando aqui é mais "high-end": cada posição da fita é um circuito integrado especial ligado a três LEDs nas cores vermelho, verde e azul. Com isto os LEDs podem ser controlados "individualmente" (são "endereçáveis").
Porque estou falando "endereçáveis" e "individualmente", com aspas? Porque na verdade as posições não tem um endereço nem podem ser controladas isoladamente (pelo menos nos modelos que vi até agora). Devem ser enviados os estados de todos os LEDs para o primeiro circuito da fita. Ele irá consumir o primeiro conjunto de estados e repassar os demais para o seguinte e assim por diante.
Existem vários modelos de circuito, que usam diferentes formas de comunicação. Um aspecto importante nesta comunicação é como indicar o início de um envio. A fita de LED que o Oda me emprestou utiliza o CI APA102. No momento ele está utilizando um Arduino Mega com a biblioteca FastLED.
A figura abaixo, extraída do datasheet, mostra o diagrama de blocos do APA102:
Além da alimentação, devem ser fornecidos um sinal de dados (SDI) e um sinal de clock (CKI). Após extrair os seus dados, o APA102 fornece ao CI seguinte um novo par dado (SDO) e clock (CKO). O APA102 suporta altas velocidades de comunicação (o datasheet é omisso, mas na página da FastLED fala-se em uso de 24MHz sem problemas) e podemos usar uma interface SPI para gerar o dado e o clock.
Os dados são tratados como frames de 32 bits (quatro bytes do ponto de vista de uma interface SPI de 8 bits). Um frame contendo zeros marca o início de um envio. Um frame destinado a uma posição contem:
- Um byte contendo três bits "1", seguido de uma "intensidade global" (que se aplica aos três LEDs) com cinco bits.
- Um byte para cada cor, contendo a respectiva intensidade.
Mais detalhes sobre o controle da intensidade podem ser vistos aqui (Tim's blog). O mesmo blog discute em detalhes o processo de comunicação (aqui).
Com estas informações, podemos agora examinar a questão do tempo necessário para atualizar todos os LEDs. Supondo que temos "n" LEDs (n menor ou igual a 64), são necessários enviar n+2 frames, ou seja 32n+64 bits.
Um Arduino Uno ou Mega trabalha com um cristal de 16MHz e o clock máximo para a SPI é metade disto (8MHz). Por exemplo, se forem 64 LEDs, a 8MHz o tempo para envio é 264 microsegundos. Isto desde que alimentemos a interface SPI suficientemente rápido. É aqui que temos alguns problemas:
- A interface SPI do ATmega não tem buffer. Você só pode enviar o próximo byte a transmitir depois que o anterior foi enviado.
- Para descobrir que o byte foi enviado é necessário ler o registrador de status e testar um bit. Isto leva algum tempo. Você pode usar também uma interrupção, mas isto é ainda mais lento (porém deixa você fazer alguma coisa enquanto o byte está sendo transmitido).
- Como o clock da CPU e da SPI são próximos, são poucas as intruções que podem ser feitas durante a transmissão de um byte. Considerando que a maioria das instruções são executadas em um único ciclo, dá para executar 16 instruções enquanto são transmitidos os 8 bits a 8MHz.
Como podemos melhorar isto? Usando um microcontrolador mais rápido e com mais recursos na interface SPI. Um recurso muito útil é o DMA, onde bytes são movidos da memória para a interface sem passar pela CPU. Veja aqui o resultado de alguns testes da velocidade bruta do SPI, com e sem DMA (quando disponível), feito com diversas placas.
Em um post futuro mostro um exemplo de uso da fita LED com um Arduino Uno. Mais para frente pretendo fazer experiências com o Arduino Due e com a Launchpad Stellaris.
Nenhum comentário:
Postar um comentário