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

esp8266 esp32 ntp server date time
Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on email
Share on whatsapp

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 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 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 DELAY_NEXT_EVENT

You can also test by activating the Deep-Sleep mode (pass the DEEP_SLEEP key to true) of the ESP8266 module.

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:

  • 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

NTPClientEasyNTPClientNTPCLientLib
WiFi UDPXX
UDP portX
Type of development boardNETWORK_ESP8266, NETWORK_ESP32,  ARDUINO_ARCH_SAMD or NETWORK_W5100 in begin()
Available Parameters
NTP Serverobject or setPoolServerNameXobject or setNtpServerName
Jet lagobject orsetTimeOffsetSetTimeOffset
Synchronization intervalobject or setUpdateIntervalobject or setInterval
Indicate time zonesetTimeZone
daylightsetDayLight
Methodes
Get NTP TimeudpategetUnixTime
Force synchronizationforceUpdategetUnixTime
Jet laggetTimeOffset
Time zonegetTimeZone ou getTimeZoneMinutes
Suspend synchronizationstop
Formatting time
UNIX (Epoch) timegetEpochTimegetUnixTime
DaysgetDay
HoursgetHours
MinutesgetMinutes
SecondesgetSecondes
HH:MM:SSgetFormattedTimegetTimeStr
Date JJ:MM:AAAAgetDateStr
date + time stringgetTimeDateString
Advanced functions
Time elapsed since startup*getLastBootTime
First synchronizationgetFirstSync
DaylightisSummerTimePeriod

(*) 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.

NTPClientEasyNTPClientNTPCLientLib
ArduinoXXX
Arduino MKR1000XXX
ESP8266XXX
ESP32XprobableX
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/).

 

Click to rate this post!
[Total: 0 Average: 0]

Are you having a problem with this topic?

Maybe someone has already found the solution, visit the forum before asking your question
Ask your question

Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on email
Share on whatsapp

Did you like this project ? Don't miss any more projects by subscribing to our weekly newsletter!

3 Comments
  1. 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);
      }

    Leave a Reply

    DIY Projects
    %d bloggers like this: