domingo, 22 de abril de 2012

Trabalhando com Displays de 7 Segmentos

Arduino by my Self
Esta barra, indica o nível de dificuldade encontrado para cada experiência realizada.
sendo:
"VERDE", indicação de nível 1 a 5 (Fácil);
"AMARELO", indicação de nível 6 a 8 (Médio);
VERMELHO, indicação de nível 9 e 10 (Difícil);



Este post traz 3 experiências com display de 7 segmentos e 4 dígitos.
Mostra como fazer a multiplexação de mais de um display, usando os mesmos pinos do arduino, para economizar conexões/pinos.

1a experiência - faz o tratamento de padrões de teste do display, assim podemos trabalhar a multiplexação e efetuar um teste de funcionamento do display.

2a experiência - é um contador temporal, usando o relógio do sistema (temporização interna), faz a contagem crescente dos segundos passados após o início, ou reinício, do sistema. O reinício é executado com um botão de reset.

3a experiência - Um relógio com hora/minuto (contagem de segundos por um LED indicador).  Através de botão é possível ajustar h/m. Conta também com uma indicação de manhã/tarde am/pm através de LED.

Utilizamos um único circuito geral de ligação do display com o Arduino.

O HARDWARE:

1 x Arduino ou Duemilanove
1 x BreadBoard
1 x Display - 4 Dígitos x 7 Segmentos
1 x Switch Dactilar
2 x LEDs
6 x Resistores de 220KO
1 x Resistor de 10KO
Fios e Cabos

O CIRCUITO:

Conectar o Arduino da seguinte maneira:
pino Display - pino Arduino
A   - 2
B   - 3
C   - 4
D   - 5
E   - 6
F   - 7
G   - 8
PT -
DIG1 - 9
DIG2 - 10
DIG3 - 11
DIG4 - 12

SWITCH - A4 (experiências 2 e 3)
LED-AM/PM - A1 (experiência 3)
LEDs 2 Pontos - 13 (experiência 3)

Como ligar o Switch:

+5V -----[ / ]-----A4-----/\/\/\/-----GND
+5V -----[ / ]-----A5-----/\/\/\/-----GND

Como Ligar um LED:

Pino Arduino -----|>|-----/\/\/\/-----GND






O SOFTWARE:

Aqui estão os softwares comentados.

Experiência 1:-


// definição dos pinos dos segmentos
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;
//int p = 8;

// definição dos pinos dos dígitos
int d4 = 9;
int d3 = 10;
int d2 = 11;
int d1 = 12;

// outras definições
int del = 100;
int buttoncount = 0;
int loopcount = 0;

