Aprenda a utilizar o RTC da Arduino Uno R4 WiFi 4

O microcontrolador do Arduino Uno R4 WiFi, o RA4M1 da Renesas, possui um recurso importante: um RTC (“Real Time Clock” ou Relógio de Tempo Real). Neste artigo vamos conhecer melhor o RTC e ver como usá-lo na versão WiFi do Uno R4.

RTC da Arduino Uno R4 WiFi

O que é um RTC?

Um Relógio de Tempo Real é um contador especializado para manter um registro atualizado de hora e data.

O RTC do RA4M1 pode operar em dois modos: no modo binário, ele é simplesmente um contador de segundos, com 32 bits (o suficiente para 135 anos). O modo que nos interessa mais é o calendário, nele o RTC armazena e incrementa automaticamente as seguintes informações em registradores internos:

  • segundos (0 a 59)
  • minutos (0 a 59)
  • hora (0 a 23 ou 0 a 11, dependendo de configuração)
  • dia da semana (0 a 6, correspondendo a Domingo a Sábado)
  • dia do mês (1 a 31)
  • mês (1 a 12)
  • ano (0 a 99)

Para usar o RTC, você precisa carregar um valor inicial válido. Ao incrementar, ele leva em conta informações como quantos dias tem cada mês (tratando inclusive anos bissextos). Cabe ressaltar que você precisa informar corretamente o dia da semana, ele não é calculado a partir da data.

Os valores são armazenados em formato BCD, onde são usados quatro bits (ou menos) para cada dígito. Por exemplo, um valor 49 (decimal) no registrador de segundos corresponde a 31 segundos:

49 (decimal) = 0011 0001 em binário
0011 é o dígito de dezena (3)
0001 é o dígito de unidade (1)

O RTC dispõe também do recurso de alarme, onde uma interrupção é gerada em determinado dia e horário.

Como usar o RTC em um programa Arduino?

Ao programarmos no ambiente Arduino estes detalhes de programação do hardware são escondidos pelas classes presentes na biblioteca RTC. Para usar esta biblioteca, incluía no inicio do seu sketch:

#include <RTC.h>

O relógio de tempo real é acessado através do objeto RTC. Datas e horas são armazenados em objetos RTCTime.

O objeto RTC possui os seguintes métodos:

  • begin(), que deve ser chamado antes dos outros (normalmente na rotina setup() do seu sketch).
  • settime(rtctime), que acerta a data e hora atual para o conteúdo de um objeto rtctime.
  • getime(rtctime), que coloca em um objeto rtctime a data e hora atuais.

Você pode criar e iniciar um objeto RTCTime da seguinte forma:

RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, 
DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_INACTIVE);

Neste exemplo, estamos iniciando o objeto com a data 30 de junho de 2023, a hora 13:37:00 (sem horário de verão) e o dia da semana quarta-feira.

A classe RTCTime possui métodos para obter e alterar os vários componentes da data e hora: getDayofMonth, setDayOfMonth, getMonth, setMonth, getYear, setYear, getHour, setHour, getMinute, setMinute, getSecond, setSecond, getDayOfWeek e setDayOfWeek.

É possível também utilizar esta classe com os dois formatos de tempo normalmente usados em C:

  • “Unix time” (tempo sem segundos desde 1/1/70 00:00:00): getUnixTime e setUnixTime.
  • estrutura tm: getTmTime e setTM

Aqui está um exemplo curto de uso do RTC, adaptado dos exemplos da placa:

#include "RTC.h"

// Iniciação
void setup() {
  Serial.begin(115200);
  RTC.begin();
  RTCTime inicio(28, Month::SEPTEMBER, 2023, 10, 54, 20,
      DayOfWeek::THURSDAY, SaveLight::SAVING_TIME_INACTIVE);
  RTC.setTime(inicio);  
}

// Loop Principal
void loop() {
  RTCTime agora;
  RTC.getTime(agora);
  Serial.print(agora.getDayOfMonth());
  Serial.print("/");
  Serial.print(Month2int(agora.getMonth()));
  Serial.print("/");
  Serial.print(agora.getYear());
  Serial.print(" ");
  Serial.print(agora.getHour());
  Serial.print(":");
  Serial.print(agora.getMinutes());
  Serial.print(":");
  Serial.println(agora.getSeconds());  
  delay (1500);
}

A biblioteca suporta também o recurso de alarme do RTC, através do método setAlarmCallback. Este método recebe três parâmetros:

  • o endereço da rotina de callback, que será chamada quando o alerta disparar. Esta rotina não recebe nenhuma parâmetro.
  • um objeto RTCTime com os dados de quando o alarme deve ser disparado
  • um objeto AlarmMatch que indica quais dados do objeto RTCTime precisam coincidir com a data e hora atual para o alarme disparar.Isto é feito chamando os métodos addMatchSecond, addMatchMinute, addMatchHour, addMatchDay, addMatchMonth, addMatchYear() e addMatchDayOfWeek.

Um exemplo curto de um alarme que dispara às 10:00:00 de todo domingo:

bool tocou = false;

void ligaAlarme() {
  RTCTime alarme;
  alarme.setSecond(0);
  alarme.setMinute(0);
  alarme.setHour(10);
  alarme.setDayOfWeek(DayOfWeek::SUNDAY);
  AlarmMatch am;
  am.addMatchSecond();
  am.addMatchMinute();
  am.addMatchHour();
  am.addMatchDayOfWeek();
  if (!RTC.setAlarmCallback(alarm_cbk, alarme, am)) {
    Serial.println("Erro ao ligar alarme");
  }
}

