Projet station météo ESP8266 (Partie 3). Récupérer l’heure avec NTPClient et stockage SPIFFS

Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

Table des matières

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

esp8266 esp32 ntp server date time

 

Si vous avez besoin d’aller plus loin avec la librairie NTPClient, vous pouvez continuer en lisant cet article plus détaillé

A LIRE AUSSI :
ESP8266. Récupérer l'heure avec NTPClient, stockage SPIFFS, calculer le temps écoulé et déclencher un événement

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.

esp8266 ntp server ntpclient library

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 <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());
}

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

Zone Serveur NTP
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

A LIRE AUSSI :
Projet station météo ESP8266 (Partie 1). Créer l'interface HTML, stockage SPIFFS
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 2). Piloter le code Arduino depuis l'interface HTML

Vous êtes ici !

A LIRE AUSSI :
Projet station météo ESP8266 (Partie 3). Récupérer l'heure avec NTPClient et stockage SPIFFS
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 4). ArduinoJson, charger, enregistrer des fichiers (SPIFFS)
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 5). Afficher des jauges et graphiques Google Charts

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]
Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

Vous avez aimé ce projet ? Ne manquez plus aucun projet en vous abonnant à notre lettre d’information hebdomadaire!

quel modèle esp8266 choisir
Quel modèle d'ESP8266EX choisir en 2020 ?
guide choix esp32 development board
Quel ESP32 choisir en 2020 ?

Vous rencontrez un problème avec ce sujet ?

Peut-être que quelqu’un a déjà trouvé la solution, visitez le forum avant de poser votre question

11 Commentaires
  1. Bonjour.
    Il n’y a que quelques partie de code !
    Et la partie stockage en zone SPIFFS est inexistente. ou je n’ai su la trouver ?

    • Bonsoir Thib, oui absolument, j’ai malheureusement effacé le contenu par erreur lors d’une mise à jour. Heureusement que j’avais la version anglaise sous le coude ! J’en ai profité pour reprendre l’article et améliorer le code Arduino. Il est transféré ici dans la catégorie débuter avec l’ESP8266. Bonne soirée

  2. Bonjour,
    Merci d’essayer de m’aider en fait j’ai fait des essais avec le code exemple livré avec
    la librairie afin de comprendre le fonctionnement je joint quand meme le code:

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    // Enter a MAC address for your controller below.

    // Newer Ethernet shields have a MAC address printed on a sticker on the shield

    byte mac[] = {

    0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02

    };

    EthernetClient client;

    void setup()

    {

    Serial.begin(115200);

    if (Ethernet.begin(mac) == 0) {

    Serial.println(“Failed to configure Ethernet using DHCP”);

    // no point in carrying on, so do nothing forevermore:

    for (;;)

    ;

    }

    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()));

    }

    });

    NTP.begin(“es.pool.ntp.org”, 1, true);

    NTP.setInterval(63);

    }

    void loop()

    {

    static int i = 0;

    static int last = 0;

    if ((millis() – last) > 5100) {

    //Serial.println(millis() – last);

    last = millis();

    Serial.print(i); Serial.print(” “);

    Serial.print(NTP.getTimeDateString()); Serial.print(“. “);

    Serial.print(NTP.isSummerTime() ? “Summer Time. ” : “Winter Time. “);

    Serial.print(“Uptime: “);

    Serial.print(NTP.getUptimeString()); Serial.print(” since “);

    Serial.println(NTP.getTimeDateString(NTP.getFirstSync()).c_str());

    i++;

    }

    delay(0);

    Ethernet.maintain(); // Check DHCP for renewal

    }

  3. 0 00:00:05 01/01/1970. Winter Time. Uptime: 0 days 00:00:05 since Time not set

    1 00:00:10 01/01/1970. Winter Time. Uptime: 0 days 00:00:10 since Time not set

    2 00:00:15 01/01/1970. Winter Time. Uptime: 0 days 00:00:15 since Time not set

    3 00:00:20 01/01/1970. Winter Time. Uptime: 0 days 00:00:20 since Time not set

    4 00:00:25 01/01/1970. Winter Time. Uptime: 0 days 00:00:25 since Time not set

    voici ce que j’obtient pour être plus clair
    Merci si vous avez une solution, moi je galère pour l’instant

  4. bonjour,
    j’ai essayé cette librairie mais sa ne m’affiche que la date du 01/01/1970
    puis un décompte de temps depuis que c’est en marche je ne comprend pas
    si j’ai bien compris je devrais avoir le temps reel?

  5. Nice article. Regards!

  6. Bonjour,

    Et merci pour vos très bon articles.

    D’après mes tests, il semble que le paramètre de réglage de la fréquence d’interrogation, s’exprime en secondes.
    Donc un paramètre de 60000 est équivalent à 1000 minutes.

    Cordialement.

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Calculateurs
×
Calculateur loi d'Ohm
Tension (U) - en Volt
Courant (I) - en Ampère
Résistance (R) - en Ohms
Puissance (P) - en Watts

