Horloge connectée avec Arduino

Ajout de code logiciel pour afficher la date et l’heure locale

Nous allons maintenant modifier notre code logiciel Arduino pour réaliser une horloge connectée affichant:

  • L’heure à la seconde près en première ligne.
  • La date du jour en deuxième ligne.
Horloge connectée à l'aide d'un ESP8285 et d'Arduino

Bibliothèque nécessaire

Pour gérer la conversion d’une date depuis le format « Unix Time » vers une date au format calendaire et une heure locale, nous allons utiliser la bibliothèque Arduino Timezone nommée « TimeZone by Jack Christensen » . Cette bibliothèque prend également en compte les changements d’heure été/hivers du pays concerné.
Pour fonctionner, cette bibliothèque nécessite que la bibliothèque Time nommée « Time by Michael Margolis » soit également installée.

Installez ces 2 bibliothèques, puis complétez le code logiciel pour indiquer au compilateur l’utilisation de Timezone:

#include <Timezone.h>

En France comme en Europe, le passage:

  • à l’heure d’été s’effectue le dernier dimanche de mars et
  • à l’heure d’hiver s’effectue le dernier dimanche d’octobre.

Nous allons traduire en langage informatique ces règle de changement d’heure en utilisant des structures du type  « TimeChangeRule » défini dans la bibliothèque Timezone.

Vous allez ajouter la déclaration de deux structures globales de type « TimeChangeRule » « RegleHeureEteEurope_G » et « RegleHeureHiverEurope_G« . Ces structures se composent des champs suivants:

  • Abbréviation: Chaîne de maximum 5 caractères permettant d’identifier de façon unique cette règle. Dans ce programme, vous choisirez les majuscules des noms de structures.
  • Semaine: Semaine du mois pour laquelle la règle s’applique. Pour les 2 changements d’heure en Europe, il s’agit des 2 dernières semaines du mois. Vous utiliserez donc le mot clef « Last« .
  • Jour de la semaine:  Jour de la semaine pour lequel la règle s’applique. Pour les 2 changements d’heure en Europe, il s’agit du dimanche. Vous utiliserez donc le mot clef « Sun« .
  • Heure: Heure de déclenchement de la règle. Le passage à l’heure d’été se déclenche à 2 heures et le passage à l’heure d’hiver à 3 heures.
  • Décalage: Décalage du fuseau horaire en nombre de minute par rapport à l’heure UTC (Temps universel coordonné). Ce décalage est de 2 heures l’été et 1 heure l’hiver.

Vous en déduisez la règle suivante pour le passage à l’heure d’été:

TimeChangeRule RegleHeureEteFrance_G = {"RHEE", Last, Sun, Mar, 2, 120}; // Règle de passage à l'heure d'été pour la France

et la règle suivante pour le passage à l’heure d’hiver:

TimeChangeRule RegleHeureHiverFrance_G = {"RHHE", Last, Sun, Oct, 3, 60}; // Règle de passage à l'heure d'hiver la France

Vous pouvez maintenant déclarer l’objet de conversion à l’heure française prenant en compte ces 2 règles de changement  d’heure:

Timezone ConvertirHeureFrance_G(RegleHeureEteFrance_G, RegleHeureHiverFrance_G); // Objet de conversion d'heure avec les caractéristiques de la métropole française

Conversion du « Unix Time » en heure locale

Tout d’abord, je vous invite à nettoyer votre fonction loop de ce tout ce qui concerne l’affichage du « Unix Time », ce qui vous permet de conserver l’ossature suivante:

// Fonction principale du programme, s'exécute en boucle:
void loop()
{
    // Variables de la fonction
    time_t HeureLocale_L;   

    if(WiFi.status()==WL_CONNECTED)
    {  
        // Internet est disponible
        HeureLocale_L = ConvertirHeureFrance_G.toLocal(ClientNtp_G.getUnixTime());
        AfficherHeureLocale(HeureLocale_L);
    }
    else
    {
        // Pas de connexion internet
        Afficheur_G.setCursor(0,0);
        Afficheur_G.print("Erreur de       ");
        Afficheur_G.setCursor(0,1);
        Afficheur_G.print("       Connexion");
    }
    delay(300);
}

