Módulos RTC – DS1307/DS3231

conteúdo revisto e atualizado – publicado originalmente em 2015

Estes módulos permitem adicionar um relógio em tempo real (RTC – Real Time Clock) aos seus projetos de uma forma bem simples e barata. Mesmo que falte energia ao seu Arduino, o relógio continua a contar pois é alimentado com uma bateria que pode durar muitos e muitos anos!

A maioria dos módulos RTC  são equipados com os circuitos integrados DS1307 e DS3231 ambos da empresa californiana Maxim Integrated e utilizam o barramento de comunicação I2C.

 

DS1307 e DS3231
DS1307 e DS3231

I2C

I2C (IIC – Inter Integrated Circuit) é um barramento de comunicação desenvolvido pela Philips, hoje NXP Semiconductors, para permitir troca de dados entre os componentes que residem na mesma placa de circuito impresso. Este barramento também é conhecido por TWI (Two Wire Interface) implementado pela ATMEL, hoje Microchip Technology.

A vantagem de usar este tipo de barramento é que precisamos de apenas dois pinos para comunicação, além do pino de alimentação (5V) e o pino terra (GND).

Os módulos I2C possuem um endereço único para cada módulo. A seleção do endereço é feita pela combinação dos pads A0, A1 e A2, para o DS3231 .

Mas como saber o endereço do módulo se não tenho a documentação disponível? 🙁

A biblioteca Wire.h (necessária para utilizar o I2C), contém um exemplo que faz uma varredura em módulos I2C acoplados a placa Arduino.  Esta biblioteca é nativa no software Arduino, ou seja, não é preciso instalar.

Na comunicação  I2C temos dois terminais conhecidos por SDA (Serial Data Line) e SCL (Serial Clock Line).

Nas placas Arduino Uno e compatíveis, o

SDA é o pino analógico  4 (A4)

e o

SCL é o pino analógico 5 (A5).

No Arduino Mega o SDA é o pino digital 20 e o SCL é o pino digital 21.

Conectando o módulo DS1307 (Tiny RTC)

Primeiro verifique se você vai usar um módulo com um dos dois chips indicados no começo do artigo. Após, verifique se tem instalado a biblioteca RTClib.h (esta biblioteca serve para os dois modelos).

Vá até o gerenciador de bibliotecas (atalho CTRL-SHIFT-i), digite rtclib. Caso não encontre, acesse o site  Arduino Library List e faça o download em https://www.arduinolibraries.info/libraries/rt-clib

 

Monte o circuito orientando-se pela tabela a seguir:

 

pino Tiny RTC pino Arduino
GND (jumper preto) GND
VCC (jumper vermelho) 5V
SDA (jumper amarelo) A4
SCL (jumper azul) A5

 

 

Agora iremos verificar o endereço do módulo. Carregue o IDE Arduino e acesse:  menu File (Arquivo)  e navegue até Examples (Exemplos), Wire e i2c_scanner. Execute o sketch e veja qual o endereço retornado no monitor serial.

Você deve ter visto esta informação:

Scanning…
I2C device found at address 0x50 !
I2C device found at address 0x68 !
done

Foram exibidos dois endereços. Um é do chip DS1307 (0x68) e o outro da memória EEPROM (0x50). Este sketch é muito útil para identificar outros módulos que usam I2C.

Exemplos

É quase certo que o seu módulo novo está com a data e hora incorretas. Vamos fazer o ajuste e será necessário apenas uma vez, visto que o módulo contém uma bateria para mantê-lo funcionando.

O ajuste será feito utilizando duas macros da linguagem C: __DATE__ e __TIME__, que retornam respectivamente a data e hora do seu sistema operacional. Note que este recurso é válido somente em tempo de compilação do sketch. Não dá para colocar estas macros em um laço de repetição, por exemplo, e exibir valores atualizados. Sempre conterá o valor no momento da compilação.

Aqui temos os métodos:

begin() – retorna false caso não seja detectado um módulo RTC ou o seu endereço é inválido.

adjust() – grava data e hora no seguinte formato ano (AAAA), mês (MM), dia (DD), hora (HH), minuto (MM) e segundo (SS). A classe DateTime formata os valores das macros __DATE__ e __TIME__  corretamente para este método.

now() – retorna data e hora corrente. Novamente usamos a classe DateTime que monta uma estrutura com os seguintes métodos: day(), month(), year(), hour(), minute() e second().

#include <Wire.h>;
#include <RTClib.h>;

RTC_DS1307 rtc;

void setup() {
  Serial.begin(9600);
  delay(1000);

  if (rtc.begin()) {
    rtc.adjust(DateTime((__DATE__), (__TIME__)));

    DateTime now = rtc.now();
    int dia     = now.day();
    int mes     = now.month();
    int ano     = now.year();
    int hora    = now.hour();
    int minuto  = now.minute();
    int segundo = now.second();
    Serial.print(dia);
    Serial.print("/");
    Serial.print(mes);
    Serial.print("/");
    Serial.print(ano);
    Serial.print("\t");
    Serial.print(hora);
    Serial.print(":");
    Serial.print(minuto);
    Serial.print(":");
    Serial.print(segundo);
  }
  else {
    Serial.println("Modulo RTC nao encontrado!");
  }
}

void loop() {

}

No próximo exemplo vamos formatar os dados retornados pelo módulo .

Foram inicializados três vetores: um para armazenar o texto formatado, um contendo os dias da semana e o último contendo os meses do ano.

Os dados foram formatados com a função sprintf() da linguagem C.  Aliás, temos um mini curso de linguagem C que acreditamos seja útil para um melhor entendimento da linguagem Arduino. Não deixe de fazê-lo 😉

Mais um método utilizado:

dayOfTheWeek() – retorna um inteiro (0 a 6) que representa o dia da semana começando em 0 (domingo).

#include <Wire.h>
#include <RTClib.h>


RTC_DS1307 rtc;

void setup() {
  char texto[255];

  char diasDaSemana[7][10] = {
    "Domingo",
    "Segunda",
    "Terca",
    "Quarta",
    "Quinta",
    "Sexta",
    "Sabado"
  };

  char mesDoAno[13][10] = {
    "",
    "Janeiro",
    "Fevereiro",
    "Marco",
    "Abril",
    "Maio",
    "Junho",
    "Julho",
    "Agosto",
    "Setembro",
    "Outubro",
    "Novembro",
    "Dezembro"
  };

  Serial.begin(9600);
  delay(1000);

  if (rtc.begin()) {
    DateTime now = rtc.now();
    int dia     = now.day();
    int mes     = now.month();
    int ano     = now.year();
    int hora    = now.hour();
    int minuto  = now.minute();
    int segundo = now.second();

    sprintf(texto, "Hoje: %s, %02d/%02d/%04d Hora: %02d:%02d:%02d",
            diasDaSemana[now.dayOfTheWeek()], dia, mes, ano, hora, minuto, segundo);
    Serial.println(texto);

    sprintf(texto, "Hoje: %s, %02d/%s/%04d Hora: %02d:%02d:%02d",
            diasDaSemana[now.dayOfTheWeek()], dia, mesDoAno[mes], ano, hora, minuto, segundo);
    Serial.println(texto);
  }
  else {
    Serial.println("Modulo RTC nao encontrado!");
  }
}

void loop() {
}

A saída no monitor serial será a data e hora do dia que você executou este sketch:

Hoje: Sexta, 21/08/2020 Hora: 17:31:42
Hoje: Sexta, 21/Agosto/2020 Hora: 17:31:42

 


Links úteis: