ESP32 Essential Guide – Network Section – WiFi Chapter – 0 – 2 – Fetching Essential Online Data with the ESP32

Home / Tutorial / ESP32 Tutorials / ESP32 Essential Guide / Network / WiFi Chapter

AvantMaker.com Article ID
E32-T-EEG-N-W-0-2

1 – Introduction

In our previous article, “How to Connect ESP32 to WiFi” we explored the steps to get your ESP32 board connected to WiFi. However, simply being connected to WiFi isn’t enough to unlock the full potential of this powerful microcontroller. For the ESP32 to shine in real-world projects, it needs to interact with the online world and fetch useful data. In this third installment of the ESP32 WiFi Chapter from the ESP32 Essential Guide, we’ll dive into a practical example: using the ESP32 to retrieve one of the most fundamental pieces of information for many IoT projects—time.

2 – Why Time?

Time might seem like a small detail, but it’s a cornerstone for many IoT projects. Here’s why it matters:

  • Scheduling Tasks: Whether it’s turning on a sprinkler system at dawn or logging sensor data every hour, knowing the current time keeps everything on track.
  • Data Logging: When your ESP32 records temperature or humidity, attaching a timestamp makes that data meaningful for later analysis.
  • User Interaction: Displaying the time on a screen or syncing actions with a user’s routine—like a morning alarm—makes your project more practical.
  • Coordination: In setups with multiple devices, synchronized time ensures they work together smoothly, like a team passing a ball without dropping it.

This article is just the beginning of our journey into the ESP32’s online capabilities. The example we’ll walk through here is like a stepping stone—once you’ve got this down, more exciting and hands-on projects are waiting for you to explore!

3 – Ways of Getting Time Online

The ESP32 can fetch the current time from the internet in several ways. Here are the main methods:

  • API (Application Programming Interface): An API is like a waiter at a restaurant—you ask for something (like the time), and it brings it to you in a neat package. APIs are incredibly useful for the ESP32 to grab all sorts of online information, not just time. We’ll dive deeper into using APIs with the ESP32 in a later chapter of this tutorial.
  • NTP (Network Time Protocol): NTP is a system built specifically to sync clocks over the internet. It’s like a global timekeeper, ensuring devices everywhere stay on the same page by connecting to special time servers.
  • Web Services: Some websites offer time data through simpler web requests. It’s like checking a clock on a webpage. This method is straightforward but may not be as precise as NTP.

There are many ways to get time online, and we won’t list them all here. For this article, we’ll focus on using the NTP (Network Time Protocol) service to demonstrate how the ESP32 can retrieve online time information.

4 – What is NTP and Why We Choose NTP?

NTP, or Network Time Protocol, is a method designed to keep clocks in sync across the internet. It works by connecting your device—like the ESP32—to a network of time servers that are constantly updated to reflect the accurate time. Think of it as a worldwide clock that your project can tap into whenever it needs to know, “What time is it?”

We’re choosing NTP for this tutorial for a few key reasons:

  • Accuracy: NTP can provide very accurate time, often within milliseconds of Coordinated Universal Time (UTC).
  • Reliability: NTP is very reliable because it uses a network of servers maintained by experts and synced with super-accurate atomic clocks. Even if one server is off, others step in to keep the time correct.
  • Simplicity: For beginners, NTP is easy to implement with the ESP32 using built-in libraries, so you can focus on learning rather than wrestling with complex code.
  • Wide Availability: NTP servers are free to use and accessible globally, making it a practical choice no matter where you are.
  • Low Resource Use: It’s lightweight, meaning it won’t overload the ESP32’s memory or processing power, leaving room for other tasks in your project.

5 – Example Code

Now, let’s get hands-on with some code! Below is an example that enables your ESP32 to fetch the current time from an NTP server and display it through the Serial Monitor. Before diving into the details, take a moment to read through the code on your own. Don’t worry if parts of it feel tricky; we’ll break it all down step-by-step in the following sections.

/*
 * Author: Avant Maker
 * Date: February 7, 2025
 * Version: 1.0
 * Description: This code is designed for ESP32 to fetch the 
 * current time and date from an NTP server and display
 * it on the serial monitor.
 * License: MIT 
 * Code Source:
 * This example code is sourced from the Comprehensive Guide
 * to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
 * For additional code examples and in-depth documentation related to
 * the ESP32 Arduino Core Library, please visit:
 *
 * https://avantmaker.com/home/all-about-esp32-arduino-core-library/
 *
 * AvantMaker.com, your premier destination for all things
 * DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
 * to empowering makers, learners, and enthusiasts with
 * the resources they need to bring their nnovative ideas to life.
 */
