|

Reloj de Internet: mostrar fecha y hora en OLED con ESP8266 NodeMCU y NTP

PorAbhishek Bakolia 05 de junio de 20190

Reloj de Internet: mostrar fecha y hora en OLED con ESP8266 NodeMCU y NTP

El RTC o reloj de tiempo real es el módulo más utilizado en electrónica y sistemas embebidos para llevar el control del tiempo. Pero el problema del RTC es que los microchips de las computadoras no son tan precisos y solo pueden proporcionar la hora del dispositivo local. Por otro lado, usar Internet para obtener la hora de servidores NTP es una mejor solución, ya que es más precisa y puede proporcionar la hora de cualquier zona geográfica del mundo. Solo necesitamos un módulo Wi-Fi y acceso a Internet para obtener la hora de cualquier lugar del mundo usando servidores NTP. En este tutorial usaremos el ESP8266 NodeMCU para obtener la fecha y hora actuales de servidores NTP y mostrarlas en una pantalla OLED.

Protocolo de Tiempo de Red (NTP)

NTP es uno de los protocolos de Internet (IP) de red más antiguos para sincronizar relojes entre redes de computadoras. Fue diseñado por David L. Mills, de la Universidad de Delaware, en 1981. Este protocolo puede usarse para sincronizar muchas redes con el Tiempo Universal Coordinado (UTC) con una precisión de pocos milisegundos. El UTC es el estándar de tiempo principal por el que el mundo regula el reloj y la hora. El UTC no cambia ni varía según las distintas ubicaciones geográficas. NTP usa el UTC como referencia de tiempo y proporciona una hora precisa y sincronizada a través de Internet.

NTP funciona con un modelo jerárquico cliente-servidor. El modelo superior tiene relojes de referencia conocidos como “stratum0” como relojes atómicos, ondas de radio, GPS y GSM, que reciben la hora del satélite. Los servidores que reciben la hora del stratum0 se llaman “stratum1” y los servidores que reciben la hora del stratum1 se llaman “stratum2” y así sucesivamente. Esto continúa y la precisión del tiempo va disminuyendo después de cada etapa. NTP selecciona automáticamente la mejor de varias fuentes de tiempo disponibles para sincronizarse, lo que lo convierte en un protocolo tolerante a fallos.

Así que en este proyecto vamos a obtener la hora de un servidor NTP usando el ESP8266 NodeMCU y mostrarla en una pantalla OLED. Este mismo tipo de reloj de Internet se construyó usando el ESP32 en un tutorial anterior.

Comunicación entre el servidor UDP y NTP

El ESP8266 puede acceder a servidores NTP mediante Internet para obtener la hora exacta. Aquí NTP funciona en modo cliente-servidorel ESP8266 funciona como dispositivo cliente y se conecta con servidores NTP usando UDP (User Datagram Protocol). El cliente transmite un paquete de solicitud a los servidores NTP y a cambio NTP envía un paquete con marca de tiempo que contiene información como precisión, zona horaria, marca de tiempo UNIX, etc. Luego el cliente separa los detalles de fecha y hora, que pueden usarse posteriormente en aplicaciones según se requiera.

Componentes necesarios

  • Pantalla OLED monocromática SSD1306 de 7 pines y 0.96”
  • ESP8266 NodeMCU
  • Cable micro USB
  • Protoboard
  • Cables de conexión macho a macho

Diagrama del circuito y conexiones

Esta pantalla OLED de 7 pines se comunica con el módulo ESP8266 usando el protocolo SPI; a continuación se muestran el diagrama del circuito y la tabla de conexiones para conectar los pines SPI de la OLED con el NodeMCU y mostrar la hora de Internet.

Diagrama del circuito de conexiones ESP8266 OLED
N.ºPantalla OLEDNodeMCU
1GNDGND
2VDD3.3V
3SCKD5
4MOSI (SPI) o SDA (I2C)D7
5RESETD3
6DCD2
7CSD8

Para saber más sobre esta pantalla OLED monocromática de 7 pines y su conexión con el ESP8266 NodeMCU, sigue el enlace.

Explicación del código

