74HC595 Shift Register 4 Led 7 Segmentos 4 Digitos

OBS: Este site não tem a intenção de ensinar a fundo o uso de componentes ou de programação. A intenção é apenas mostrar a solução e forma de uso do Arduino.

Estive trabalhando com o led de 7 Segmentos e 4 digitos (com 12 pinos), e como ele gasta muitos pinos do Arduino, resolvi fazer uma versão usando 2 Shift Registers 74HC595.

Usando dois Shift Register, deixaremos de gastar 12 pinos do Arduino para gastar apenas 3 pinos.

Novamente o exemplo será de um contador, usando um dos modelos de Led de 7 Segmentos de 4 dígitos, com 12 pinos e Anodo Comum.

Utilizei dois 74HC595 e 12 resistores de 220 ohms. Se o led ficar com uma intensidade muito forte, use resistores um pouco maiores (330 ohms por exemplo).

Enquanto pesquisava sobre o assunto, encontrei dois sites muito bons que falam sobre o 74HC595.

O primeiro é em um alemão Arduino-Projekte.de que tem uma biblioteca bem interessante para controlar diversos 74HC595 independentes. Apesar disto, não usei essa biblioteca porque  queria usar os 595 de forma única.

O outro site é o Bildr.com que tem um artigo muito bom explicando o funcionamento deo 595 e tambem possui um algorítimo bem simples para usar até 20 desses Shift Registers em sequencia.

Fiz algumas adaptações no código e implementei o contador, melhorando a rotina que usei no exemplo anterior deste componente, e posto ele a seguir:

OBS: Criei uma library para facilitar a utilização dos leds de 4 segmentos e shift register, veja em:
https://arduinoexamples.wordpress.com/2012/12/11/library-para-led-de-7-segment-com-shift-register-library-for-7-segment-led-with-shift-register

//*----------------------------------------------------------------------------------

-------------------------------------------------------------------------------------*//
int SER_Pin = 8;      // pino 14 no 75HC595 principal
int RCLK_Pin = 9;     // pino 12 no 75HC595 principal
int SRCLK_Pin = 10;   // pino 11 no 75HC595 principal

//------------------------------------------------------
// Informe a quantidade de shift registers utilizados
#define number_of_74hc595s 2 

//---------------------------------------------------------
// Não altere essa informação.
// Aqyu é definido a quantidade de pinos do shift register
#define numOfRegisterPins number_of_74hc595s * 8

#define DISPLAY_BRIGHTNESS  5

boolean registers[numOfRegisterPins];

int numberSeq = 0;
int currentMillis = 0;

//---------------------------------------------------------
// Mapeamento de cada seguemento do componente

// Ponto digital
int dp = 8;

// Segmentos
int a = 1;
int b = 5;
int c = 9;
int d = 7;
int e = 6;
int f = 2;
int g = 10;

// Digitos
int ls1 = 0;
int ls2 = 3;
int ls3 = 4;
int ls4 = 11;

byte seven_seg_digits[10][7] = { { 0,0,0,0,0,0,1 },  // = 0
                                 { 1,0,0,1,1,1,1 },  // = 1
                                 { 0,0,1,0,0,1,0 },  // = 2
                                 { 0,0,0,0,1,1,0 },  // = 3
                                 { 1,0,0,1,1,0,0 },  // = 4
                                 { 0,1,0,0,1,0,0 },  // = 5
                                 { 0,1,0,0,0,0,0 },  // = 6
                                 { 0,0,0,1,1,1,1 },  // = 7
                                 { 0,0,0,0,0,0,0 },  // = 8
                                 { 0,0,0,1,1,0,0 }   // = 9
                               };
byte pin_order[7] = { a,b,c,d,e,f,g };

byte digit_order[4] = { ls1,ls2,ls3,ls4 };
byte digitos[4][4] = { { 0,0,0,1 },
                       { 0,0,1,0 },
                       { 0,1,0,0 },
                       { 1,0,0,0 }
                     };

void setup(){
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);

  //--------------------------------------------------------------------------
  // Limpa todos os registradores que armazenam informações sobre os pinos
  clearRegisters();
  writeRegisters();
}               

//-------------------------------------------------------
// Seta todos os pinos para LOW. Limpa
void clearRegisters(){
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
     registers[i] = LOW;
  }
} 

//------------------------------------------------------
// Descarrega os registradores no shift register de forma
// que ele execute a configuração armazenada
// É importante configurar todos os registradores antes
// de chamar esta funcao para que seja realizado tudo de uma
// unica vez
void writeRegisters(){
  digitalWrite(RCLK_Pin, LOW);

  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(SRCLK_Pin, LOW);

    int val = registers[i];

    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);

  }
  digitalWrite(RCLK_Pin, HIGH);
}

//-----------------------------------------------------
// Seta um determinado registro para HIGH ou LOW
void setRegisterPin(int index, int value){
  registers[index] = value;
}

//-----------------------------------------------------
// Configura para usar um determinado digito dos 4 
// disponiveis
void pickDigit(int number)
{
  int pinseq = 0;

  for (byte digCount = 0; digCount < 4; ++digCount) 
  {
    setRegisterPin(digit_order[pinseq], digitos[number-1][digCount]);
    ++pinseq;
  }
}

//-----------------------------------------------------
// Configura uma série de registros que irão desenhar
// um determinado valor para o digito em uso
void digWrite(byte digit, byte number) {
  int pinseq = 0;

  pickDigit(digit);

  for (byte segCount = 0; segCount < 7; ++segCount) 
  {
    setRegisterPin(pin_order[pinseq], seven_seg_digits[number][segCount]);
    ++pinseq;
  }

  // Desabilita o botao de ponto. Nao irei usar neste exemplo  
  setRegisterPin(dp, HIGH); 

  // Agora força que os registradores sejam enviados para o LED
  writeRegisters();

  delay(DISPLAY_BRIGHTNESS); 
}

//------------------------------------------------------------------
// Faz o loop de contagem
void loop(){
  if (numberSeq < 10)
  {
    digWrite(1, numberSeq);
    digWrite(2, 0);
    digWrite(3, 0);
    digWrite(4, 0);
  }
  else if (numberSeq < 100)
  {
    digWrite(1, numberSeq % 10);
    digWrite(2, numberSeq / 10);
    digWrite(3, 0);
    digWrite(4, 0);
  }
  else if (numberSeq < 1000)
  {
     digWrite(1, numberSeq % 10);
     digWrite(2, (numberSeq % 100) / 10);
     digWrite(3, numberSeq / 100);
     digWrite(4, 0);
   }
   else
   {
     digWrite(1, numberSeq % 10);
     digWrite(2, (numberSeq % 100) / 10);
     digWrite(3, (numberSeq % 1000) / 100);
     digWrite(4, numberSeq / 1000);
   }

   currentMillis = currentMillis + (DISPLAY_BRIGHTNESS * 4); // Soma cada delay para utilizar no contador

   if( currentMillis >= 1000)
   {
     numberSeq++;
     currentMillis = 0;
   }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s