RTC DS3231 – Registrando data e hora com Arduino
Bem sabemos como o tempo é a variável mais importante do mundo e da nossa vida. Nos organizamos a partir de horários e datas e por isso precisamos de relógios e agendas para nos guiar a todo momento. Se queremos construir sistemas inteligentes que auxiliam nossas atividades cotidianas, é fundamental saber como manter nosso Arduino sincronizado com a hora e a data do local onde estamos. Pensando nisso, elaboramos este tutorial voltado para contemplar o uso de um Relógio de Tempo Real (Real-Time Clock) em conjunto com uma placa Arduino, em especial o RTC DS3231.
Neste conteúdo será demonstrado como utilizar o RTC em questão para adquirir valores de data e hora, assim como, envia-los, por exemplo, através da porta serial para que o leitor possa conferir o resultado do projeto. Além disso, explicaremos também a importância desse módulo.
[toc]
O que é um RTC?
Um RTC, do inglês Real-Time Clock, é um elemento que possibilita o registro de valores de data e hora no decorrer do tempo. Em poucas palavras, um RTC é um relógio em que o usuário indica os valores iniciais de data e hora, para que então, a partir destes, o mesmo passe a contar o tempo por conta própria (geralmente este dispositivo possui uma fonte de energia própria (como a apresentada na figura abaixo) para manter continuamente os valores de data e hora, de modo que, se o equipamento ao qual o RTC está conectado, ficar sem alimentação, a contagem do tempo não é interrompida).
Note que este tipo de dispositivo existe dentro de muitos aparelhos, como relógios digitais, despertadores, microondas, entre outros, que mesmo após serem desligados, podem manter a contagem correta do tempo até serem ligados novamente .
Caso você já tenha desmontando um computador certamente já viu uma bateria como a da imagem acima. Ela está associada ao circuito de um circuito RTC, que por sua vez, é responsável por manter seu computador com a data e a hora atualizadas mesmo estando desligado. Quando o horário e data do computador começam a ficar defasados dos valores reais da região, deve-se ficar atento, pois, este pode ser um sinal de que está na hora de trocar esta bateria.
As funções delay() e millis()
Quando um programa é desenvolvido para ser inserido em uma placa Arduino, de modo que, este tenha alguma relação com o conceito de tempo, fala-se, na maioria das vezes em progressão de tempo, por exemplo, pode-se determinar que o Arduino execute uma ação x após alguns segundos de ocorrência de uma condição y. Em grande parte destes casos, a função delay() é suficiente para atingir o objetivo proposto, ao passo que, em alguns casos é mais conveniente a utilização da função millis().
- delay(): Pausa o programa por um certo tempo (especificado em milissegundos).
- millis(): Retorna um número (em milissegundos) referente ao tempo que passou desde que o programa atual inserido na placa Arduino começou a rodar.
Note que a função millis() pode ser utilizada para determinar se uma certa quantidade de tempo já se passou, porém, sem que haja algum tipo de “congelamento” do programa que está rodando no Arduino.
Por que utilizar um RTC junto com um Arduino?
Como dito anteriormente, a função millis() atua como um contador, de modo que este, é incrementado a cada momento, no entanto, quando o Arduino for desligado, este contador começará novamente do zero. Por este motivo, pode-se utilizar um RTC para ter um controle melhor sobre a progressão do tempo.
Além disso, é importante saber que a função millis() retorna um elemento do tipo unsigned long (que representa a quantidade de milissegundos), que por sua vez, possui o tamanho de 32 bits. Com esta informação, pode-se chegar a conclusão de que com este tipo de dado pode-se realizar a contagem do tempo em aproximadamente 50 dias, ou seja, pouco menos de 2 meses até que o contador seja reiniciado. Em contrapartida, a autonomia de um RTC pode chegar a 10 anos dependendo do modelo do mesmo e da bateria utilizada.
Características do RTC DS3231
O RTC que será utilizado no desenvolvimento do projeto proposto neste tutorial é o RTC DS3231. Este RTC consiste em um relógio de tempo real de alta precisão, baixo consumo de energia e baixo custo. Este módulo é capaz de trabalhar com informações como segundos, minutos, horas, dias, meses, anos e ainda é capaz de ajustar-se automaticamente em casos de meses com menos de 31 dias e em situações de ocorrência de anos bissextos. Além disso, o RTC DS3231 pode operar tanto no formato 12 horas (utilizando a nomenclatura AM/PM) como no formato 24 horas.
Ao lado das características citadas, também deve-se ressaltar que o RTC DS3231 se comunica com uma placa Arduino através do protocolo I2C (onde os dados são transferidos através de um barramento bidirecional) e que o mesmo possui um compartimento para que seja inserida uma bateria externa (em caso de falha de energia no elemento principal, esta é automaticamente acionada para manter o controle sobre a passagem do tempo), um sensor de temperatura embutido, dois alarmes programáveis, além de outras características mais avançadas que serão apresentadas em tutoriais posteriores.
Mãos à obra – Realizando a aquisição dos valores de data e hora com o Arduino
Componentes utilizados:
Montando o projeto
Na figura abaixo, o leitor poderá conferir como foi realizada a montagem do projeto apresentado neste tutorial. Lembre-se de montar o projeto com o seu Arduino desligado.
Veja como ficou o nosso:
Programando
Antes de adentrarmos na apresentação do código, disponibilizamos uma seção para ajudar aqueles que são iniciantes no assunto. Sinta-se livre para prosseguir caso você já tem domínio da IDE do Arduino.
Conectando o Arduino ao computador
Primeiramente, conecte seu Arduino ao computador e abra a IDE Arduino. Em seguida, é necessário selecionar a porta COM na qual o Arduino está conectado (este procedimento pode ser feito clicando no menu Ferramentas (tools) e em seguida escolhendo-se a porta correspondente no submenu Porta (port). Neste caso, a porta na qual está o Arduino é apresentada da seguinte maneira: COM3 (Arduino Micro).
Por fim, garanta também que o tipo de placa apropriado esteja selecionado (isso pode ser feito acessando o menu Ferramentas (tools) e o submenu Placa (board)).
– Biblioteca
Para desenvolver o projeto proposto com o RTC DS3231 utilizou-se uma biblioteca capaz de atuar sobre o protocolo I2C para facilitar os processos de endereçamento e troca de dados que fazem parte do funcionamento do protocolo citado. Esta biblioteca foi produzida por Jarzebski e pode ser encontrada aqui.
Adquirindo e instalando a biblioteca que será utilizada
Para adquirir a biblioteca em questão, basta acessar o link apresentado anteriormente, clicar no botão clone or Download e por fim, no botão Download ZIP, conforme a figura abaixo.
Após a realização do download dos arquivos compactados no formato ZIP, abra a IDE do Arduino, selecione o menu Sketch, o submenu Incluir Bilioteca e por fim, basta clicar na opção Adicionar biblioteca .ZIP (Add ZIP Library) e encontrar o arquivo que acabou de ser baixado.
Uma outra forma de fazer isso é extrair o conteúdo do arquivo ZIP dentro da pasta Libraries (onde foi instalada a IDE do Arduino).
– Código do projeto
Segue o código a ser utilizado no Arduino para imprimir os valores de data e hora no Serial Monitor.
#include <Wire.h> //Biblioteca para manipulação do protocolo I2C #include <DS3231.h> //Biblioteca para manipulação do DS3231 DS3231 rtc; //Criação do objeto do tipo DS3231 RTCDateTime dataehora; //Criação do objeto do tipo RTCDateTime void setup() { Serial.begin(9600); //Inicialização da comunicação serial rtc.begin(); //Inicialização do RTC DS3231 rtc.setDateTime(__DATE__, __TIME__); //Configurando valores iniciais //do RTC DS3231 } void loop() { dataehora = rtc.getDateTime(); //Atribuindo valores instantâneos de //data e hora à instância dataehora Serial.print(dataehora.year); //Imprimindo o Ano Serial.print("-"); Serial.print(dataehora.month); //Imprimindo o Mês Serial.print("-"); Serial.print(dataehora.day); //Imprimindo o Dia Serial.print(" "); Serial.print(dataehora.hour); //Imprimindo a Hora Serial.print(":"); Serial.print(dataehora.minute); //Imprimindo o Minuto Serial.print(":"); Serial.print(dataehora.second); //Imprimindo o Segundo Serial.println(""); delay(1000); //Tempo p atualização do valor enviado pela porta //serial }
Nota: é importante ler a seção Entendendo a fundo deste tutorial para entender como funciona o ajuste de data e hora.
Após escrever o código, salve e depois clique em Carregar (Upload) para que o programa seja transferido para seu Arduino.
Colocando para funcionar
Para verificar o resultado da gravação deste código no Arduino Micro basta acessar o Serial Monitor (para realizar este procedimento, basta utilizar o atalho Ctrl+Shift+M). Espera-se que o leitor consiga obter um resultado semelhante ao demonstrado a seguir.
Entendendo a fundo
Software
– Incluindo as bibliotecas a serem utilizadas no projeto
Inicialmente, observe que foi necessário incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca wire.h é a responsável pela comunicação utilizando o protocolo I2C enquanto a biblioteca DS3231.h atua sobre a biblioteca wire.h simplificando o processo de comunicação através do protocolo citado, para que assim, o usuário possa utilizar o RTC DS3231 de maneira mais fácil.
#include <Wire.h> #include <DS3231.h>
– Declarando os objetos rtc e dataehora
Em seguida, cria-se dois objetos que serão utilizados posteriormente, de modo que, um destes é do tipo DS3231, chamado rtc (que representará o RTC DS3231 no código) e outro do tipo RTCDateTime, chamado dataehora (que será responsável por manipular os valores de data e hora existentes).
Lembre-se: rtc e dataehora são apenas nomes, sendo assim, é importante ressaltar que, os objetos identificados por rtc e dataehora poderiam ser chamados de quaisquer outros nomes, como por exemplo, modulo e informacaoatual, respectivamente.
DS3231 rtc; //construindo o objeto rtc da classe DS3231 RTCDateTime dataehora; //construindo o objeto dataehora da classe RTCDateTime
– Definindo as configurações iniciais
Primeiramente, na função setup(), utiliza-se a função Serial.begin() para inicializar a comunicação serial do Arduino Micro com o computador (onde será possível ver o resultado do projeto)
Serial.begin(9600);
Em seguida, utiliza-se a função rtc.begin() (repare que o nome rtc corresponde ao objeto criado anteriormente) para inicializar o RTC DS3231.
rtc.begin();
Posteriormente, recorre-se à função rtc.setDateTime() para configurar os valores iniciais do RTC DS3231, ou seja, os valores de data e hora que servirão de ponto de partida para o mesmo.
Conforme será explicado em seguida, na seção Ajuste de hora do RTC, ao passarmos __DATE__, __TIME__ como parâmetros da função rtc.setDateTime(), fazemos com que os valores iniciais de data e hora do RTC DS3231 sejam correspondentes ao momento da compilação do código.
rtc.setDateTime(__DATE__, __TIME__);
De acordo com a explicação dada, a função setup() deve possuir o seguinte conteúdo:
void setup() { Serial.begin(9600); rtc.begin(); rtc.setDateTime(__DATE__, __TIME__); }
– Aquisição dos valores de data e hora
Na função loop(), utiliza-se primeiramente a função rtc.GetDateTime() para atribuir os valores de data e hora de um determinado momento ao objeto dataehora. Neste momento é importante ressaltar que o objeto em questão irá conter várias informações (segundo, minuto, hora, dia, mês e ano), que por sua vez, podem ser acessadas separadamente.
dataehora = rtc.getDateTime();
Imagine que seja necessário extrair a informação referente ao ano que o RTC DS3231 está registrando. Para isso, basta referir-se ao objeto dataehora por dataehora.year. Portanto, se quisermos enviar o valor do ano através da porta serial, deve-se utilizar dataehora.year como argumento da função Serial.print().
Serial.print(dataehora.year);
Observe as demais correspondências na figura abaixo:
Por fim, veja como ficou a função loop() (perceba que ao final da mesma existe uma função delay() determinando a disponibilização das informações a cada um segundo).
void loop() { dataehora = rtc.getDateTime(); Serial.print(dataehora.year); //Imprimindo o ano Serial.print("-"); Serial.print(dataehora.month); //Imprimindo o mês Serial.print("-"); Serial.print(dataehora.day); //Imprimindo o dia Serial.print(" "); Serial.print(dataehora.hour); //Imprimindo a hora Serial.print(":"); Serial.print(dataehora.minute); //Imprimindo os minutos Serial.print(":"); Serial.print(dataehora.second); //Imprimindo os segundos Serial.println(""); delay(1000); }
Hardware
As ligações realizadas no hardware em questão são bem simples, de modo que, deve-se lembrar apenas, que a comunicação entre o RTC DS3231 e uma placa Arduino é dada através do protocolo I2C, portanto, no Arduino Micro, além dos pinos referentes à alimentação do módulo, utilizou-se os pinos SDA (pino 3, responsável pela troca de dados entre os dispositivos) e SCL (pino 4, responsável pela sincronização entre os dispositivos). No RTC DS3231 estes pinos estão nomeados, portanto, são de fácil identificação.
Ajuste de hora do RTC
É importante que nosso RTC esteja com a hora correta, portanto, torna-se necessário saber como mante-lo com a hora ajustada.
Primeiramente, note que no código apresentado anteriormente, fizemos o uso um recurso muito interessante, disponibilizado pela biblioteca DS3231.h. Este recurso consiste na utilização dos parâmetros __DATE__ e __TIME__ dentro da função rtc.setDateTime(), que por sua vez, fazem com que os valores data e hora da compilação sejam usados para ajustar a data e a hora do nosso módulo RTC DS3231.
rtc.setDateTime(__DATE__, __TIME__);
Neste momento, o leitor deve estar atento a um pequeno detalhe: Apesar da função apresentada anteriormente determinar os valores iniciais de data e hora do RTC de acordo com o momento da compilação, caso o seu Arduino seja reiniciado, o ele irá definir novamente as informações de partida do módulo RTC DS3231 com os valores referentes ao momento da compilação realizada anteriormente (e não com as dados de data e hora de quando ele foi reiniciado, pois, sempre que o Arduino for ligado, o conteúdo da função setup() será executado e consequentemente, a função rtc.setDateTime() também), portanto, teremos um relógio desatualizado.
Solução para o ajuste dos valores de data e hora
O ideal é que a gravação do programa no Arduino seja feita duas vezes:
- Na primeira vez você deve enviar o código tal como apresentado anteriormente.
- Em seguida, você terá que modificar a função setup(), comentando ou excluindo a linha que contém a função de ajuste de data e hora, para então, gravar novamente o programa no Arduino.
Primeira gravação:
#include <Wire.h> //Biblioteca para manipulação do protocolo I2C #include <DS3231.h> //Biblioteca para manipulação do DS3231 DS3231 rtc; //Criação do objeto do tipo DS3231 RTCDateTime dataehora; //Criação do objeto do tipo RTCDateTime void setup() { Serial.begin(9600); //Inicialização da comunicação serial rtc.begin(); //Inicialização do RTC DS3231 rtc.setDateTime(__DATE__, __TIME__); //Configurando valores iniciais //do RTC DS3231 } void loop() { dataehora = rtc.getDateTime(); //Atribuindo valores instantâneos de //data e hora à instância dataehora Serial.print(dataehora.year); //Imprimindo o Ano Serial.print("-"); Serial.print(dataehora.month); //Imprimindo o Mês Serial.print("-"); Serial.print(dataehora.day); //Imprimindo o Dia Serial.print(" "); Serial.print(dataehora.hour); //Imprimindo a Hora Serial.print(":"); Serial.print(dataehora.minute); //Imprimindo o Minuto Serial.print(":"); Serial.print(dataehora.second); //Imprimindo o Segundo Serial.println(""); delay(1000); //Tempo p atualização do valor enviado pela porta //serial }
Segunda gravação:
#include <Wire.h> //Biblioteca para manipulação do protocolo I2C #include <DS3231.h> //Biblioteca para manipulação do DS3231 DS3231 rtc; //Criação do objeto do tipo DS3231 RTCDateTime dataehora; //Criação do objeto do tipo RTCDateTime void setup() { Serial.begin(9600); //Inicialização da comunicação serial rtc.begin(); //Inicialização do RTC DS3231 //rtc.setDateTime(__DATE__, __TIME__); *******ESTA LINHA DEVE SER COMENTADA OU EXCLUÍDA******* } void loop() { dataehora = rtc.getDateTime(); //Atribuindo valores instantâneos de //data e hora à instância dataehora Serial.print(dataehora.year); //Imprimindo o Ano Serial.print("-"); Serial.print(dataehora.month); //Imprimindo o Mês Serial.print("-"); Serial.print(dataehora.day); //Imprimindo o Dia Serial.print(" "); Serial.print(dataehora.hour); //Imprimindo a Hora Serial.print(":"); Serial.print(dataehora.minute); //Imprimindo o Minuto Serial.print(":"); Serial.print(dataehora.second); //Imprimindo o Segundo Serial.println(""); delay(1000); //Tempo p atualização do valor enviado pela porta //serial }
Considerações finais
Neste tutorial elaboramos um conteúdo introdutório sobre o RTC DS3231 visando apresentar os conceitos básicos de funcionamento do mesmo e como utiliza-lo em conjunto com uma placa Arduino. Esperamos que você tenha gostado deste conteúdo, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.
37 Comments
Deixe uma pergunta, sugestão ou elogio! Estamos ansiosos para ter ouvir!Cancelar resposta
Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.
Tenho o mesmo problema do do Valterlei, se coloco 13, 11,2019 e 01:40:00 por exemplo, da erro.
Mas como insere a hora e data em rtc.setDateTime(__DATE__, __TIME__); ? eu coloco 04/05/2019 ? e na hora 10:31:00 ? Só colocar os números e barra e a hora e os dois pontos ?
avrdude: stk500v2_ReceiveMessage(): timeout
Estou tendo problema com este erro acima.
Depois ocorre isso
avrdude: stk500v2_getsync(): timeout communicating with programmer
teria como deixar a opção para setar os valores? pois uma hora a bateria vai acabar, sendo assim terá de ser ajustado o codigo e compiladonovamente, como ficaria se fosse deixar um botão de set para ajustar os parametros? grato
Estou aguardando a resposta!
Olá, fiquei sem saber como inserir a data, hora, minutos e segundos atuais??? Não entendi onde foi inserido esses dados??
Olá Luiz! Os dados são automaticamente inseridos no código através dos parâmetros __DATE__ e __TIME__ dentro da função rtc.setDateTime(), como explicado mas, observe que vc tem que compilar duas vezes o sketch, uma vez, com esse parâmetro não comentado e a segunda vez comentado, assim: //rtc.setDateTime(__DATE__, __TIME__);
Abç
Poderia fazer um tutorial utilizando o rtc ds3231 para acionar varias cargas(relés), em hora e dias programados. Obrigado.
Parabéns pelo grande trabalho a frente do site!
Obrigado e parabéns pelo tutorial mas, uma curiosidade: percebo que nos dois lados do DS3231 tem SCL, SDA, VCC e GND; porventura, com isso, é possível usar duas programações em dois circuitos com o mesmo módulo? E, nesse caso, a alimentação é separada? Estou certo? Obrigado
Olá, quando escrevo o código fornecido:
…
DS3231 rtc; //Criação do objeto do tipo DS3231
RTCDateTime dataehora; //Criação do objeto do tipo RTCDateTime
…
Surge-me o erro:
no matching function for call to ‘DS3231::DS3231()’
Pode ajudar-me por favor?
problema resolvido, eu esqueci de colocar as barras // onde eu setava e caregar novamente com elas comentadas e esta funcionando normal!
gostaria de saber se tem como colocar um botão para setar as horas minutos e data desde ja agradeço
ola boa tarde estou usando o ds1302 mas quando eu tiro da fonte, mesmo estando com a bateria nova a hora zera ou volta do inicio no qual foi programado vc poderia me ajudar? o que pode ser? desde ja agradeço
Preciso de ajuda.
sempre retorna esse erro quanto tá compilando:
‘RTCDateTime’ does not name a type
já baixei várias vezes a biblioteca e nada…
Boa noite, como faço pra ler o dia da semana (seg, ter, qua etc)?
Como faço para colocar um lcd 16×2 que mostre a data e a hora com este circuito? Soldei um conector femea atras do lcd e encaixei o i2c junto com o lcd. O modulo i2c possui as saídas gnd, vcc, scl e sda iguais ao do rtc ds3231. Também encaixei o rtc na saída do i2c, fiz o teste sem colocar programa nenhum no arduino e pelo menos ligou, parece que funciona neste método. Upei o scan i2c e descobri todas as saídas e anoitei, subi um programa de exemplo de lcd e funcionou. Testei desta maneira:
LiquidCrystal_I2C lcd(0x3F,16,2);
as outras eram 57 hexa e 68 hexa.
Não conheço muito de programação e gostaria de aprender como fazer um programa que mostre a data e a hora no lcd por este método de encaixar o lcd o i2c e o rtc tudo junto.
Obrigado pelo tutorial Daniel, me ajudou muito!
Olá, estou fazer um projeto e necessito puxar do RTC a contagem de segundos exata para fazer condições, caso o tempo seja X ele faz a comparação, até o momento puxei somente dados de data e hora, mas como char não consigo utilizar como int para fazer condições que desejo.
Fui orientado a usar uma função chamada unix timestemp mas não encontrei nenhum exemplo para tal.
Tens como me auxxilhar?
Alguém pode me ajudar ?
Toda vez que ligo o Arduino o rtc reinicia com o horário que foi programado na IDE .Como que faço para que o rtc fique com o horário correto sem que precise mexer no código pra arrumar o horário ?????
Ja verificou a bateria de backup?
Gostaria de apresender a usar melhor a memória de 32kb presente neste módulo!
Muito obrigado Edson!
Daniel, quero parabenizar seus tutoriais, são muito bons!!!
funcionou por um tempo, hj a tarde parou de funcionar e deu esse erro: RTC DateTime does not name a type.
O que pode ser?
Meu amigo, não sei te dizer, ele funcionou por quanto tempo?
Quando eu fui carregar o código, apareceu na tela: ‘class DS3231’ has no member named ‘begin’.
E estava marcando a parte rtc.begin();
O que eu faço?
Quando eu fui carregar o código, apareceu na tela: ‘class DS3231’ has no member named ‘begin’.
E estava marcando a parte rtc.begin();
O que eu faço?
Gostaria de conectar um DS1302 no nodemcu v3 e armazenar as horas no cartão sd… A parte do cartão eu já consegui mas não consegui ligar e ler o DS1302…Como faço????
Quando você fala em ligar, você quer dizer fazer as ligações ou ligar ele, de fato?
Daniel fiz e refiz varias vezes e da um erro (DS does not name a type) não nomeia um tipo.
qual a solução?
Samuca, isso está acontecendo quando você copia e cola o código?
Como faço para ligar dois dispositivos I2C (no meu caso o DS3231 e o Display OLED) no arduino MEGA ?
Como você já tentou proceder Marcio?
Olá amigo, boa noite! Não sei se a dúvida persiste ainda, mas o protocolo I2C funciona no modo slave. Dessa forma, você pode conectar vários dispositivos I2C em apenas uma placa Arduino que contenha pinos que aceitam esse protocolo. Segue link para maiores informações: http://www.arduinobr.com/arduino/i2c-protocolo-de-comunicacao/
Abraços.
Como posso fazer o mesmo que isso, só que com o ds1307. Preciso das informações todas separadas igual foi feito por ultimo e impresso na serial, mas n estou me achando pelo 1307. E por fim, acaba de ganhar um novo leitor.
Douglas, faremos um tutorial sobre o ds1307 e poderemos esclarecer suas dúvidas quanto ao procedimento, porém, de antemão, eu não sei te dizer ainda como fazer. Obrigado por nos acompanhar!
Daniel, seus tutoriais estão cada vez melhores! Parabéns!!