18 de dezembro de 2011

Matriz de LEDs 8x8

E a experîencia dessa vez foi controlar uma matriz de LEDs.



Foi usado um microcontrolador ATmega328 com bootloader Arduino, dois registradores 74HC595 e uma matriz de LEDs 8x8 com anodo comum.
Pode-se fazer um letreiro e infinitas animações.

A ideia seria mostrar como ampliar o número de saídas do Arduino utilizando registradores de deslocamento. Para cada registrador, você ganha 8 saídas. Nesse caso, temos dois registradores para controlar os 16 pinos da matriz.
Para utilizar mais de uma matriz, o ideal é utilizar um driver de LEDs, mas isso fica para um próximo post.

Segue o código e o esquema elétrico.

Yippie ki-yay!


/*----------------
 MATRIZ DE LED 8x8 
 Fellipe Couto
 17/12/2011
 ---------------*/
#include <TimerOne.h> //http://www.arduino.cc/playground/Code/Timer1
int latchPin = 8;  //Conectado ao pino 12 do 74HC595.
int clockPin = 12; //Conectado ao pino 11 do 74HC595.
int dataPin = 11;  //Conectado ao pino 14 do 74HC595.
byte led[8];

void setup(){
  pinMode(latchPin,OUTPUT);
  pinMode(clockPin,OUTPUT);
  pinMode(dataPin,OUTPUT);
  Timer1.initialize(10000); //Timer de 10000 microssegundos (1/100 de um segundo).
  Timer1.attachInterrupt(screenUpdate); //Anexa a função screenUpdate ao timer de interrupção.
}

void loop(){
  for (int i=0; i<2; i++){
    linhaHorizontal(1);
    linhaVertical(1);
    linhaHorizontal(2);
    linhaVertical(2);
  }
  quadrados();
  explode();
  quadros();
  coracao();
  seta();
  pisca();
  piscaTudo();
  randomico();
}

void screenUpdate(){ //Função para exibir a imagem.
  byte row = B10000000; //Linha 1.
  for (byte k=0; k<9; k++){
    digitalWrite(latchPin,LOW); //Abre o latch, para receber dados.
    shiftIt(~led[k]); //Envia o array LEDs (invertido).
    shiftIt(row); //Envia o número binário da linha.
    digitalWrite(latchPin,HIGH); //Fecha o latch, para enviar os dados do registrador para a matriz.
    row = row>>1; //Deslocamento para direita.
  }
}

void shiftIt(byte dataOut){ //Desloca 8 bits, com o menos significativo deslocado primeiro, durante o extremo ascendente do clock.
  boolean pinState;
  digitalWrite(dataPin,LOW); //Libera o registrador , deixando-o pronto para enviar dados.
  for (int i=0; i<8; i++){ //Para cada bit em dataOut, envia um bit.
    digitalWrite(clockPin,LOW); //Define clockPin como LOW, antes de enviar o bit.
    //Se o valor de dataOut e (E lógico) de uma mascara de bits forem verdadeiros, defina pinState como 1 (HIGH)
    if (dataOut & (1<<i)){
      pinState = HIGH;
    }
    else{
      pinState = LOW;
    }
    digitalWrite(dataPin,pinState); //Define dataPin como HIGH ou LOW, dependendo de pinState.
    digitalWrite(clockPin,HIGH); //Envia o bit no extremo ascendente do clock.
    digitalWrite(dataPin,LOW);
  }
  digitalWrite(clockPin,LOW); //Interrompe o deslocamento de dados.
}

void linhaHorizontal(int x){
  switch (x){
  case 1: //x = 1 (Desce)
    for (int j=0; j<8; j++){
      for (int i=0; i<8; i++){
        if (i==j){
          led[i] = B11111111;
        }
        else{
          led[i] = B00000000;
        }
      }
      delay(40);
    }
    break;
  case 2: //x = 1 (Sobe)
    for (int j=8; j>=0; j--){
      for (int i=0; i<8; i++){
        if (i==j){
          led[i] = B11111111;
        }
        else{
          led[i] = B00000000;
        }
      }
      delay(40);
    }
    break;
  }
}

void linhaVertical(int x){
  switch (x){
  case 1: //x = 1 (Direita)
    for (int j=0; j<8; j++){
      for (int i=0; i<8; i++){
        switch (j){
        case 0:
          led[i] = B10000000;
          break;
        case 1:
          led[i] = B01000000;
          break;
        case 2:
          led[i] = B00100000;
          break;
        case 3:
          led[i] = B00010000;
          break;
        case 4:
          led[i] = B00001000;
          break;
        case 5:
          led[i] = B00000100;
          break;
        case 6:
          led[i] = B00000010;
          break;
        case 7:
          led[i] = B00000001;
          break;
        }
      }
      delay(40);
    }
    break;
  case 2: //x = 2 (Esquerda)
    for (int j=8; j>=0; j--){
      for (int i=0; i<8; i++){
        switch (j){
        case 0:
          led[i] = B10000000;
          break;
        case 1:
          led[i] = B01000000;
          break;
        case 2:
          led[i] = B00100000;
          break;
        case 3:
          led[i] = B00010000;
          break;
        case 4:
          led[i] = B00001000;
          break;
        case 5:
          led[i] = B00000100;
          break;
        case 6:
          led[i] = B00000010;
          break;
        case 7:
          led[i] = B00000001;
          break;
        }
      }
      delay(40);
    }
    break;
  }
}

