Construye un reloj Wi-Fi con ESP32 y pantalla TM1637

¿Te imaginas tener un reloj digital que nunca necesites ajustar, incluso después de un apagón o un cambio de horario de verano? En este artículo, te mostraremos cómo construir un reloj digital completamente automatizado y sincronizado con internet utilizando un ESP32 y un display de 7 segmentos TM1637. Este reloj no solo mantendrá la hora precisa hasta el segundo, sino que también te permitirá aprender sobre la conectividad y la programación en el proceso. ¡Vamos a empezar!

Índice de contenido
  1. Materiales necesarios para el proyecto
  2. Descripción del proyecto
  3. Lecturas recomendadas
  4. Conexión del módulo TM1637 al ESP32
  5. Configuración del entorno de desarrollo Arduino IDE
  6. Instalación de la biblioteca necesaria
  7. Subiendo el código al ESP32
  8. Demostración del funcionamiento
  9. Explicación del código

Materiales necesarios para el proyecto

Para llevar a cabo este proyecto, necesitarás reunir los siguientes componentes:

  • Placa de desarrollo ESP32
  • Módulo de visualización TM1637 de 4 dígitos
  • Wires de conexión (jumper wires)
  • Un cable USB compatible con tu placa ESP32
  • Ordenador para subir el programa
  • Una placa de pruebas (breadboard) opcional para facilitar las conexiones y pruebas

Descripción del proyecto

El primer paso es conectar el ESP32 a tu red Wi-Fi local. Una vez conectado, se comunicará con un servidor NTP (Network Time Protocol) altamente preciso a través del Protocolo de Datagramas de Usuario (UDP) en el puerto 123 para obtener la hora actual. La placa enviará un paquete de solicitud al servidor, el cual responderá con un paquete de marca de tiempo. El ESP32 leerá la hora actual a partir de esa respuesta y aplicará la zona horaria local y las reglas de horario de verano, convirtiendo así el tiempo global en la hora local correcta.

Una vez establecido el tiempo local correcto, el ESP32 almacenará esta información y comenzará a llevar el tiempo de manera interna. No se volverá a conectar al servidor NTP cada segundo; en su lugar, utilizará su propio temporizador interno para mantener la hora una vez completada la sincronización inicial.

Finalmente, actualizará el display TM1637 cada segundo para mostrar la hora actual, haciendo parpadear el punto central para indicar que el reloj está en funcionamiento.

Lecturas recomendadas

Antes de avanzar con este proyecto, es recomendable revisar algunos tutoriales que te ayudarán a comprender los conceptos básicos sobre el uso del display TM1637 con el ESP32 y el proceso de obtención de la hora desde internet utilizando un servidor NTP. Algunos recursos útiles incluyen:

Conexión del módulo TM1637 al ESP32

Es momento de conectar el módulo TM1637 al ESP32. Sigue las instrucciones a continuación para realizar las conexiones adecuadas:

  • Conecta el pin VCC del módulo TM1637 al pin VIN del ESP32.
  • Conecta el pin GND del módulo a un pin GND del ESP32.
  • Conecta el pin CLK del módulo al GPIO 26 del ESP32.
  • Conecta el pin DIO del módulo al GPIO 25 del ESP32.

A continuación, se muestra un esquema de referencia para las conexiones:

Pin TM1637Conexión ESP32
VCCVIN
GNDGND
CLKGPIO 26
DIOGPIO 25

Configuración del entorno de desarrollo Arduino IDE

Utilizaremos el entorno de desarrollo Arduino IDE para programar el ESP32. Asegúrate de tener instalado el complemento para ESP32 antes de continuar con los siguientes pasos. Si no lo has hecho, puedes seguir las instrucciones que se encuentran en la documentación oficial de ESP32.

Instalación de la biblioteca necesaria

Para comunicarte con el chip TM1637, necesitarás usar una biblioteca específica. Una opción muy recomendada es la TM1637Display library, creada por Avishay Orpaz. Esta biblioteca incluye muchas funciones integradas que facilitan el control del display.

Para instalar la biblioteca, sigue estos pasos:

  1. Abre tu programa Arduino IDE.
  2. Haz clic en el icono de Gestor de Bibliotecas en la barra lateral izquierda.
  3. Escribe "tm1637" en el cuadro de búsqueda para filtrar tus resultados.
  4. Busca la biblioteca TM1637 de Avishay Orpaz.
  5. Haz clic en el botón Instalar para añadirla a tu Arduino IDE.

