Skip to Content

Alarmes avec l’horloge temps réel DS3231

Alarmes avec l’horloge temps réel DS3231

Dans ce tutoriel, vous apprendrez à utiliser les alarmes avec le Real-Time-Clock (RTC) DS3231 et un Arduino.

Le module DS3231 est une horloge externe. Il possède sa propre batterie et garde la trace de l’heure et de la date actuelles même lorsque l’alimentation principale est coupée. Il dispose en outre de deux registres d’alarme que vous pouvez configurer pour déclencher des alarmes à des heures et dates spécifiées.

Un Real-Time-Clock est particulièrement utile lorsque vous souhaitez mettre l’Arduino en veille pour de longues périodes. La durée maximale de veille pour un Arduino Uno est de 8 secondes. Mais avec un RTC, vous pouvez avoir des durées de veille arbitrairement longues, ce qui est idéal pour prolonger la durée de vie des batteries de journaux de données, par exemple.

Pièces requises

Pour ce projet, vous aurez besoin d’un module RTC DS3231 et d’un Arduino. J’ai utilisé un Arduino Uno, mais tout autre Arduino fonctionnera également. Enfin, dans un des exemples de code de ce tutoriel, j’utilise un buzzer passif pour émettre une alarme.

Module RTC DS3231

Arduino

Arduino Uno

USB Data Sync cable Arduino

Câble USB pour Arduino UNO

Buzzer passif

Dupont wire set

Jeu de fils Dupont

Half_breadboard56a

Plaque d’essai (breadboard)

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Notions de base sur le module RTC DS3231

Le module RTC DS3231 est une horloge temps réel précise basée sur le DS3231 Chip. En plus du DS3231, il possède une AT24C32 EEPROM, et un support pour une CR2032 pile.

Grâce à sa batterie, le DS3231 maintient une heure précise même si l’Arduino perd son alimentation, redémarre ou passe en mode veille. L’image ci-dessous montre le devant et le dos d’un module RTC DS3231 typique :


Front and back of DS3231 RTC Module
Devant et dos du module RTC DS3231

Si vous avez besoin de plus de détails sur le module RTC DS3231, consultez notre Arduino and RTC Module DS3231 tutoriel.

Brochage du module RTC DS3231

Le brochage du module RTC DS3231 est le suivant : VCC et GND sont pour l’alimentation, avec une tension d’alimentation de 3,3 à 5,5 V. SCL et SDA sont les broches pour l’interface I2C. Les broches 32K et SQW sont des sorties pour le signal d’horloge 32 kHz et un signal carré programmable. La sortie SQW peut aussi être configurée comme sortie de signal d’interruption, que nous utiliserons plus tard.

Pinout of DS3231 RTC Module
Brochage du module RTC DS3231

Bien que le module RTC DS3231 fonctionne sous 5 V, vous devriez utiliser 3,3 V comme alimentation si vous avez une pile CR2032 insérée. Le module possède un circuit de charge très basique qui endommagerait la pile si vous alimentez le module en 5 V. Pour plus d’informations, lisez le Arduino and RTC Module DS3231 tutoriel et l’article Battery charging circuit of DS3231 module.

Connexion du module RTC DS3231 à l’Arduino

Connecter le module RTC DS3231 à un Arduino est simple. D’abord, connectez les broches SCL et SDA du module RTC DS3231 aux broches correspondantes sur la carte Arduino comme montré ci-dessous. Ensuite, connectez la masse à GND et 3,3 V à VCC du module RTC DS3231, et c’est tout.

Connecting DS3231 RTC Module to Arduino
Connexion du module RTC DS3231 à l’Arduino

N’oubliez pas d’alimenter le module RTC DS3231 en 3,3 V, sinon une pile CR2032 insérée pourrait être endommagée.

Code de test simple pour le module RTC DS3231

