domingo, 22 de abril de 2012

Relógio Digital

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 é um complemento do post anterior "Trabalhando com Displays de 7 Segmentos"

A modificação foi:

Acrescentado um segundo botão para decrementar o valor de segundos.
Assim pode se incrementar e decrementar os segundo, ajustando a hora/minuto conforme desejado.

Abaixo o programa completo e comentado:


// 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 BUTTONUP A4
#define BUTTONDW A5

#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 buttonStateDW;
int lastButtonState = LOW;   // leitura anterior do pino do botão
int lastButtonStateDW = LOW;
unsigned long button_down_start = 0; // quanto tempo o botão foi pressionado
unsigned long button_down_startDW = 0;
unsigned long lastDebounceTime = 0;  // a última vez que o pino de saída foi alternado
unsigned long lastDebounceTimeDW = 0;
unsigned long debounceDelay = 50;    // tempo de debouncing
unsigned long debounceDelayDW = 50;

// 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(BUTTONUP, INPUT);
  pinMode(BUTTONDW, 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 UP pressionado, aumenta os minutos
    int reading = digitalRead(BUTTONUP);
    // 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();
        
      }
    } 
    
  // botão DOWN pressionado, diminui os minutos
    int readingDW = digitalRead(BUTTONDW);
    // verifica se estado do botão mudou, por ruído ou pressionamento
    if (readingDW != lastButtonStateDW) {
      // reset o temporizador de debouncing
      lastDebounceTimeDW = millis();
    }
    if ((millis() - lastDebounceTimeDW) > debounceDelayDW) {
      // qualquer que seja a leitura, estava por mais tempo
      // que o atraso de estabilização, então leva-o como estado atual corrente
      if (buttonStateDW != readingDW) {
      button_down_startDW = millis(); 
      // armazena o inicio do estado corrente do botão
      }
      buttonStateDW = readingDW;
      // o estado do botão é agora ligado ou desligado
      if (buttonStateDW == HIGH) {
        // se o botão foi segurado por mais de 5 segundos, faça o ir mais rapido
        if ((millis() - button_down_startDW) > 5000) {
          seconds -= 10;
          if (seconds > 0) seconds = 0;
        }
        
        // botão foi pressionado
        decrementTime();
        
      }
    }

    lastButtonStateDW = readingDW;
    lastButtonState = reading;
     
  }// fim do while

  lastTime += 1000;
  
  incrementTime();
} // fim do loop principal

//
// uma chamada a função incrementTime aumenta o tempo em 1 minuto
//
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++;  
  }
}


//
// uma chamada a função decrementTime diminue o tempo em 1 minuto
//
void decrementTime() {
  
  if (seconds == 0) {
    seconds = 59;
    
    if (minutes == 0) {
      minutes = 59;
      
      if (hours == 1) {          
        hours = 12;
      }
      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




Vejam o vídeo:
Também no youtube http://www.youtube.com/watch?v=y2owd8Pa4Y0&feature=youtu.be

Dúvidas e sugestões enviem para: arduinobymyself@gmail.com

video