Primero tenemos que descargar e instalar la librería NTP en el ESP8266. Hay muchas librerías disponibles para el cliente NTP. Puedes instalar cualquiera de ellas desde el IDE de Arduino. En este tutorial he instalado la librería NTPClient de Taranais porque es fácil de usar y tiene funciones para obtener la fecha y hora de los servidores NTP. El ESP8266 NodeMCU se puede programar fácilmente usando el IDE de Arduino.

Instalando la librería NTPClient en el IDE de Arduino

Para instalar la librería NTP, primero descarga la librería usando el enlace anterior y luego instálala usando el IDE de Arduino. Para instalarla ve a Sketch > Include Library > Add .ZIP Library, luego abre la carpeta Zip yendo a la ubicación donde descargaste la carpeta zip y reinicia el IDE de Arduino.

Descargando la librería NTPClient para el reloj de Internet
Agregando el Zip de la librería NTPClient a Arduino

La librería NTPClient incluye ejemplos. Abre el IDE de Arduino y ve a Goto Examples > NTPClient > Advanced. El código de este sketch muestra la hora del servidor NTP en el monitor serie. Usaremos este sketch para mostrar la fecha y hora actuales en la pantalla OLED.

Librería NTPClient agregada correctamente para el reloj de Internet

El código completo está disponible al final de este tutorial; aquí he explicado algunas partes importantes del código.

La librería ESP8266WiFi proporciona las rutinas Wi-Fi específicas del ESP8266 para conectarse a la red. WiFiUDP.h maneja el envío y la recepción de paquetes UDP. Como estamos usando el protocolo SPI para conectar la OLED con el NodeMCU, importaremos la librería “SPI.h”. Y “Adafruit_GFX.h” y “Adafruit_SSD1306.h” se usan para la pantalla OLED.

#include <NTPClient.h>
#include <ESP8266WiFi.h> // provides ESP8266 specific Wi-Fi routines we are calling to connect to network
#include <WiFiUdp.h> //handles sending and receiving of UDP packages
#include <SPI.h> // SPI for interfacing OLED with NodeMCU
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

El tamaño de nuestra OLED es 128×64, así que configuramos el ancho y alto de pantalla como 128 y 64 respectivamente. Después define las variables para los pines de la OLED conectados al NodeMCU para la comunicación SPI.

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI   D7
#define OLED_CLK   D5
#define OLED_DC    D2
#define OLED_CS    D8
#define OLED_RESET D3

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

Reemplaza “your_ssid” y “your_password” con el SSID y la contraseña de tu Wi-Fi en las siguientes líneas de código.

const char *ssid     = "your_ssid";
const char *password = "your_password";

Configura la conexión Wi-Fi pasando el SSID y la contraseña a la función WiFi.begin. La conexión del ESP8266 tarda un poco en conectarse al NodeMCU, así que tenemos que esperar hasta que se conecte.

WiFi.begin(ssid, password);
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }

Para solicitar la fecha y la hora, inicializa el cliente de tiempo con la dirección de los servidores NTP. Para mayor precisión elige la dirección de servidores NTP cercanos a tu zona geográfica. Aquí usamos “pool.ntp.org”, que ofrece servidores de todo el mundo. Si deseas elegir servidores de Asia puedes usar “asia.pool.ntp.org”. timeClient también toma el desfase de tiempo UTC en milisegundos de tu zona horaria. Por ejemplo, el desfase UTC de la India es +5:30, así que convertimos este desfase en milisegundos, que equivale a 5*60*60+30*60 = 19800.

ZonaDesfase de tiempo UTC (horas y minutos)Desfase de tiempo UTC (segundos)
INDIA+5:3019800
LONDRES0:000
NUEVA YORK-5:00-18000
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 19800,60000);

Se le pasa SSD1306_SWITCHCAPVCC para generar 3.3V internamente e inicializar la pantalla. Cuando la OLED arranca, muestra “WELCOME TO CIRCUIT DIGEST” con tamaño de texto 2 y color BLUE durante 3 segundos.

