sexta-feira, 29 de agosto de 2025

Acionando fita de leds (WS2812) endereçável sem nenhuma biblioteca externa.

    Olá amigos! aqui vou demonstrar como acionar a fita de leds WS2812 usando o ESP32, e usando o mesmo raciocínio é possível portar este código pra qualquer microcontrolador que consiga rodar numa frequência rápida o suficiente para gerar os sinais. 

    Como sempre recomendo a ler o datasheet da fita que você quer acionar pois estes tempos dos bits podem variar conforme o modelo de fita utilizado. Claro que você também pode usar uma biblioteca pronta como a "FASTLED" porém o intuito aqui é desmistificar o pensamento de que é difícil controlar os leds.  

// CLIENTE: microcontroladores-c

// AUTOR: Aguivone M. Fógia
// HARDWARE: ESP32
// CONFIG = FREQUENCIA CPU ->240MHZ  e FREQUENCIA FLASH -> 80MHZ
////////////////////////////////////////////////////
//acionando fita de led WS2812 sem usar nenhuma biblioteca
/////////////////////////////////////////////////////
void setup()
{
  pinMode(13, OUTPUT); //pino D13
}
void BIT_0()//bit 0
{   // para outros modelos de fitas consultar datasheet
   for(int a=0 ; a<8; a++)//aprox.400ns
   {//só repete
     REG_WRITE(GPIO_OUT_W1TS_REG, BIT13);
   }
    for(int a=0; a<16; a++)//aprox.850ns
   {
     REG_WRITE(GPIO_OUT_W1TC_REG, BIT13);
   }
}
void BIT_1()//bit 1
{// para outros modelos de fitas consultar datasheet  
   for(int a=0 ; a<17; a++)//aprox.800ns
   {//só repete
     REG_WRITE(GPIO_OUT_W1TS_REG, BIT13);
   }
    for(int a=0; a<7; a++)//aprox.450ns
   {
     REG_WRITE(GPIO_OUT_W1TC_REG, BIT13);
   }
}
void pacote(char BLUE,char RED,char GREEN)//1 pacote de 24bits
{
    uint32_t dados = (GREEN<<16) + (RED<<8) + BLUE;//verificar sequencia  
    uint32_t aux = 1;
    while(aux<0X1000000)
    {
        if((dados & aux)>1)
        {//bit 1
          BIT_1();
        }
        else
        {
          BIT_0();
        }
        aux = aux<<1;
    }
}
void apagar_fita(long num_leds)
{
  long aux = 0;
  num_leds = num_leds*24; // 24bits por led
   while(aux<num_leds)
    {
      BIT_0();
      aux++;
    }
}
void preencher_fita(long num_leds)
{//com as 3 cores é mais rapido assim // cor branca
  long aux = 0;
  num_leds = num_leds*24; // 24bits por led
   while(aux<num_leds)
    {
      BIT_1();
      aux++;
    }
}
void preencher_cor(char GREEN,char RED,char BLUE,long num_leds)
{//preenche com a cor desejada
  long aux = 0;
   num_leds++;
   while(aux<num_leds)
    {
      pacote(GREEN,RED,BLUE);//só repete o pacote
      aux++;
    }
     
}
void preencher_cor_tempo(char GREEN,char RED,char BLUE,long num_leds,long milisegundos)
{//preenche com a cor desejada de tempo em tempo
  long aux = 1;
   while(aux<num_leds)
    {
      preencher_cor(GREEN,RED,BLUE,aux);//só repete o pacote
      aux++;
      delay(milisegundos);
    }
     
}
void move_ponto(char GREEN,char RED,char BLUE,long Pos)
{
   uint32_t dados = (GREEN<<16) + (RED<<8) + BLUE;//verificar sequencia  
   apagar_fita(Pos-1);    
    uint32_t aux = 1;
    while(aux<0X1000000)
    {
        if((dados & aux)>1)
        {//bit 1
          BIT_1();
        }
        else
        {
          BIT_0();
        }
        aux = aux<<1;
    }
}

void loop()
{
  apagar_fita(500);//limpa fita toda(ver numero de leds totais)
  for(;;)
  {
  // a barra vai sendo preencida ate um determinado led e depois apaga e começa novamente
    preencher_cor_tempo(0,25,0,49,200);
    apagar_fita(100);//se quiser apagar toda a fita colocar o numero total de leds
    delay(500);
    move_ponto(0,25,0,5);
    delay(100);
    move_ponto(0,25,0,10);
    delay(100);
    move_ponto(0,25,0,20);
    delay(100);
    move_ponto(0,25,0,30);
    delay(100);
    move_ponto(0,25,0,40);
    delay(100);
    move_ponto(0,25,0,50);
    delay(100);
  }
}