void alarm_cbk() {
  tocou = true;
}

IMPORTANTE! Cuidado que a rotina de callback é chamada durante uma interrupção ao programa principal. Ela deve ser curta e precisa tomar o cuidado de não interferir no que está sendo interrompido. O mais seguro é apenas acionar um flag que é testado no loop principal do programa.

Acertando a Data e Hora do RTC da Arduino Uno R4 WiFi

No exemplo anterior a data e hora inicial estão fixos no programa, o que claramente não é correto. Uma opção é pedir para alguém digitar a data e hora, usando o Monitor Serial do Arduino, mas temos uma opção melhor se tivermos conexão com a Internet: NTP.

NTP (Network Time Protocol) é um protocolo para obter a data e hora atuais a partir de servidores na Internet. Para usá-lo, instale a biblioteca NTPClient:

O programa a seguir usar o NTP para iniciar o RTC. Para usá-lo você precisa acrescentar no seu projeto um arquivo secrets.h contendo o nome e a senha da sua rede:

#define SECRET_SSID "RedeWiFi"
#define SECRET_PASS "Senha"

O programa principal fica assim:

#include "RTC.h"
#include "WiFiS3.h"
#include <WiFiUdp.h>
#include <NTPClient.h>
#include "secrets.h"

char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;

int status = WL_IDLE_STATUS;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, -3*60*60); // hora Brasil = UTC-3

// Iniciação

void setup() {
  // Inicia serial
  Serial.begin(115200);
  // Connecta WiFi
  while (status != WL_CONNECTED) {
    Serial.print("Conectando a rede WiFi... ");
    status = WiFi.begin(ssid, pass);
    uint32_t timeout = millis() + 10000;
    while (millis() < timeout) {
      status = WiFi.status();
      if (status == WL_CONNECTED) {
        Serial.println("Conectado");
        break;
      }
      delay(100);
    }
    if (status == WL_CONNECTED) {
      break;
    }
    Serial.println("Falhou!");
  }
  // Pega hora na internet
  timeClient.begin();
  while (!timeClient.update()) {
    delay(500);
  }

  // Inicia RTC
  RTC.begin();
  RTCTime agora;
  agora.setUnixTime(timeClient.getEpochTime());
  RTC.setTime(agora);  
}

// Laço Principal
void loop() {
  RTCTime agora;
  RTC.getTime(agora);
  Serial.print(agora.getHour());
  Serial.print(":");
  Serial.print(agora.getMinutes());
  Serial.print(":");
  Serial.println(agora.getSeconds());  
  delay (1500);
}

Como Manter a Data e Hora do RTC com o Arduino Desligado?

Uma limitação dos exemplos anteriores é que quando o Arduino é desligado a data e hora são perdidas e só estarão corretas após serem introduzidas manualmente ou comunicando com um servidor NTP via WiFi. Não seria bom se ao ligar o Arduino ele já estivesse com data e hora atualizadas?

Para isto, a placa Uno R4 WiFi permite conectar uma bateria. Esta bateria mantém funcionando apenas o RTC, o resto do Arduino (e o seu programa) continuam desligados. 

A bateria pode ser ligada no conector de três pinos que fica ao lado do conector principal de alimentação. A bateria deve fornecer ente 1,6 e 3,3 V; o positivo da bateria deve ser ligado ao pino VRTC e o negativo ao pino GND.

RTC da Arduino Uno R4 WiFi

Duas opções práticas de bateria são uma bateria de lítio do tipo CR3021 (bateria do tipo “moeda”) ou duas baterias alcalinas de 1,5V  em série.

Nota: Precisão do RTC do Arduino Uno R4 WiFi

O RTC atualiza a data e hora a partir de um sinal de clock. Infelizmente, o Arduino Uno R4 não inclui um cristal específico para este clock. Na sua ausência, é usado um oscilador de baixa frequência interno ao microcontrolador (o LOCO). Embora a frequência nominal deste oscilador seja a mesma dos cristais usados para relógio (32.768 kHz) a sua variação é bem maior (a especificação fala em frequências variando entre 27.8528 e 37.6832 kHz). Portanto não é recomendado usar o RTC do Uno R4 por longos períodos de tempo sem acertá-lo a partir de uma fonte confiável (como um servidor NTP).


Gostou de aprender como utilizar o RTC da Arduino Uno R4 WiFi? Deixe um comentário quais outros recursos da Arduino Uno R4 WiFi você quer que a gente de ensine a utilizar. Não esqueça de nos seguir nos Instagram para não perder nenhum conteúdo como este.

Faça seu comentário

Acesse sua conta e participe

4 Comentários

  1. Ótimo post, minha duvida como ver a data?

    1. O primeiro exemplo mostra a data. Use RTC.getTime() para pegar os dados do RTC e depois os métodos getDayOfMonth(), getMonth() e getYear() para obter dia, mês e ano.

    2. Obrigado Daniel fui direto pro exemplo do ntp não observei o exemplo acima, consegui so nao consegui imprimir o dia da semana, pode me ajudar?
      obrigado

      1. O dia da semana é retornado por getDayOfWeek(), o resultado é uma das constantes definidas em DayOfWeek. No momento a melhor documentação da classe RTC é o próprio código fonte: https://github.com/arduino/ArduinoCore-renesas/tree/main/libraries/RTC/src