Dans cette troisième partie du projet de station météo avec interface WEB, nous allons apprendre comment récupérer l’heure depuis un serveur de temps à l’aide de la librairie NTPClient. L’Arduino et l’ESP8266 ne disposent pas d’horloge temps réel. On peut ajouter une horloge temps réelle (module RTC, Real Time Clock), mais il sera beaucoup plus facile et moins chère de récupérer l’heure sur un serveur de temps (NTP) directement sur internet via la connexion WiFi .
Projet actualisé le 29 juillet 2020
Dès que vous disposez d’une connexion Internet, il est très facile de récupérer la date et l’heure actuelles à partir d’un serveur externe ou d’un serveur de temps NTP. Il sera possible d’horodater les mesures, de connaître le temps écoulé entre deux événements, d’afficher l’heure actuelle sur l’interface WEB, de déclencher une action programmée…
Le schéma ci-dessous explique comment nous allons faire
Si vous avez besoin d’aller plus loin avec la librairie NTPClient, vous pouvez continuer en lisant cet article plus détaillé
Sommaire
Installer la librairie NTPClient
Ouvrez le gestionnaire de librairies de l’IDE Arduino et cherchez la librairie NTPClient de Fabrice Weinberg. C’est une librairie puissante et simple d’utilisation.
Lors du développement d’objets connectés fonctionnant sur batterie, on peut souhaiter connaître rapidement le temps de déclenchement pour appeler éventuellement une autre fonction. La bibliothèque NTPClient peut le faire très facilement en forçant la récupération du temps en appelant la connexion UDP pour se connecter à un serveur NTP. Pour cela, il faudra inclure la bibliothèque standard WiFiUdp.h dans l’en-tête du croquis.
Ensuite, il est possible d’initialiser l’objet NTPClient avec la configuration par défaut:
- Serveur, pool.ntp.org
- Intervalle de mise à jour, 60 secondes
- Décalage horaire (en secondes), aucun
NTPClient timeClient(ntpUDP);
Ou pour spécifier des paramètres. Ici, nous appliquons un décalage horaire d’une heure
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
Ensuite, il ne reste plus qu’à démarrer le service avec la méthode forceUpdate (). Il est idéal pour les projets fonctionnant sur batterie.
Voici un petit exemple qui récupère et affiche l’heure toutes les 10 secondes
#include
#include
#include
#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());
}
Stockez l’heure dans la zone SPIFFS, calculez le temps écoulé depuis le premier démarrage
Dans de nombreux cas, on voudra garder une trace du temps pour d’autres utilisations :
- Calculer le temps écoulé depuis le dernier démarrage ou la dernière réinitialisation
- Déclenchez une action si le temps écoulé est supérieur à un point de consigne.
- Déclenchez une action pré-programmée.
Pour stocker l’heure, il est beaucoup plus facile de la sauvegarder dans un simple fichier texte dans la zone SPIFFS que de la stocker dans l’EEPROM. Pour cela, il suffit de déclarer simplement la bibliothèque fs.h au début du programme.
Ensuite, il sera très facile de calculer le temps écoulé depuis le dernier démarrage.
Collez le code suivant dans un nouveau croquis sans oublier de modifier les paramètres suivants :
- ssid identifiant de connexion au réseau WiFi
- password mot de passe du réseau WiFi
- NB_TRYWIFI permet de spécifier le nombre de tentatives de connexion au réseau WiFi. Sur batterie, le mieux est de mettre le module ESP8266 ou ESP32 en veille et recommencer ultérieurement pour éviter de drainer cette dernière.
- LOOP_DELAY permet de spécifier le temps d’attente entre deux exécution de la boucle loop. Par défaut, il est de 60 secondes. Attention, ici on force l’actualisation du temps, évitez d’envoyer trop de requêtes au serveur NTP.
- RESET_INITIAL_NTPTIME permet de réinitialiser manuellement le temps initial à partir duquel est calculé le temps écoulé. Il suffira par exemple de modifier la méthode resetInitialTime() sur un événement, par exemple un déclencheur tel qui bouton poussoir pour l’initialiser manuellement.
#include
#include
#include
#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 LOOP_DELAY 30 * 1000 // Fréquence d'actualisation | update frequency
#define RESET_INITIAL_NTPTIME false // Permet de réinitialisé le temps initial | Allows to reset initial NTP time
// Paramètres WiFi | WiFi settings
const char* ssid = "****";
const char* password = "****";
WiFiClient espClient;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
void resetInitialTime() {
timeClient.forceUpdate();
_now = timeClient.getEpochTime();
saveLastEvent();
}
int lastEvent;
int start = millis();
long int _now = 0;
bool lastEventExist() {
File f = SPIFFS.open("/lastEvent.txt", "r");
if (!f) {
return false;
}
return true;
}
bool loadLastEvent() {
// Recharge le dernier horodatage depuis la zone SPIFFS | Reload last date/time from SPIFFS area
File f = SPIFFS.open("/lastEvent.txt", "r");
if (!f) {
Serial.println("Failed to open file, force NTP");
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 calculateTimeSpent() {
loadLastEvent();
timeClient.forceUpdate();
_now = timeClient.getEpochTime();
int timeSpent = _now - lastEvent;
Serial.print("Time spent since last update (s): "); Serial.println(timeSpent);
return timeSpent;
}
void setup() {
Serial.begin(115200);
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");
}
}
Serial.println("Connected to the WiFi network");
// Démarrage du client NTP - Start NTP client
timeClient.begin();
if ( RESET_INITIAL_NTPTIME ) {
resetInitialTime();
}
if ( !lastEventExist() ) {
Serial.println("First Boot, store NTP time on SPIFFS area");
saveLastEvent();
} else {
Serial.println("NTP time already stored on SPIFFS area");
calculateTimeSpent();
}
}
void loop() {
timeClient.update();
calculateTimeSpent();
delay(LOOP_DELAY);
}
Comment fonctionnent les principales méthode du code
loadLastEvent() permet de recharger la dernière heure NTP enregistrée dans le fichier lastEvent.txt situé dans la zone mémoire SPIFFS de l’ESP8266
La librairie fs.h met à disposition la classe SPIFFS qui permet de lire et d’enregistrer des fichiers.
La méthode open(fichier, option) permet d’ouvrir le fichier (attention, il n’est pas possible d’avoir des dossiers dans la zone SPIFFS). L’option “r” indique qu’on souhaite un accès uniquement en lecture (read).
La méthode readStringUntil(‘n’) lit le contenu du fichier jusqu’au caractère indiqué, ici “n” qui est le caractère de contrôle du retour à la ligne.
On n’oublie pas de convertir en entier avec la méthode .toInt() ce qui nous permettra de calculer le temps écoulé avec une simple soustraction.
On ferme le fichier avec la méthode close().
File f = SPIFFS.open("/lastEvent.txt", "r");
lastEvent = f.readStringUntil('n').toInt();
f.close();
saveLastEvent() enregistre le temps NTP au format EPOCH Unix
Comme précédemment, on ouvre le fichier avec la méthode SPIFFS.open(). Cette fois, on indique qu’on souhaite écrire dans le fichier avec l’option “w”.
On enregistre dans un fichier comme sur le port série avec les méthode print() ou println(). La méthode println() ajoute un renvoi à la ligne, souvenez-vous, c’est le caractère “n” utilisé précédemment.
On ferme le fichier avec la méthode close().
File f = SPIFFS.open("/lastEvent.txt", "w")
f.println(_now);
f.close();
lastEventExist() permet de vérifier si le fichier lastEvent.txt existe déjà dans la zone SPIFFS. Cette méthode retourne un booléen qui prend l’état vrai si le fichier existe et faux dans le cas contraire. Pour savoir si le fichier existe, on procède de la même façon que précédemment en ouvrant en lecture le fichier.
Il suffit ensuite de tout simplement tester l’état de l’objet f
lastEventExist() {
File f = SPIFFS.open("/lastEvent.txt", "r");
if (!f) {
return false;
}
return true;
}
calculateTimeSpent() calcule le temps écoulé en secondes depuis que le fichier lastEvent.txt a été actualisé, par exemple depuis le premier démarrage
Pour calculer facilement la durée écoulée, il suffit de récupérer le temps au format Unix à l’aide de la méthode getEpochTime(). Connaissant le temps précédent lastEvent, il suffit de faire une simple soustraction pour calculer le temps écoulé
_now = timeClient.getEpochTime();
int timeSpent = _now - lastEvent;
Quelques serveurs de temps (NTP)
Voici une petite liste de serveurs de temps (en France et dans le monde). Il en existe des centaines, voici les principaux
Monde entier | pool.ntp.org |
Asie | asia.pool.ntp.org |
Europe | europe.pool.ntp.org |
Amérique du Nord | north-america.pool.ntp.org |
America du Sud | south-america.pool.ntp.org |
Oceanie | oceania.pool.ntp.org |
Accéder rapidement aux autres parties du projet
Voici les liens pour accéder aux autres parties du projet
Vous êtes ici !
Mises à jour
29/07/2020 Rétablissement de la partie consacrée au stockage dans la zone SPIFFS du temps récupéré sur un serveur NTP
Avez-vous aimé cet article ?
[Total: 0 Moyenne: 0]