// inicialização do Arduino
void setup()
{
  pinMode(d1, OUTPUT);
  pinMode(d2, OUTPUT);
  pinMode(d3, OUTPUT);
  pinMode(d4, OUTPUT);
  pinMode(a, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(d, OUTPUT);
  pinMode(e, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(g, OUTPUT);
  //pinMode(p, OUTPUT);
}

// loop principal do programa
void loop()
{
  roulette(4); // padrão de teste #1, 4 é o numero de vezes que será 
               // executado o padrão; será passado a rotina
               // como um argumento
  delay(100);
  zigzag(4); // padrão de teste #2
  delay(100);
  circles(4); // padrão de teste #3
  delay(100);
}

// subrotina para multiplexar os dígitos do display
void pickDigit(int x)
{
  digitalWrite(d1, HIGH); // vlor HIGH no pino desabilita o dígito
  digitalWrite(d2, HIGH);
  digitalWrite(d3, HIGH);
  digitalWrite(d4, HIGH);

  switch(x) // cria uma estrutura switch, tendo como entrada
            // o número do display a ser habilitado
  {
  case 1: 
    digitalWrite(d1, LOW); // colocando LOW no pino, estamos habilitando
                           // o acendimento dos segmento
    break; // executou? sai da estrutura switch
  case 2: 
    digitalWrite(d2, LOW); 
    break;
  case 3: 
    digitalWrite(d3, LOW); 
    break;
  default: 
    digitalWrite(d4, LOW); 
    break;
  }
}

// subrotina para apagar todos os segmentos
void clearLEDs()
{
  digitalWrite(a, LOW); // colocando LOW nos pinos dos segmentos
                        // apagamos o segmento
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
  //digitalWrite(p, LOW);
}

// primeiro padrão de teste
void roulette(int x) // o argumento x define quantas vezes será executado
                     // o padrão de teste
{
  loopcount = 0; // inicia variável de contagem do loop
  while (loopcount < x) // loop com o valor do argumento
  {
    digitalWrite(a, HIGH); // valor HIGH no pino do segmentos
                           // acende o segmento
    pickDigit(1); // seleciona dígito 1
    delay(del); // delay
    pickDigit(2);
    delay(del);
    pickDigit(3);
    delay(del);
    pickDigit(4);
    delay(del);
    digitalWrite(a, LOW); // apaga segmento anterior
    digitalWrite(f, HIGH); // acende próximo segmento
    delay(del);
    digitalWrite(f, LOW);
    digitalWrite(e, HIGH);
    delay(del);
    digitalWrite(e, LOW);
    digitalWrite(d, HIGH);
    delay(del);
    pickDigit(3);
    delay(del);
    pickDigit(2);
    delay(del);
    pickDigit(1);
    delay(del);
    digitalWrite(d, LOW);
    digitalWrite(c, HIGH);
    delay(del);
    digitalWrite(c, LOW);
    digitalWrite(b, HIGH);
    delay(del);
    clearLEDs(); // limpa o display
    loopcount++; // incrementa o contador do número de vezes
                 // de execução do teste
  }
}

// segundo padrão de teste
void zigzag(int x)
{
  loopcount = 0;
  while(loopcount < x)
  {
    digitalWrite(a, HIGH);
    pickDigit(1);
    delay(del);
    pickDigit(2);
    delay(del);
    pickDigit(3);
    delay(del);
    pickDigit(4);
    delay(del);
    digitalWrite(a, LOW);
    digitalWrite(f, HIGH);
    delay(del);
    digitalWrite(f, LOW);
    digitalWrite(g, HIGH);
    delay(del);
    pickDigit(3);
    delay(del);
    pickDigit(2);
    delay(del);
    pickDigit(1);
    delay(del);
    digitalWrite(g, LOW);
    digitalWrite(c, HIGH);
    delay(del);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    delay(del);
    pickDigit(2);
    delay(del);
    pickDigit(3);
    delay(del);
    pickDigit(4);
    delay(del);
    digitalWrite(d, LOW);
    digitalWrite(e, HIGH);
    delay(del);
    digitalWrite(e, LOW);
    digitalWrite(g, HIGH);
    delay(del);
    pickDigit(3);
    delay(del);
    pickDigit(2);
    delay(del);
    pickDigit(1);
    delay(del);
    digitalWrite(g, LOW);
    digitalWrite(b, HIGH);
    delay(del);
    clearLEDs();
    loopcount++;
  }
}


// terceiro padrão de teste
void circles(int x)
{
  loopcount = 0;
  while (loopcount < x)
  {
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    pickDigit(1);
    delay(250);
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(f, LOW);
    digitalWrite(c, HIGH);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    pickDigit(2);
    delay(250);
    digitalWrite(a, HIGH);
    digitalWrite(b, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    pickDigit(3);
    delay(250);
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(f, LOW);
    digitalWrite(c, HIGH);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    pickDigit(4);
    delay(250);
    clearLEDs();
    loopcount++;
  }
}
// Fim da Compilação


Experiência 2:-


// definição dos pinos dos segmentos
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;
//int p = 8;

//definição dos pinos dos dígitos
int d1 = 9;
int d2 = 10;
int d3 = 11;
int d4 = 12;

// outras definições
long n = 0;
int x = 200;
int del = 1000;

// inicialização do Arduino
void setup()
{
  pinMode(d1, OUTPUT);
  pinMode(d2, OUTPUT);
  pinMode(d3, OUTPUT);
  pinMode(d4, OUTPUT);
  pinMode(a, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(d, OUTPUT);
  pinMode(e, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(g, OUTPUT);
  //pinMode(p, OUTPUT);
}

// loop principal do programa
void loop()
{
  clearLEDs(); // apaga todos os segmentos
  pickDigit(1); // seleciona dígito 1
  pickNumber((n/x/1000)%10); // gera o número a ser mostrado
                             // baseado em n e x
                                
  delayMicroseconds(del); // delay em microsegundos
  
  clearLEDs();
  pickDigit(2);
  pickNumber((n/x/100)%10);
  delayMicroseconds(del);
  
  clearLEDs();
  pickDigit(3);
  //dispDec(3);
  pickNumber((n/x/10)%10);
  delayMicroseconds(del);
  
  clearLEDs();
  pickDigit(4);
  pickNumber(n/x%10);
  delayMicroseconds(del);
  
  n++; // incrementa n
  
  if (digitalRead(A4) == HIGH) // verifica se botão foi pressionado
  {
    n = 0; // se sim zera o contador
  }
}

// subrotina para multiplexar os dígitos do display
void pickDigit(int x)
{
  digitalWrite(d1, HIGH);// valor HIGH no pino desabilita o dígito
  digitalWrite(d2, HIGH);
  digitalWrite(d3, HIGH);
  digitalWrite(d4, HIGH);
  
  switch(x) // cria uma estrutura switch, tendo como entrada
            // o número do display a ser habilitado
  {
    case 1: 
      digitalWrite(d1, LOW); // colocando LOW no pino, estamos habilitando
                             // o acendimento dos segmentos
      break; // executou? sai da estutura
    case 2: 
      digitalWrite(d2, LOW); 
      break;
    case 3: 
      digitalWrite(d3, LOW); 
      break;
    default: 
      digitalWrite(d4, LOW); 
      break;
  }
}

// subrotina para acender um determinado número no display
void pickNumber(int x)
{
  switch(x) // cria uma estrutura switch para seleção
  {
    default: 
      zero(); // chama rotina para apresentar número 0 no display 
      break;  // executou? retorna da subrotina
    case 1: 
      one(); 
      break;
    case 2: 
      two(); 
      break;
    case 3: 
      three(); 
      break;
    case 4: 
      four(); 
      break;
    case 5: 
      five(); 
      break;
    case 6: 
      six(); 
      break;
    case 7: 
      seven(); 
      break;
    case 8: 
      eight(); 
      break;
    case 9: 
      nine(); 
      break;
  }
}

//void dispDec(int x)
//{
  //digitalWrite(p, HIGH);
//}

// subrotina para apagar todos os segmentos
void clearLEDs()
{
  digitalWrite(a, LOW); // valor low no pino, apaga segmento
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
  //digitalWrite(p, LOW);
}

// mostra número sero no display
void zero()
{
  digitalWrite(a, HIGH); // valor HIGH no pino, acende segmento
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, LOW);
}

void one()
{
  digitalWrite(a, LOW);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void two()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, LOW);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, LOW);
  digitalWrite(g, HIGH);
}

void three()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, HIGH);
}