Vous devriez utiliser une bibliothèque logicielle pour communiquer avec le module RTC DS3231. Il en existe plusieurs, mais ici j’utilise la bibliothèque Arduino-DS3231 de Korneliusz Jarzębski. Pour l’installer, allez dans github repo et cliquez sur le bouton vert « Code ». Puis sélectionnez « Download Zip » dans le menu comme montré ci-dessous :

Download ZIP file for Arduino-DS3231library
Télécharger le fichier ZIP pour Arduino-DS3231library

Cela téléchargera un fichier nommé « Arduino-DS3231-dev.zip » sur votre ordinateur. Pour installer cette bibliothèque ZIP, suivez les étapes habituelles. Cliquez sur Sketch -> Add .ZIP Library, puis sélectionnez le fichier Arduino-DS3231-dev.zip que vous venez de télécharger.

Installing a .ZIP Arduino library
Installation d’une bibliothèque Arduino au format .ZIP

Avec la bibliothèque installée, vous pouvez tester le fonctionnement du module RTC DS3231. L’exemple de code simple suivant règle l’heure et la date du module RTC à l’heure de compilation du sketch, puis affiche l’heure et la date en boucle :

#include "Wire.h"
#include "DS3231.h"

DS3231 rtc;

void setup() {
  Serial.begin(9600);
  rtc.begin();
  rtc.setDateTime(__DATE__, __TIME__);
}

void loop() {
  RTCDateTime  dt = rtc.getDateTime();
  Serial.println(rtc.dateFormat("d-m-Y H:i:s", dt));
  delay(1000);
}

Le code commence par inclure la bibliothèque Wire.h pour la communication I2C et la bibliothèque DS3231.h pour communiquer avec le RTC DS3231.

Ensuite, nous créons une instance de la classe DS3231. Dans la fonction setup(), nous initialisons le RTC et réglons la date et l’heure actuelles en utilisant rtc.setDateTime(). Les macros __DATE__ et __TIME__ insèrent automatiquement la date et l’heure de compilation du sketch. Notez que l’heure ne sera pas à jour si l’Arduino est redémarré après la compilation et le téléversement du code.

Dans la fonction loop, nous récupérons la date et l’heure du RTC avec RTCDateTime dt = rtc.getDateTime(), formatons la date et l’heure en chaîne de caractères et l’affichons dans le moniteur série avec Serial.println(rtc.dateFormat("d-m-Y H:i:s", dt)). Le format spécifié ici est day-month-year hours:minutes:seconds. Consultez le DS3231_dateformat.ino file de la bibliothèque Arduino-DS3231 pour plus d’exemples de formatage.

Enfin, nous introduisons un délai d’une seconde, pour éviter que le moniteur série ne soit saturé de messages.

Exemple de sortie

Si vous téléversez le code et ouvrez le moniteur série, vous devriez voir la date et l’heure s’afficher comme suit :

RTC date and time printed in Serial Monitor
Date et heure du RTC affichées dans le moniteur série

Après avoir vérifié que le DS3231 est correctement câblé et fonctionne, parlons de la fonction alarme du DS3231.

Registres d’alarmes du DS3231

Le module RTC DS3231 possède deux registres d’alarme : Alarme 1 et Alarme 2. Ces deux alarmes peuvent déclencher des événements basés sur des conditions temporelles spécifiques. Le tableau suivant montre les réglages des bits pour ces conditions :

Alarms register bit masks of the DS3231
Masques de bits des registres d’alarmes du DS3231 (source)

Comme vous pouvez le voir, l’Alarme 1 offre plus d’options de configuration. Vous pouvez la régler pour déclencher en fonction des secondes, minutes, heures et jour/date. L’Alarme 2 ne permet de régler que les minutes, heures et jour/date. De plus, l’Alarme 1 peut être configurée pour se déclencher toutes les minutes, quotidiennement ou hebdomadairement, tandis que l’Alarme 2 ne peut se déclencher qu’une fois ou toutes les minutes.