void quadrados(){
  int tempo = 100;
  for (int i=0; i<20; i++){
    //Quadro 1
    for (int j=0; j<4; j++){
      led[j] = B11110000;
    }
    for (int j=4; j<8; j++){
      led[j] = B00000000;
    }
    delay(tempo);
    //Quadro 2
    for (int j=0; j<4; j++){
      led[j] = B00001111;
    }
    for (int j=4; j<8; j++){
      led[j] = B00000000;
    }
    delay(tempo);
    //Quadro 3
    for (int j=0; j<4; j++){
      led[j] = B00000000;
    }
    for (int j=4; j<8; j++){
      led[j] = B00001111;
    }
    delay(tempo);
    //Quadro 4
    for (int j=0; j<4; j++){
      led[j] = B00000000;
    }
    for (int j=4; j<8; j++){
      led[j] = B11110000;
    }
    delay(tempo);
    tempo -= 5;
  }
}

void explode(){
  int tempo = 80;
  for (int j=0; j<10; j++){
    for (int i=0; i<8; i++){
      led[i] = B00000000;
    }
    delay(tempo);
    //-----------------
    led[0] = B00000000;
    led[1] = B00000000;
    led[2] = B00000000;
    led[3] = B00011000;
    led[4] = B00011000;
    led[5] = B00000000;
    led[6] = B00000000;
    led[7] = B00000000;
    delay(tempo);
    //-----------------
    led[0] = B00000000;
    led[1] = B00000000;
    for (int i=3; i<6; i++){
      led[i] = B00111100;
    }
    led[6] = B00000000;
    led[7] = B00000000;
    delay(tempo);
    //-----------------
    led[0] = B00000000;
    for (int i=1; i<7; i++){
      led[i] = B01111110;
    }
    led[7] = B00000000;
    delay(tempo);
    //-----------------
    for (int i=0; i<8; i++){
      led[i] = B11111111;
    }
    delay(tempo);
  }
}

void quadros(){
  int tempo = 200;
  for (int j=0; j<10; j++){
    led[0] = B11111111;
    led[1] = B10000001;
    led[2] = B10111101;
    led[3] = B10100101;
    led[4] = B10100101;
    led[5] = B10111101;
    led[6] = B10000001;
    led[7] = B11111111;
    delay(tempo);
    //-----------------
    for (int i=0; i<8; i++){
      led[i] = ~led[i];
    }
    delay(tempo);
  }
}

void coracao(){
  int tempo = 300;
  for (int j=0; j<5; j++){
    led[0] = B01100110;
    led[1] = B11111111;
    led[2] = B11111111;
    led[3] = B11111111;
    led[4] = B11111111;
    led[5] = B01111110;
    led[6] = B00111100;
    led[7] = B00011000;
    delay(tempo);
    //-----------------
    for (int i=0; i<8; i++){
      led[i] = B00000000; 
    }
    delay(tempo/2);
  }
}

void seta(){
  int tempo = 200;
  for (int j=0; j<10; j++){
    //Pra cima.
    led[0] = B00011000;
    led[1] = B00111100;
    led[2] = B01111110;
    led[3] = B00011000;
    led[4] = B00011000;
    led[5] = B00011000;
    led[6] = B00011000;
    led[7] = B00011000;
    delay(tempo);
    //-----------------
    //Pra esquerda.
    led[0] = B00000000;
    led[1] = B00100000;
    led[2] = B01100000;
    led[3] = B11111111;
    led[4] = B11111111;
    led[5] = B01100000;
    led[6] = B00100000;
    led[7] = B00000000;
    delay(tempo);
    //-----------------
    //Pra baixo.
    led[0] = B00011000;
    led[1] = B00011000;
    led[2] = B00011000;
    led[3] = B00011000;
    led[4] = B00011000;
    led[5] = B01111110;
    led[6] = B00111100;
    led[7] = B00011000;
    delay(tempo);
    //-----------------
    //Pra direita.
    led[0] = B00000000;
    led[1] = B00000100;
    led[2] = B00000110;
    led[3] = B11111111;
    led[4] = B11111111;
    led[5] = B00000110;
    led[6] = B00000100;
    led[7] = B00000000;
    delay(tempo);
    tempo -= 10;
  }
}

