We’ll learn how to use the ESP32 and Arduino IDE to request date and time from an NTP server. In data recording applications, getting the date and time helps timestamp readings. The ESP32 requires an Internet connection to obtain time from an NTP server, but no additional hardware is required.

NTP (Network Time Protocol)

Network Time Protocol (NTP) is a networking protocol that allows computer systems to synchronise their clocks. In other words, it is utilised in a network to synchronise computer clock times.

NTP servers, such as pool.ntp.org, allow anyone to request time as a client. The ESP32 is an NTP Client in this example, requesting time from an NTP Server (pool.ntp.org).

NTP SERVER ARCHITECTURE

The NTP Server is built on a three-level hierarchical structure, each referred to as a stratum. There are precise atomic/radio clocks that offer the exact time on the first level (Stratum 0). The second level (Stratum 1) is linked directly to the first level and contains the most precise time accessible from the first level. The device at the third and final level (Stratum 2) requests the date/time from the second level from the NTP server. Each level in the hierarchy synchronises with the level above it.

NTP SERVER WORKING

The server will use a client-server model to obtain the date and time with our ESP32 via the NTP server. We’ll utilise the pool.ntp.org NTP server, which is readily available from anywhere on the planet. The client will be our ESP32 development board, which will connect to the NTP server over UDP on port 123. The server (pool.ntp.org) will be able to connect to the client using this port. After the connection is established, the ESP32 will submit a request to the server. When the NTP gets the request, it sends the time stamp containing the time and date information.

Getting Date and Time from NTP Server

You don’t need to install any libraries to get date and time with the ESP32. To use the time.h library, simply include it in your code.

The code below obtains date and time from the NTP Server and displays the information on the Serial Monitor. It was created using the time.h library’s example as a guide.

CODE

#include <WiFi.h>
#include "time.h"

const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 3600;

void setup(){
  Serial.begin(115200);

  // Connect to Wi-Fi
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi 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();
}

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");
  Serial.print("Day of week: ");
  Serial.println(&timeinfo, "%A");
  Serial.print("Month: ");
  Serial.println(&timeinfo, "%B");
  Serial.print("Day of Month: ");
  Serial.println(&timeinfo, "%d");
  Serial.print("Year: ");
  Serial.println(&timeinfo, "%Y");
  Serial.print("Hour: ");
  Serial.println(&timeinfo, "%H");
  Serial.print("Hour (12 hour format): ");
  Serial.println(&timeinfo, "%I");
  Serial.print("Minute: ");
  Serial.println(&timeinfo, "%M");
  Serial.print("Second: ");
  Serial.println(&timeinfo, "%S");

  Serial.println("Time variables");
  char timeHour[3];
  strftime(timeHour,3, "%H", &timeinfo);
  Serial.println(timeHour);
  char timeWeekDay[10];
  strftime(timeWeekDay,10, "%A", &timeinfo);
  Serial.println(timeWeekDay);
  Serial.println();
}

HOW CODE WORKS

First, include the libraries to connect to Wi-Fi and get time.

#include <WiFi.h>
#include “time.h”

Setting SSID and Password

Type your network credentials in the following variables so that the ESP32 can establish an Internet connection and get the date and time from the NTP server.

// Replace with your network credentials

const char* ssid = “REPLACE_WITH_YOUR_SSID”;
const char* password = “REPLACE_WITH_YOUR_PASSWORD”;

NTP Server and Time Settings

Then, you need to define the following variables to configure and get time from an NTP server: ntpServer, gmtOffset_sec and daylightOffset_sec.

NTP Server

We’ll request the time from pool.ntp.org, a cluster of timeservers that anyone can use to request the time.

const char* ntpServer = “pool.ntp.org”;

GMT Offset

The gmtOffset_sec variable defines the offset in seconds between your time zone and GMT. We live in Portugal, so the time offset is 0. Change the time gmtOffset_sec variable to match your time zone.

const long gmtOffset_sec = 0;