#include <WiFi.h>
#include <time.h>

// WiFi credentials
const char* ssid = "YOUR-WIFI-SSID"; // Replace with your WiFi SSID
const char* password = "YOUR-WIFI-PASSWORD"; // Replace with your WiFi password

// NTP server settings
const char* ntpServer = "pool.ntp.org"; // Public NTP server for time synchronization
const char* timezone = "EST5EDT,M3.2.0,M11.1.0"; // Eastern Time with DST rules (USA/Canada)

// Alternative timezones you can use (uncomment the one you want):
// const char* timezone = "CST6CDT,M3.2.0,M11.1.0";  // Central Time with DST
// const char* timezone = "MST7MDT,M3.2.0,M11.1.0";  // Mountain Time with DST
// const char* timezone = "PST8PDT,M3.2.0,M11.1.0";  // Pacific Time with DST

void setup() {
  Serial.begin(115200); // Initialize serial communication for debugging

  // Connect to WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password); // Attempt to connect to the specified WiFi network

  while (WiFi.status() != WL_CONNECTED) { // Wait until connected to WiFi
    delay(500); // Wait for 500 milliseconds
    Serial.print("."); // Print a dot to indicate progress
  }

  Serial.println("");
  Serial.println("WiFi connected"); // Indicate successful WiFi connection

  // Setup the time zone
  setTimeZone(); 
  Serial.println("Time configured. Now ready to display date and time...");
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) { // Check if WiFi is still connected
    Serial.print("Current Time: ");
    Serial.println(getCurrentTimeString());
    Serial.print("Current Date: ");
    Serial.println(getCurrentDateString());
  } else {
    Serial.println("WiFi Disconnected"); // Indicate WiFi disconnection
    WiFi.begin(ssid, password); // Attempt to reconnect to WiFi
  }

  // Wait 10 seconds before updating again
  delay(10000); // Delay for 10 seconds (10000 milliseconds)
}

void setTimeZone() {
  configTime(0, 0, ntpServer); // Get UTC time from the NTP server (0 offset for UTC)
  setenv("TZ", timezone, 1); // Set the timezone environment variable
  tzset(); // Apply the timezone setting
}

String getCurrentTimeString() {
  struct tm timeinfo; // Structure to hold time information
  if (!getLocalTime(&timeinfo)) { // Attempt to get the local time
    return "Failed to get time"; // Return an error message if time retrieval fails
  }
  char timeStr[9]; // Character array to store the formatted time string (HH:MM:SS\0)
  strftime(timeStr, sizeof(timeStr), "%H:%M:%S", &timeinfo);// Format the time string
  // strftime() formats the time according to the specified format string.
  // %H: Hour (24-hour format, 00-23)
  // %M: Minute (00-59)
  // %S: Second (00-59)
  // timeinfo: The time structure containing the time data.
  return String(timeStr);
}

String getCurrentDateString() {
  struct tm timeinfo; // Structure to hold time information
  if (!getLocalTime(&timeinfo)) { // Attempt to get the local date
    return "Failed to get date";  // Return an error message if date retrieval fails
  }
  char dateStr[11]; // Character array to store the formatted date string (YYYY-MM-DD\0)
  strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", &timeinfo);// Format the date string
  // strftime() formats the date according to the specified format string.
  // %Y: Year (4 digits, e.g., 2023)
  // %m: Month (01-12)
  // %d: Day of the month (01-31)
  // timeinfo: The time structure containing the date data.  
  return String(dateStr);
}

5.1 – Example Code Explanation

This code is designed for ESP32 to fetch the current time and date from an NTP server and display it on the serial monitor.

It starts by including necessary libraries for WiFi and time functions. You’ll need to input your WiFi network credentials in the designated placeholders. The code then defines settings for the NTP server and your desired timezone.

In the setup() function, it initializes serial communication, connects to your WiFi network, and configures the timezone. The loop() function continuously checks for a WiFi connection and, if connected, retrieves the current time and date, printing them to the serial monitor every 10 seconds.

Helper functions setTimeZone(), getCurrentTimeString(), and getCurrentDateString() handle the time synchronization, time formatting, and date formatting respectively.

5.2 – Key Code Segments Explained

The following sections dive into the most important parts of the code. We’ll break each segment down with detailed explanations to help you understand how it all works. Let’s explore these building blocks one by one!

