Obteniendo fecha y hora desde un servidor NTP con ESP32
En el mundo de la electrónica y la programación de microcontroladores, a menudo se presentan situaciones en las que la gestión precisa del tiempo es crucial. Ya sea para activar un relé en un momento específico o para registrar datos a intervalos exactos, la capacidad de mantener una sincronización horaria adecuada es fundamental. Aunque muchas veces se recurre a los chips de reloj en tiempo real (RTC), estos pueden ser imprecisos y requieren ajustes regulares. Por ello, el uso del Protocolo de Tiempo de Red (NTP) se convierte en una solución más eficiente, especialmente para proyectos que cuentan con acceso a Internet.
Este artículo explorará en profundidad cómo utilizar NTP para obtener la fecha y hora en proyectos basados en el ESP32. Este microcontrolador, conocido por su conectividad Wi-Fi y su potencia, facilitará la sincronización horaria de manera precisa y sin necesidad de hardware adicional.
¿Qué es el NTP?
El Protocolo de Tiempo de Red (NTP, por sus siglas en inglés) es un protocolo estándar diseñado para la sincronización de relojes de computadoras a través de una red. Al funcionar sobre el Protocolo de Datagramas de Usuario (UDP), NTP permite que los dispositivos conectados a la red se sincronicen con una precisión de milisegundos respecto al Tiempo Universal Coordinado (UTC).
La precisión de NTP es notable, ya que puede alcanzar hasta 50 milisegundos en Internet y menos de 5 milisegundos en redes locales (LAN). La estructura de NTP permite que dispositivos en diferentes zonas horarias se sincronicen adecuadamente, aplicando ajustes de horario local y horario de verano.
Arquitectura del NTP
La arquitectura de NTP es jerárquica y se organiza en diferentes niveles, conocidos como estratos. Esta estructura se compone de:
- Estrato 0: Consiste en dispositivos de cronometraje de alta precisión, como relojes atómicos, GPS y relojes de radio.
- Estrato 1: Servidores que tienen conexión directa con dispositivos de estrato 0 y proporcionan la hora más precisa.
- Estrato 2 y superiores: Servidores que se sincronizan con servidores de estrato superior y actúan como fuente de hora para dispositivos en estratos inferiores.
Este diseño asegura que la información temporal se propague de manera eficiente y precisa a través de la red, manteniendo la sincronización en todos los niveles.
¿Cómo funciona el NTP?
El funcionamiento de NTP se basa en un modelo cliente-servidor. A continuación, se describen los pasos básicos de este proceso:
- El dispositivo cliente, como el ESP32, se conecta a un servidor NTP utilizando UDP en el puerto 123.
- El cliente envía un paquete de solicitud al servidor NTP.
- El servidor responde enviando un paquete de marca de tiempo, que incluye información como la marca de tiempo UNIX, precisión, retraso y zona horaria.
- El cliente extrae la fecha y hora actual del paquete recibido.
Este método permite que los dispositivos obtengan la hora de manera rápida y eficiente, garantizando una sincronización precisa.
Preparación del entorno de programación Arduino
Antes de comenzar a trabajar con el ESP32 en el entorno de Arduino IDE, es necesario asegurarse de que el complemento para ESP32 esté instalado. Si aún no lo has hecho, puedes consultar tutoriales en línea que explican cómo realizar esta instalación.
A continuación, se presenta un código de ejemplo que demuestra cómo obtener la fecha y hora desde un servidor NTP utilizando el ESP32:
#include <WiFi.h>
#include "time.h"
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASS";
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
void printLocalTime()
{
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}
void setup()
{
Serial.begin(115200);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
//disconnect WiFi as it's no longer needed
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
void loop()
{
delay(1000);
printLocalTime();
}
Es esencial realizar algunas modificaciones antes de cargar el código:
- Modifica las variables ssid y password con tus credenciales de red para que el ESP32 pueda conectarse.
- Ajusta el gmtOffset_sec según tu zona horaria. Puedes consultar esta lista de UTC para encontrar el valor correcto. Ejemplos:
- UTC -5.00 : -5 * 60 * 60 : -18000
- UTC +1.00 : 1 * 60 * 60 : 3600
- UTC +0.00 : 0 * 60 * 60 : 0
- Establece el daylightOffset_sec en 3600 si tu región aplica horario de verano; de lo contrario, déjalo en 0.
Una vez que hayas cargado el código, presiona el botón EN en tu ESP32. El monitor serie mostrará la fecha y hora cada segundo.
Explicación del código
Analicemos brevemente cómo funciona el código presentado. Primero, se incluyen las bibliotecas necesarias:
- WiFi.h: Contiene los métodos específicos del ESP32 para conectarse a redes Wi-Fi.
- time.h: Biblioteca nativa del ESP32 que maneja la sincronización con el servidor NTP.
Las constantes definidas incluyen las credenciales de red, el desplazamiento UTC y el desplazamiento del horario de verano.
También se especifica la dirección del servidor NTP:
const char* ntpServer = "pool.ntp.org";
Este servidor selecciona automáticamente servidores de tiempo cercanos a tu ubicación. Sin embargo, si deseas elegir un servidor específico, puedes utilizar uno de los sub-zonas de pool.ntp.org.
Durante la configuración, primero se establece la comunicación serial y luego se conecta a la red Wi-Fi mediante la función WiFi.begin()
.
Serial.begin(115200);
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
Una vez conectado, utilizamos la función configTime()
para inicializar el cliente NTP y obtener la fecha y hora del servidor NTP.
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Finalmente, se llama a la función personalizada printLocalTime()
para mostrar la fecha y hora actual en el monitor serie. Esta función invoca getLocalTime()
, que gestiona la solicitud al servidor NTP y almacena la información en una estructura de tiempo llamada timeinfo.
Obteniendo el tiempo en milisegundos
En algunos proyectos, puede ser necesario obtener la hora en milisegundos en lugar de en un formato legible. Para esto, puedes modificar el código anterior para incluir una función que retorne la hora en milisegundos desde la época UNIX:
unsigned long getMilliseconds()
{
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
return 0; // Error al obtener el tiempo
}
return (timeinfo.tm_hour * 3600 + timeinfo.tm_min * 60 + timeinfo.tm_sec) * 1000;
}
Este método es útil en aplicaciones que requieren un seguimiento más preciso del tiempo, como en sistemas de control o aplicación en tiempo real.
Obteniendo la marca de tiempo
Además de la hora, a menudo es importante obtener una marca de tiempo que se puede utilizar para registros o comparaciones. El siguiente fragmento de código muestra cómo obtener la marca de tiempo actual:
unsigned long getCurrentTimestamp()
{
return (unsigned long)time(nullptr);
}
Esta función devuelve la marca de tiempo UNIX (número de segundos desde el 1 de enero de 1970), que puede ser utilizada para realizar cálculos o almacenar en bases de datos.
Tiempo sin conexión a Internet
En situaciones donde la conectividad a Internet no está disponible, es posible mantener una hora aproximada en el ESP32 utilizando un reloj en tiempo real (RTC) o estimando el tiempo basado en un contador. Sin embargo, esto puede resultar en inexactitudes. Para aplicaciones críticas, se recomienda tener un mecanismo de recuperación, como la sincronización automática una vez que se recupere la conexión.
Ejemplo de aplicación NTP en ESP32
Finalmente, un ejemplo práctico de cómo implementar NTP en un proyecto de ESP32 incluye la integración con un sensor o dispositivo que requiere sincronización horaria. Por ejemplo, un sistema de riego automático que activa las válvulas a horas específicas puede beneficiarse de la precisión de NTP. Con el código anterior, puedes programar el riego en función de la hora obtenida del servidor NTP.
La combinación de un microcontrolador potente como el ESP32 y la capacidad de NTP proporciona una solución robusta para proyectos que requieren un control preciso del tiempo. Esto abre un abanico de posibilidades en la creación de dispositivos IoT, sistemas de automatización y mucho más.
Deja una respuesta
Estos temas te pueden interesar