ESP8266, retrieve time from a time server (NTP), elapsed time since last Reset, store time in SPIFFS [Update]

In this third tutorial dedicated to creating a web interface for DIY projects based on ESP8266, we will learn how to recover the time from a Network Time Protocol (NTP) time server. The Arduino and the ESP8266 and ESP32 WiFi modules do not have a real-time clock (except for a few specific exceptions).

As soon as you have an internet connection, it is very easy to retrieve the current date and time from an external server or an NTP time server. It will be possible to time stamp (timestamp) measurements, to know the time elapsed between two events, to display the current time on the WEB interface, to trigger a programmed action …

esp8266 esp32 ntp server date time

 

NTPClient library (the easiest)

If you search from the Arduino IDE library manager, you will find several libraries that can retrieve time from an NTP server

After having tested almost all NTP libraries on ESP8266, I advise you to use Fabrice Weinberg’s NTPClient library. It is very simple to use.

esp8266 ntp server ntpclient library

 

When developing connected objects that operate on battery, one may wish to know the time quickly to trigger to call possibly another function. The NTPClient library can do this very easily by forcing the recovery of time by calling the forceUpdate() method.

The NTPCLient library uses a UDP connection to connect to an NTP server. For that, it will be necessary to include the standard library WiFiUdp.h in the header of the sketch.

Then, it is possible to initialize the NTPClient object with the default configuration:

  • Server: pool.ntp.org
  • Update interval: 60 seconds
  • Time difference (in seconds): none
NTPClient timeClient(ntpUDP);

Or to specify parameters. Here, we apply a time difference of one hour

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);

Then, all that remains is to start the service with the timeClient.begin() method. Then, we can let the library update the time according to the interval configured with the update() method, or force the update manually with the forceUpdate() method. It’s ideal for projects that run on battery power.

Here is a small example that retrieves and displays the time every 10 seconds

#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

#define NB_TRYWIFI        10    // Nbr de tentatives de connexion au réseau WiFi - Number of try to connect to WiFi network

const char* ssid = "xxxx";
const char* password = "xxxx";

WiFiClient espClient;
WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.print("Startup reason:");Serial.println(ESP.getResetReason());

  WiFi.begin(ssid, password);

  Serial.println("Connecting to WiFi.");
  int _try = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("..");
    delay(500);
    _try++;
    if ( _try >= NB_TRYWIFI ) {
        Serial.println("Impossible to connect WiFi network, go to deep sleep");
        ESP.deepSleep(10e6);
    }
  }
  Serial.println("Connected to the WiFi network");
  
  // Démarrage du client NTP - Start NTP client
  timeClient.begin();
}

void loop() {
    // Met à jour l'heure toutes les 10 secondes - update time every 10 secondes
    timeClient.update();
    Serial.println(timeClient.getFormattedTime());
}

Store the time in the SPIFFS area, calculate the elapsed time since the last start or reset

In many cases, we will want to keep track of the time we have just recovered for other uses:

  • Calculate the time elapsed since last start or last reset
  • Trigger an action if the elapsed time is greater than a setpoint. For example sent the status of a motion detector if a second movement is detected 30 seconds after the first one. This
  • will avoid multiplying unnecessary notifications on a smartphone
    Trigger a pre-programmed action. For example, trigger a relay that opens a garden watering valve for 1 minute …

To store the time, it is much easier to save it in a simple text file in the SPIFFS area than to store it in the EEPROM. For this, simply declare the library fs.h at the beginning of the program.

Then it will be very easy to calculate the time elapsed since the last start or reset. Here is an adaptation of the previous program. The following functions have been added:

  • saveLastEvent(), saves in a file named lastEvent.txt the NTP time in EPOCH Unix format
  • loadLastEvent(), reload the last saved NTP time
  • timeSpent(), calculates the elapsed time in seconds since the last start
  • runEvent(), executes an event if the elapsed time is greater than the time specified in the variable DELAY_NEXT_EVENT

You can also test by activating the Deep-Sleep mode (pass the DEEP_SLEEP key to true) of the ESP8266 module. Read this tutorial to learn everything about standby and this one if you are new to ESP8266 modules. The runEvent method is executed if the elapsed time exceeds DELAY_NEXT_EVENT.

#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "FS.h"