5.2.1 – Including the Time Library

#include <time.h>

This line includes the time.h library, which is essential for working with time-related functions in C and C++. This library provides functions that allow you to get the current time, format time, and perform other time-related operations. For our ESP32 project, it’s crucial for synchronizing with NTP servers and managing timezones to display the correct local time.

5.2.2 – Setting the NTP Server

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

Here, we define the NTP server the ESP32 will connect to. pool.ntp.org is a free, public service that links to a group of reliable time servers around the world. By pointing our ESP32 to this service, we are instructing it to fetch the current time from this pool of NTP servers, ensuring our ESP32’s clock is accurate and synchronized with internet time standards.

5.2.3 – Defining the Timezone

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

This line sets the timezone for your ESP32. The timezone variable is set to "EST5EDT,M3.2.0,M11.1.0", which represents Eastern Time in the USA and Canada, including Daylight Saving Time (DST) rules.

Let’s break down this timezone string"EST5EDT,M3.2.0,M11.1.0":

  • EST5EDT: This is the standard timezone designation.
    • EST stands for Eastern Standard Time.
    • 5 indicates that EST is 5 hours behind Coordinated Universal Time (UTC).
    • EDT stands for Eastern Daylight Time.
  • ,M3.2.0: This part defines the rule for when Daylight Saving Time starts.
    • M3 means “the third month” (March).
    • 2 means “the second Sunday of the month”.
    • 0 means “at 00:00:00” (midnight).
    • So, DST starts on the second Sunday of March at midnight.
  • ,M11.1.0: This part defines the rule for when Daylight Saving Time ends.
    • M11 means “the eleventh month” (November).
    • 1 means “the first Sunday of the month”.
    • 0 means “at 00:00:00” (midnight).
    • So, DST ends on the first Sunday of November at midnight.

The code also provides alternative timezone settings commented out for Central, Mountain, and Pacific Time, allowing users to easily switch to their specific timezone by uncommenting the relevant line.

5.2.4 – Configuring the Time Zone Settings

setTimeZone();
void setTimeZone() {
  configTime(0, 0, ntpServer); // Get UTC time from the NTP server (0 offset for UTC)
  setenv("TZ", timezone, 1); // Set the timezone environment variable
  tzset(); // Apply the timezone setting
}

This function sets up the ESP32 to use the NTP server and apply your timezone. configTime() fetches the universal time (UTC) from the NTP server, while setenv() and tzset() adjust it to your local time based on the timezone string "EST5EDT,M3.2.0,M11.1.0". (Remember? We just explained this string in the 5.2.3 section of this article.)Let’s examine each line within this setTimeZone() function:

  • configTime(0, 0, ntpServer);: This function, configTime(), is used to initialize time synchronization with an NTP server.
    • The first two arguments, 0, 0, are time offsets (seconds offset from UTC and daylight offset), set to 0 here because we are setting the timezone using the TZ environment variable in the next step.
    • The third argument, ntpServer, is the NTP server address we defined earlier ("pool.ntp.org").
    • This line essentially tells the ESP32 to fetch the current UTC time from the specified NTP server.
  • setenv("TZ", timezone, 1);: This function, setenv(), sets the timezone environment variable.
    • The first argument, "TZ", is the name of the environment variable for timezone.
    • The second argument, timezone, is the timezone string we defined (e.g., "EST5EDT,M3.2.0,M11.1.0").
    • The third argument, 1, means to overwrite the environment variable if it already exists.
    • This line configures the system’s timezone based on the provided timezone string, enabling the ESP32 to convert UTC time to local time.
  • tzset();: The tzset() function applies the timezone settings specified by the TZ environment variable. It updates the internal time conversion functions to use the newly set timezone. After calling tzset(), subsequent time operations will be performed in the configured local timezone.

In summary, the setTimeZone() function first gets the UTC time from the NTP server and then configures the timezone, allowing for correct local time display via Serial Monitor.

5.2.5 – Checking WiFi and Displaying Time

  if (WiFi.status() == WL_CONNECTED) { // Check if WiFi is still connected
    Serial.print("Current Time: ");
    Serial.println(getCurrentTimeString());
    Serial.print("Current Date: ");
    Serial.println(getCurrentDateString());
  } else {
    Serial.println("WiFi Disconnected"); // Indicate WiFi disconnection
    WiFi.begin(ssid, password); // Attempt to reconnect to WiFi
  }