Una vez que la biblioteca esté instalada, ¡estarás listo para programar!

Subiendo el código al ESP32

Ahora es el momento de copiar el siguiente código en tu Arduino IDE. Antes de subirlo al ESP32, hay algunos cambios importantes que debes realizar para asegurarte de que todo funcione correctamente:

  1. Primero, actualiza las siguientes dos variables con tus credenciales de red para que el ESP32 pueda conectarse a tu red:
    const char* ssid = "TU_SSID";
    const char* password = "TU_CONTRASENA";
  2. Luego, cambia la cadena de la zona horaria para que coincida con tu región. Puedes encontrar una lista de cadenas de zona horaria en este recurso de GitHub:
    const char* tzInfo = "EST5EDT,M3.2.0,M11.1.0";

Después de realizar estos cambios, procede a subir el código.

#include 
#include 

Demostración del funcionamiento

Después de subir el código, presiona el botón EN (reset) en tu ESP32. Si todo está configurado correctamente, deberías ver la hora actual mostrada en el display TM1637 cada segundo.

Para verificar que el reloj esté funcionando correctamente, puedes comparar la salida con la hora actual en EST de una búsqueda en Google. Si todo está bien, la hora en el display TM1637 coincidirá con el resultado de la búsqueda, confirmando que el ESP32 se ha sincronizado con el servidor NTP y está manteniendo la hora local de manera precisa.

Explicación del código

El código comienza incluyendo tres bibliotecas importantes. La biblioteca WiFi.h permite que el ESP32 se conecte a la red Wi-Fi. La biblioteca time.h ayuda al ESP32 a comunicarse con el servidor NTP y formatear la hora en un formato legible. La biblioteca TM1637Display.h es la encargada de controlar el módulo de visualización TM1637.

#include 
#include 

A continuación, definimos dos variables para tu conexión Wi-Fi: una para el nombre de la red (SSID) y otra para la contraseña. Este paso es crucial ya que el ESP32 necesita acceso a internet para llegar al servidor NTP y obtener la hora correcta, por lo que es necesario reemplazar el texto de marcador de posición con tus credenciales reales.

const char* ssid = "TU_SSID";
const char* password = "TU_CONTRASENA";

Luego, configuramos dos diferentes servidores NTP, pool.ntp.org y time.nist.gov. Estos indican a nuestro ESP32 exactamente dónde en internet debe buscar la hora correcta.

const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";

Usamos “pool.ntp.org”, que es en realidad un enorme clúster global de servidores de tiempo, como nuestro reloj principal. También hemos añadido “time.nist.gov” como una copia de seguridad altamente confiable. Proporcionamos dos servidores distintos para que, si uno se desconecta o se vuelve temporalmente inalcanzable, nuestro reloj pueda consultar al segundo y seguir funcionando sin problemas.

Si encuentras que un servidor en particular está bloqueado en tu red o simplemente prefieres uno regional, puedes sustituir estas direcciones web por otras locales que funcionen mejor para tu configuración específica.

Después de definir los servidores, necesitamos indicarle al ESP32 cómo ajustar esa hora global de internet para que coincida con nuestra hora local. Hacemos esto configurando una cadena de información de zona horaria en tzInfo.

En este ejemplo, la zona horaria está configurada para la Hora Estándar del Este de EE. UU., con ajuste automático para el horario de verano. Si deseas que el reloj muestre la hora correcta para tu ubicación, debes cambiar esta cadena de zona horaria para que coincida con tu región. Puedes encontrar una lista de cadenas de zona horaria en este recurso de GitHub.

const char* tzInfo = "EST5EDT,M3.2.0,M11.1.0";

Luego, definimos los pines del ESP32 conectados al display TM1637: CLK se establece en GPIO 26 y DIO se establece en GPIO 25.

#define CLK 26
#define DIO 25

A continuación, creamos un objeto display de la clase TM1637Display. Este objeto nos permite enviar comandos al TM1637. Cuando creamos el objeto, debemos indicarle cuáles son los dos pines que estamos utilizando.

TM1637Display display(CLK, DIO);