Olá fiz algumas alterações para funcionar para outros modelos e fiz melhoramentos
no código, veja como ficou minha segunda versão 20 dias depois:
// CLIENTE: microcontroladores-c
// AUTOR: Aguivone M. Fógia
// HARDWARE: ESP32
// CONFIG = FREQUENCIA CPU ->240MHZ  e FREQUENCIA FLASH -> 80MHZ
/////////////////////////// escolha qual será a fita de leds a ser utilizadas //////////////////////////////////////////////////////
//acionando fita de led WS2811 sem usar nenhuma biblioteca
//parametros:
/*
#define T0H  10   // aprox.500ns
#define T0L  35  //aprox.2000ns

#define T1H  24  //aprox.1200ns
#define T1L  26   //aprox.1300ns
*/
//acionando fita de led WS2812B sem usar nenhuma biblioteca
//parametros:
#define T0H  8   // aprox.400ns
#define T0L  16  //aprox.800ns

#define T1H  17  //aprox.850ns
#define T1L  7   //aprox.450ns

#define T_FIM  24   //será a soma das duas anteriores

//acionando fita de led WS2815B sem usar nenhuma biblioteca
//parametros:
/*#define T0H  6   // aprox.300ns
#define T0L  16  //aprox.850ns

#define T1H  16  //aprox.800ns
#define T1L  7   //aprox.370ns */

void setup()
{
  pinMode(13, OUTPUT);
}

void UM_BIT(char Temp) /// colocar T0H ou T1H
{
    REG_WRITE(GPIO_OUT_W1TS_REG, BIT13);
    for(int a=0 ; a<Temp; a++)
    {//só repete  
    NOP();  
    }
    REG_WRITE(GPIO_OUT_W1TC_REG, BIT13);
    for(int a=0; a<T_FIM; a++)
    {
      NOP();    
    }
}
void pacote(char BLUE,char RED,char GREEN)//1 pacote de 24bits
{
    uint32_t dados = (GREEN<<16) + (RED<<8) + BLUE;//verificar sequencia  
    uint32_t aux = 1;
    while(aux<0X1000000)
    {
        if((dados & aux)>1)
        {//bit 1
          UM_BIT(T1H);
        }
        else
        {
          UM_BIT(T0H);
        }
        aux = aux<<1;
    }
}
void apagar_fita(long num_leds)
{
  long aux = 0;
  num_leds = num_leds*24; // 24bits por led
   while(aux<num_leds)
    {
      UM_BIT(T0H);
      aux++;
    }
}
void preencher_fita(long num_leds)
{//com as 3 cores é mais rapido assim // cor branca
  long aux = 0;
  num_leds = num_leds*24; // 24bits por led
   while(aux<num_leds)
    {
      UM_BIT(T1H);
      aux++;
    }
}
void preencher_cor(char GREEN,char RED,char BLUE,long num_leds)
{//preenche com a cor desejada
  long aux = 0;
   num_leds++;
   while(aux<num_leds)
    {
      pacote(GREEN,RED,BLUE);//só repete o pacote
      aux++;
    }
     
}
void preencher_cor_tempo(char GREEN,char RED,char BLUE,long num_leds,long milisegundos)
{//preenche com a cor desejada de tempo em tempo
  long aux = 1;
   while(aux<num_leds)
    {
      preencher_cor(GREEN,RED,BLUE,aux);//só repete o pacote
      aux++;
      delay(milisegundos);
    }
     
}
void move_ponto(char GREEN,char RED,char BLUE,long Pos)
{
   uint32_t dados = (GREEN<<16) + (RED<<8) + BLUE;//verificar sequencia  
   apagar_fita(Pos-1);    
    uint32_t aux = 1;
    while(aux<0X1000000)
    {
        if((dados & aux)>1)
        {//bit 1
          UM_BIT(T1H);
        }
        else
        {
          UM_BIT(T0H);
        }
        aux = aux<<1;
    }
}

void loop()
{
  apagar_fita(500);//limpa fita toda(ver numero de leds totais)
  for(;;)
  {
  // a barra vai sendo preencida ate um determinado led e depois apaga e começa novamente
    preencher_cor_tempo(0,25,0,49,200); // preenche piscando.
    apagar_fita(100);//se quiser apagar toda a fita colocar o numero total de leds
    delay(500);
    move_ponto(0,25,0,5); // cor vermelha em 10% do brilho
    delay(200);
    move_ponto(0,25,0,10);
    delay(200);
    move_ponto(0,25,0,20);
    delay(200);
    move_ponto(0,25,0,30);
    delay(200);
    move_ponto(0,25,0,40);
    delay(200);
    move_ponto(0,25,0,50);
    delay(200);
    apagar_fita(100);
    delay(200);
  }
}



bom projetos pra vocês!

Nenhum comentário :

Postar um comentário

olá,digite aqui seu comentário!