Daylight Offset

The daylightOffset_sec variable defines the offset in seconds for daylight saving time. It is generally one hour, that corresponds to 3600 seconds

const int daylightOffset_sec = 3600;

setup()

In the setup() you initialize the Serial communication at baud rate 115200 to print the results:

Serial.begin(115200);
// Connect to Wi-Fi
Serial.print(“Connecting to “);
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(“.”);
}
Serial.println(“”);
Serial.println(“WiFi connected.”);
Configure the time with the settings you’ve defined earlier:
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

PrintLocalTime()

After configuring the time, call the printLocalTime() function to print the time in the Serial Monitor.

In that function, create a time structure (struct tm) called timeinfo that contains all the details about the time (min, sec, hour, etc…).

struct tm timeinfo;

The tm structure contains a calendar date and time broken down into its components:

  • tm_sec: seconds after the minute;
  • tm_min: minutes after the hour;
  • tm_hour: hours since midnight;
  • tm_mday: day of the month;
  • tm_year: years since 1900;
  • tm_wday: days since Sunday;
  • tm_yday: days since January 1;
  • tm_isdst: Daylight Saving Time flag;

Get all the details about date and time and save them on the timeinfo structure.

if(!getLocalTime(&timeinfo)){
  Serial.println(“Failed to obtain time”);
  return;
}

Then, print all details about the time in the Serial Monitor.

Serial.println(&timeinfo, “%A, %B %d %Y %H:%M:%S”);
Serial.print(“Day of week: “);
Serial.println(&timeinfo, “%A”);
Serial.print(“Month: “);
Serial.println(&timeinfo, “%B”);
Serial.print(“Day of Month: “);
Serial.println(&timeinfo, “%d”);
Serial.print(“Year: “);
Serial.println(&timeinfo, “%Y”);
Serial.print(“Hour: “);
Serial.println(&timeinfo, “%H”);
Serial.print(“Hour (12 hour format): “);
Serial.println(&timeinfo, “%I”);
Serial.print(“Minute: “);
Serial.println(&timeinfo, “%M”);
Serial.print(“Second: “);
Serial.println(&timeinfo, “%S”);

To access the members of the date and time structure you can use the following specifiers:

%AFull weekday name
%BFull month name
%dDay of the month
%YYear
%HAn hour in 24h format
%IAn hour in 12h format
%MMinute
%SSecond

Other specifiers, such as abbreviated month name (per cent b), abbreviated weekday name (per cent a), week number with the first Sunday as the first day of week one (per cent U), and others, can be used to retrieve information in a different format (read more).

We also offer you an example if you wish to keep time information in variables. Create a char variable with a length of three characters if you wish to save the hour into a variable called timeHour (it must save the hour characters plus the terminating character). Then, using the strftime() method, copy the information about the hour from the timeinfo structure into the timeHour variable.

Serial.println(“Time variables”);
char timeHour[3];
strftime(timeHour,3, “%H”, &timeinfo);
Serial.println(timeHour);

To get other variables, use a similar process. For example, for the weekday, we need to create a char variable with a length of 10 characters because the longest day of the week contains nine characters (Saturday).

char timeWeekDay[10];
strftime(timeWeekDay,10, “%A”, &timeinfo);
Serial.println(timeWeekDay);
Serial.println();

DEMONSTRATION

You can test the example after inputting your network credentials and changing the variables to alter your timezone and daylight saving time.

The code should be uploaded to your ESP32 board. Make sure you’re using the correct board and COM port. Press the ESP32 “Enable” button after uploading the code, and you should obtain the date and time every second.

CONCLUSION

We learnt how to receive date and time from an NTP server using an ESP32 programmed with the Arduino IDE in this lesson. You may now utilise what you’ve learned to date sensor readings in your own projects using you’ve learned here.

Only if the ESP32 is connected to the Internet will this method function. If your project does not have internet connectivity, you will need to use another approach.

author avatar
Aravind S S