Relógio Inteligente LCD 128x64 com Hora Analógica/Digital e Temperatura – Arduino Nano + RTC DS3231
Componentes e Materiais Necessários
- Arduino Nano R3 × 1
- Maxim Integrated DS3231M - ±5ppm, I2C Real-Time Clock × 1
- Potenciômetro de Volta Única - 10k ohms × 1 (para ajuste de contraste do display)
- Chave Táctil Momentânea × 1
- Display Gráfico LCD 128x64 × 1
Ferramentas Necessárias
- Ferro de Solda (genérico)
Sobre este Projeto
Na página web arduinoecia é apresentado um relógio Arduino com display gráfico LCD 128x64, potenciômetro para ajuste de contraste, módulo RTC DS3231 e botão pulsador. O módulo RTC conecta-se ao Arduino nos pinos A4 (SDA) e A5 (SCL). O botão conecta-se ao pino digital 3, com resistor pull-up interno do Arduino habilitado via software. O programa usa bibliotecas que devem ser instaladas antes de compilar. Descompacte as bibliotecas e coloque-as na pasta LIBRARIES da IDE Arduino.
O programa possui duas telas:
- Tela 1 (screen_1): mostra relógio analógico, relógio digital, data atual e temperatura.
- Tela 2 (screen_2): mostra relógio digital, dia da semana, data, temperatura atual, temperatura mínima e máxima.
As telas são alternadas pressionando o botão conectado ao pino digital 3.
Para configurar data e hora do módulo RTC DS3231, use o Monitor Serial e insira as informações no formato: ano, mês, dia, hora, minuto, segundo. Se digitado corretamente, a mensagem "" será exibida.
Código
Código Principal (Arduino)
//Programa: Display LCD 128x64 e RTC DS3231
//Autor: Arduino e Cia
#include <U8glib.h>
#include <DS3232RTC.h>
#include <Streaming.h>
#include <Time.h>
#include <Wire.h>
// A linha abaixo define as conexões do display e deve ser ajustada conforme o modelo
U8GLIB_ST7920_128X64_1X u8g(6, 5, 4, 7); // Enable, RW, RS, RESET
int X2 = 0, Y2 = 0, X3 = 0, Y3 = 0;
float angulo = 0;
int posicao = 0, posicaoh = 0;
int temperatura = 0;
int min_temp = 500, max_temp = -500;
int ScreenWith = 128, ScreenWithC = 96;
int ScreenHeight = 64, ScreenHeightC = 32;
#define botao 3
int estado_botao = 0;
char* dia_da_semana[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
void tela_1() {
u8g.drawRFrame(0, 0, 128, 64, 3);
// Mostra temperatura
u8g.setPrintPos(20, 30);
u8g.print(temperatura);
u8g.drawStr(42, 30, "C");
u8g.drawCircle(37, 34, 2);
mostra_relogio_digital();
// Mostra relógio analógico
fundo_relogio();
// Atualiza ponteiro de horas
desenha_ponteiro(hour()-1, 12.0, 10);
// Atualiza ponteiro de minutos
desenha_ponteiro(minute()-5, 60.0, 19);
// Atualiza ponteiro de segundos
desenha_ponteiro(second()-5, 60, 21);
}
void tela_2() {
u8g.drawRFrame(0, 0, 128, 64, 3);
u8g.drawRFrame(68, 4, 55, 56, 2);
mostra_relogio_digital();
u8g.setFont(u8g_font_5x8);
u8g.drawStr(78, 35, "MIN");
u8g.drawStr(78, 53, "MAX");
u8g.setFont(u8g_font_6x13);
u8g.setPrintPos(25, 41);
u8g.print(dia_da_semana[(weekday()-1)]);
// Temperatura atual
u8g.setPrintPos(83, 19);
u8g.print(temperatura);
u8g.drawStr(105, 19, "C");
u8g.drawCircle(100, 12, 2);
// Temperatura mínima
u8g.setPrintPos(98, 36);
u8g.print(min_temp);
u8g.drawCircle(113, 29, 2);
// Temperatura máxima
u8g.setPrintPos(98, 54);
u8g.print(max_temp);
u8g.drawCircle(113, 47, 2);
}
void desenha_ponteiro(float valor, float rotacao, int Radius) {
angulo = valor * 2.0 * 3.1415 / rotacao - 1.5707;
X2 = ScreenWithC + Radius * cos(angulo);
Y2 = ScreenHeightC + Radius * sin(angulo);
u8g.drawLine(ScreenWithC, ScreenHeightC, X2, Y2);
}
void fundo_relogio() {
u8g.drawCircle(ScreenWithC, ScreenHeightC, 27);
u8g.drawCircle(ScreenWithC, ScreenHeightC, 1);
u8g.setFont(u8g_font_6x13);
u8g.setFontPosTop();
u8g.drawStr(90, 9, "12");
u8g.drawStr(114, 25, "3");
u8g.drawStr(94, 44, "6");
u8g.drawStr(74, 25, "9");
for(int traco_minuto = 0; traco_minuto < 12; traco_minuto++) {
angulo = traco_minuto / 12.0 * 2 * 3.1415;
X2 = ScreenWithC + 25 * cos(angulo);
Y2 = ScreenHeightC + 25 * sin(angulo);
X3 = ScreenWithC + 25 * cos(angulo);
Y3 = ScreenHeightC + 25 * sin(angulo);
u8g.drawLine(X2, Y2, X3, Y3);
}
}
void mostra_relogio_digital() {
// Mostra a data
u8g.setFont(u8g_font_5x8);
u8g.setPrintPos(8, 55);
u8g.print(day());
u8g.drawStr(19, 55, "/");
u8g.setPrintPos(24, 55);
u8g.print(month());
u8g.drawStr(35, 55, "/");
u8g.setPrintPos(41, 55);
u8g.print(year());
// Mostra hora e minutos
u8g.drawRBox(3, 4, 62, 21, 2);
u8g.setColorIndex(0);
u8g.setFont(u8g_font_fub17);
u8g.drawStr(29, 21, ":");
// Ajusta posição do dígito se hora < 10
if (hour() < 10) {
u8g.drawStr(3, 23, "0");
posicaoh = 16;
} else posicaoh = 3;
u8g.setPrintPos(posicaoh, 23);
u8g.print(hour());
// Ajusta posição do dígito se minuto < 10
if (minute() < 10) {
u8g.drawStr(38, 23, "0");
posicao = 51;
} else posicao = 38;
u8g.setPrintPos(posicao, 23);
u8g.print(minute());
u8g.setColorIndex(1);
}
void setup() {
pinMode(3, INPUT_PULLUP);
Serial.begin(9600);
if (u8g.getMode() == U8G_MODE_R3G3B2) u8g.setColorIndex(255); // white
else if (u8g.getMode() == U8G_MODE_GRAY2BIT) u8g.setColorIndex(3); // max intensity
else if (u8g.getMode() == U8G_MODE_BW) u8g.setColorIndex(1); // pixel on
setSyncProvider(RTC.get);
Serial << F("RTC Sync");
if (timeStatus() != timeSet) Serial << F(" FAIL!");
Serial << endl;
}
void loop() {
temperatura = RTC.temperature() / 4.0;
if (temperatura >= max_temp) max_temp = temperatura;
if (temperatura <= min_temp) min_temp = temperatura;
static time_t tLast;
time_t t;
tmElements_t tm;
// Verifica se foi setado novo horário via Serial
// Formato: ano, mes, dia, hora, minuto, segundo
if (Serial.available() >= 12) {
int y = Serial.parseInt();
if (y >= 100 && y < 1000) Serial << F("Erro: Ano deve ter dois ou quatro digitos!") << endl;
else {
if (y >= 1000) tm.Year = CalendarYrToTm(y);
else tm.Year = y2kYearToTm(y);
tm.Month = Serial.parseInt();
tm.Day = Serial.parseInt();
tm.Hour = Serial.parseInt();
tm.Minute = Serial.parseInt();
tm.Second = Serial.parseInt();
t = makeTime(tm);
RTC.set(t);
setTime(t);
Serial << F("Horario modificado para: ");
printDateTime(t);
Serial << endl;
while (Serial.available() > 0) Serial.read();
}
}
t = now();
if (t != tLast) {
tLast = t;
printDateTime(t);
Serial << endl;
}
// Verifica se botão foi pressionado
boolean valor_botao = digitalRead(3);
if (valor_botao != 1) {
while(digitalRead(3) != 1) delay(100);
estado_botao = !estado_botao; // Inverte estado
}
// Picture loop
u8g.firstPage();
do {
if (estado_botao == 0) tela_1();
if (estado_botao == 1) tela_2();
} while(u8g.nextPage());
delay(10);
}
// Mostra data e hora na serial
void printDateTime(time_t t) {
printI00(day(t), 0);
Serial << monthShortStr(month(t)) << _DEC(year(t));
Serial << ' ';
printI00(hour(t), ':');
printI00(minute(t), ':');
printI00(second(t), ' ');
}
// Correção para imprimir "00" em vez de "0" se valor < 10
void printI00(int val, char delim) {
if (val < 10) Serial << '0';
Serial << _DEC(val);
if (delim > 0) Serial << delim;
return;
}
Bibliotecas Necessárias
As bibliotecas necessárias estão disponíveis para download no repositório do projeto. Incluem: U8glib, DS3232RTC, Streaming, Time e Wire.
Esquemático
Processo de manufatura
- Sinais Analógicos e Digitais: Fundamentos da Instrumentação Industrial
- Sensores Analógicos vs Digitais: Tipos, Aplicações e Exemplos Práticos
- Relógio POV com Arduino: Construa um Display LED de Persistência de Visão
- Construa um Relógio Mestre LED Personalizado com Alarme – Visível a 12 Metros
- Crie Animações e Jogos Envolventes em LCD com Arduino UNO
- Monitor de Temperatura e Relógio Tempo Real com Arduino Due e Display TFT 3.2"
- Relógio Digital TM1637 com Configuração de Hora e Alarme – Prototipo Arduino Nano
- Construa um Voltímetro DIY com Arduino e Display Nokia 5110 – Guia Passo a Passo
- Exibir Temperatura, Umidade e Pressão do BME280 em Touchscreen Nextion
- Construa um Relógio Despertador Confiável com RTC DS1302 e Arduino UNO