if(!display.begin(SSD1306_SWITCHCAPVCC))
  {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(BLUE);
  display.setCursor(5, 2);
  display.println("WELCOME TO");
  display.println("  CIRCUIT");
  display.println("  DIGEST");
  display.display();
  delay(3000);

El cliente NTP se inicializa usando la función  begin() para fijar la fecha y hora desde los servidores NTP.

timeClient.begin();

La función Update() se usa para recibir la fecha y la hora cada vez que hacemos una solicitud a los servidores NTP.

timeClient.update();

Se fija una velocidad de 115200 baudios para imprimir la hora en el monitor serie.

Serial.begin(115200);
Serial.println(timeClient.getFormattedTime());

getHours(), getMinutes(), getSeconds(), getDay son las funciones de la librería y devuelven la hora, los minutos, los segundos y el día actuales del servidor NTP. El código de abajo se usa para diferenciar la hora entre AM y PM. Si la hora que obtenemos con getHours() es mayor que 12, entonces fijamos esa hora como PM; de lo contrario es AM.

int hh = timeClient.getHours();
int mm = timeClient.getMinutes();
int ss = timeClient.getSeconds();
int day = timeClient.getDay();

if(hh>12)
  {
    hh=hh-12;
    display.print(hh);
    display.print(":");
    display.print(mm);
    display.print(":");
    display.print(ss);
    display.println(" PM");
  }
  else
  {
    display.print(hh);
    display.print(":");
    display.print(mm);
    display.print(":");
    display.print(ss);
    display.println(" AM");  
  }
  int day = timeClient.getDay();
  display.println("'"+arr_days[day]+"'");

getFormattedDate() se usa para obtener la fecha en formato “yyyy-mm-dd” desde el servidor NTP. Esta función devuelve la fecha y la hora en formato “yyyy-mm-dd T hh:mm:ss. Pero solo necesitamos la fecha, así que tenemos que dividir esta cadena, que se almacena en formato date_time, hasta la “T”, lo cual se hace con la función substring(), y luego almacenar la fecha en la variable “date”.

date_time = timeClient.getFormattedDate();
  int index_date = date_time.indexOf("T");
  String date = date_time.substring(0, index_date);
  Serial.println(date);
  display.println(date);
  display.display();     

Así es como se verá finalmente el reloj de Internet OLED:

Reloj de Internet DIY con ESP8266

Código

#include <NTPClient.h>
#include <ESP8266WiFi.h> // provides ESP8266 specific Wi-Fi routines we are calling to connect to network
#include <WiFiUdp.h> //handles sending and receiving of UDP packages
#include <SPI.h> // SPI for interfacing OLED with NodeMCU
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI   D7
#define OLED_CLK   D5
#define OLED_DC    D2
#define OLED_CS    D8
#define OLED_RESET D3
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

const char *ssid     = “CircuitLoop”;
const char *password = “circuitdigest101”;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, “pool.ntp.org”, 19800,60000);
String arr_days[]={“Sunday”,”Monday”,”Tuesday”,”Wednesday”,”Thursday”,”Friday”,”Saturday”};
String date_time;
// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
  

void setup(){
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( “.” );
  }

  if(!display.begin(SSD1306_SWITCHCAPVCC))
  {
    Serial.println(F(“SSD1306 allocation failed”));
    for(;;); // Don’t proceed, loop forever
  }
  display.clearDisplay();
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(5, 2);
  display.println(“WELCOME TO”);
  display.println(”  CIRCUIT”);
  display.println(”  DIGEST”);
  display.display();
  delay(3000);
  timeClient.begin();
}

void loop() {
  timeClient.update();
  
  display.clearDisplay();
  
  Serial.println(timeClient.getFormattedTime());
  
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(BLUE);
  display.setCursor(0, 2);
  int hh = timeClient.getHours();
  int mm = timeClient.getMinutes();
  int ss = timeClient.getSeconds();
  
  if(hh>12)
  {
    hh=hh-12;
    display.print(hh);
    display.print(“:”);
    display.print(mm);
    display.print(“:”);
    display.print(ss);
    display.println(” PM”);
  }
  else
  {
    display.print(hh);
    display.print(“:”);
    display.print(mm);
    display.print(“:”);
    display.print(ss);
    display.println(” AM”);   
  }

  int day = timeClient.getDay();
  display.println(“‘”+arr_days[day]+”‘”);
  
  date_time = timeClient.getFormattedDate();
  int index_date = date_time.indexOf(“T”);
  String date = date_time.substring(0, index_date);
  Serial.println(date);
  display.println(date);
  display.display();      // Show initial text
}

Artículo traducido al español. Fuente original: Internet Clock: Display Date and Time on OLED using ESP8266 NodeMCU with NTP — CircuitDigest

Similar Posts

Deja un comentario