void pisca(){
  int tempo = 200;
  for (int j=0; j<30; j++){
    led[0] = B10101010;
    led[1] = B01010101;
    led[2] = B10101010;
    led[3] = B01010101;
    led[4] = B10101010;
    led[5] = B01010101;
    led[6] = B10101010;
    led[7] = B01010101;
    delay(tempo);
    for (int i=0; i<8; i++){
      led[i] = ~led[i];
    }
    delay(tempo);
    tempo -= 5;
  }
}

void piscaTudo(){
  int tempo = 50;
  for (int j=0; j<30; j++){
    for (int i=0; i<8; i++){
      led[i] = B11111111;
    }
    delay(tempo);
    for (int i=0; i<8; i++){
      led[i] = B00000000;
    }
    delay(tempo);
  }
}

void randomico(){
  int tempo = 70;
  int p = 0;
  randomSeed(analogRead(0));  //Para o random ficar aleatorio, sem repetir a sequencia.
  for (int i=0; i<40; i++){
    p = random(200);
    led[0] = p;
    p = random(200);
    led[1] = p;
    p = random(100);
    led[2] = p;
    p = random(200);
    led[3] = p;
    p = random(100);
    led[4] = p;
    p = random(200);
    led[5] = p;
    p = random(100);
    led[6] = p;
    p = random(200);
    led[7] = p;
    delay(tempo);
  }
}

17 comentários:

  1. Olá. Muito bom seu blog!
    Poderia fazer uma função para exibir texto?
    Eu consegui esse exemplo mas ele nao usa o 74HC595.
    Mas voce pode adaptar a funcao e aproveitar o mapa das letras para o seu código.
    http://oomlout.com/8X8M/8X8M-ScrollMessage.txt
    Favor me comunicar por e-mail caso consiga: sharkpolo@hotmail.com
    Obrigado

    ResponderExcluir
  2. Amigo, dá uma ajuda pra outro amigo, já conseguir fazer as letras,
    mas não consigo fazer o scrool das mesma, dá uma luz. No aguardo meu email,
    domingosjff@gmail.com. obrigado e seu blog é nota 10, de grande ajuda pra iniciantes no arduino.

    ResponderExcluir
  3. DEU ERRO ?! eu baxei o TimerOne-v9.zip, até ai tudo certo ^^ ....

    Binary sketch size: 4.488 bytes (of a 32.256 byte maximum)
    avrdude: stk500_recv(): programmer is not responding


    Meu e-mail: engenheirogenio@hotmail.com

    ResponderExcluir
    Respostas
    1. Binary sketch size: 4.488 bytes (of a 32.256 byte maximum)
      avrdude: stk500_recv(): programmer is not responding

      Excluir
    2. Boa tarde, Luís Henrique!
      Esse erro costuma ser problema com a conexão entre Arduino e o pc. Você testou com outro pc?! Dei uma pesquisada aqui, e sobre esse erro, só encontrei duas coisas: Conexão serial entre Arduino e pc ou problema com o bootloader do Arduino. Nunca tive problemas com esse erro.
      Dá uma olhada se não é a conexão serial.
      Abraços!

      Excluir
    3. eu usando o arduino atmega2560 , fica a mesma coisa?!?!

      Excluir
    4. Desde que esteja usando as mesmas portas do arduino, o código poderia se manter o mesmo. Abraços!

      Excluir
  4. muinto bom mesmo show de bola ,como faço para ampliar mais com 4ci

    ResponderExcluir
    Respostas
    1. Boa tarde! Uma forma seria cascateando, assim como já estão o CI 1 e 2. Abraços!

      Excluir
  5. Este comentário foi removido pelo autor.

    ResponderExcluir
  6. NERD, como faço pra colocar 3- matrizes de leds com 6- 74hc595? aguardo retorno e obrigado pela atenção. tchau

    ResponderExcluir
  7. Fellipe, eu tenho o módulo de matriz montada com o MAX7219 - eu posso usar esse seu código?
    obrigado

    ResponderExcluir
    Respostas
    1. Boa noite! Esse código ta pro 595 mesmo.

      Excluir
    2. Então, o que teria que ser mudado no código?
      Obrigado

      Excluir
  8. Boa noite, de cara eu quero te agradecer, seu blog me tirou muitas dúvidas e fez com que eu conseguisse fazer "funcionar" a minha matrix de LED 8x8 com driver 74HC595, na verdade 4 matrix. Estou tendo difuldades com o código para scrll de texto. Você poderia me enviar o sketch? com texto simples, como "FELIZ ANO NOVO".
    MEU E-MAIL: ROBERTOCARLOSALVARENGA@HOTMAIL.COM

    muito obrigado...

    ResponderExcluir
  9. Parabéns pelos projetos, você é fera Felipe!

    ResponderExcluir