La función connectWiFi() es responsable de conectar el ESP32 a la red Wi-Fi. Primero, configuramos el ESP32 en modo estación utilizando WiFi.mode(WIFI_STA). Esto le indica al ESP32 que se conecte a una red Wi-Fi existente en lugar de crear la suya propia. Luego, iniciamos el proceso de conexión utilizando la función WiFi.begin(). Después, seguimos revisando el estado del Wi-Fi dentro de un bucle. Mientras la placa no esté conectada, esperamos medio segundo y volvemos a comprobar.

void connectWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

La función syncTime() se encarga de obtener la hora correcta. Primero llamamos a configTime(0, 0, ntpServer1, ntpServer2) para iniciar la sincronización NTP usando los dos servidores que definimos anteriormente. Los dos ceros significan que no estamos aplicando un desplazamiento UTC fijo aquí, ya que el manejo de la zona horaria se hace por separado. Después, establecemos la variable de entorno de la zona horaria con setenv("TZ", tzInfo, 1) y la aplicamos utilizando tzset(). Esto asegura que el ESP32 sepa cómo interpretar la hora local correctamente.

Para asegurarnos de tener realmente una hora válida descargada antes de continuar, comparamos la hora interna actual con una fecha pasada conocida; en este caso, el timestamp Unix para el 1 de enero de 2020. Si nuestra hora interna es anterior a esa fecha, sabemos que la sincronización por internet no ha finalizado, así que esperamos un momento y seguimos revisando hasta que se actualice.

void syncTime() {
  configTime(0, 0, ntpServer1, ntpServer2);
  setenv("TZ", tzInfo, 1);
  tzset();

  time_t now = 0;
  while (time(&now) < 1577836800) {
    delay(500);
  }
}

La lógica principal de nuestro reloj reside en la función displayTime(). Primero, creamos una variable booleana estática llamada colonOn para rastrear el estado de nuestro dos puntos; cada vez que se ejecuta esta función, alternamos su estado para obtener un agradable efecto de parpadeo cada segundo.

Luego pedimos al ESP32 que llene nuestra estructura de tiempo con la hora local actual. Si, por alguna razón, no podemos obtenerla, simplemente limpiamos la pantalla y salimos de la función para no mostrar datos incorrectos.

Suponiendo que obtenemos la hora con éxito, extraemos la hora y el minuto actuales. Para mostrar esto en nuestra pantalla, combinamos estos dos números en un único valor de cuatro dígitos multiplicando las horas por cien y sumando los minutos. Por ejemplo, si son las 9:05, esta operación lo convierte en 905. Posteriormente, creamos una máscara de bits específica que activa o desactiva el dos puntos central en función de nuestro estado de alternancia.

Finalmente, enviamos este valor combinado y el estado del dos puntos al display, asegurándonos de indicarle que mantenga los ceros iniciales para que horas como 6:04 se muestren correctamente en los cuatro dígitos.

void displayTime() {
  static bool colonOn = false;  
  colonOn = !colonOn;           

  struct tm timeinfo;
  if (!getLocalTime(&timeinfo, 2000)) {
    display.clear();  
    return;
  }

  int hours = timeinfo.tm_hour;   
  int minutes = timeinfo.tm_min;  

  int value = hours * 100 + minutes;

  uint8_t colonMask = colonOn ? 0b01000000 : 0;

  display.showNumberDecEx(value, colonMask, true);
}

En la sección de configuración, preparamos todo una vez cuando la placa arranca. Primero, establecemos el brillo del display en 5 utilizando la función setBrightness(). Dado que el rango válido es de 0 a 7, esto proporciona un nivel de brillo medio. Luego, limpiamos el display para que comience en blanco. Después de eso, llamamos a connectWiFi() para unirnos a la red y luego llamamos a syncTime() para obtener la hora actual de internet.

void setup() {
  display.setBrightness(5);
  display.clear();

  connectWiFi();
  syncTime();
}

Finalmente, en la sección de bucle, simplemente actualizamos la hora en el display cada segundo.

void loop() {
  displayTime();
  delay(1000);
}

Carlos Julián

Carlos Julián es el fundador de Ingtelecto, es Ingeniero Mecatrónico, Profesor y Programador, cuenta con una Maestria en Ciencias de la Educación, creador de contenido educativo en redes sociales. Lee más sobre mi trayectoria aquí.

Estos temas te pueden interesar

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Tu puntuación: Útil

Subir