Cependant, aucune des deux alarmes ne permet de déclencher une alarme périodiquement si elle ne correspond pas à une unité de base. Par exemple, vous pouvez déclencher une alarme toutes les minutes, ou à la dixième seconde de chaque minute, mais vous ne pouvez pas déclencher une alarme toutes les 10 secondes en utilisant les registres d’alarme. Mais je vais vous montrer comment contourner cette limitation.

Exemples de code pour les alarmes avec DS3231

Dans cette section, nous allons discuter de divers exemples de code pour déclencher ou utiliser des alarmes.

Déclencher des événements sans utiliser les registres d’alarme du DS3231

Commençons par un exemple qui n’utilise pas réellement le registre d’alarme. À la place, nous interrogeons continuellement le DS3231 et vérifions son heure et sa date. Si elles correspondent à certaines conditions spécifiées, nous exécutons une action. L’exemple de code suivant affiche l’heure actuelle toutes les 10 secondes :

#include "Wire.h"
#include "DS3231.h"

DS3231 rtc;

void setup() {
  Serial.begin(9600);
  rtc.begin();
  rtc.setDateTime(__DATE__, __TIME__);
}

void loop() {
  RTCDateTime dt = rtc.getDateTime();
  if (dt.second % 10 == 0) {   
    Serial.println(rtc.dateFormat("H:i:s", dt)); 
    delay(1000);  
  }
}

La ligne critique est la suivante, où nous vérifions si les secondes sont divisibles par 10 en utilisant l’opérateur modulo (%) :

if (dt.second % 10 == 0) 

Si c’est le cas, nous affichons l’heure. Notez que vous devez ajouter un délai d’au moins 1 seconde (delay(1000)), sinon l’heure sera affichée plusieurs fois, car la boucle s’exécute plus vite qu’une seconde.

L’avantage de déclencher des alarmes de cette manière est que vous n’êtes pas limité aux conditions de déclenchement supportées par les registres d’alarme. Par exemple, si vous voulez afficher l’heure toutes les 10 secondes mais seulement le week-end (dt.dayOfWeek >= 6), vous pouvez écrire la condition suivante :

  if ((dt.dayOfWeek >= 6) && (dt.second % 10 == 0)) {   
    Serial.println(rtc.dateFormat("H:i:s", dt)); 
    delay(1000);  
  }

La classe RTCDateTime struct de la bibliothèque Arduino-DS3231 possède les membres temps et date suivants que vous pouvez utiliser pour implémenter votre propre condition de déclenchement :

struct RTCDateTime {
    uint16_t year;
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
    uint8_t dayOfWeek;
    uint32_t unixtime;
};

Bien que cela vous donne une liberté totale, implémenter correctement les conditions de déclenchement peut être assez complexe et vous ne pouvez pas utiliser les interruptions de cette façon. Nous parlerons des interruptions plus tard.

Dans la section suivante, je vous montre comment utiliser les registres d’alarme pour déclencher un événement. Les conditions sont plus limitées, mais le code sera plus court et plus robuste.

Déclencher des événements en utilisant les registres d’alarme du DS3231

L’exemple de code suivant affiche l’heure actuelle du RTC toutes les heures en utilisant l’Alarme 2 :

#include "Wire.h"
#include "DS3231.h"

DS3231 rtc;

void setup() {
  Serial.begin(9600);
  rtc.begin();
  rtc.setDateTime(__DATE__, __TIME__);
  rtc.setAlarm2(0, 0, 0, DS3231_MATCH_M);
}

void loop() {
  if (rtc.isAlarm2()) {  // also clears alarm
    RTCDateTime dt = rtc.getDateTime();
    Serial.println(rtc.dateFormat("H:i:s", dt));
  }
}

Il y a deux nouvelles lignes de code. Premièrement, nous définissons la condition de déclenchement pour l’Alarme 2 dans la fonction setup via

rtc.setAlarm2(0, 0, 0, DS3231_MATCH_M);

Cette condition se déclenche lorsque la minute est égale à 0 (DS3231_MATCH_M), c’est-à-dire une fois par heure.