Sous Arduino et plus généralement en langage C embarqué, le type dédié à la mémorisation d’une date/heure locale est le type « time_t« . Vous commencez donc par déclarer la variable destinée à recevoir cette donnée:

    // Variables de la fonction
    time_t HeureLocale_L;   

Concernant la conversion en elle-même, la méthode « toLocal » de notre objet ConvertirHeureFrance_G permet d’effectuer cette conversion de l' »Unix Time » en heure locale:

        // Internet est disponible
        HeureLocale_L = ConvertirHeureFrance_G.toLocal(ClientNtp_G.getUnixTime());

Afin de rendre le code plus lisible, je vous propose de séparer l’affichage de l’heure locale du reste du code en créant une fonction dédiée appelée « AfficherHeureLocale« . Nous lui passerons l’heure locale en paramètre en utilisant le type C standard « time_t » :

        AfficherHeureLocale(HeureLocale_L);

Fonction d’affichage de l’heure locale

Il ne nous reste plus qu’à écrire la fonction Arduino d’affichage de l’heure locale de notre horloge connectée. Vous commencez par écrire son ossature:

void AfficherHeureLocale(time_t Heure_P)
{
}

Afin de pouvoir afficher

  •  l’abréviation du jour de la semaine en utilisant l’expression « AbreviationJour_L[…] »
  • et du mois en utilisant l’expression « AbreviationMois_L[…]  »

vous déclarez les tableaux suivants:

    char AbreviationMois_L[12][4]={"Jan","Fev","Mar","Avr","Mai","Jun","Jul","Aou","Sep","Oct","Nov","Dec"};
    char AbreviationJour_L[7][4]={"Dim","Lun","Mar","Mer","Jeu","Ven","Sam"};

Pour le reste de la fonction d’affichage de l’heure local, vous utilisez les fonctions de la bibliothèque « Time« :

  • « hour« , « minute« , « second » pour extraire heure, minute et seconde.
  • « weekday » pour le jour de la semaine.
  • « day« , « month » et « year » pour la date complète.

 Vous obtenez alors une fonction d’affichage de la date et l’heure réutilisable dans d’autres programmes, quelque-soit votre source de temps:

void AfficherHeureLocale(time_t Heure_P)
{
    char Buffer_L[50];
    char AbreviationMois_L[12][4]={"Jan","Fev","Mar","Avr","Mai","Jun","Jul","Aou","Sep","Oct","Nov","Dec"};
    char AbreviationJour_L[7][4]={"Dim","Lun","Mar","Mer","Jeu","Ven","Sam"};
    
    Afficheur_G.setCursor(0,0);
    sprintf(Buffer_L, "    %.2d:%.2d:%.2d", hour(Heure_P), minute(Heure_P), second(Heure_P));
    Afficheur_G.print(Buffer_L);
    Afficheur_G.setCursor(0,1);
    sprintf(Buffer_L, "%s %.2d %s %d", AbreviationJour_L[weekday(Heure_P)-1], day(Heure_P), AbreviationMois_L[month(Heure_P)-1], year(Heure_P));
    Afficheur_G.print(Buffer_L);
}

Et voilà votre programme est fini. Voici le code complet:

// Déclaration des librairies utilisées
#include <ESP8266WiFi.h>
#include <LiquidCrystal_I2C.h>
#include <EasyNTPClient.h>
#include <WiFiUdp.h>
#include <Timezone.h>
 