This chunk runs in the loop() function. It checks if the WiFi is connected. If it is, it prints the time and date by calling helper functions getCurrentTimeString() and getCurrentDateString(). If the connection drops, it alerts you and tries to reconnect. It acts like a diligent assistant who continuously monitors the internet connection and updates you with the latest time information.

  • if (WiFi.status() == WL_CONNECTED): This line checks the WiFi connection status using WiFi.status(). The value WL_CONNECTED indicates that ESP32 is now successfully connected to WiFi. The code inside the if block will only execute if the ESP32 is currently connected to the WiFi network.
  • Serial.print("Current Time: "); and Serial.println(getCurrentTimeString());: These lines print the label “Current Time: ” to the serial monitor, followed by the current time obtained by calling the getCurrentTimeString() function.
  • Serial.print("Current Date: "); and Serial.println(getCurrentDateString());: Similar to the time output, these lines print the label “Current Date: ” followed by the current date, which is obtained by calling the getCurrentDateString() function.
  • else { ... }: This else block is executed if the condition in the if statement is false, meaning the ESP32 is not connected to the WiFi network.
  • Serial.println("WiFi Disconnected");: This line prints “WiFi Disconnected” to the serial monitor, informing you that the WiFi connection has been lost.
  • WiFi.begin(ssid, password);: If WiFi is disconnected, this line attempts to reconnect to the WiFi network using the stored ssid (network name) and password. This ensures that the ESP32 tries to re-establish a connection automatically if it gets disconnected.

In summary, this code segment ensures that the current time and date are displayed on the serial monitor every 10 seconds (due to the delay(10000); at the end of the loop() function), but only when the ESP32 has an active WiFi connection. If the WiFi connection is lost, it reports the disconnection and attempts to reconnect.

5.2.6 – Formatting the Current Time: getCurrentTimeString() Function

String getCurrentTimeString() {
  struct tm timeinfo; // Structure to hold time information
  if (!getLocalTime(&timeinfo)) { // Attempt to get the local time
    return "Failed to get time"; // Return an error message if time retrieval fails
  }
  char timeStr[9]; // Character array to store the formatted time string (HH:MM:SS\0)
  strftime(timeStr, sizeof(timeStr), "%H:%M:%S", &timeinfo);// Format the time string
  // strftime() formats the time according to the specified format string.
  // %H: Hour (24-hour format, 00-23)
  // %M: Minute (00-59)
  // %S: Second (00-59)
  // timeinfo: The time structure containing the time data.
  return String(timeStr);
}

This function grabs the current time and formats it as “HH:MM:SS” (e.g., 14:30:45). getLocalTime() fills a structure with time data, and strftime() turns it into a readable string. Let’s break down its operation step-by-step:

  • struct tm timeinfo;: This line declares a variable timeinfo of type struct tmstruct tm is a structure defined in the <time.h> library, used to hold calendar time, broken down into components such as seconds, minutes, hours, day of the month, month, year, etc.
  • if (!getLocalTime(&timeinfo)): This line attempts to get the current local time and store it in the timeinfo structure.
    • getLocalTime(&timeinfo) is a function that tries to retrieve the current time, adjusted for the configured timezone, and stores it in the timeinfo structure.
    • getLocalTime() returns true on success and false on failure (e.g., if time synchronization hasn’t been successful yet). So, the if condition checks if getLocalTime() failed.
    • If getLocalTime() fails to get the time, the code inside the if block is executed.
  • return "Failed to get time";: If getLocalTime() fails, this line returns a string "Failed to get time". This serves as an error message that will be printed to the serial monitor, indicating that there was a problem retrieving the time.
  • char timeStr[9];: If getLocalTime() is successful, this line declares a character array timeStr of size 9. This array will be used to store the formatted time string. The size 9 is chosen to accommodate the “HH:MM:SS” format (8 characters) plus a null terminator character (\0) at the end of the string, which is required for C-style strings.
  • strftime(timeStr, sizeof(timeStr), "%H:%M:%S", &timeinfo);: This line uses the strftime() function to format the time information stored in timeinfo into a string and store it in timeStr.
    • strftime() stands for “string format time”. It’s a standard C library function for formatting time and date.
    • The first argument, timeStr, is the character array where the formatted string will be stored.
    • The second argument, sizeof(timeStr), is the maximum number of characters to write into timeStr, which prevents buffer overflow.
    • The third argument, "%H:%M:%S", is the format string that specifies how the time should be formatted.
      • %H: Hour in 24-hour format (00-23).
      • %M: Minute (00-59).
      • %S: Second (00-59).
      • The colons : are literal characters that will be included in the output string, separating hours, minutes, and seconds.
    • The fourth argument, &timeinfo, is a pointer to the struct tm structure that contains the time information to be formatted.
  • return String(timeStr);: Finally, this line creates a String object from the C-style string timeStr and returns it. The String class is an Arduino-specific class that makes working with strings easier in Arduino environments.