Deuxièmement, nous vérifions si la condition est déclenchée pour l’Alarme 2 dans la fonction loop via

if (rtc.isAlarm2())

C’est plus court et plus robuste, comparé à vérifier la condition nous-mêmes. Par exemple, vous devriez écrire le code suivant pour déclencher toutes les minutes si vous vérifiez vous-même les champs de temps et date :

  if ((rtc.minute==0) & (rec.second==0)) {
    RTCDateTime dt = rtc.getDateTime();
    Serial.println(rtc.dateFormat("H:i:s", dt));
    delay(1000);
  }

En utilisant la fonction isAlarm2(), la condition devient plus simple et nous n’avons plus besoin de delay(), car isAlarm2() efface l’alarme une fois qu’elle a été déclenchée. Vous pouvez désactiver ce comportement en appelant isAlarm2(false) à la place.

Correspondance temps et date

Les conditions de déclenchement sont définies en spécifiant quelles parties du temps et de la date doivent correspondre à des valeurs données. Par exemple, si vous voulez déclencher une alarme tous les lundis (=1) à 10:45:30, vous régleriez la condition d’alarme suivante :

setAlarm1(1, 10, 45, 30, DS3231_MATCH_DY_H_M_S);

Notez que seule l’Alarme 1 supporte la correspondance des secondes. L’énumération ci-dessous montre les constantes matching avec leurs masques de bits supportés par la bibliothèque Arduino-DS3231 pour l’Alarme 1 :

typedef enum {
    DS3231_EVERY_SECOND   = 0b00001111,
    DS3231_MATCH_S        = 0b00001110,
    DS3231_MATCH_M_S      = 0b00001100,
    DS3231_MATCH_H_M_S    = 0b00001000,
    DS3231_MATCH_DT_H_M_S = 0b00000000,
    DS3231_MATCH_DY_H_M_S = 0b00010000
} DS3231_alarm1_t;

et voici celles pour l’Alarme 2 :

typedef enum {
    DS3231_EVERY_MINUTE   = 0b00001110,
    DS3231_MATCH_M        = 0b00001100,
    DS3231_MATCH_H_M      = 0b00001000,
    DS3231_MATCH_DT_H_M   = 0b00000000,
    DS3231_MATCH_DY_H_M   = 0b00010000
} DS3231_alarm2_t;

Vous pouvez trouver plus d’exemples sur la correspondance de certaines heures et dates dans le fichier d’exemple DS3231_alarm.ino de la bibliothèque Arduino-DS3231.

Que vous utilisiez isAlarm1(), isAlarm2() ou que vous compariez vous-même les champs de date et heure (par exemple dt.second==10), cela implique toujours une interrogation continue dans la fonction loop pour détecter si une alarme a été déclenchée.

Selon la charge de travail dans la fonction loop et sa durée d’exécution, cela peut retarder la détection d’une alarme. Par exemple, si le code dans loop prend 30 secondes à s’exécuter mais que vous voulez réagir à une alarme en moins d’une seconde, cela ne sera pas possible.

Les interruptions sont une solution à ce problème et seront le sujet de la section suivante.

Activation de la sortie d’interruption

Le DS3231 supporte les interruptions sur la broche SQW. Par défaut, cette broche émet un signal en onde carrée (SQW) avec une fréquence configurable, mais peut être configurée pour envoyer un signal d’interruption lorsqu’une alarme est déclenchée.

Pour tester cela, connectez une LED avec une résistance de limitation de courant d’environ 220Ω à la broche SQW du DS3231 comme montré ci-dessous :

Connecting an LED to the interrupt pin SQW of the DS3231
Connexion d’une LED à la broche d’interruption SQW du DS3231

Le code suivant règle l’Alarme 1 pour se déclencher à chaque dixième de seconde (setAlarm1(0, 0, 0, 10, DS3231_MATCH_S)) :

#include "Wire.h"
#include "DS3231.h"

DS3231 rtc;