// Déclaration globales
LiquidCrystal_I2C Afficheur_G(0x27, 16, 2); // Afficheur LCD1206 d'addresse 0x27 avec écran de 2 lignes de 16 caractères
WiFiUDP Udp_G; // Objet UDP permettant d'envoyer et recevoir des trames Wi-Fi selon le protocole UDP
EasyNTPClient ClientNtp_G(Udp_G, "pool.ntp.org"); // Objet NTP synchronisé avec "pool.ntp.org"
TimeChangeRule RegleHeureEteFrance_G = {"RHEE", Last, Sun, Mar, 2, 120}; // Règle de passage à l'heure d'été pour la France
TimeChangeRule RegleHeureHiverFrance_G = {"RHHE", Last, Sun, Oct, 3, 60}; // Règle de passage à l'heure d'hiver la France
Timezone ConvertirHeureFrance_G(RegleHeureEteFrance_G, RegleHeureHiverFrance_G); // Objet de conversion d'heure avec les caractéristique de la métropole française

// Fonction de démarrage, s'exécute une seule fois:
void setup()
{
    // Constantes de la fonction
    const char* SSID_L = "LiveBox_1324"; // Nom du réseau Wi-Fi
    const char* MOT_DE_PASSE_L = "12345?ABCDE"; // Mot De Passe du réseau 

    // Variables de la fonction
    wl_status_t StatutConnexion_L; // Pour mémoriser l'état de la connexion
    
    Afficheur_G.init(5,4); // Initialisation de l'afficheur, SDA=5, SCL=4
    Afficheur_G.backlight(); // Allumage du rétroéclairage
 
    WiFi.begin(SSID_L, MOT_DE_PASSE_L); // Tentative de connexion au point d'accès Wi-Fi
    StatutConnexion_L = WiFi.status(); // Lecture de l'état de la connexion et mémorisation dans la variable "StatutConnexion_L"
    while ((StatutConnexion_L != WL_NO_SSID_AVAIL)&&(StatutConnexion_L != WL_CONNECTED)&&(StatutConnexion_L != WL_CONNECT_FAILED))
    {
        delay(500);
        Afficheur_G.print("."); // Pour visualiser la tentative de connexion et faire patienter
        StatutConnexion_L = WiFi.status(); // Lecture de l'état de la connexion et mémorisation dans la variable "StatutConnexion_L"
    }
    
    Afficheur_G.clear(); // On efface l'écran avant l'affichage de l'heure
}

// Fonction principale du programme, s'exécute en boucle:
void loop()
{
    // Variables de la fonction
    time_t HeureLocale_L;   

    if(WiFi.status()==WL_CONNECTED)
    {  
        // Internet est disponible
        HeureLocale_L = ConvertirHeureFrance_G.toLocal(ClientNtp_G.getUnixTime());
        AfficherHeureLocale(HeureLocale_L);
    }
    else
    {
        // Pas de connexion internet
        Afficheur_G.setCursor(0,0);
        Afficheur_G.print("Erreur de       ");
        Afficheur_G.setCursor(0,1);
        Afficheur_G.print("       Connexion");
    }
    delay(300);
}

void AfficherHeureLocale(time_t Heure_P)
{
    char Buffer_L[50];
    char AbreviationMois_L[12][4]={"Jan","Fev","Mar","Avr","Mai","Jun","Jul","Aou","Sep","Oct","Nov","Dec"};
    char AbreviationJour_L[7][4]={"Dim","Lun","Mar","Mer","Jeu","Ven","Sam"};
    
    Afficheur_G.setCursor(0,0);
    sprintf(Buffer_L, "    %.2d:%.2d:%.2d", hour(Heure_P), minute(Heure_P), second(Heure_P));
    Afficheur_G.print(Buffer_L);
    Afficheur_G.setCursor(0,1);
    sprintf(Buffer_L, "%s %.2d %s %d", AbreviationJour_L[weekday(Heure_P)-1], day(Heure_P), AbreviationMois_L[month(Heure_P)-1], year(Heure_P));
    Afficheur_G.print(Buffer_L);
}

Une compilation, un transfert dans l’ESP8285 et voilà le résultat:

Votre horloge connectée est terminée. Si projet Arduino vous a plus, n’hésitez pas à ajouter vos commentaires !

Laisser un commentaire