In summary, the getCurrentTimeString() function attempts to get the local time, checks for errors, formats the time into “HH:MM:SS” string, and returns this formatted time string. If it fails to get the time, it returns an error message string.

5.2.7 – Formatting the Current Date: getCurrentDateString() Function

String getCurrentDateString() {
  struct tm timeinfo; // Structure to hold time information
  if (!getLocalTime(&timeinfo)) { // Attempt to get the local date
    return "Failed to get date";  // Return an error message if date retrieval fails
  }
  char dateStr[11]; // Character array to store the formatted date string (YYYY-MM-DD\0)
  strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", &timeinfo);// Format the date string
  // strftime() formats the date according to the specified format string.
  // %Y: Year (4 digits, e.g., 2023)
  // %m: Month (01-12)
  // %d: Day of the month (01-31)
  // timeinfo: The time structure containing the date data.  
  return String(dateStr);
}

The getCurrentDateString() function mirrors the functionality of getCurrentTimeString(), but instead, it focuses on retrieving and formatting the current date into a string of “YYYY-MM-DD” format. Let’s examine its parts:

  • struct tm timeinfo;: Just like in getCurrentTimeString(), this line declares a struct tm variable to hold date and time information.
  • if (!getLocalTime(&timeinfo)): This line, identical to the one in getCurrentTimeString(), attempts to get the current local date and time and store it in timeinfo. It also checks for failure in retrieving the time (which would also mean date retrieval failed).
  • return "Failed to get date";: If getLocalTime() fails, this function returns the error message string "Failed to get date".
  • char dateStr[11];: This line declares a character array dateStr of size 11 to store the formatted date string. The size 11 is chosen to accommodate the “YYYY-MM-DD” format (10 characters) plus the null terminator \0.
  • strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", &timeinfo);: This line uses strftime() to format the date information from timeinfo into the dateStr array.
    • The format string is "%Y-%m-%d".
      • %Y: Year with century (e.g., 2023).
      • %m: Month as a number (01-12).
      • %d: Day of the month (01-31).
      • The hyphens - are literal characters that will separate the year, month, and day in the output string.
  • return String(dateStr);: Finally, the function converts the C-style string dateStr into an Arduino String object and returns it.

In summary, getCurrentDateString() retrieves the local date and time, checks for errors, formats the date into “YYYY-MM-DD” format, and returns the formatted date string. If there’s an issue retrieving the date (which relies on successful time synchronization), it returns an error message string.

6 – Hands-on Practice

You’ve just learned how to make your ESP32 fetch the current time from an NTP server—great work! Now it’s time to put that knowledge into practice with a small assignment. This task will help you get comfortable with the code and explore a bit on your own.

Your Assignment: Modify the example code to display the time in a 12-hour format (e.g., “02:30:45 PM” instead of “14:30:45”) instead of the 24-hour format we used. Here’s a hint: you’ll need to tweak the getCurrentTimeString() function, particularly the strftime() format string. Look up the strftime() documentation online for format options like %I (hours in 12-hour format) and %p (AM/PM indicator). Once you’ve made the change, upload the code to your ESP32 and check the Serial Monitor to see your new time display in action!

7 – Conclusion

The ESP32 is capable of tackling much more complex online tasks than what we’ve covered here. Fetching the current time from an NTP server is just one of its simplest tricks—a starting point to get you comfortable with connecting to the internet. But don’t let its simplicity fool you. I can promise you this: knowing how to grab the time online will come in handy for your future project you build. Time is a vital ingredient in IoT—whether you’re scheduling tasks, logging data, or keeping devices in sync, this skill will be your foundation.

Next up in our ESP32 WiFi Chapter, we’ll explore how to use the ESP32 in AP (Access Point) mode. Just like Station mode helped you connect to a network, AP mode lets your ESP32 act as its own network—a powerful feature for many creative projects. Keep pushing forward; each step you take unlocks more of the ESP32’s potential! Please click the link below to jump to the next article.

ESP32 Essential Guide Index

Network Section

error: Content is protected !!