void setup() {
  Serial.begin(9600);
  rtc.begin();
  rtc.setDateTime(__DATE__, __TIME__);
  rtc.setAlarm1(0, 0, 0, 10, DS3231_MATCH_S);
  rtc.enableOutput(false);
}

void loop() {
  RTCDateTime dt = rtc.getDateTime();
  Serial.println(rtc.dateFormat("H:i:s", dt));
  delay(1000);
}

La ligne importante dans ce code est

rtc.enableOutput(false);

qui indique au DS3231 de désactiver la sortie du signal en onde carrée sur la broche SQW et d’envoyer un signal d’interruption à la place. Sans cette ligne, vous verrez la LED clignoter à une fréquence constante de 1 Hz.

Le code affiche l’heure chaque seconde mais ne vérifie pas le déclenchement dans la fonction loop. Si vous exécutez ce code et regardez le moniteur série et la LED, vous verrez que la LED s’éteint (et reste éteinte) une fois que le dixième de seconde est atteint. Ainsi, les interruptions sont signalées par un passage de SQW à LOW !

La LED reste éteinte car nous ne réinitialisons pas l’alarme. Si vous voulez que la LED s’éteigne pendant, disons, 5 secondes (delay(5000)), toutes les 10 secondes, vous pourriez modifier la fonction loop comme suit :

void loop() {
  if (rtc.isAlarm1(false)) { 
    delay(5000);
    rtc.clearAlarm1();
  }
}

Le code vérifie l’alarme sans la réinitialiser. Si l’alarme est déclenchée, il attend 1 seconde, pendant laquelle la LED est éteinte, puis réinitialise l’alarme, ce qui efface le signal d’interruption sur SQW et rallume la LED.

Réveil depuis le sommeil profond avec les interruptions du DS3231

Le cas d’usage le plus courant des interruptions est de réveiller un Arduino depuis un sommeil profond à intervalles réguliers pour effectuer certaines actions comme la journalisation de données. Par exemple, vous pourriez vouloir mesurer la température ambiante toutes les 30 minutes tout en laissant l’Arduino dormir entre-temps pour économiser la batterie.

Pour cela, nous retirons la LED connectée à la broche SQW et connectons à la place la broche SQW du DS3231 à la broche 2 de l’Arduino comme montré ci-dessous :

Connecting interrupt pin SQW of DS3231 to Arduino
Connexion de la broche d’interruption SQW du DS3231 à l’Arduino

Notez que vous devez utiliser une broche Arduino qui supporte les interruptions. Pour un Arduino Uno, seules les broches 2 et 3 peuvent être utilisées pour les interruptions.

Avec la connexion d’interruption en place, nous pouvons maintenant réveiller l’Arduino du sommeil profond lorsqu’une alarme se déclenche. L’exemple de code suivant met l’Arduino en sommeil profond, le réveille chaque minute, puis affiche l’heure :

#include "Wire.h"
#include "DS3231.h"
#include "avr/sleep.h"

const int intPin = 2;

DS3231 rtc;

void wakeUp() {
}

void setup() {
  Serial.begin(9600);

  pinMode(intPin, INPUT);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();

  rtc.begin();
  rtc.setDateTime(__DATE__, __TIME__);
  rtc.setAlarm1(0, 0, 0, 0, DS3231_MATCH_S);
  rtc.enableOutput(false);
}

void loop() {
  attachInterrupt(digitalPinToInterrupt(intPin), wakeUp, LOW);
  Serial.println("sleeping...");
  delay(100); // finish printing
  sleep_cpu();  // <= go to sleep

  // waking up here when interrupt detected
  detachInterrupt(digitalPinToInterrupt(intPin));
  rtc.clearAlarm1();
  RTCDateTime dt = rtc.getDateTime();
  Serial.println(rtc.dateFormat("H:i:s", dt)); 
  delay(100); // finish printing   
}

Décomposons le code en ses composants pour mieux comprendre.

Includes