void four()
{
  digitalWrite(a, LOW);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void five()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, LOW);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, LOW);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void six()
{
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void seven()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void eight()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void nine()
{
  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}
// Fim da Compilação


Experiência 3:-


// nomes dos pinos e definições
#define DIGIT1 9
#define DIGIT2 10
#define DIGIT3 11
#define DIGIT4 12

#define SEGMENTA 2
#define SEGMENTB 3
#define SEGMENTC 4
#define SEGMENTD 5
#define SEGMENTE 6
#define SEGMENTF 7
#define SEGMENTG 8

#define COLON 13
#define AMPM A1

#define BUTTON A4

#define ON  HIGH
#define OFF LOW

#define DELAYTIME 50

// definições de variáveis
unsigned short hours, minutes, seconds;
boolean pm;
unsigned long lastTime; // mantém um registro de quando o segundo
                        // aconteceu

// debouncing do botão
int buttonState;             // leitura corrente do pino do botão
int lastButtonState = LOW;   // leitura anterior do pino do botão
unsigned long button_down_start = 0; // quanto tempo o botão foi pressionado
unsigned long lastDebounceTime = 0;  // a última vez que o pino de saída foi alternado
unsigned long debounceDelay = 50;    // tempo de debouncing

// parametros de inicialização do Arduino
void setup() {                
  // inicializando todos os pinos requeridos como saída
  pinMode(DIGIT1, OUTPUT);
  pinMode(DIGIT2, OUTPUT);
  pinMode(DIGIT3, OUTPUT);
  pinMode(DIGIT4, OUTPUT);

  pinMode(SEGMENTA, OUTPUT);
  pinMode(SEGMENTB, OUTPUT);
  pinMode(SEGMENTC, OUTPUT);
  pinMode(SEGMENTD, OUTPUT);
  pinMode(SEGMENTE, OUTPUT);
  pinMode(SEGMENTF, OUTPUT);
  pinMode(SEGMENTG, OUTPUT);

  pinMode(COLON, OUTPUT);
  pinMode(AMPM, OUTPUT);
  
  // inicializando o pino do botão como entrada
  pinMode(BUTTON, INPUT);
  
  // configuração da hora inicial no display
  hours = 12;
  minutes = 0;
  seconds = 0;
  pm = true; // post meridiam?

  lastTime = millis(); // armazena o segundo do sistema em "lastTime"
}


// loop principal do programa
void loop() {
  
  // continua mostrando o visor enquanto aguarda o cronômetro expirar
  while (millis() - lastTime < 1000) {
    clock_show_time(hours, minutes);

    // pisca os leds : a cada segundo
    if (seconds % 2 == 0) {
      clock_show_colon();
    }

    // botão pressionado, aumenta os minutos
    int reading = digitalRead(BUTTON);

     // verifica se estado do botão mudou, por ruído ou pressionamento
    if (reading != lastButtonState) {
      // reset o temporizador de debouncing
      lastDebounceTime = millis();
    }
    
    if ((millis() - lastDebounceTime) > debounceDelay) {
      // qualquer que seja a leitura, estava por mais tempo
      // que o atraso de estabilização, então leva-o como estado atual corrente
      
      if (buttonState != reading) {
        button_down_start = millis(); 
        // armazena o inicio do estado corrente do botão
      }
      
      buttonState = reading;
      
      // o estado do botão é agora ligado ou desligado
      if (buttonState == HIGH) {
        // se o botão foi segurado por mais de 5 segundos, faça o ir mais rapido
        if ((millis() - button_down_start) > 5000) {
          seconds += 10;
          if (seconds > 59) seconds = 59;
        }
        
        // botão foi pressionado
        incrementTime();
      }
    } 

    lastButtonState = reading;
  }

  lastTime += 1000;
  
  incrementTime();
}

//
// uma chamada a função incrementTime aumenta o tempo em 1 segundo
//
void incrementTime() {
  
  if (seconds == 59) {
    seconds = 0;
    
    if (minutes == 59) {
      minutes = 0;
      
      if (hours == 12) {          
        hours = 1;
      }
      else {
        hours++;
        
        if (hours == 12) {
          pm = !pm;
        }
      }
    }
    else {
      minutes++;
    }
  }
  else {
    seconds++;  
  }
}

//
//   clock_show_time - mostra um dado tempo no relógio
//   Note que em vez de hr/min o usuário pode usar min/sec
//   Máximo horas é de 99, Máximo minutos é de  59, e um mínimo de 0.
//
void clock_show_time(unsigned short hours, unsigned short minutes) {
  unsigned short i;
  unsigned short delaytime;
  unsigned short num_leds[10] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };
  unsigned short digit[4];
  unsigned short hide_leading_hours_digit;
    
  // converte minutos e segundos em dígitos individuais
  // verifica os limites
  if (hours > 99) hours = 99;
  if (minutes > 59) minutes = 59;
  
  // converte hora
  if (hours < 10 && hours > 0) {
    hide_leading_hours_digit = 1;
  }
  else {
    hide_leading_hours_digit = 0;
  }
  
  digit[0] = hours / 10;
  digit[1] = hours % 10; // restante
  digit[2] = minutes / 10;
  digit[3] = minutes % 10; // restante

  for (i = hide_leading_hours_digit; i < 4; i++) {
    clock_all_off();
    clock_show_digit(i, digit[i]);

    // poucos LEDs = display luminoso, então o delay depende do número de LEDs acesos.
    delaytime = num_leds[digit[i]] * DELAYTIME;   
    delayMicroseconds(delaytime);
  }
  
  clock_all_off();
  
  if (pm) {
    clock_show_ampm();
  }
  
  clock_all_off();
}

