Obtener la fecha y hora del servidor NTP con ESP32


De vez en cuando se encontrará con una idea en la que mantener el tiempo es una preocupación principal. Por ejemplo, imagine un relé que debe activarse en un momento determinado o un registrador de datos que debe almacenar valores en intervalos precisos.

Lo primero que se te viene a la mente es usar un chip RTC (Real Time Clock). Pero estos chips no son perfectamente precisos, por lo que debe realizar ajustes manuales una y otra vez para mantenerlos sincronizados.

La solución aquí es usar Network Time Protocol (NTP). Si su proyecto ESP32 tiene acceso a Internet, puede obtener la fecha y la hora (con una precisión de unos pocos milisegundos de UTC) GRATIS . No necesita ningún hardware adicional.

¿Qué es un NTP?

Un NTP significa Network Time Protocol . Es un Protocolo de Internet (IP) estándar para sincronizar los relojes de la computadora con alguna referencia a través de una red.

El protocolo se puede usar para sincronizar todos los dispositivos en red con el tiempo universal coordinado (UTC) en unos pocos milisegundos (50 milisegundos en la Internet pública y menos de 5 milisegundos en un entorno LAN).

El tiempo universal coordinado (UTC) es un estándar de tiempo mundial, estrechamente relacionado con GMT (hora del meridiano de Greenwich). UTC no varía, es el mismo en todo el mundo.

NTP establece los relojes de las computadoras en UTC, el cliente aplica cualquier compensación de zona horaria local o compensación de horario de verano. De esta manera, los clientes pueden sincronizarse con los servidores independientemente de las diferencias de ubicación y zona horaria.

Arquitectura NTP

NTP utiliza una arquitectura jerárquica. Cada nivel de la jerarquía se conoce como estrato .

En la parte superior se encuentran los dispositivos de cronometraje de alta precisión, como relojes atómicos, GPS o relojes de radio, conocidos como relojes de hardware de estrato

Los servidores Stratum 1 tienen una conexión directa a un reloj de hardware stratum 0 y, por lo tanto, tienen la hora más precisa.

Arquitectura jerárquica NTP con estratos

Cada estrato en la jerarquía se sincroniza con el estrato superior y actúa como servidor para las computadoras del estrato inferior.

¿Cómo funciona NTP?

NTP puede funcionar de varias maneras. La configuración más habitual es la de operar en modo cliente-servidor . El principio básico de funcionamiento es el siguiente:

  1. El dispositivo cliente, como ESP32, se conecta al servidor mediante el Protocolo de datagramas de usuario (UDP) en el puerto 123.
  2. Luego, un cliente transmite un paquete de solicitud a un servidor NTP.
  3. En respuesta a esta solicitud, el servidor NTP envía un paquete de marca de tiempo.
  4. Un paquete de marca de tiempo contiene información múltiple, como la marca de tiempo UNIX, la precisión, el retraso o la zona horaria.
  5. Luego, un cliente puede analizar los valores de fecha y hora actuales.
Funcionamiento del servidor NTP: transferencia de paquetes de solicitud y marca de tiempo

Obtener fecha y hora del servidor NTP

El siguiente esquema le brindará una comprensión completa de cómo obtener la fecha y la hora del servidor NTP.

Antes de subir el boceto, debe realizar algunos cambios para que funcione para usted.

  • Debe modificar las siguientes dos variables con sus credenciales de red, para que ESP32 pueda establecer una conexión con la red existente.const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASS";
  • Debe ajustar el desplazamiento UTC para su zona horaria en milisegundos. Consulte la lista de compensaciones de tiempo UTC . Aquí hay algunos ejemplos para diferentes zonas horarias:
    • Para UTC -5.00 : -5 * 60 * 60 : -18000
    • Para UTC +1.00 : 1 * 60 * 60 : 3600
    • Para UTC +0.00 : 0 * 60 * 60 : 0
    const long gmtOffset_sec = 3600;
  • Cambie la compensación de la luz del día en milisegundos. Si su país observa el horario de verano , configúrelo en 3600. De lo contrario, configúrelo en 0.const int daylightOffset_sec = 3600;

Una vez que haya terminado, continúe y pruebe el boceto.

#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();
}

Después de cargar el boceto, presione el botón EN en su ESP32 y debería obtener la fecha y la hora cada segundo, como se muestra a continuación.

ESP32 lee la fecha y la hora de la salida del servidor NTP en el monitor serie

Código Explicación

Echemos un vistazo rápido al código para ver cómo funciona. Primero, incluimos las bibliotecas necesarias para este proyecto.

  • La biblioteca WiFi.h proporciona métodos WiFi específicos de ESP32 que llamamos para conectarse a la red.
  • time.h es la biblioteca de tiempo nativo de ESP32 que realiza una sincronización elegante del servidor NTP.
#include <WiFi.h>
#include "time.h"

A continuación, configuramos algunas constantes como SSID, contraseña WiFi, UTC Offset y Daylight offset que ya conoce.

Junto con eso, debemos especificar la dirección del servidor NTP que deseamos usar. pool.ntp.org es un proyecto NTP abierto ideal para cosas como esta.

const char* ntpServer = "pool.ntp.org";

El pool.ntp.org selecciona automáticamente los servidores de tiempo que están geográficamente cerca de usted. Pero si desea elegir explícitamente, use una de las subzonas de pool.ntp.org.

ÁreaNombre de host
En todo el mundopiscina.ntp.org
Asiaasia.pool.ntp.org
Europaeuropa.pool.ntp.org
América del nortenorteamerica.pool.ntp.org
Oceaníaoceania.pool.ntp.org
Sudamericasudamerica.pool.ntp.org

En la sección de configuración, primero inicializamos la comunicación en serie con la PC y nos unimos a la red WiFi usando la WiFi.begin()función.

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");

Una vez que ESP32 está conectado a la red, inicializamos el cliente NTP usando la configTime()función para obtener la fecha y la hora de un servidor NTP.

//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

Ahora podemos simplemente llamar a la printLocalTime()función personalizada cada vez que queramos imprimir la fecha y hora actuales.

getLocalTime()La función se utiliza para transmitir un paquete de solicitud a un servidor NTP y analizar el paquete de marca de tiempo recibido en un formato legible. Toma la estructura del tiempo como parámetro.

Puede acceder a la información de fecha y hora accediendo a los miembros de esta estructura de tiempo.

%Adevuelve el día de la semana
%Bdevuelve el mes del año
%ddevuelve el día del mes
% Yaño de retorno
%Hhora de regreso
%Mdevuelve minutos
%Sdevuelve segundos
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");
}