Nous commençons par inclure les bibliothèques nécessaires à notre projet : Wire.h pour la communication I2C, DS3231.h pour l’interface avec le RTC DS3231, et avr/sleep.h pour gérer les modes de sommeil.

#include "Wire.h"
#include "DS3231.h"
#include "avr/sleep.h"

Constantes et variables

Ensuite, nous définissons une constante pour la broche d’interruption et créons une instance de la classe DS3231 pour interagir avec le RTC.

const int intPin = 2;
DS3231 rtc;

Fonction de réveil

La fonction wakeUp() est définie mais reste vide. Elle est requise par la fonction attachInterrupt() et ne peut pas être nulle. Cette fonction sera appelée lorsque l’interruption sera déclenchée.

void wakeUp() { }

Vous pourriez y faire des choses simples, comme incrémenter une variable, mais ce n’est pas nécessaire ici et nous ne l’utiliserons pas. Attention toutefois, vous ne devez rien faire de complexe lié aux interruptions dans cette fonction, ce qui inclut Serial.print()!

Fonction setup

Dans la fonction setup(), nous initialisons la communication série, configurons la broche d’interruption et réglons le Arduino sleep mode.

void setup() {
  Serial.begin(9600);

  pinMode(intPin, INPUT);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();

  rtc.begin();
  rtc.setDateTime(__DATE__, __TIME__);
  rtc.setAlarm1(0, 0, 0, 0, DS3231_MATCH_S);
  rtc.enableOutput(false);
}

Nous réglons aussi l’heure et la date du RTC, configurons l’Alarme 1 pour se déclencher chaque minute (seconde = 0) et configurons la sortie (SQW) pour envoyer des interruptions.

Fonction loop

Dans la fonction loop(), nous attachons une interruption à la broche d’interruption, permettant au microcontrôleur de se réveiller lorsque la broche 2 passe à LOW. Nous affichons « sleeping… » dans le moniteur série puis mettons l’Arduino en mode sommeil.

void loop() {
  attachInterrupt(digitalPinToInterrupt(intPin), wakeUp, LOW);
  Serial.println("sleeping...");
  delay(100); // finish printing
  sleep_cpu();

  detachInterrupt(digitalPinToInterrupt(intPin));
  rtc.clearAlarm1();
  RTCDateTime dt = rtc.getDateTime();
  Serial.println(rtc.dateFormat("H:i:s", dt)); 
  delay(100); // finish printing   
}

Si une interruption survient (broche 2 passe à LOW), nous nous réveillons (juste après la ligne avec sleep_cpu()). D’abord, nous désactivons l’interruption pour éviter qu’elle ne se déclenche à nouveau immédiatement. Nous réinitialisons aussi l’alarme pour ramener la broche d’interruption SQW du DS3231 à HIGH.

Ensuite, nous affichons l’heure actuelle et attendons un peu pour laisser le moniteur série finir l’affichage. Sans ce délai, la sortie vers le moniteur série pourrait être tronquée.

Exemple de sortie

Si vous téléversez ce code, vous devriez voir la sortie suivante dans votre moniteur série :

Output on Serial Monitor
Sortie sur le moniteur série

Notez que l’Arduino se met en veille, se réveille chaque minute et affiche l’heure.

Nous n’avons pas eu besoin de vérifier si une alarme était déclenchée en utilisant isAlarm1(), car nous savons qu’une interruption ne se déclenche que lorsque l’Alarme 1 configurée est activée. Cependant, si vous configurez l’Alarme 1 et l’Alarme 2, ce que vous pouvez faire, vous pouvez identifier laquelle a été déclenchée en vérifiant isAlarm1() et isAlarm2().

Je vous montre un exemple dans la section suivante, où nous connectons aussi un buzzer pour signaler qu’une alarme a été déclenchée.

Différencier les alarmes et faire sonner le buzzer

Nous commençons par connecter un buzzer actif buzzer à la broche 3 de l’Arduino. Toute autre broche supportant PWM fonctionnerait aussi.