#define NB_TRYWIFI        10    // Nbr de tentatives de connexion au réseau WiFi - Number of try to connect to WiFi network
#define DELAY_NEXT_EVENT  60    // délai entre deux événements en secondes - delay before new event in second 
#define DEEP_SLEEP        false
const char* ssid = "xxxx";
const char* password = "xxxx";

WiFiClient espClient;
WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);

int lastEvent;
int start = millis();
long int _now = 0;

bool loadLastEvent(){
  File f = SPIFFS.open("/lastEvent.txt", "r");
  if (!f) {
    Serial.println("Failed to open file");
    return false;
  }
  lastEvent = f.readStringUntil('\n').toInt();
  return true;
}

bool saveLastEvent(){
  File f = SPIFFS.open("/lastEvent.txt", "w");
  if (!f) {
      Serial.println("file open failed");
      return false;
  }
  f.println(_now);
  f.close();
  return true;
}

long int timeSpent(){
  loadLastEvent();
  timeClient.forceUpdate();
  _now = timeClient.getEpochTime();
  int timeSpent = _now - lastEvent;
  Serial.println("Time spent since last alarm (s): ");Serial.print(timeSpent);
  return timeSpent;
}
void runEvent(){
    
  if ( timeSpent() >= DELAY_NEXT_EVENT ) {
    Serial.println("RUN EVENT");
    saveLastEvent();
  } 
}

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.print("Startup reason:");Serial.println(ESP.getResetReason());

  SPIFFS.begin();

  WiFi.begin(ssid, password);

  Serial.println("Connecting to WiFi.");
  int _try = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("..");
    delay(500);
    _try++;
    if ( _try >= NB_TRYWIFI ) {
        Serial.println("Impossible to connect WiFi network, go to deep sleep");
        ESP.deepSleep(10e6);
    }
  }
  Serial.println("Connected to the WiFi network");
  
  // Démarrage du client NTP - Start NTP client
  timeClient.begin();
   
  
  if ( DEEP_SLEEP){ 
    runEvent();
    Serial.println("Go to deep sleep");
    ESP.deepSleep(10e6);
  }  
}

void loop() {
  if ( !DEEP_SLEEP ){
    timeClient.update();
    Serial.println(timeClient.getFormattedTime());
    delay(10000); 
  }
}

NTPClientLib and Time libraries (oldest, for memory)

The Time and NTPClientLib libraries are two very old libraries. The Time Library is the official bookstore for managing time with Arduino code. The NTPClientLib library is an overlay adapted to ESP8266 modules. It now supports Arduino MKR1000 cards as well as ESP32.

However, I encountered timing synchronization issues. The NTPClientLib library is not suitable for projects that run on battery. Time synchronization may take a few moments. The time is recovered via a callback procedure which can take time and therefore consume the battery unnecessarily. However, I preferred to keep this part of the tutorial for the record and in case the NTPClient library is unsuitable for your project.

It is very easy to recover time on the Internet using the library NTPClientLib developed by gmag11. To operate, you will also need to install and declare the standard Arduino TimeLib library. These two libraries are available from the Arduino IDE library manager.

esp8266 ntp server ntpclientlib timelib arduino

Once the libraries are installed, it remains only to declare them in the sketch.

#include <TimeLib.h>
#include <NtpClientLib.h>

The NtpClient library provides all the methods necessary for time management, but it uses the TimeLib library to function. You will find many (old) tutorials on the internet that directly decode the UDP messages sent by the time server. With the library developed by gmag11, everything works becomes useless.

Before you can retrieve the time on the Internet, you must already start the NTP object. It is started with the begin() method which takes 3 parameters in the setup():

  • The time server URL. By default, you can query pool.ntp.org
  • Time difference that matches your time zone
  • Summer time. Set to True to manage daylight saving mode, winters

The setInterval method is used to set the polling frequency of the time server. Stay reasonable, unnecessary to re-synchronize the clock of the ESP8266 10 times per second! You will unnecessarily overload the NTP server. Here, the time will be re-synchronized every minute (which is already too much).

NTP.begin("pool.ntp.org", 1, true);
NTP.setInterval(60000);

You can create a callback function that will be called whenever an event occurs (inaccessible server, bad URL, time request).

NTP.onNTPSyncEvent([](NTPSyncEvent_t error) {
  if (error) {
    Serial.print("Time Sync error: ");
    if (error == noResponse)
      Serial.println("NTP server not reachable");
    else if (error == invalidAddress)
      Serial.println("Invalid NTP server address");
    }
  else {
    Serial.print("Got NTP time: ");
    Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
  }
});

