ESP32 – Utilizando o RTC interno do ESP32
Se você já tentou fazer algum acionamento por datas e horários específicos, já deve conhecer os RTC’s (Real Time Clock), que são na maioria dos casos, placas externas e dedicadas a esta função. Manter uma placa dedicada para este propósito pode ser necessário quando a precisão deve ser alta e atrasos/avanços em datas e horas são indesejáveis (Clock Drift), mas em muitos casos (principalmente com internet disponível) você pode utilizar o RTC interno do seu microcontrolador (se disponível, como no caso do ESP32) para baratear produtos. Neste tutorial, nós vamos aprender a utilizar o RTC interno do ESP32 para manter a nossa data atualizada.
O que é um RTC ?
RTC (Real Time Clock, Relógio de Tempo Real) é um “sistema” utilizado para manter datas atualizadas e “seguras” em caso de quedas de energia (na maioria do casos). O ESP32 tem um RTC interno que faz esse trabalho de manter a data atualizada, porém assim como os outros RTC externos que se compram com Arduino, ele também precisa de uma bateria dedicada em caso de queda da alimentação, pois, caso contrário, a hora irá se perder ou congelar. Para manter a data atualizada e de fácil gerenciamento pelo MCU, vamos utilizar a data no formato Unix time, que são os segundos corridos desde 01/01/1970.
- Depois da data configurada no código, o ESP32 manterá a data atualizada automaticamente mesmo durante DEEP-SLEEP, então você poderá lê-la a qualquer momento que estará atualizada pro momento atual.
- O clock do interno do RTC no ESP32 tem 5% de variação (drift), então você pode perceber a data atrasada ou adiantada caso utilize o sistema por longos períodos. Para corrigir isso, basta atualizar a data de tempos em tempos com NTP por exemplo, ou até aplicar algoritmos de correção do drift.
O que é Unix time ?
Unix time é a contagem de segundos desde 01/01/1970 que os sistemas computacionais usam para guardar datas em memórias, efetuar operações como IF’s e também mostrar as informações de data e hora ao usuário formatadas, claro. Foi esse mesmo Unix time que foi responsável pelo famoso “Bug do milênio” nos anos 2000, que fez alguns computadores voltarem para 01/01/1970 por conta da variável utilizada sofrer de Overflow.
No momento que escrevo esse post, o Unix time esta com o valor de 1551355200 segundos desde 01/01/1970. Se você quer pegar o Unix time de agora ou uma data especifica, consulte: https://www.unixtimestamp.com/
Mãos à obra – Utilizando o RTC do ESP32
Componentes necessários
Programando
Foi utilizada a ESP-IDF, mas funciona perfeitamente na Arduino IDE bastando trocar o void app_main() pelo void setup() e adicionar o void loop() ao fim do código, como é feito na Arduino IDE.
Se você ainda não conhece ou instalou a ESP-IDF (local de programação nativo do ESP32), veja nosso artigo clicando AQUI.
A biblioteca responsável pelas funções de tempo (time.h) já vem baixada por padrão nos arquivos do ESP32, basta apenas inclui-la.
#include <freertos/FreeRTOS.h> #include <freertos/task.h> #include <esp_system.h> #include <time.h> #include <sys/time.h> struct tm data;//Cria a estrutura que contem as informacoes da data. void app_main() { timeval tv;//Cria a estrutura temporaria para funcao abaixo. tv.tv_sec = 1551355200;//Atribui minha data atual. Voce pode usar o NTP para isso ou o site citado no artigo! settimeofday(&tv, NULL);//Configura o RTC para manter a data atribuida atualizada. while (1) { vTaskDelay(pdMS_TO_TICKS(1000));//Espera 1 seg time_t tt = time(NULL);//Obtem o tempo atual em segundos. Utilize isso sempre que precisar obter o tempo atual data = *gmtime(&tt);//Converte o tempo atual e atribui na estrutura char data_formatada[64]; strftime(data_formatada, 64, "%d/%m/%Y %H:%M:%S", &data);//Cria uma String formatada da estrutura "data" printf("\nUnix Time: %d\n", int32_t(tt));//Mostra na Serial o Unix time printf("Data formatada: %s\n", data_formatada);//Mostra na Serial a data formatada /* Com o Unix time, podemos facilmente controlar acoes do MCU por data, visto que utilizaremos os segundos e sao faceis de usar em IFs Voce pode criar uma estrutura com a data desejada e depois converter para segundos (inverso do que foi feito acima) caso deseje trabalhar para atuar em certas datas e horarios No exemplo abaixo, o MCU ira printar o texto **APENAS** na data e horario (28/02/2019 12:00:05) ate (28/02/2019 12:00:07) */ if (tt >= 1551355205 && tt < 1551355208)//Use sua data atual, em segundos, para testar o acionamento por datas e horarios { printf("Acionando carga durante 3 segundos...\n"); } } }
Colocando para funcionar
Entendendo a fundo
struct tm data;
struct tm { tm_sec; /* seconds, range 0 to 59 */ tm_min; /* minutes, range 0 to 59 */ tm_hour; /* hours, range 0 to 23 */ tm_mday; /* day of the month, range 1 to 31 */ tm_mon; /* month, range 0 to 11 */ tm_year; /* The number of years since 1900 */ tm_wday; /* day of the week, range 0 to 6 */ tm_yday; /* day in the year, range 0 to 365 */ tm_isdst; /* daylight saving time */ };
A estrutura “data” nos permite obter os dados individuais da data atual, como por exemplo mês, dia, hora, segundo, ano, etc.
Se você deseja obter apenas a hora atual, basta utilizar data.tm_hour
strftime(data_formatada, 64, "%d/%m/%Y %H:%M:%S", &data);
A função strftime() formata a data atual (da estrutura indicada) num formato que você deseja. Caso você queira alterar o formato da data, veja mais detalhes clicando AQUI
Considerações finais
Unix time é de enorme importância na computação por facilitar extremamente as operações por datas e horários, já que podemos trabalhar facilmente com os segundos dentro de IF’s e etc. Continue praticando e olhe a referência abaixo para mais detalhes sobre a biblioteca time.h utilizada.
Referências
https://en.wikipedia.org/wiki/Unix_time
https://pt.wikipedia.org/wiki/Problema_do_ano_2000
https://www.tutorialspoint.com/c_standard_library/time_h.htm
Uma outra alternativa para atualizar o RTC pode ser o um módulo de GPS
Se for 5% de desvio, sem internet é muito inconveniente, compensa mais usar o RTC DS3231. Eu usei o DS3231 em uma igreja, está rodando a anos sem precisar atualizar, devido a compensação automática de variação.
Boa noite. Preciso fazer um relógio horário para desligar um equipamento em alguns horário aos finais de semana e feriados. Consigo utilizar o esp32 com a biblioteca do RTC?
Codigo bugado:
expected expression before ‘int32_t’
Field ‘tv_sec’ could not be resolved
request for member ‘tv_sec’ in something not a structure or union
Type ‘int32_t’ could not be resolved
Type ‘timeval’ could not be resolved
unknown type name ‘timeval’; use ‘struct’ keyword to refer to the type
Usando:
Operating System: windows 10
Java Runtime Version: 17.0.6+10-LTS
Eclipse Version: 4.25.0.v20220831-1800
Eclipse CDT Version: 10.7.1.202208160035
IDF Eclipse Plugin Version: 2.9.1.202304060814
ESP-IDF v5.0.1-dirty
Python set for IDF_PYTHON_ENV: Python 3.11.2
O bug do milênio não tem absolutamente NADA a ver com o epoch time do *nix.
o que eu devo ou posso fazer para se obter a alteração no formato da hora, para que fique de acordo com o fuso-horário local?
Artigo muito bom, estou recebendo o timeStamp em string, e estou com problema p fazer a conversão
tv.tv_sec , p ficar dinâmico, vc pode me ajudar ?
olá ! esp32cam tambem possui esse opção ?
Claro!
Olá! Tentei passar para a IDE do Arduino, mas não funcionou… É necessário incluir alguma biblioteca alem da “time.h”?
qual erro apareceu?
Olá, gostei bastante do artigo.
Estou a tentar fazer um pequeno projecto com o ESP32 embora não seja grande expert em programação.
Nesse projecto o ESP32 está como WebServer e eu queria actualizar a data e hora via internet, é possivél?
Como?
Desde já Obrigado.
Sim, utilize NTP ou um RTC externo.
Como posso converter data pega no ntp para Unix Time????
A biblioteca “time.h”, padrão em diversas de linguagens (inclusive no C), permite.
Olá Jaiminho, Estou horas tentando. Vc conseguiu ? vlw, Abraçao
Muito bom este artigo! Estou usando esta técnica e vou ter que corrigir o drift com algum algoritmo, ja que meu equipamento vai trabalhar offline.
Um algoritmo que implementei em um produto foi tão simples quanto eficiente. Os devices que ficavam longos periodos em sleep, se conectavam na internet 1x por dia e com isso acabavam obtendo a hora atual, logo que temos o horario do device e hora real, podemos calcular a diferença de horarios e compensar no tempo de sleep!
Enquanto mais dias se passavam, mais preciso ficava, mas logo no primeiro ciclo, já era suficiente pro segundo ciclo errar menos de 1seg.
Gostei da sua solução, teria o algoritmo pra passar?
Boa noite, o que aconteceria caso a esp32 perdesse a conexão a internet? ou caso ocorra uma queda de energia? esse horário seria atualizado quando retornar a energia e quando o acesso a internet estiver restabelecido? valeww
O RTC pode servir na maioria dos casos pra justamente manter a data atualiza sem internet. Já em relação a queda de alimentação, você teria que utilizar uma bateria de backup, do mesmo jeito que os RTC externos usam.
E vc tem algum esquema de como colocar essa bateria de backup no ESP32?
Não, é uma ligação normal, direto no pino 3.3V
Parabens pelo artigo será de grande ajuda, tenho uma pergunta tenho um projeto que utiliza a ram do rtc o esp tem essa ram para armazenar parametros?
Sim, você pode utilizar essa RAM do RTC no esp32 para manter dados inclusive no Deep Sleep. Há também um atributo especial que não inicializa a variável, permitindo assim o uso com qualquer tipo de reset, já que o MCU nunca irá altera-la exceto que você mande.