La Real Time Clock (RTC)
Ce tutoriel explique comment mettre en œuvre l’horloge temps réel ou RTC pour “Real Time Clock” en anglais avec STM32duino.
L’horloge temps réel (Real-Time Clock en anglais, abrégée RTC) est un circuit électronique intégré dans le microcontrôleur remplissant les fonctions d’une horloge très précise pour des problématiques d’horodatage, de gestions d’alarmes déclenchées suivant un calendrier et capable de mettre le microcontrôleur en sommeil ou de le réveiller, etc. Afin qu’elle soit aussi précise et stable que possible, la RTC peut utiliser comme source de fréquence un quartz vibrant à 32kHz.
Utilisation
En premier, il est nécessaire d’importer les bibliothèques :
Elle se télécharge depuis le gestionnaire Arduino sous Croquis > Inclure une bibliothèque > Gérer les bibliothèques
et en cherchant STM32duino RTC
.
// Importation des bibliothèques
#include <STM32RTC.h>
Ensuite nous déclarons la RTC
STM32RTC& rtc = STM32RTC::getInstance();
Puis nous la démarrons
rtc.begin();
Nous pouvons maintenant nous servir de la RTC.
Les profils des fonctions principales sont les suivants :
void setHours(uint8_t hours);
void setMinutes(uint8_t minutes);
void setSeconds(uint8_t seconds);
void setTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds = 1000, AM_PM period = AM);
void setWeekDay(uint8_t weekDay); // 1 pour lundi et 7 pour dimanche
void setDay(uint8_t day);
void setMonth(uint8_t month);
void setYear(uint8_t year);
void setDate(uint8_t weekDay, uint8_t day, uint8_t month, uint8_t year);
uint8_t getHours();
uint8_t getMinutes();
uint8_t getSeconds();
void getTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, AM_PM *period = nullptr);
uint8_t getWeekDay(); // 1 pour lundi et 7 pour dimanche
uint8_t getDay();
uint8_t getMonth();
uint8_t getYear();
void getDate(uint8_t *weekDay, uint8_t *day, uint8_t *month, uint8_t *year);
Pour les valeurs non-souhaitées de getTime
et getDate
il suffit de mettre NULL
lors de l’appel. Par exemple getTime(&hours, &minutes, &seconds, NULL);
permet de récupérer les heures, minutes et secondes sans les sous-secondes.
La date du samedi 2 janvier 2021 à 12h21 51s peut alors être définie comme ceci :
rtc.setTime(12, 21, 51);
rtc.setDate(6, 2, 1, 21);
Et elle peut être récupérée comme cela :
uint8_t hours, minutes, seconds, weekDay, day, month, year;
rtc.getTime(&hours, &minutes, &seconds, NULL);
rtc.getDate(&weekDay, &day, &month, &year);
Ainsi un premier code pour afficher sur le terminal serait :
// Importation des bibliothèques
#include <STM32RTC.h>
// on declare la RTC
STM32RTC& rtc = STM32RTC::getInstance();
void setup(){
// on démarre la rtc
rtc.begin();
// on initialise l'heure et la date
rtc.setTime(12, 21, 51);
rtc.setDate(6, 2, 1, 21);
}
void loop() {
uint8_t hours, minutes, seconds, weekDay, day, month, year;
// on récupère la date et l'heure
rtc.getTime(&hours, &minutes, &seconds, NULL);
rtc.getDate(&weekDay, &day, &month, &year);
// on affiche
printf("%d -- %d/%d/%d -- %02d:%02d:%02d\n", weekDay, day, month, year, hours, month, seconds);
// toutes les secondes
delay(1000);
}
On notera que la RTC ne prend son intérêt que s’il est possible de la (re)mettre à la date et à l’heure automatiquement et régulièrement. C’est un sujet nettement plus complexe. Le deuxième exemple, ci-après, montre comment s’y prendre avec une connexion Wi-Fi à l’Internet.
Deux applications plus abouties
Premier exemple : Une horloge avec affichage LED
Cet exemple montre comment réaliser une horloge à l’aide d’un afficheur 8x7-segments TM1638 et de la RTC d’un microcontrôleur STM32. Le tutoriel sur le module TM1638 est un prérequis indispensable à cet exercice.
Matériel requis
- Une carte NUCLEO-L476RG de STMicroelectronics.
- Un module afficheur 8x7-segments TM1638, comme celui de ce tutoriel.
Bibliothèque(s) requise(s) pour ce sketch
Deux bibliothèques tierce-partie sont requises pour cet exemple :
- La bibliothèque TM1638plus de Gavin Lyons
- La bibliothèque STM3duino RTC de STMicroelectronics, Wi6Labs
Le sketch Arduino
Le sketch pour cet exemple (et tous les autres) peut être téléchargé en cliquant ici.
Lancez l’IDE Arduino, ouvrez un nouveau sketch vide et copiez-y le code qui suit :
// Importation des bibliothèques
#include <STM32RTC.h>
#include <TM1638plus.h>
// Déclaration de la RTC
STM32RTC& rtc = STM32RTC::getInstance();
// Déclaration du module TM1638
// STB CLK DIO
TM1638plus tm(D2, D3 , D4);
void setup() {
// On démarre la RTC
rtc.begin();
// On initialise l'heure et la date de la RTC
rtc.setTime(0, 0, 0);
rtc.setDate(5, 1, 1, 21);
// Début de l'affichage
tm.displayBegin();
// On réduit la luminosité du module TM1638
tm.brightness(0);
}
void loop() {
uint8_t hours, minutes, seconds, weekDay, day, month, year, boutons;
char str[9];
// On récupère la date et l'heure
rtc.getTime(&hours, &minutes, &seconds, NULL);
if (seconds % 2){
sprintf(str, "%02dh%02d .%02d", hours, minutes, seconds);
tm.displayText(str);
}
else{
sprintf(str, "%02dh%02d %02d", hours, minutes, seconds);
tm.displayText(str);
}
// On récupère l'information sur les boutons
boutons = tm.readButtons();
// On compare bit à bit pour identifier le bouton
if (boutons & 1) {
hours++;
if (hours > 23) {
hours = 0;
}
rtc.setHours(hours);
}
if (boutons & 1<<1) {
minutes++;
if (minutes > 59) {
minutes = 0;
}
rtc.setMinutes(minutes);
}
if (boutons & 1<<2) {
seconds++;
if (seconds > 59) {
seconds = 0;
}
rtc.setSeconds(seconds);
}
// On actualise toute les 100 milisecondes (pour une lecture des boutons plus sensible, peut être modifié)
delay(100);
}
Deuxième exemple : Réglage automatique de la RTC avec un serveur NTC via Wi-Fi
Cet exercice est un prolongement du tutoriel sur le NTP avec module Grove UART Wi-Fi V2, qui est donc un prérequis indispensable à cet exercice. Il s’agit de réaliser une requête sur un serveur NTP après s’être connecté en Wi-Fi à Internet et d’utiliser la réponse de celui-ci pour régler la RTC du STM32. Nous en profitons pour gérer deux complications classiques :
- L’ajustement d’heure dû au fuseau horaire ;
- L’ajustement d’heure saisonnier. Sa suppression est prévue en France depuis 2019, mais l’application de cette décision se fait désirer …
Matériel requis
- Une carte NUCLEO-L476RG de STMicroelectronics. N’importe quelle autre carte NUCLEO fera l’affaire à condition qu’elle expose sur ses broches un port série UART libre en plus de celui utilisé pour l’interaction avec le ST-LINK et l’IDE Arduino (voir plus loin).
- Un câble adaptateur Grove / Dupont (mâle ou, de préférence, femelle) pour connecter le module Grove sur les broches de la carte NUCLEO.
- Un module Grove UART Wi-Fi v2 avec STM32duino.
Attention : Il est bien question ici de la version 2 de ce module. Nous ne sommes pas parvenus à faire fonctionner la version 1 ; la raison de cet échec étant probablement liée à une incompatibilité de son firmware AT avec la bibliothèque Arduino WiFiESP.
Bibliothèque(s) requise(s) pour ce sketch
Deux bibliothèques tierce-partie sont requises pour cet exemple :
- La bibliothèque WiFiESP de Bruno Portaluri
- La bibliothèque STM32duino RTC de STMicroelectronics, Wi6Labs
Le sketch Arduino
Le sketch ci-dessous peut être téléchargé par ce lien.
Lancez l’IDE Arduino, ouvrez un nouveau sketch vide et copiez-y le code qui suit :
/*------------------------------------------------------------------------------------------------------------
Objet(s) du sketch :
- Connectivité Wi-Fi avec un module ESP01 ou Grove Wi-Fi V2
- Interrogation d'un serveur NTP et affichage du temps universel coordonné (UTC) sous un format lisible
- Réglage de la RTC à partir des informations du serveur NTP, gestion du décalage horaire méridien
et saisonnier
-------------------------------------------------------------------------------------------------------------
Matériel & brochage :
- Carte NUCLEO-L476RG
- Module Wi-Fi ESP-01 ou Grove UART Wi-Fi v2 sur UART4
-----------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* Variables globales, includes, defines */
/*----------------------------------------------------------------------------*/
/* Déclarations pour le Wi-Fi */
#include <WiFiEsp.h>
#define WIFI_BDRATE (115200)
#define WIFI_SSID "mySSID"
#define WIFI_PASS "myPASS"
#define RESET_RETRY (2)
#define DELAY_5S (5000)
HardwareSerial WiFi_Serial(PA1, PA0);
char ssid[] = WIFI_SSID;
char pass[] = WIFI_PASS;
/* Déclarations pour le service UDP */
/* et pour l'interrogation du NTP */
#include <WiFiEspUdp.h>
#define UDP_PORT (2390)
WiFiEspUDP Udp;
// Adresses IP de deux serveurs NTP
#define NTP_SERVER_1 "216.239.35.4"
#define NTP_SERVER_2 "time.nist.gov"
char TimeServer1[] = NTP_SERVER_1;
char TimeServer2[] = NTP_SERVER_2;
/* Gestion de l'interrogation réglière du NTP avec un timer */
// Fréquence du Timer 1 en Hz
#define TIMER1_FREQ (1) // Un tic par seconde
// Nombre d'overflows du timer 1 constituant la base de temps
#define TIME_BASE (3600) // Soit, un heure dans notre cas
// Instanciation du timer 1
TIM_TypeDef *Instance = TIM1;
HardwareTimer Timer1(Instance);
// Compteur pour le temps écoulé
volatile uint32_t TickCounter = 0;
// Déclarations pour la RTC
#include <STM32RTC.h>
STM32RTC &rtc = STM32RTC::getInstance();
/* Déclarations diverses */
// Débit du port série du ST-LINK
#define STLK_BDRATE (115200)
// Variable pour repérer la prmière itération de la fonction loop()
bool start = true;
// Déclarations pour le fuseau horaire et l’ajustement d’heure saisonnier
#define SUMMER_TIME_MONTH (3) // Mois du passage à l'heure d'été
#define WINTER_TIME_MONTH (10) // Mois du passage à l'heure d'hivers
#define DST_WEEKDAY (7) // Jour du changement d'heure saisonnier
#define SECS_PER_DAY (86400) // Dans une journée on a 86400 secondes
#define GMT_OFFSET (+1) // Ajustement d'heure dû au fuseau horaire
byte dst_offset; // Ajustement d'heure saisonnier
// Structure pour le calcul de la date et de l'heure locales
struct DateTime {
byte Year;
byte Month;
byte Day;
byte Hours;
byte Minutes;
byte Seconds;
byte WeekDay;
};
/* Initialisations */
void setup() {
// Initialisation du port série
Serial.begin(STLK_BDRATE);
while (!Serial) delay(100);
Serial.println("Port série du ST-LINK initialisé");
// Initialise le module Wi-Fi
Initialize_WiFi(&Serial);
// Liste les réseaux Wi-Fi à proximité
listWiFiNetworks(&Serial);
// Connexion du module Wi-Fi au réseau spécifié
Connect_WiFi(&Serial);
// Initialisation et démarrage du Timer 1 et de son interruption pour la base de temps
Timer1_Start();
// Démarre la RTC
rtc.setClockSource(STM32RTC::LSE_CLOCK); // Choix de la source d'horloge
rtc.begin();
Serial.println("Initialisations terminées !");
}
/* Boucle principale */
void loop() {
// Interrogation du serveur NTP
// à la prmière entrée dans loop() puis
// toutes les TIME_BASE interruptions du timer 1
if (start || TickCounter > TIME_BASE - 1) {
// Signale qu'on est entré au moins une fois dans loop()
start = false;
// Réglage de la RTC
Set_RTC_Time(&Serial);
// Affichage de la date et de l'heure locales
// On interroge la RTC pour extraire le temps universel coordonné
uint32_t UTC_time = rtc.getEpoch();
// On écrit dans le tableau datetime la date et le temps locaux
char datetime[18];
Make_Local_TimeStamp(datetime, UTC_time);
Serial.print("Date et heure locales : " + String(datetime));
TickCounter = 0;
}
}
/****************************************************************/
/* Démarrage du Timer 1 et de son interruption (base de temps) */
/****************************************************************/
void Timer1_Start(void) {
Timer1.setOverflow(TIMER1_FREQ, HERTZ_FORMAT);
Timer1.attachInterrupt(Timer1_ISR);
Timer1.resume();
Serial.println("Timer 1 actif !");
}
/*******************************************************************/
/* Fonction de service de l'interruption de dépassement du Timer 1 */
/*******************************************************************/
void Timer1_ISR(void) {
TickCounter++;
}
/*----------------------------------------------------------------------------*/
/* Initialisation du module WiFi */
/*----------------------------------------------------------------------------*/
void Initialize_WiFi(HardwareSerial *serial) {
// Initialise le port série du WiFi
WiFi_Serial.begin(WIFI_BDRATE);
while (!WiFi_Serial) delay(100);
serial->println("Port série du module Wi-Fi initialisé");
// Initialise le module ESP01
WiFi.init(&WiFi_Serial);
if (WiFi.status() == WL_NO_SHIELD) {
serial->println("Aucun module Wi-Fi n'a été détecté !");
while (true)
;
}
serial->println("Module Wi-Fi initialisé");
}
/*----------------------------------------------------------------------------*/
/* Connexion au WiFi */
/*----------------------------------------------------------------------------*/
void Connect_WiFi(HardwareSerial *serial) {
uint8_t status = WL_IDLE_STATUS;
uint8_t n = 0;
// Aussi longtemps que le module ne valide pas sa connexion au point d'accès
while (status != WL_CONNECTED) {
serial->println("Tentative de connexion à " + (String)ssid);
status = WiFi.begin(ssid, pass);
n++;
// Si trop de tentatives de reconnexion infructueuses, RESET !
if (n > RESET_RETRY) HAL_NVIC_SystemReset();
// Cinq secondes entre deux tentatives de connexion
delay(DELAY_5S);
}
serial->println("Module Wi-Fi connecté au point d'accès");
}
/*----------------------------------------------------------------------------*/
/* Renvoie la liste de réseaux WiFi présents sur le port série spécifié */
/*----------------------------------------------------------------------------*/
void listWiFiNetworks(HardwareSerial *serial) {
// Cherche les réseaux Wifi à proximité
int numSsid = WiFi.scanNetworks();
if (numSsid == -1) {
serial->println("Aucun point d'accès Wi-Fi n'a été trouvé");
while (true)
;
}
// Renvoie la liste des réseaux trouvés sur le port série serial
serial->println("Points d'accès Wi-Fi disponibles :");
for (int thisNet = 0; thisNet < numSsid; thisNet++) {
if (strlen(WiFi.SSID(thisNet))) {
// Si des points d'accès on été trouvés affiche les informations :
serial->print(" - ");
serial->print(thisNet); // Numéro détecté
serial->print(" ");
serial->print(WiFi.SSID(thisNet)); // Identifiant
serial->print(" Signal: ");
serial->print(WiFi.RSSI(thisNet)); // Atténuation
serial->print(" dBm");
serial->print(" Encryption: "); // Mode de sécurité
int thisType = WiFi.encryptionType(thisNet);
switch (thisType) {
case ENC_TYPE_WEP:
serial->println("WEP");
break;
case ENC_TYPE_WPA_PSK:
serial->println("WPA_PSK");
break;
case ENC_TYPE_WPA2_PSK:
serial->println("WPA2_PSK");
break;
case ENC_TYPE_WPA_WPA2_PSK:
serial->println("WPA_WPA2_PSK");
break;
case ENC_TYPE_NONE:
serial->println("Aucune");
break;
}
}
}
}
/*----------------------------------------------------------------------------*/
/* Récupération du temps universel et mise à l'heure de la RTC. */
/* Gère également l'heure d'hivers / d'été en France (changements les */
/* derniers dimanches des mois de mars et octobre) */
/*----------------------------------------------------------------------------*/
void Set_RTC_Time(HardwareSerial *serial) {
serial->println("Interrogation du serveur de temps");
uint8_t n = 0;
bool try_alternative_ntp_server = false;
bool success = false;
// Aussi longtemps qu'on n'a pas obtenu une réponse à la requête NTP
while (!success) {
uint32_t UTC_NOW;
// Récupère l'heure et la date universelles de l'instant
if (!try_alternative_ntp_server) {
UTC_NOW = getUTC(TimeServer1); // Interroge le serveur NTP n°1
} else { // Si le serveur NTP n°1 n'a pas répondu ...
UTC_NOW = getUTC(TimeServer2); // ... interroge le serveur NTP n°2
}
// Si la requête au serveur NTP est un succès
if (UTC_NOW) {
// Règle le calendrier et l'horloge de la RTC avec le temps universel ...
rtc.setEpoch(UTC_NOW);
// ... pour en extraire l'année courante
byte Current_Year = rtc.getYear();
// Obtient la date du changement d'heure en été pour l'année en cours
uint32_t UTC_SUMMER = Get_DST_Date(Current_Year, SUMMER_TIME_MONTH, DST_WEEKDAY);
// Obtient la date du changement d'heure en hivers pour l'année en cours
uint32_t UTC_WINTER = Get_DST_Date(Current_Year, WINTER_TIME_MONTH, DST_WEEKDAY);
// Si on n'est pas encore en été ou si on est en hivers ...
if (UTC_NOW < UTC_SUMMER || UTC_NOW > UTC_WINTER) {
dst_offset = 0; // ... pas d'ajustement
}
// Si on est en été ou en automne
else if (UTC_NOW > UTC_SUMMER && UTC_NOW < UTC_WINTER) {
dst_offset = 1; // ... rajoute 1 heure
}
serial->println("Décalage horaire saisonnier : +" + String(dst_offset) + " heure(s)");
// Le calcul de l'ajustement d'heure a utilisé, et de ce fait déréglé, la RTC.
// Nous devons à nouveau interroger le serveur NTP pour remettre la RTC à l'heure courante.
// Nous imposons une pause de DELAY_5S avant d'interroger à nouveau le NTP pour que celui-ci
// ne rejette pas notre requête.
delay(DELAY_5S);
if (!try_alternative_ntp_server) {
UTC_NOW = getUTC(TimeServer1);
} else {
UTC_NOW = getUTC(TimeServer2);
}
rtc.setEpoch(UTC_NOW);
success = true;
} else { // Si la requête au serveur NTP a échoué
serial->println("Echec de la requête NTP !");
// Teste l'autre serveur NTP
try_alternative_ntp_server = true;
n++;
// Si c'est le deuxième échec consécutif, reset du microcontrôleur
if (n > RESET_RETRY) HAL_NVIC_SystemReset();
delay(DELAY_5S);
}
}
}
/*----------------------------------------------------------------------------*/
/* Fournit la date de l'heure d'été/d'hivers */
/* Entrée : */
/* Year : année concernée */
/* Month : mois concerné */
/* WeekDay : jour concerné (lundi = 1 ... dimanche = 7) */
/* Sortie : */
/* valeur UTC de la date du changement d'heure en entrée */
/* ATTENTION : Gère l'heure d'hivers / d'été selon la règle appliquée en */
/* France (changements les DERNIERS dimanches des mois de mars et octobre) */
/*----------------------------------------------------------------------------*/
uint32_t Get_DST_Date(byte Year, byte Month, byte WeekDay) {
const byte day_one = 1;
// L'heure avant le changement est toujours 3h00
const byte dsts = 0;
const byte dstm = 0;
const byte dsth = 3;
rtc.setTime(dsth, dstm, dsts);
// On initialise la RTC au premier jour du mois du changement d'heure
rtc.setDay(day_one);
rtc.setMonth(Month);
rtc.setYear(Year);
/* On récupère le temps universel et on re-paramètre l'horloge avec setEpoch() */
/* afin que la fonction getWeekDay() renvoie par la suite des valeurs correctes */
// Temps universel du premier jour du mois du changement d'heure
uint32_t utc = rtc.getEpoch();
rtc.setEpoch(utc);
// Calcul itératif de la date exacte du changement d'heure en France :
// Renvoie le DERNIER WeekDay du mois en question.
byte WeekDay_ = rtc.getWeekDay();
byte Month_ = rtc.getMonth();
uint32_t utc_ = 0;
// Aussi longtemps que l'on reste dans le mois sélectionné
while (Month_ == Month) {
// Si le jour est susceptible d'être celui du changement d'heure
if (WeekDay_ == WeekDay) {
utc_ = utc; // alors sauvegarde le temps universel de ce jour
}
// Passe au jour suivant
utc = utc + SECS_PER_DAY;
// Avance la RTC d'un jour
rtc.setEpoch(utc);
WeekDay_ = rtc.getWeekDay();
Month_ = rtc.getMonth();
}
// A la sortie de la boucle, _utc contient bien le DERNIER WeekDay du mois
// du changement d'heure !
return utc_;
}
/*----------------------------------------------------------------------------*/
/* Requête au serveur de temps internet pour récupérer le temps universel */
/* coordonné (UTC). */
/*----------------------------------------------------------------------------*/
uint32_t getUTC(char *ntpSrv) {
const uint32_t NTP_PACKET_SIZE = 48;
const uint32_t UDP_TIMEOUT = 2000;
byte packetBuffer[NTP_PACKET_SIZE];
uint32_t UTC = 0;
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011;
packetBuffer[1] = 0;
packetBuffer[2] = 6;
packetBuffer[3] = 0xEC;
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.begin(UDP_PORT);
Udp.beginPacket(ntpSrv, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
uint32_t startMs = millis();
while (!Udp.available() && (millis() - startMs) < UDP_TIMEOUT)
;
if (Udp.parsePacket()) {
Udp.read(packetBuffer, NTP_PACKET_SIZE);
uint32_t highWord = word(packetBuffer[40], packetBuffer[41]);
uint32_t lowWord = word(packetBuffer[42], packetBuffer[43]);
uint32_t secsSince1900 = highWord << 16 | lowWord;
const uint32_t seventyYears = 2208988800UL;
UTC = secsSince1900 - seventyYears;
Udp.stop();
}
return UTC;
}
/*-----------------------------------------------------------------------------*/
/* Remplis un tableau de caractères avec la date et l'heure à partir */
/* des données exprimées en temps universel. */
/* Intègre les corrections de méridien et les corrections d'heure d'été/hivers.*/
/*-----------------------------------------------------------------------------*/
void Make_Local_TimeStamp(char *timestamp, uint32_t UTC_time) {
DateTime date_time;
date_time.Year = rtc.getYear();
date_time.Month = rtc.getMonth();
date_time.Day = rtc.getDay();
// Le modulo sur 24 heures (%24) ci-dessous permet de conserver une heure
// entre 00:00 et 23:59 après les corrections saisonnière et méridienne
date_time.Hours = ((rtc.getHours() + (byte)GMT_OFFSET + dst_offset) % 24);
date_time.Minutes = rtc.getMinutes();
date_time.Seconds = rtc.getSeconds();
// Remplis un tableau de caractères avec la date et l'heure à partir
// des données exprimées en bytes
char two_bytes[3];
snprintf(two_bytes, 3, "%02d", date_time.Year);
timestamp[0] = two_bytes[0];
timestamp[1] = two_bytes[1];
timestamp[2] = '/';
snprintf(two_bytes, 3, "%02d", date_time.Month);
timestamp[3] = two_bytes[0];
timestamp[4] = two_bytes[1];
timestamp[5] = '/';
snprintf(two_bytes, 3, "%02d", date_time.Day);
timestamp[6] = two_bytes[0];
timestamp[7] = two_bytes[1];
timestamp[8] = ' ';
snprintf(two_bytes, 3, "%02d", date_time.Hours);
timestamp[9] = two_bytes[0];
timestamp[10] = two_bytes[1];
timestamp[11] = ':';
snprintf(two_bytes, 3, "%02d", date_time.Minutes);
timestamp[12] = two_bytes[0];
timestamp[13] = two_bytes[1];
timestamp[14] = ':';
snprintf(two_bytes, 3, "%02d", date_time.Seconds);
timestamp[15] = two_bytes[0];
timestamp[16] = two_bytes[1];
timestamp[17] = '\0';
}
Affichage sur le terminal série
Si tout s’est passé correctement vous devriez observer cette séquence de messages (où, bien sûr, “mySSID” devrait être remplacé par le nom de votre point d’accès) sur le terminal série de l’IDE Arduino :
16:50:07.708 -> Port série du ST-LINK initialisé
16:50:07.708 -> Port série du module Wi-Fi initialisé
16:50:07.708 -> [WiFiEsp] Initializing ESP module
16:50:11.133 -> [WiFiEsp] Initilization successful - 2.2.1
16:50:11.133 -> Module Wi-Fi initialisé
16:50:13.320 -> Points d'accès Wi-Fi disponibles :
16:50:13.320 -> - 0 mySSID Signal: -48 dBm Encryption: WPA2_PSK
16:50:13.320 -> Tentative de connexion à mySSID
16:50:18.399 -> [WiFiEsp] Connected to mySSID
16:50:23.385 -> Module Wi-Fi connecté au point d'accès
16:50:23.385 -> Timer 1 actif !
16:50:23.556 -> Initialisations terminées !
16:50:23.556 -> Interrogation du serveur de temps
16:50:23.705 -> Décalage horaire saisonnier : +0 heure(s)
16:50:28.991 -> Date et heure locales : 23/02/26 16:50:28
On remarquera que le décalage horaire saisonnier est nul car nous sommes le 26 février 2023 au moment de ce test (“heure d’hiver”).