Now that everything is ready, one can ask for time at any time in turn the Arduino code. The NtpClientLib library offers many functions that will make our work easier, in addition to synchronizing time with an NTP server:

  • TimeZone(get or set): time offset -11 to + 13
  • Stop(): stops time synchronization
  • Interval(get or set): time in milliseconds before the next time synchronization with the NTP server
  • DayLight(get or set): daylight saving time management
  • GetTimeStr(unix time): directly converts unix time to string, convenient to create a display
  • GetDateStr()
  • GetDateStr(unix time): string containing the date
  • GetTimeDateString(): string containing the date and time
  • GetLastNTPSync(): last sync

As you can see, there are almost all combinations. Only problem, the chains are not (yet) in an ISO standard. You may encounter problems if you have to process these dates in browser code (Javascript). For now, the best is to keep the unix timestamp returned by the getTime () function. The timestamp also has several advantages:

Two dates can easily be compared by a simple subtraction. The time difference will be in seconds.
It is a fairly short number, therefore economical in memory. This is important in an Arduino / ESP8266 project.
It will be easy to process in Javascript code. The new date (timestamp) function allows to create a date very simply.
There are also some handy functions for managing the system

  • GetUptimeString(): running time of the ESP8266
  • GetUptime(): idem but in the form of a Unix timestamp
  • GetLastBootTime(): elapsed time since the last ESP8266 boot
  • GetFirstSync(): first synchronization with the server since startup

Comparison of libraries

Here is a small table summarizing the functions offered by the main libraries available

Days

NTPClient EasyNTPClient NTPCLientLib
WiFi UDP X X
UDP port X
Type of development board NETWORK_ESP8266, NETWORK_ESP32,  ARDUINO_ARCH_SAMD or NETWORK_W5100 in begin()
Available Parameters
NTP Server object or setPoolServerName X object or setNtpServerName
Jet lag object orsetTimeOffset SetTimeOffset
Synchronization interval object or setUpdateInterval object or setInterval
Indicate time zone setTimeZone
daylight setDayLight
Methodes
Get NTP Time udpate getUnixTime
Force synchronization forceUpdate getUnixTime
Jet lag getTimeOffset
Time zone getTimeZone ou getTimeZoneMinutes
Suspend synchronization stop
Formatting time
UNIX (Epoch) time getEpochTime getUnixTime
Days getDay
Hours getHours
Minutes getMinutes
Secondes getSecondes
HH:MM:SS getFormattedTime getTimeStr
Date JJ:MM:AAAA getDateStr
date + time string getTimeDateString
Advanced functions
Time elapsed since startup* getLastBootTime
First synchronization getFirstSync
Daylight isSummerTimePeriod

(*) does not work in case of RESET or manual reboot

Compatibility

Here is also a list of development boards supported by libraries. Developers can not test all platforms. Some cards could be supported without being in the table below. Feel free to share your experience if this is the case.

NTPClient EasyNTPClient NTPCLientLib
Arduino X X X
Arduino MKR1000 X X X
ESP8266 X X X
ESP32 X probable X
AVR ? ? X

What is Unix time (Unix timestamp)?

The unix time started on 1 January 1970 at midnight. It is a counter in seconds. You can directly convert a unix time into the Arduino code to deduce a date or time (or all) using the getTimeStr (unix time) and getDateStr (unix time) functions. There are also many converters on the internet (http://www.unixtimestamp.com/).

 

Subscribe to the weekly newsletter

No spam and no other use will be made of your email. You can unsubscribe anytime.

Tags:

  • Samizard

    Hi, can you tell me how do i install that NTP library in arduino, since it not showing in board managers and even after copy-pasting the library in libraries folder the NTP header file shows error.
    Can you please tell me solution for this??

    • Hello Samizard. Which version of the IDE Arduino do you use. I just checked on mine (version 1.8.2) and I find it well in the list. I compiled this little piece of code without error. It’s strange.
      #include
      #include

      void setup() {
      NTP.begin(“pool.ntp.org”, 1, true);
      NTP.setInterval(60);
      }

      void loop() {
      Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
      delay(60000);
      }

      • Samizard

        version 1.8.5

DIY Projects