//
// clock_all_off - desliga todos os LEDsdo relógio e faz o display apagado
//
void clock_all_off(void) {
  
  // digitos devem ser ON para qualquer LED ser on
  digitalWrite(DIGIT1, ON);
  digitalWrite(DIGIT2, ON);
  digitalWrite(DIGIT3, ON);
  digitalWrite(DIGIT4, ON);
  
  // segmentos devem ser OFF para qualquer LED ser on
  digitalWrite(SEGMENTA, OFF);
  digitalWrite(SEGMENTB, OFF);
  digitalWrite(SEGMENTC, OFF);
  digitalWrite(SEGMENTD, OFF);
  digitalWrite(SEGMENTE, OFF);
  digitalWrite(SEGMENTF, OFF);
  digitalWrite(SEGMENTG, OFF);
  
  // desliga os : e alarme também
  digitalWrite(COLON, OFF);
  digitalWrite(AMPM, OFF);
}

//
// clock_show_digit - liga os LEDs para um digito de uma dada posição
//
//      (se o valor está fora da faixa, exibe um 9. se dígito está fora
//      do intervalo de exibição, permanece em branco
//
void clock_show_digit(unsigned short position, unsigned short value) {
  byte a;
  byte b;
  byte c;
  byte d;
  byte e;
  byte f;
  byte g;

  switch (position) {
    case 0:
      digitalWrite(DIGIT1, OFF);
      break;
    case 1:
      digitalWrite(DIGIT2, OFF);
      break;
    case 2:
      digitalWrite(DIGIT3, OFF);
      break;
    case 3:
      digitalWrite(DIGIT4, OFF);
      break;
  }

  a = !(value == 1 || value == 4);
  b = !(value == 5 || value == 6);
  c = !(value == 2);
  d = !(value == 1 || value == 4 || value == 7);
  e =  (value == 0 || value == 2 || value == 6 || value == 8);
  f = !(value == 1 || value == 2 || value == 3 || value == 7);
  g = !(value == 0 || value == 1 || value == 7);
  
  if (a) digitalWrite(SEGMENTA, ON);
  if (b) digitalWrite(SEGMENTB, ON);
  if (c) digitalWrite(SEGMENTC, ON);
  if (d) digitalWrite(SEGMENTD, ON);
  if (e) digitalWrite(SEGMENTE, ON);
  if (f) digitalWrite(SEGMENTF, ON);
  if (g) digitalWrite(SEGMENTG, ON);
}

//
// clock_show_colon - mostra os : que separa minutos de segundos
//
void clock_show_colon(void) {
  unsigned short delaytime;

  digitalWrite(COLON, ON);  
                              // 2 leds = 2 delays necessários
  delaytime = DELAYTIME * 2;  // deve usar uma variávelpara ter atraso similar 
  delayMicroseconds(delaytime);   //  porque o uso da variável retarda um pouco
  digitalWrite(COLON, OFF);
}

//
// clock_show_alarm - mostra o ponto de ampm
//
void clock_show_ampm(void) {
  unsigned short delaytime;

  digitalWrite(AMPM, ON);
                      
  delaytime = DELAYTIME;  
  delayMicroseconds(delaytime);  
  digitalWrite(AMPM, OFF);
}
//Fim da Compilação





O VÍDEO:
vejam no youtube http://www.youtube.com/watch?v=e1Zl5pf2AP4

video