Início›Relógio
⬤ LCD · Avançado

🕐 Relógio e Cronómetro

⏱️ 35 min 🧩 millis() · HH:MM:SS · Cronómetro · Acertar hora · Alarme

Nesta página

⏰ Relógio Digital com millis()

ℹ️
O Arduino não tem RTC (Real Time Clock) integrado. Simula-se um relógio com millis(), que conta milissegundos desde o início. Não é perfeito (deriva ~1s/hora) mas é suficiente para displays educativos. Para projetos reais usa um módulo DS3231.
ex_relogio.ino
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Hora inicial (acerta aqui antes de carregar)
int h=10, m=30, s=0;
unsigned long tUltimoTick = 0;

// Imprime inteiro com zero à esquerda: 7 → "07"
void p2(int v) { if(v < 10) lcd.print("0"); lcd.print(v); }

void mostrarHora() {
  lcd.setCursor(4, 1);   // centrado — 4 + 8 chars = 12; 20-12=8÷2=4
  p2(h); lcd.print(":"); p2(m); lcd.print(":"); p2(s);
}

void tick() {
  s++;
  if(s >= 60) { s=0; m++; }
  if(m >= 60) { m=0; h++; }
  if(h >= 24) h=0;
}

void setup() {
  lcd.init(); lcd.backlight();
  lcd.setCursor(3, 0); lcd.print("RELOGIO DIGITAL");
  lcd.setCursor(0, 3); lcd.print("PR.FT9_5 LED 2025   ");
  mostrarHora();
}

void loop() {
  if (millis() - tUltimoTick >= 1000) {
    tick();
    mostrarHora();
    tUltimoTick = millis();
  }
  // [outros sensores/motores podem actualizar aqui sem bloqueio]
}
RELOGIO DIGITAL 10:30:47 PR.FT9_5 LED 2025

🎛️ Acertar a Hora com Dois Botões

ex_relogio_set.ino
#define BTN_SEL 2   // Seleciona campo (h → m → s → normal)
#define BTN_INC 3   // Incrementa o campo selecionado

int campo = 0;  // 0=normal, 1=horas, 2=minutos, 3=segundos
unsigned long tSel=0, tInc=0;

void mostrarModoSet() {
  lcd.setCursor(0, 3);
  switch(campo) {
    case 0: lcd.print("SEL: normal         "); break;
    case 1: lcd.print("SEL: >>> HORAS <<<  "); break;
    case 2: lcd.print("SEL: >>> MINUTOS <<"); break;
    case 3: lcd.print("SEL: >>> SEGUNDOS <"); break;
  }
}

void loop() {
  // Botão SEL — seleciona campo
  if (digitalRead(BTN_SEL)==LOW && millis()-tSel>300) {
    campo = (campo+1) % 4;
    mostrarModoSet(); tSel=millis();
  }
  // Botão INC — incrementa campo selecionado
  if (digitalRead(BTN_INC)==LOW && millis()-tInc>200) {
    switch(campo) {
      case 1: h=(h+1)%24; break;
      case 2: m=(m+1)%60; break;
      case 3: s=(s+1)%60; break;
    }
    mostrarHora(); tInc=millis();
  }
  // Tick normal apenas quando não está a acertar
  if (campo==0 && millis()-tUltimoTick>=1000) {
    tick(); mostrarHora(); tUltimoTick=millis();
  }
}

⏱️ Cronómetro com Lap Time

ex_cronometro.ino
#define BTN_START 4  // START/STOP
#define BTN_LAP   5  // LAP / RESET (quando parado)

bool          a_correr  = false;
unsigned long acumulado = 0;
unsigned long tInicio   = 0;
unsigned long lap       = 0;
int           nLap      = 0;
unsigned long tStart=0, tLap=0;

unsigned long tempoTotal() {
  return acumulado + (a_correr ? millis() - tInicio : 0);
}

void printCrono(int linha, unsigned long ms) {
  int cs  = (ms/10) % 100;
  int sg  = (ms/1000) % 60;
  int mn  = (ms/60000) % 60;
  lcd.setCursor(4, linha);
  p2(mn); lcd.print(":"); p2(sg); lcd.print("."); p2(cs);
}

void setup() {
  lcd.init(); lcd.backlight();
  pinMode(BTN_START, INPUT_PULLUP); pinMode(BTN_LAP, INPUT_PULLUP);
  lcd.setCursor(2,0); lcd.print("CRONOMETRO   LAP:0");
}

void loop() {
  // Actualiza display
  printCrono(1, tempoTotal());
  if (lap > 0) {
    lcd.setCursor(0,2); lcd.print("LAP "); lcd.print(nLap); lcd.print(":");
    printCrono(2, lap);
  }
  lcd.setCursor(0,3); lcd.print(a_correr ? "A CORRER   " : "PARADO     ");

  // Botão START/STOP
  if (digitalRead(BTN_START)==LOW && millis()-tStart>300) {
    if(!a_correr) { tInicio=millis(); a_correr=true; }
    else          { acumulado=tempoTotal(); a_correr=false; }
    tStart=millis();
  }
  // Botão LAP (em curso) / RESET (parado)
  if (digitalRead(BTN_LAP)==LOW && millis()-tLap>300) {
    if(a_correr) { lap=tempoTotal(); nLap++; lcd.setCursor(17,0); lcd.print(nLap); lcd.print(" "); }
    else         { acumulado=0; lap=0; nLap=0; lcd.setCursor(17,0); lcd.print("0  "); }
    tLap=millis();
  }
}
CRONOMETRO LAP:3 01:23.45 LAP 3: 00:28.91 A CORRER

🔔 Alarme Simples

ex_alarme.ino
// Alarme: quando h==hA && m==mA, o buzzer soa e o LCD pisca
#define BUZZER 8
int hA=11, mA=0;   // Alarme às 11:00
bool alarmeSoou=false;

void loop() {
  if(millis()-tUltimoTick>=1000) { tick(); mostrarHora(); tUltimoTick=millis(); }

  bool hora_alarme = (h==hA && m==mA && s<30);

  if(hora_alarme && !alarmeSoou) {
    // Toca 3 bips e pisca retroiluminação
    for(int i=0;i<3;i++) {
      tone(BUZZER, 1000, 400);
      lcd.noBacklight(); delay(400);
      lcd.backlight();   delay(200);
    }
    lcd.setCursor(0,3); lcd.print("** ALARME ATIVO **  ");
    alarmeSoou = true;
  }
  if(!hora_alarme) alarmeSoou=false;
}

🏆 Para ir mais longe

PR.FT9_5 · LCD 20×4 · L293D Motor Driver · Arduino UNO Rev3 · Início · led.dge.medu.pt