Connecting a Buzzer to Arduino
Connexion d’un buzzer à l’Arduino

Notez que pour cet exemple, j’ai retiré le fil de signal d’interruption de SQW, car je n’utiliserai pas les interruptions ici. Mais vous pourriez.

Le code suivant fait sonner le buzzer toutes les minutes et toutes les heures :

#include "Wire.h"
#include "DS3231.h"

const int buzzerPin = 3;

DS3231 rtc;

void setup() {
  rtc.begin();
  rtc.setDateTime(__DATE__, __TIME__);
  rtc.setAlarm1(0, 0, 0, 0, DS3231_MATCH_S); // every minute
  rtc.setAlarm2(0, 0, 0, DS3231_MATCH_M);  // every hour
}

void loop() {
  if (rtc.isAlarm1() && !rtc.isAlarm2()) { 
     tone(buzzerPin, 1000, 200);
  }
  if (rtc.isAlarm2()) {
     tone(buzzerPin, 2000, 200);
  }
}

Dans la fonction setup, nous définissons les deux alarmes. L’Alarme 1 correspond aux secondes égales à zéro, ce qui signifie qu’elle se déclenche chaque minute. L’Alarme 2 correspond aux minutes égales à zéro, ce qui signifie qu’elle se déclenche chaque heure :

void setup() {
  ...
  rtc.setAlarm1(0, 0, 0, 0, DS3231_MATCH_S); // every minute
  rtc.setAlarm2(0, 0, 0, DS3231_MATCH_M);  // every hour
}

Dans la fonction loop, nous vérifions quelle alarme a été déclenchée et jouons un son différent tone :

void loop() {
  if (rtc.isAlarm1() && !rtc.isAlarm2()) { 
     tone(buzzerPin, 1000, 200);
  }
  if (rtc.isAlarm2()) {
     tone(buzzerPin, 2000, 200);
  }
}

Comme, au début de chaque heure, les minutes et les secondes sont égales à 0, les deux alarmes sont déclenchées. Mais nous voulons jouer uniquement le son de l’Alarme 2 à l’heure pile. Donc, nous ne jouons le son de l’Alarme 1 que si l’Alarme 2 n’est pas déclenchée (rtc.isAlarm1() && !rtc.isAlarm2()).

Vous pourriez aussi implémenter cela de manière plus élégante comme suit :

  if (rtc.isAlarm1()) { 
     tone(buzzerPin, rtc.isAlarm2() ? 2000 : 1000, 200);
  }

Et voilà. J’espère qu’à présent vous en savez beaucoup plus sur la fonction alarme du DS3231.

Conclusions

Dans ce tutoriel, vous avez appris à utiliser les alarmes avec le Real-Time-Clock (RTC) DS3231 et un Arduino.

Nous n’avons pas abordé comment régler l’heure et la date du RTC. Nous avons simplement pris l’heure de compilation pour initialiser le RTC, ce qui est suffisant tant que vous ne redémarrez pas l’Arduino. Si vous souhaitez régler ou ajuster l’heure après un reset ou pendant que l’Arduino fonctionne, consultez le tutoriel Arduino and RTC Module DS3231, où nous utilisons des boutons poussoirs pour cela. Vous y apprendrez aussi comment afficher l’heure sur un écran LCD.

Si vous voulez en savoir un peu plus sur les différents modes de sommeil, jetez un œil au tutoriel How Do I Wake Up My Arduino From Sleep Mode?. Cependant, pour des projets alimentés par batterie, un ESP32 pourrait être plus adapté.

De plus, comme un ESP32 supporte le Wi-Fi, synchroniser l’horloge RTC avec un internet time server est facile et élimine le besoin de boutons pour ajuster l’heure. Cela résout aussi le problème de l’heure d’été. Consultez le tutoriel Real-Time-Clock DS3231 with ESP32.

Si vous avez des questions, n’hésitez pas à les laisser dans la section commentaires.

Bon bricolage ; )