Relógio com display LCD 128×64 e módulo RTC DS3231
Já faz um bom tempo que escrevi sobre o display gráfico LCD 128×64 aqui no blog, e sempre recebo mensagens de usuários perguntando como eu posso atualizar o display de acordo com dados de sensores e módulos. Assim, hoje vou mostrar como usar o módulo RTC DS3231 com Arduino e display gráfico 128×64, montando um relógio como esse, que além da data e hora mostra também a temperatura ambiente:
O módulo DS3231 é um módulo RTC (Real Time Clock, ou Relógio de Tempo Real), que conta com um sensor de temperatura e é muito mais preciso do que os modelos anteriores DS1302 ou DS1307, já que possui um cristal oscilador embutido.
Esse módulo tem a comunicação por interface I2C e aceita alimentação de 3,3 à 5V, trabalhando com nível de sinal de 5V. Uma bateria no módulo garante que as informações de data e hora não sejam perdidas em caso de falta de alimentação do circuito.
Circuito relógio com DS3231
No nosso circuito vamos utilizar o display gráfico LCD 128×64, um potenciômetro para ajuste do contraste do display (usei um de 10K), o módulo RTC DS3231 e um push button.
Para maiores informações sobre a pinagem e funcionamento desse display, veja o post Display gráfico LCD 128×64 – ST7920.
O módulo RTC é conectado ao Arduino nos pinos A4 (SDA) e A5 (SCL). O botão está conectado ao pino digital 3, com o resistor pull-up interno do Arduino habilitado via software.
Programa display LCD 128×64 e RTC DS3231
O programa utiliza algumas bibliotecas que você terá que instalar antes de compilar. Descompacte as bibliotecas e coloque-as dentro da pasta LIBRARIES da IDE do Arduino. São elas:
Separei o programa em duas telas: a primeira (tela_1), mostra o relógio analógico, o relógio digital, e também a data atual e a temperatura.
A segunda tela (tela_2), mostra o relógio digital, o dia da semana, a data e as informações de temperatura atual, temperatura mínima e temperatura máxima. As telas são selecionadas ao pressionar o push button, ligado ao pino digital 3.
A biblioteca u8glib (até onde eu sei), não permite que você desenhe apenas uma “parte” da tela. Assim, quando é selecionada a rotina de desenho da tela, toda a memória do display é reescrita, logo precisamos desenhar novamente as bordas, textos, valores, etc.
Essa biblioteca também é um pouco pesada, principalmente quando você utiliza muitas fontes dentro do programa. O código abaixo, por exemplo, ocupou quase 29 dos 32K disponíveis no Arduino Uno.
//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 conexoes do display e deve ser //ajustada conforme o modelo utilizado U8GLIB_ST7920_128X64_1X u8g(6, 5, 4 , 7); //Enable, RW, RS, RESET int X2 = 0; int Y2 = 0; int X3 = 0; int Y3 = 0; float angulo = 0; int posicao = 0; int posicaoh = 0; int temperatura =0; int min_temp = 500; int max_temp = -500; int ScreenWith = 128; int ScreenWithC = 96; int ScreenHeight = 64; int ScreenHeightC = 32; #define botao 3 int estado_botao = 0; char* dia_da_semana[]={ "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"}; 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 relogio analogico 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)]); //Mostra temperatura atual u8g.setPrintPos(83, 19); u8g.print(temperatura); u8g.drawStr( 105, 19, "C"); u8g.drawCircle(100, 12, 2); //Mostra temperatura minima u8g.setPrintPos(98, 36); u8g.print(min_temp); u8g.drawCircle(113, 29, 2); //Mostra temperatura maxima 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++) { //Desenha linhas relogio analogico 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,":"); //Acerta a posicao do digito caso a hora //seja menor do que 10 if (hour() < 10) { u8g.drawStr(3,23,"0"); posicaoh = 16; } else posicaoh = 3; u8g.setPrintPos(posicaoh, 23); u8g.print(hour()); //Acerta a posicao do digito caso o minuto //seja menor do que 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.; 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 um novo horario //Formato: ano, mês, 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 //(y < 100) 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 o botao foi pressionado boolean valor_botao = digitalRead(3); if (valor_botao != 1) { while(digitalRead(3) != 1) { delay(100); } // Inverte o estado estado_botao = !estado_botao; } //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), ' '); } //Correcao para imprimir "00" ao inves de "0" caso //o valor seja menor do que 10 void printI00(int val, char delim) { if (val < 10) Serial << '0'; Serial << _DEC(val); if (delim > 0) Serial << delim; return; }
Carregue o programa e pressione o botão para alternar entre as telas. Para setar a data e a hora do módulo RTC DS3231, utilize o serial monitor e digite as informações no formato
ano, mês, dia, hora, minuto, segundo
Se você digitou as informações corretamente, a mensagem “Horario modificado para….” será exibida:
Para finalizar, um vídeo do projeto em funcionamento:
Gostou? Confira outros posts com módulos RTC aqui no Arduino e Cia!
Bom dia, gostaria de saber como faço pra saber o dia da semana? Gostaria de saber se posso implementar com os dados obtidos de um gps.
Boa noite Fran,
Poderia sim, eu só não sei te dizer de antemão como você poderia pegar as informações de data e hora à partir do GPS Shield, por exemplo. Vou pesquisar isso.
Quanto ao dia da semana, a "tela 2" do programa mostra o dia da semana, usando a função weekday().
Abraço!
Gostaria muito de saber se tem como adicionar um despertador neste projeto?
Quando coloco para compilar, dá erro.
Arduino e Cia, poderia responder minha pergunta e dos amigos que estão com o mesmo problema? Grato!!
Oi Luan,
Ajudo sim, se você me disser qual erro está apresentando. 🙂
Abraço!
O Arduíno da erro quando está compilando. Fiz todo procedimento correto em relação a biblioteca. Me ajude a gravar o programa. Agradeço.
Não consigo finalizar a compilação, diz que tem algum erro. Salvei todas às bibliotecas corretamente, mas mesmo assim não compila. Pode me ajudar?
Se caso você me vender um CI com o programa gravado, eu compro.
Oi Luan,
Entre em contato utilizando o formulário de contato no lado direito da página. Combinamos por email.
Abraço!
Amigo, você pode me ajudar a gravar esse programa no arduino, porque não estou conseguindo, só dá erro.
A linha “Wire.h”. coloque no topo da lista de inicialização da biblioteca e você será feliz.
Lo he montado y funciona muy bien. Gracias.
Ustedes pueden hacer con este LCD display un analizador de audio, es decir un VUMeter?
Saludos y nuevamente gracias.
boa tarde amigo, tambem não consigo carregar, pois dá o seguinte erro
Erro compilando.
#include
fatal error: U8glib.h: No such file or directory
Biblioteca inválida encontrada em C:Documents and SettingsDesktopBIBLIOTECA RELOGIOlibrariesu8glib-master:
Só Que as pastas estão Lá, em livraries
Olá bom dia, muito obrigada por compartilhar, deu certinho funciona legal. Vc poderia me tirar uma duvida? seria possivel eu eliminar o computador, e usar um modulo bluetoth para fazer os ajustes? tipo esse modulos baratinho HC5 ou HC6!
Boa noite,
Preciso fazer testes, mas a princípio é uma boa solução para ajuste remoto do relógio. vou pesquisar! 🙂
Abraço e obrigado!
Oii, você conseguiu gravar certinho o programa no Arduíno? Eu não estou conseguindo, dá erro ao compilar.
sim
Boa noite, qual simulador você usa para montar o projeto da imagem?
Obrigada
Oi Priscila,
Para desenhar os circuitos, eu uso o Fritzing: fritzing.org
Abraço!
Adilson
olá, montei o projeto testei por varios dias, e constatei que ele começa a atrasar depois de algumas horas de uso, no final de 3 dias ele ficou 10 segundos atrasados em relação ao meu relogio. ja troquei o modulo RTC, ja mudei algumas coisas no codigo mas não resolve. isso é normal nos RTC ja que são de presição.
Oi Sidnei,
Os módulos RTC são sensíveis à variação de temperatura (principalmente o DS1307). O DS3231 e menos sensível, mas ainda assim eu já tive notícia de algumas variações durante o uso.
Abraço!
Olá, como imprimo uma tela simples ? Ex; Tenho tela 1 e tela 2. quero um botão para escolher entre ambas.
o que é esse u8g.firstPage(); e o u8g.nextPage()
ola, como faço para colocar o digito do calendário (tela 2) ao centro quando os meses nao tem dois dígitos (ex Agosto = 08)
Oi André,
Você pode montar uma lógica para centralizar o número, de acordo com a quantidade de pixels, ou substituir a linha 118 do programa, esta:
u8g.drawStr( 19, 55, "/");
por outras assim:
if (month() <=10)
{u8g.drawStr( 19, 55, "/0");}
Assim você insere a barra e um "zero" antes de imprimir o mês.
Acho que fica melhor. 🙂
Abraço!
Olá, você poderia me ajudar, preciso realizar um projeto que apareça a mensagem de boa vinda em um modulo matrix max7219 e depois apareça a data, hora e temperatura no modulo ds3231 rtc.. poderia me ajudar?
Oi Adenilson,
Qual módulo você está usando ? Aquele com apenas 1 display ?
Abraço!
Irei usar três dislay e um modulo rtc DS3231.. consegue me ajudar?
Boa tarde
E o seguinte eu tenho o modulo ds3231
Quando eu fecho o serial ele para de ler
ai quando eu abro o serial e começa a contar do zero
o que tenho que fazer pra parar de acontecer isto ?
Se puder ajudar eu agradeço
Oi Yago,
O horário deveria ser alterado somente após você enviar os comandos pela serial. Você alterou alguma coisa no código ?
Abraço!
printI00(hour(t), ' : '); esta linha aparece grifada e da erro ao compilar alguem pode me dizer o que fazer 😕
Será que alguém poderia me ajudar a solucionar este erro:
exit status 1
'hour' was not declared in this scope
printI00(hour(t), ':');
Estou tentando montar um relógio com display 128×64 conforme o site ensina: http://www.arduinoecia.com.br/2015/12/relogio-arduino-display-128×64-rtc-ds3231.html
adiciona a TIME LIB
Será que alguém poderia me ajudar a solucionar este erro:
exit status 1
'hour' was not declared in this scope
printI00(hour(t), ':');
Estou tentando montar um relógio com display 128×64 conforme o site ensina: http://www.arduinoecia.com.br/2015/12/relogio-arduino-display-128×64-rtc-ds3231.html
Olá pessoal segue o endereço para a resolução do problema acima, e obrigado Anônimo pela ajuda!
Link:https://github.com/PaulStoffregen/Time
Consegui compilar, tive de baixar a biblioteca TimeLib.h e também incluir no código
cara qual foi o programa que voce usou pra fazer o esquema grafico?
http://4.bp.blogspot.com/-1Ni_JTTBg4w/VmynkBOZsrI/AAAAAAAAEbs/oy7yICKucYg/s1600/Circuito_Arduino_Uno_display_128x64_RTC_DS3231.png
me ajuda cara por favor
Tive o mesmo problema na hora de compilar,
exit status 1
'hour' was not declared in this scope
printI00(hour(t), ':'); entre outros como minute, segundos etc.
Comprei o display na alegria de ver um relogio bacana mais fiquei na ilusão.
Oi José,
Entendo, mas o problema não está no display, e sim na programação. Peço que reveja os procedimentos e principalmente a questão da biblioteca.
Abraço!
instale a versao 1.0.6 do arduino, disponível no próprio site para download
o erro nao esta no código nem nas bibliotecas, mas sim na actualização que o programa foi sofrendo ao longo do tempo em que algumas funcionalidades foram mudando
Estou tentando simular o display ST7920 no Proteus 8.5 mas estou com dificuldades em encontrar a library para adicionar este componente. Alguém tem essa library? Obrigado!
Prezado, estou com o mesmo problema:
exit status 1
'hour' was not declared in this scope
Não estou conseguindo compilar o programa.
Alguma luz? Comprei todos os componentes especialmente para fazer esse relógio.
Prezados, estou com o mesmo problema relatado. Talvez seja algum problema em relação às bibliotecas. Alguém tem alguma luz? Talvez pudessem ser disponibilizados os arquivos originais, ao invés dos links para download.
Boa noite Bruno,
Pode ser. Já faz um tempinho que eu fiz esse post, e a versão da IDE mudou bastante. Vou ver se consigo "resgatar" a biblioteca que usei originalmente.
Abraço!
Adilson
Deu certo, parceiros! Eu segui a dica do André Correia e usei a versão 1.0.6 da IDE. Também me certifiquei que cada biblioteca estava devidamente instalada (o arquivo dentro da primeira pasta no diretório 'libraries') e de que o arquivo das bibliotecas no código correspondiam exatamente ao nome do arquivo do repositório. Por fim, foi só verificar a porta na qual a placa estava conectada ao pc, para conseguir transferir o arquivo. 🙂 Valeu a força!
Blz Bruno!
Obrigado pelo retorno. Bom saber que funcionou. Abraço e obrigado!
Adilson
Boa tarde. Como faço pra acrescentar uma 3ª tela?
Muito bom montei o relógio e funciona perfeitamente , tive alguns problemas no inicio mas com muita perseverança e paciência consegui finalizar a montagem parabéns equipe da "Arduinoecia"………….
Thank you from Russia
You are always welcome! Thank you! 🙂
Adilson
Tutto perfetto e molto bello. Grazie di avere compartito questo tuo progetto.
Saluti dall'Italia.
Sono contento che abbia funzionato! Grazie per aver visitato Arduino e Cia. Saluti dal Brasil! 🙂
Boa tarde, gostaria de saber se em vez de printar o relógio analógico no display se eu quiser fazer um relógio com ponteiro e os ponteiros acompanhem o relógio digital tal qual a demonstração, alguém pode me ajudar.
Aderbal Neves
18 981364383
OLÁ
muito interessado no programa, gostaria de alterar telas (liquidCrystalI2C)
por st7920 você poderia me ajudar codificando com antecedência obrigado.
email:[email protected]
Olá boa noite montei o circuito e funciona muito bem, acrescentei temperatura e umidade externa mas estou con dificuldade de colocar uma terceira tela.como faço para adicionar mais um botão e mais uma tela.
grato
Olá boa tarde.
Seria possível incluir a função alarme no seu código? Eu teria que acrescentar mais botões? Tem alguma dica de como posso fazer?
Grato.
Não estou conseguindo,finalizar projeto fiz todas as ligações corretamente e baixei as bibliotecas corretas,estou usando 1.8.8
Obrigado.
Oi José,
O que acontece?
Abraço!
Adilson
Hola que tal saludos excelente trabajo, me podrías ayudar de que manera van separados las telas 1 y 2…. de que parte a que parte gracias, de antemano felicidades gran trabajo GRACIAS
¡Hola Darwin!
La parte del programa que realiza la verificación del bota y cambio de pantallas va de las líneas 215 a 241.
Gracias. Saludos!
Adilson
ola blz posso usar um arduino nano
Oi Paulo,
Perfeitamente 🙂
Abraço!
Adilson
Baixei o programa em um pro mini, deu tudo certo, carregou sem problema , será que na montagem vai funcionar sem problema?
Oi Reis!
Vai depender da montagem e dos componentes que vc vai usar, mas fique de olho em eventuais mudanças de porta dependendo do Pro Mini que você estiver usando.
Abraço!
Adilson
hi, can you launched sensor fluxgate flc100 magnetometr with ardunio and conected to pc wiht bleuthos? thack you very much, please reply on my email
Hi!
I don´t have this sensor yet, but I will buy it as soon as possible. 🙂
Best regards!
Adilson
Bom trabalho, estou interessado em seguir seus passos, mas a verdade é que sou novo nesse aspecto. Seria possível incluir esp8266 com o protocolo MQTT para monitoramento de temperatura?
Oi Manuel!
Tudo bem? Eu tenho um post exatamente com o que você precisa. Dê uma olhada neste link, por favor: https://www.arduinoecia.com.br/enviando-mensagens-mqtt-modulo-esp32-wifi/
Abraço e obrigado!
Adilson
It IS Showing That RTC was Not Declared In this scope what should i do
Hi! Check the library installation, please.
Best regards!
Adilson