Ce calculateur permet de calculer les relations entre le courant, la tension, la résistance et la puissance dans les circuits résistifs.

Saisir au moins deux valeurs puis cliquer sur calculer pour calculer les valeurs restantes. Réinitialisez après chaque calcul.

Rappel sur la Loi d'Ohm
La loi d'Ohm explique la relation entre la tension, le courant et la résistance en déclarant que le courant traversant un conducteur entre deux points est directement proportionnel à la différence de potentiel entre les deux points.
La loi d'Ohm s'écrit U = IR, où U est la différence de tension, I est le courant en ampère et R est la résistance en Ohms (symbole Ω).
Loi d'Ohm (U=RI)
×
Déchiffrer le code couleur d'une résistance à 4 bandes
Bande 1 Bande 2 Multiplicateur Tolérance
   

Résistance:  

1 000 Ω ±5%

Comment déchiffrer le code couleur d'une résistance à 4 anneaux
Formule : ab*cΩ ±d%
Les deux premières bandes (a, b) permettent de déterminer le chiffre significatif. La première bande correspond au chiffre de la dizaine, le second anneau le chiffre de l'unité. Par exemple Brun(1), Noir (0) donne le nombre 10.
La troisième bande (c) est un coefficient multiplicateur. Par exemple, l'anneau rouge est un coefficient multiplicateur de 100, ce qui donne 10 X 100 = 1000Ω.
Le quatrième anneau (d) indique la tolérance de la valeur nominale de la résistance. Par exemple l'anneau Or correspond à ±5%. Donc le fabricant de la résistance s'engage à ce que sa valeur soit comprise entre 950 Ω et 1050 Ω.
Déchiffrer code couleur 4 bandes
×
Déchiffrer le code couleur d'une résistance à 5 bandes
Bande 1 Bande 2 Bande 3 Multiplicateur Tolérance

Résistance:  

1 000 Ω ±5%

Comment déchiffrer le code couleur d'une résistance à 5 anneaux
Formule : abc*dΩ ±e%
Les trois premières bandes permettent de déterminer le chiffre significatif. La première bande correspond au chiffre de la dizaine, le second anneau le chiffre de l'unité. Par exemple Brun(1), Noir (0), Noir (0) donne le nombre 100
La quatrième bande est un coefficient multiplicateur. Par exemple, l'anneau brun correspond au coefficient multiplicateur 10, ce qui donne 100 X 10 = 1000Ω.
Le cinquième anneau indique la tolérance de la valeur nominale de la résistance. Par exemple l'anneau Or correspond à ±5%. Donc le fabricant de la résistance s'engage à ce que la valeur de la résistance soit comprise entre 950 Ω et 1050 Ω.
Déchiffrer code couleur 5 bandes
×
Calculateur de résistance série pour une ou plusieurs LED
Tension d'alimentation en Volt
Tension directe en Volt
Courant en mA
Résistance calculée en Ω
Puissance estimée en W

Ce calculateur permet de déterminer la résistance requise pour piloter une ou plusieurs LED connectées en série à partir d'une source de tension à un niveau de courant spécifié.

Remarque. Il est préférable d'alimenter le circuit avec une puissance nominale comprise entre 2 et 10 fois la valeur calculée afin d'éviter la surchauffe
Couleur Longueur d'onde (nm) Tension (V) pour LED ⌀3mm Tension(V) pour LED ⌀5mm
Rouge 625-630  1,9-2,1 2,1-2,2
Bleu 460-470 3,0-3,2 3,2-3,4
Vert 520-525 2,0-2,2 2,0-2,2
Jaune 585-595 2,0-2,2 3,0-3,2
Blanc 460-470 3,0-3,2 1,9-2,1
Résistance en série pour une ou plusieurs LED
×
Calculateur durée de vie d'une batterie
Capacité de la batterie
Consommation de l'appareil ou objet connecté

Ce calculateur estime la durée de vie d'une batterie, en fonction de sa capacité nominale et du courant ou de la puissance qu'une charge en tire.

La durée de vie de la batterie est une estimation idéalisée. La durée de vie réelle peut varier en fonction de l'état de la batterie, de son âge, de la température, du taux de décharge et d'autres facteurs. C'est le mieux que vous pouvez espérer obtenir.

Autonomie de la batterie = capacité de la batterie en mAh / courant de charge en mA

Durée de vie batterie
Publicité
À lire aussi
Composants
Sur le Forum
Derniers Sujets
Domotique et objets connectés à faire soi-même
Domotique et objets connectés à faire soi-même
Vous avez aimé ce tutoriel

Ne manquez plus les prochains projets

Recevez chaque semaine le récapitulatif des tutoriels et projets.

Vous pouvez vous désabonner à tout moment. 

Shopping cart