Module RTC Arduino : DS3231, DS1307 et DS1302, heure et alarmes
Module RTC Arduino : DS3231, DS1307 et DS1302, régler l'heure avec RTClib, horloge sur LCD, arrosage programmé, piège de charge de la CR2032 et NTP sur ESP32.
Un module RTC pour Arduino est une petite carte horloge qui continue de compter la date et l'heure même quand ta carte n'est plus alimentée. RTC signifie « Real Time Clock », c'est-à-dire horloge temps réel. Le compteur millis() de l'Arduino repart de zéro à chaque mise sous tension et peut dériver de plusieurs minutes en quelques jours ; un module RTC, lui, fonctionne à la seconde près pendant des années grâce à sa pile bouton (CR2032). On le retrouve dans les horloges de bureau, l'arrosage automatique, les distributeurs de croquettes, les enregistreurs de données horodatés et l'éclairage programmé.
Dans ce guide, tu vas comparer les trois puces les plus courantes, le DS1307, le DS3231 et le DS1302, et voir laquelle choisir et pourquoi. Ensuite, étape par étape, nous allons régler et lire l'heure avec la bibliothèque RTClib, afficher l'heure et la date sur un LCD I2C, construire une minuterie qui lance une pompe à heures fixes chaque jour et utiliser l'alarme matérielle du DS3231. Les dernières sections expliquent le piège du circuit de charge de la CR2032 qui abîme de nombreux modules, la récupération de l'heure sur Internet par NTP avec l'ESP32 et la RTC intégrée de la Raspberry Pi Pico.

Qu'est-ce qu'un module RTC et comment fonctionne-t-il ?
Au cœur d'une puce RTC se trouve un quartz d'horlogerie de 32,768 kHz. Ce nombre n'a rien d'un hasard : 32 768 est égal à 2 puissance 15, donc la puce divise cette fréquence par deux 15 fois pour obtenir un top exact de 1 seconde. À chaque top, les registres des secondes, minutes, heures, jour, mois et année sont mis à jour ; la longueur des mois et les années bissextiles sont gérées automatiquement jusqu'en 2100. L'Arduino lit ces registres par I2C ou y écrit une nouvelle heure. Les valeurs sont stockées au format BCD (par exemple, 59 secondes sont enregistrées sous la forme 0x59) ; les bibliothèques font cette conversion pour toi.
Le vrai atout d'une RTC, ce sont ses deux entrées d'alimentation. Quand VCC disparaît, la puce bascule automatiquement sur l'entrée de la pile (VBAT) et ne consomme que le courant nécessaire pour continuer à compter : moins d'un microampère ou quelques microampères. Pendant ce temps, le DS1307 coupe la communication I2C, alors que le DS3231 reste lisible sur pile ; dans les deux cas, l'horloge ne s'arrête pas. Quand le courant revient, l'Arduino redémarre, lit l'heure exacte dans la RTC et reprend là où il s'était arrêté. À cause de la tolérance du résonateur céramique de l'Arduino Uno, une horloge tenue avec millis() peut dériver de plusieurs minutes par jour et se perd à chaque reset ; voilà pourquoi tout projet qui dépend de l'heure a besoin d'une RTC séparée.
Différences entre DS1307, DS3231 et DS1302
| Caractéristique | DS1307 | DS3231 | DS1302 |
|---|---|---|---|
| Interface | I2C (100 kHz), adresse 0x68 | I2C (jusqu'à 400 kHz), adresse 0x68 | Série 3 fils : CE (RST), I/O (DAT), SCLK (CLK) |
| Tension d'alimentation | 4,5–5,5 V | 2,3–5,5 V | 2,0–5,5 V |
| Quartz | Externe de 32,768 kHz (12,5 pF) | Intégré à la puce, compensé en température (TCXO) | Externe de 32,768 kHz (6 pF) |
| Précision | Dépend du quartz ; avec ±20 ppm environ 1,7 s/jour, environ 1 min/mois | ±2 ppm (0–40 °C) : environ 5 s/mois, environ 1 min/an | Dépend du quartz ; proche du DS1307 ou moins bonne |
| Fonctions en plus | 56 octets de RAM sauvegardée par pile, sortie signal carré (SQW) | 2 alarmes, sortie INT/SQW, capteur de température (±3 °C), réglage du vieillissement | 31 octets de RAM, chargeur d'entretien intégré (trickle charger) |
| Courant sur pile | Environ 300–500 nA | Environ 1–3 µA | Moins de 300 nA sous 2 V |
| Bibliothèque Arduino | RTClib (Adafruit) | RTClib (Adafruit) | Rtc by Makuna |
| Idéal pour | Horloges simples en 5 V | Presque tous les projets ; idéal aussi pour l'ESP32 et la Pico | Anciens kits et projets d'apprentissage |
Rendons la différence de précision concrète : 1 ppm signifie une partie par million, et une journée compte 86 400 secondes. Un quartz ordinaire de ±20 ppm peut dériver jusqu'à 1,7 seconde par jour, soit environ 52 secondes par mois, et plus on s'éloigne de la température ambiante, plus la fréquence du quartz change et plus l'erreur grandit. Le DS3231, lui, embarque son quartz dans la puce, mesure la température toutes les 64 secondes et corrige la fréquence en conséquence. Il atteint ainsi ±2 ppm entre 0 et 40 °C, soit environ une minute par an, et reste dans ±3,5 ppm même de -40 à +85 °C.
Quel module RTC choisir ?
- Nouveau projet, ESP32 ou Pico : prends un DS3231. Il fonctionne en 3,3 V comme en 5 V, possède des alarmes et donne l'heure la plus précise. La différence de prix est minime.
- Tu as déjà un DS1307 et tu utilises un Arduino Uno : utilise-le sans souci ; prévois simplement une dérive d'environ une minute par mois et remets l'heure à jour de temps en temps.
- Ton kit de démarrage contenait un DS1302 : il convient pour apprendre le fonctionnement d'une RTC, mais n'attends pas une horloge qui reste précise pendant des mois.
- ESP32 connecté en permanence à Internet : commence avec NTP sans module ; ajoute un DS3231 si l'heure doit être connue après une coupure de courant avant le retour d'Internet.
Tu croiseras surtout deux cartes toutes prêtes : la ZS-042 avec une puce DS3231 et la Tiny RTC avec un DS1307. Toutes deux embarquent aussi une EEPROM AT24C32 de 4 Ko pour stocker des données. C'est pourquoi il est normal de voir une deuxième adresse à côté de 0x68 quand tu lances un scanner I2C (en général 0x57 sur la ZS-042 et 0x50 sur la Tiny RTC) ; cette adresse appartient à l'EEPROM, pas à l'horloge. Le DS1302, lui, n'utilise pas l'I2C : il communique avec son propre protocole 3 fils et occupe trois broches numériques.
Branchement du module RTC : Arduino Uno, ESP32 et Pico
| Broche RTC | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 (DS3231) | 3V3(OUT), broche physique 36 (DS3231) |
| GND | GND | GND | GND |
| SDA | A4 | GPIO 21 | GP4 (I2C0) |
| SCL | A5 | GPIO 22 | GP5 (I2C0) |
| SQW / INT (facultatif) | D2 (broche d'interruption) | N'importe quel GPIO (ex. GPIO 4) | N'importe quelle broche GP (ex. GP15) |
Sur l'Uno R3, les connecteurs SDA et SCL situés près de la broche AREF sont eux aussi reliés à A4 et A5 : peu importe lesquels tu utilises. La RTC peut partager les deux mêmes fils avec un LCD I2C ou un écran OLED ; chaque appareil a sa propre adresse, il n'y a donc pas de conflit. Garder des fils de moins de 20–30 cm évite les erreurs de lecture aléatoires, surtout sur une breadboard. Tu n'as besoin de relier la broche SQW/INT que si tu comptes utiliser l'alarme matérielle.
Installer RTClib et régler l'heure
- Ouvre le Gestionnaire de bibliothèques de l'IDE Arduino, tape RTClib et installe la bibliothèque d'Adafruit. Quand il te demande les dépendances, choisis Install all pour installer aussi Adafruit BusIO. Si tu n'as jamais ajouté de bibliothèque, Ajouter une bibliothèque Arduino t'explique tout pas à pas.
- Branche le module comme dans le tableau ci-dessus et mets la pile dans son support.
- Téléverse le code ci-dessous. Au premier démarrage, le module ne connaît pas l'heure : le code écrit donc dans la RTC l'heure de compilation de ton ordinateur.
- Ouvre le Moniteur série à 9600 bauds avec la fin de ligne « Nouvelle ligne ». Pour régler l'heure à la seconde près, tape-la au format 2026-11-03 14:30:00 puis appuie sur Entrée.
- Débranche le câble USB, attends quelques minutes et rebranche-le. Si l'horloge reprend correctement là où elle s'était arrêtée, la sauvegarde par pile fonctionne.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc; // DS1307 kullanıyorsan: RTC_DS1307 rtc; / for a DS1307: RTC_DS1307 rtc;
5
6void setup() {
7 Serial.begin(9600);
8 if (!rtc.begin()) { // modül I2C hattında yok / module not found on the I2C bus
9 Serial.println(F("RTC bulunamadi / RTC not found"));
10 while (true);
11 }
12 if (rtc.lostPower()) { // ilk çalıştırma ya da pil bitmiş / first run or dead battery
13 rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // derleme saatini yaz / write the compile time
14 Serial.println(F("Saat derleme zamanina ayarlandi / Clock set to compile time"));
15 }
16 Serial.println(F("Ayar icin yaz / To set, type: 2026-11-03 14:30:00"));
17}
18
19void loop() {
20 // Seri monitörden saat geldiyse ayarla / set the time sent from the Serial Monitor
21 if (Serial.available()) {
22 String line = Serial.readStringUntil('\n');
23 int y, mo, d, h, mi, s;
24 if (sscanf(line.c_str(), "%d-%d-%d %d:%d:%d", &y, &mo, &d, &h, &mi, &s) == 6) {
25 rtc.adjust(DateTime(y, mo, d, h, mi, s));
26 Serial.println(F("Saat ayarlandi / Time set"));
27 }
28 }
29
30 DateTime now = rtc.now();
31 char buf[] = "DD.MM.YYYY hh:mm:ss"; // biçim şablonu / format template
32 Serial.print(now.toString(buf));
33 Serial.print(F(" "));
34 Serial.print(rtc.getTemperature()); // yalnız DS3231 / DS3231 only
35 Serial.println(F(" C"));
36 delay(1000);
37}rtc.begin() renvoie false si le module est introuvable sur le bus I2C ; dans ce cas, vérifie d'abord le câblage. rtc.lostPower() lit l'indicateur d'arrêt de l'oscillateur (OSF) du DS3231 : il renvoie true si le module fonctionne pour la première fois ou si l'horloge s'est arrêtée parce que la pile était vide, et le code règle alors l'horloge sur l'heure de compilation. DateTime(F(__DATE__), F(__TIME__)) utilise l'instant où le compilateur a construit ton code ; comme le téléversement prend quelques secondes, l'horloge se retrouve légèrement en retard, d'où l'intérêt d'un réglage fin depuis le Moniteur série. toString() remplace les lettres du modèle « DD.MM.YYYY hh:mm:ss » par les vraies valeurs.
| Fonction | Rôle |
|---|---|
| rtc.begin() | Démarre le module ; renvoie false s'il est introuvable |
| rtc.adjust(DateTime(...)) | Écrit l'heure et la date |
| rtc.now() | Lit l'heure actuelle sous forme d'objet DateTime |
| now.year(), now.month(), now.day() | Année, mois, jour |
| now.hour(), now.minute(), now.second() | Heure (0–23), minute, seconde |
| now.dayOfTheWeek() | Jour de la semaine : 0 = dimanche, 6 = samedi |
| now.unixtime() | Secondes écoulées depuis le 1er janvier 1970 ; idéal pour comparer deux instants |
| now + TimeSpan(0, 1, 30, 0) | Ajoute 1 heure 30 minutes (jours, heures, minutes, secondes) |
| rtc.lostPower() / rtc.isrunning() | Indique si l'heure est valide (DS3231 / DS1307) |
| rtc.getTemperature() | Température de la puce en °C (DS3231 uniquement) |
Si tu utilises un DS1307, seule la déclaration de l'objet change : écris RTC_DS1307 rtc;, teste !rtc.isrunning() au lieu de lostPower() et supprime la ligne getTemperature(). À sa toute première mise sous tension, le DS1307 démarre avec l'oscillateur arrêté (bit CH à 1) ; adjust() efface ce bit et lance l'horloge. Dans les 56 octets de RAM sauvegardée par pile du DS1307, tu peux enregistrer de petits réglages, comme une heure d'alarme, avec rtc.writenvram() et rtc.readnvram() ; grâce à la pile, ces données survivent elles aussi aux coupures de courant.
Afficher l'heure et la date sur un LCD
Voir l'heure sur un écran plutôt que dans le Moniteur série transforme le projet en véritable horloge de bureau. Un LCD I2C 16x2 et la RTC se branchent sur le même bus SDA-SCL : le LCD est généralement à l'adresse 0x27 ou 0x3F, la RTC à 0x68. Le code ci-dessous écrit sur la ligne du haut la date et l'abréviation du jour, et sur la ligne du bas l'heure et la température mesurée par le DS3231. Pour le branchement du LCD et l'installation de sa bibliothèque, jette un œil à Utiliser un écran LCD I2C.
1#include <Wire.h>
2#include <RTClib.h>
3#include <LiquidCrystal_I2C.h>
4
5RTC_DS3231 rtc;
6LiquidCrystal_I2C lcd(0x27, 16, 2); // adres 0x27 ya da 0x3F / address 0x27 or 0x3F
7
8// dayOfTheWeek(): 0 = Pazar / 0 = Sunday
9const char* const days[7] = {"Paz", "Pzt", "Sal", "Car", "Per", "Cum", "Cmt"};
10int lastSecond = -1;
11
12void setup() {
13 lcd.init();
14 lcd.backlight();
15 if (!rtc.begin()) {
16 lcd.print("RTC yok!"); // modül bulunamadı / module not found
17 while (true);
18 }
19 if (rtc.lostPower()) rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
20}
21
22void loop() {
23 DateTime now = rtc.now();
24 if (now.second() == lastSecond) return; // saniye değişmediyse yazma / skip until the second changes
25 lastSecond = now.second();
26
27 char line1[17], line2[17];
28 snprintf(line1, sizeof(line1), "%02d.%02d.%04d %s",
29 now.day(), now.month(), now.year(), days[now.dayOfTheWeek()]);
30 snprintf(line2, sizeof(line2), "%02d:%02d:%02d %2dC",
31 now.hour(), now.minute(), now.second(), (int)rtc.getTemperature());
32 lcd.setCursor(0, 0);
33 lcd.print(line1); // ör. / e.g. 03.11.2026 Sal
34 lcd.setCursor(0, 1);
35 lcd.print(line2); // ör. / e.g. 14:05:09 23C
36}Le %02d dans snprintf ajoute un zéro devant les nombres à un chiffre : l'heure s'affiche ainsi 09:05:03 et non 9:5:3, et la longueur de la ligne ne change jamais. Grâce à cette longueur fixe, pas besoin de lcd.clear() ; effacer l'écran à chaque tour de boucle provoque un scintillement. Le code n'écrit sur l'écran que lorsque la seconde change, ce qui évite d'occuper le bus I2C pour rien. Le tableau days contient des abréviations en turc ; remplace-les par Dim, Lun, Mar, etc., en gardant le dimanche en premier.
Alarmes et tâches programmées : arrosage automatique et distributeur de croquettes
Le plus utile avec une RTC, c'est de faire exécuter des tâches à heure fixe : arroser les plantes chaque matin à 08:00, servir les croquettes du chat à 19:30 ou éteindre la lumière de l'aquarium la nuit. Il existe deux façons de faire. La première est une comparaison logicielle : tu lis l'heure dans loop() et tu vérifies si le moment d'une tâche est arrivé. C'est simple et tu peux ajouter autant de tâches que tu veux. La seconde est l'alarme matérielle du DS3231 : au moment prévu, la puce met sa broche INT à LOW et prévient l'Arduino par une interruption ; elle peut même réveiller un microcontrôleur en veille.
Une erreur courante avec la comparaison logicielle est de chercher une seconde exacte, comme now.second() == 0. S'il y a un long delay() dans loop(), cette seconde peut passer inaperçue et la tâche ne s'exécute jamais. Le code ci-dessous compare l'heure et la minute, mémorise une clé formée du jour et de la minute pour que la tâche ne se lance pas deux fois dans la même minute, et chronomètre la pompe avec millis(). La pompe est commandée par un module relais ; tu trouveras son branchement dans l'article sur la mini pompe à eau.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc;
5
6const byte RELAY_PIN = 7;
7const byte RELAY_ON = LOW; // çoğu röle modülü LOW ile çeker / most relay modules switch on LOW
8const byte RELAY_OFF = HIGH;
9const unsigned long RUN_MS = 10000; // pompa 10 saniye çalışır / the pump runs for 10 seconds
10
11struct Task { byte hour; byte minute; };
12Task tasks[] = { {8, 0}, {19, 30} }; // her gün 08:00 ve 19:30 / every day at 08:00 and 19:30
13const byte TASK_COUNT = sizeof(tasks) / sizeof(tasks[0]);
14
15long lastRunKey = -1; // aynı dakikada ikinci kez çalışmasın / never run twice in one minute
16bool running = false;
17unsigned long startMs = 0;
18
19void setup() {
20 pinMode(RELAY_PIN, OUTPUT);
21 digitalWrite(RELAY_PIN, RELAY_OFF); // açılışta kapalı / off at start-up
22 rtc.begin();
23}
24
25void loop() {
26 DateTime now = rtc.now();
27 long key = (long)now.day() * 1440 + now.hour() * 60 + now.minute(); // gün + dakika / day + minute
28
29 for (byte i = 0; i < TASK_COUNT; i++) {
30 if (now.hour() == tasks[i].hour && now.minute() == tasks[i].minute && key != lastRunKey) {
31 lastRunKey = key;
32 running = true;
33 startMs = millis();
34 digitalWrite(RELAY_PIN, RELAY_ON); // pompayı aç / pump on
35 }
36 }
37
38 if (running && millis() - startMs >= RUN_MS) {
39 running = false;
40 digitalWrite(RELAY_PIN, RELAY_OFF); // pompayı kapat / pump off
41 }
42 delay(200);
43}Inclure le jour dans la clé est important : si tu ne mémorisais que la minute avec une seule tâche, la clé serait encore la même à cette minute le lendemain et la tâche ne s'exécuterait plus jamais. Pour fabriquer un distributeur de croquettes, utilise un servomoteur à la place du relais : le tourner à 90 degrés au moment de la tâche puis le ramener une seconde plus tard ouvre la trappe du réservoir et fait tomber une portion. Pour un arrosage plus intelligent, lis un capteur d'humidité du sol au moment de la tâche et ne lance pas la pompe si la terre est déjà humide. Le deuxième exemple ci-dessous fait la même chose avec l'alarme matérielle du DS3231.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc;
5const byte ALARM_PIN = 2; // DS3231 SQW/INT -> D2 (kesme pini / interrupt pin)
6volatile bool alarmFlag = false;
7
8void onAlarm() { // kesme fonksiyonu kısa olmalı / keep the ISR short
9 alarmFlag = true;
10}
11
12void setup() {
13 Serial.begin(9600);
14 rtc.begin();
15 rtc.disable32K(); // 32K çıkışını kapat / turn off the 32K output
16 rtc.writeSqwPinMode(DS3231_OFF); // SQW pini alarm çıkışı olur / SQW becomes the alarm output
17 rtc.clearAlarm(1);
18 rtc.clearAlarm(2);
19 rtc.disableAlarm(2);
20
21 // Her gün 07:30:00; tarih kısmı yok sayılır / every day at 07:30:00; the date part is ignored
22 rtc.setAlarm1(DateTime(2026, 1, 1, 7, 30, 0), DS3231_A1_Hour);
23
24 pinMode(ALARM_PIN, INPUT_PULLUP); // INT çıkışı open-drain / INT is an open-drain output
25 attachInterrupt(digitalPinToInterrupt(ALARM_PIN), onAlarm, FALLING);
26}
27
28void loop() {
29 if (alarmFlag) {
30 alarmFlag = false;
31 rtc.clearAlarm(1); // temizlenmezse pin LOW kalır / the pin stays LOW until cleared
32 Serial.println(F("Alarm: mama vakti / Feeding time"));
33 // Servo, röle ya da buzzer kodunu buraya yaz / put your servo, relay or buzzer code here
34 }
35}Le DS3231 possède deux alarmes. L'alarme 1 a une résolution d'une seconde ; le mode DS3231_A1_Hour se déclenche quand les heures, minutes et secondes correspondent, c'est-à-dire tous les jours à la même heure. Avec les autres modes, tu peux régler une alarme chaque seconde (PerSecond), chaque minute (Second), chaque heure (Minute), un jour précis du mois (Date) ou un jour précis de la semaine (Day). L'alarme 2 a une résolution d'une minute. La broche SQW/INT est une sortie à drain ouvert (open-drain), active à l'état LOW : elle passe à LOW quand l'alarme se déclenche et y reste jusqu'à l'appel de clearAlarm(). C'est pourquoi il vaut mieux se contenter de lever un drapeau dans la fonction d'interruption et faire le vrai travail dans loop(). Pour comprendre les interruptions, consulte Les interruptions Arduino.
Combien de temps dure la pile d'une RTC ?
Estimer l'autonomie de la pile est simple : durée (heures) = capacité de la pile (mAh) ÷ courant consommé (mA). Une CR2032 fait environ 220 mAh. En mode pile, le DS3231 consomme dans le pire des cas environ 3 µA, soit 0,003 mA : 220 ÷ 0,003 ≈ 73 000 heures, soit environ 8 ans. La pile ne sert que lorsque VCC est coupé ; si le module se trouve dans un appareil toujours alimenté, elle ne s'use presque pas et dure bien plus longtemps. En pratique, la limite vient le plus souvent de la durée de conservation de la pile elle-même et du circuit de charge du module.
| Puce | Courant sur pile | Durée calculée avec une CR2032 (220 mAh) |
|---|---|---|
| DS1307 | ~0,5 µA | ~50 ans ; en pratique limitée par la durée de conservation de la pile (environ 10 ans) |
| DS3231 | ~3 µA (pire cas) | ~8 ans |
| DS1302 | ~0,3 µA | Limitée par la durée de conservation de la pile |
| Module avec chargeur actif + CR2032 | Du courant est injecté dans la pile | Imprévisible ; la pile peut gonfler et mourir tôt |
Le piège de la pile CR2032 et du circuit de charge
La plupart des modules bon marché à DS3231 (ZS-042) et DS1307 (Tiny RTC) comportent un circuit de charge simple, en réalité prévu pour une pile rechargeable LIR2032. Sur la ZS-042, le courant passe de VCC à la pile à travers une diode 1N4148 et une résistance de 200 Ω ; la Tiny RTC possède un circuit similaire. Le problème, c'est que ces modules sont souvent vendus avec une CR2032 non rechargeable. Quand le module est alimenté en 5 V, les quelque 4,3 V restant après la diode poussent en permanence du courant dans la pile au lithium de 3 V. Une pile qui n'a jamais été prévue pour être chargée peut gonfler, couler et se vider prématurément, et tu te retrouves avec le problème « la pile est là, mais l'horloge se réinitialise sans arrêt ».
- Si tu utilises une CR2032, coupe le chemin de charge : sur la ZS-042, dessoude la résistance CMS de 200 Ω marquée « 201 » près du connecteur, ou la diode juste à côté. Pour les résistances dont tu ne sais pas lire le code, utilise le décodeur de codes CMS. C'est la solution la plus courante et la plus sûre.
- Si tu laisses le circuit tel quel, mets une LIR2032 : la capacité de la pile rechargeable (environ 40 mAh) vaut à peu près un cinquième de celle d'une CR2032 (environ 220 mAh), mais elle reste chargée tant que le module est alimenté.
- Si tu alimentes le module en 3,3 V : seuls 2,6 V environ arrivent à la pile après la diode ; une LIR2032 ne se charge jamais complètement et une CR2032 ne reçoit quasiment aucun courant. Retirer la résistance reste malgré tout la solution la plus propre.
- Le chargeur intégré du DS1302 est désactivé à la mise sous tension ; si tu utilises une CR2032, ne l'active pas dans le code.
- Mesure la pile : une CR2032 neuve affiche 3,0–3,2 V ; remplace-la si elle descend sous 2,5 V.
Utiliser le DS1302 (liaison 3 fils)

Le module DS1302 possède cinq broches : VCC, GND, CLK, DAT et RST. Comme il n'utilise pas l'I2C, il se branche non pas sur A4-A5 mais sur trois broches numériques quelconques ; dans l'exemple ci-dessous, DAT va sur D4, CLK sur D5 et RST sur D2, et le module est alimenté en 5V. La RTClib d'Adafruit ne prend pas en charge le DS1302 : installe plutôt la bibliothèque Rtc by Makuna depuis le Gestionnaire de bibliothèques. Le DS1302 a deux bits de protection : tant que la protection en écriture est active, l'heure ne peut pas être réglée, et tant que le bit d'arrêt de l'horloge est à 1, l'horloge n'avance pas. Le code vérifie les deux et règle l'horloge sur l'heure de compilation si l'heure enregistrée n'est pas valide.
1#include <RtcDS1302.h>
2
3ThreeWire myWire(4, 5, 2); // DAT, CLK, RST pinleri / DAT, CLK, RST pins
4RtcDS1302<ThreeWire> rtc(myWire);
5
6void setup() {
7 Serial.begin(9600);
8 rtc.Begin();
9 if (rtc.GetIsWriteProtected()) rtc.SetIsWriteProtected(false); // yazma korumasını kaldır / remove write protection
10 if (!rtc.GetIsRunning()) rtc.SetIsRunning(true); // saati başlat / start the clock
11
12 RtcDateTime compiled(__DATE__, __TIME__);
13 if (!rtc.IsDateTimeValid() || rtc.GetDateTime() < compiled) {
14 rtc.SetDateTime(compiled); // derleme saatine ayarla / set to compile time
15 }
16}
17
18void loop() {
19 RtcDateTime now = rtc.GetDateTime();
20 char buf[20];
21 snprintf(buf, sizeof(buf), "%02u.%02u.%04u %02u:%02u:%02u",
22 now.Day(), now.Month(), now.Year(), now.Hour(), now.Minute(), now.Second());
23 Serial.println(buf);
24 delay(1000);
25}La plainte la plus fréquente au sujet des modules DS1302 est une dérive de plusieurs minutes par semaine. L'une des raisons est que la puce exige un quartz ajusté pour une capacité de charge de 6 pF, alors que les modules bon marché peuvent utiliser des quartz d'une autre valeur. Des fils longs et mal fixés provoquent aussi des erreurs de lecture sur la liaison série du DS1302. Si tu as un DS1302, c'est un excellent point de départ pour comprendre une RTC ; mais si tu construis une horloge qui doit rester précise pendant des mois, passe au DS3231.
NTP au lieu d'une RTC sur l'ESP32 : l'heure depuis Internet
Comme l'ESP32 peut se connecter au Wi-Fi, il n'a souvent besoin d'aucun module RTC : grâce à NTP (Network Time Protocol), il obtient en quelques secondes l'heure exacte auprès de serveurs de temps comme pool.ntp.org. Le cœur Arduino de l'ESP32 fournit pour cela les fonctions configTzTime() et getLocalTime(), et le fuseau horaire s'indique sous forme de chaîne de règles. La Turquie reste à UTC+3 sans heure d'été depuis 2016 ; la règle du code est donc un décalage fixe de +3 heures. En France, en Belgique, en Suisse et dans les autres régions qui passent à l'heure d'été, utilise la règle d'Europe centrale indiquée en commentaire dans le code ; elle calcule elle-même les dates de changement d'heure.
Le point faible de NTP est sa dépendance à Internet : après une coupure de courant, tant que la box n'a pas redémarré, ou si le mot de passe Wi-Fi change, l'ESP32 ne peut pas connaître l'heure. Le minuteur RTC interne de l'ESP32 conserve l'heure pendant le deep sleep, mais il est remis à zéro en cas de perte totale d'alimentation. La solution la plus robuste combine les deux : au démarrage, si l'ESP32 joint un serveur NTP, il synchronise le DS3231 sur l'heure d'Internet ; sinon, il lit l'heure dans le DS3231, et il se resynchronise une fois par jour. Pour plus de détails sur NTP, consulte L'heure NTP avec l'ESP32.
1#include <WiFi.h>
2#include <Wire.h>
3#include <RTClib.h>
4#include <time.h>
5
6const char* WIFI_SSID = "AgAdin"; // Wi-Fi ağ adı / Wi-Fi network name
7const char* WIFI_PASS = "Sifren"; // Wi-Fi şifresi / Wi-Fi password
8// Türkiye: UTC+3, yaz saati yok / Turkey: UTC+3, no daylight saving
9// Orta Avrupa / Central Europe: "CET-1CEST,M3.5.0,M10.5.0/3"
10const char* TZ_INFO = "<+03>-3";
11
12RTC_DS3231 rtc;
13unsigned long lastSync = 0;
14
15void syncFromNtp() {
16 struct tm t;
17 if (getLocalTime(&t, 10000)) { // en fazla 10 sn bekle / wait up to 10 s
18 rtc.adjust(DateTime(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec));
19 Serial.println("DS3231 NTP ile ayarlandi / DS3231 synced from NTP");
20 }
21 lastSync = millis();
22}
23
24void setup() {
25 Serial.begin(115200);
26 Wire.begin(21, 22); // SDA, SCL pinleri / SDA, SCL pins
27 rtc.begin();
28
29 WiFi.begin(WIFI_SSID, WIFI_PASS);
30 unsigned long start = millis();
31 while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) delay(250);
32
33 if (WiFi.status() == WL_CONNECTED) {
34 configTzTime(TZ_INFO, "pool.ntp.org", "time.google.com");
35 syncFromNtp();
36 } else {
37 Serial.println("Wi-Fi yok, DS3231 saati kullaniliyor / No Wi-Fi, using the DS3231");
38 }
39}
40
41void loop() {
42 DateTime now = rtc.now();
43 char buf[] = "DD.MM.YYYY hh:mm:ss";
44 Serial.println(now.toString(buf));
45
46 if (WiFi.status() == WL_CONNECTED && millis() - lastSync > 86400000UL) {
47 syncFromNtp(); // günde bir kez eşitle / sync once a day
48 }
49 delay(1000);
50}La RTC intégrée de la Raspberry Pi Pico
La puce RP2040 de la Raspberry Pi Pico contient un bloc RTC, tandis que le RP2350 de la Pico 2 assure la même fonction avec un minuteur toujours actif (AON timer). En MicroPython, les deux s'utilisent avec la même classe machine.RTC : RTC().datetime() lit ou écrit l'heure sous la forme (année, mois, jour, jour de la semaine, heures, minutes, secondes, sous-secondes), et time.localtime() utilise aussi cette horloge. Mais cette horloge n'a pas de pile : quand la Pico perd son alimentation, MicroPython redémarre l'horloge au 1er janvier 2021 à 00:00.
Voici un piège qui surprend les débutants : par défaut, Thonny synchronise l'horloge de la Pico sur celle de ton ordinateur lors de la connexion. Pendant les tests, tout semble donc correct, mais dès que tu branches la Pico sur un chargeur de téléphone ou une batterie, l'horloge revient en 2021. La solution : relier un DS3231 à la Pico et régler la RTC interne à partir de lui au démarrage. Le code ci-dessous ne nécessite aucun fichier pilote ; il lit les sept premiers registres du DS3231 en I2C et les convertit du BCD en décimal. Avec une Pico W, tu peux aussi récupérer l'heure sur Internet avec ntptime.settime() ; comme cette fonction renvoie l'heure UTC, tu dois ajouter toi-même le décalage de ton fuseau horaire (+1 heure en hiver et +2 heures en été en France). Si tu débutes avec la Pico, commence par Qu'est-ce que la Raspberry Pi Pico ?.
1from machine import Pin, I2C, RTC
2import time
3
4i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=100000)
5DS_ADDR = 0x68 # DS3231 ve DS1307 adresi / DS3231 and DS1307 address
6
7def bcd2dec(b):
8 return (b >> 4) * 10 + (b & 0x0F)
9
10def dec2bcd(d):
11 return ((d // 10) << 4) | (d % 10)
12
13def ds_read():
14 b = i2c.readfrom_mem(DS_ADDR, 0x00, 7) # saniyeden yıla 7 kayıt / 7 registers, seconds to year
15 return (2000 + bcd2dec(b[6]), bcd2dec(b[5] & 0x1F), bcd2dec(b[4] & 0x3F),
16 bcd2dec(b[2] & 0x3F), bcd2dec(b[1] & 0x7F), bcd2dec(b[0] & 0x7F))
17
18def ds_write(y, mo, d, h, mi, s):
19 # 24 saat biçiminde yazar; 4. bayt haftanın günü (1-7) / writes 24-hour time; 4th byte is day of week (1-7)
20 i2c.writeto_mem(DS_ADDR, 0x00, bytes([dec2bcd(s), dec2bcd(mi), dec2bcd(h), 1,
21 dec2bcd(d), dec2bcd(mo), dec2bcd(y - 2000)]))
22
23# İlk kurulumda bir kez çalıştır, sonra satırı sil / run once on first setup, then delete the line
24# ds_write(2026, 11, 3, 14, 30, 0)
25
26y, mo, d, h, mi, s = ds_read()
27RTC().datetime((y, mo, d, 0, h, mi, s, 0)) # dahili RTC'yi ayarla / set the internal RTC
28
29while True:
30 t = time.localtime() # artık dahili RTC'den okunur / now read from the internal RTC
31 print("{:02d}.{:02d}.{} {:02d}:{:02d}:{:02d}".format(t[2], t[1], t[0], t[3], t[4], t[5]))
32 time.sleep(1)Idées de projets avec un module RTC
- Horloge de bureau numérique avec calendrier : affiche l'heure, la date et la température mesurée par le DS3231 sur un LCD, un OLED ou une matrice LED.
- Arrosage automatique des plantes : vérifie l'humidité du sol chaque matin et, si besoin, fais tourner la pompe pendant une durée fixe.
- Distributeur de croquettes : ouvre la trappe du réservoir avec un servo deux ou trois fois par jour et fais tomber une portion.
- Enregistreur de données horodaté : écris les mesures de température et d'humidité avec la date et l'heure sur un module carte SD, puis trace le graphique dans Excel.
- Sonnerie d'école ou d'atelier : fais sonner un buzzer ou une sonnerie via un relais au début et à la fin de chaque cours, et saute les week-ends avec dayOfTheWeek().
- Minuterie pour aquarium et lampe de culture : allume la lumière le matin et éteins-la le soir, en faisant varier lentement la luminosité en PWM pour un effet lever et coucher de soleil.
Erreurs fréquentes et solutions
- « RTC introuvable », begin() renvoie false : SDA et SCL sont inversés, la masse (GND) n'est pas commune ou le module n'est pas alimenté. Lance un scanner I2C et vérifie que l'adresse 0x68 apparaît.
- Valeurs absurdes comme l'année 2165, 165 ou 85 : aucune donnée ne vient de la puce et tous les octets lus valent 0xFF. Vérifie le câblage ; si tu alimentes un DS1307 en 3,3 V, passe en 5 V.
- Après chaque reset, l'horloge revient au même instant : la ligne rtc.adjust() est restée sans condition dans setup() ; rends-la dépendante de lostPower().
- L'horloge se réinitialise après une coupure de courant : la pile est vide, montée à l'envers ou absente. Mesure sa tension, et souviens-toi que le circuit de charge a peut-être tué la CR2032.
- L'horloge dérive de plusieurs minutes par semaine : le quartz du DS1307 ou du DS1302 et les variations de température en sont la cause. Passe à un DS3231 ou synchronise l'heure régulièrement par NTP.
- L'heure est décalée d'exactement une heure ou plus : le fuseau horaire ou l'heure d'été est mal configuré. Écris l'heure locale dans la RTC ; si tu utilises NTP, choisis la bonne règle de fuseau horaire.
- Le DS3231 indique plus chaud que la pièce : cette valeur est la température de la puce elle-même, précise à ±3 °C et influencée par l'échauffement de la carte. Utilise un capteur séparé pour la température ambiante.
En résumé, le DS3231 est le bon choix pour presque tous les projets qui ont besoin de la date et de l'heure ; le DS1307 fait l'affaire dans les projets simples en 5 V et le DS1302 convient pour apprendre. Sur l'ESP32, utilise NTP quand Internet est disponible et un DS3231 sinon ; sur la Pico, régler la RTC interne à partir d'un DS3231 au démarrage est la méthode la plus fiable. Dans l'application BlueGrays, tu trouveras des projets pas à pas avec schémas et code : réglage d'une horloge DS1302 et horloge sur LCD, horloge et calendrier à matrice de points avec DS1307, horloge numérique à RTC sur ESP32, heure Internet par NTP et enregistreur de température horodaté.
Questions fréquentes
Un module RTC fonctionne-t-il sans pile ?
Tant que VCC est branché, l'horloge tourne et peut être lue. Mais dès que le courant est coupé, l'horloge s'arrête ou se réinitialise et tu dois la régler de nouveau au démarrage suivant. Comme le rôle même d'une RTC est de garder l'heure pendant les coupures, la pile est presque toujours nécessaire ; si tu utilises un DS1307 sans pile, sa broche VBAT doit être reliée à GND.
Lequel est le meilleur, le DS3231 ou le DS1307 ?
Le DS3231, dans presque tous les cas. Grâce à son quartz intégré compensé en température, il ne dérive que d'environ une minute par an, alors qu'un DS1307 peut dériver jusqu'à une minute par mois. Le DS3231 fonctionne en outre de 2,3 à 5,5 V, donc directement avec l'ESP32 et la Pico, et il possède deux alarmes et un capteur de température. Avec RTClib, le code est presque identique pour les deux.
Combien de temps dure la pile d'un module RTC ?
Quand le module fonctionne uniquement sur pile, un DS3231 consomme au maximum environ 3 µA et un DS1307 environ 0,5 µA. Sur le papier, une CR2032 de 220 mAh tient plus de 8 ans avec ces courants. En pratique, la durée de conservation de la pile et le circuit de charge du module peuvent réduire cette durée ; dans un module dont le chargeur est actif, une CR2032 peut se vider bien plus tôt.
Pourquoi mon module RTC remet-il l'heure à zéro ?
Il y a trois causes fréquentes : la ligne rtc.adjust() dans setup() qui remet l'heure de compilation à chaque démarrage, une pile vide ou montée à l'envers, et un circuit de charge qui a abîmé la CR2032. Rends d'abord la ligne adjust() dépendante de lostPower(), puis mesure la tension de la pile au multimètre et remplace-la si elle est sous 2,5 V.
Faut-il un module RTC avec l'ESP32 ?
Pas si l'appareil est toujours connecté ; l'ESP32 obtient l'heure exacte par NTP en quelques secondes. Pour les projets où Internet peut tomber, où l'heure doit être connue après une coupure avant le redémarrage de la box, ou qui fonctionnent entièrement hors ligne, ajouter un DS3231 est l'option la plus sûre. L'idéal est d'utiliser les deux et de synchroniser le DS3231 par NTP une fois par jour.
Peut-on mettre une CR2032 dans un module DS3231 ?
Oui, mais sur les modules équipés d'un circuit de charge, comme la ZS-042, tu dois d'abord couper le chemin de charge. Si tu dessoudes la résistance de 200 Ω (code 201) ou la diode voisine, une CR2032 fonctionnera en toute sécurité pendant des années. Si tu ne veux pas modifier la carte, utilise plutôt une pile rechargeable LIR2032.
Projets à réaliser après cet article
Voir tous les projets
Configuration du module horloge RTC DS1302
Tu fais fonctionner un petit module horloge qui n'oublie jamais l'heure, même quand l'Arduino est éteint. Le module a sa propre petite pile et, une fois l'heure réglée, la date et l'heure s'affichent

Horloge RTC DS1302 avec écran LCD
Une petite horloge de bureau qui n'oublie pas l'heure, même en cas de coupure de courant. Le module horloge DS1302 garde l'heure grâce à sa propre petite pile ; chaque seconde, l'Arduino la lit et écr

Horloge numérique avec ESP32 et RTC DS1307 (I2C + LCD)
Dans ce projet, nous affichons l'heure et la date sur un écran LCD 16x2 I2C à l'aide du module d'horloge en temps réel (RTC) DS1307. Le DS1307 est une RTC avec batterie de secours qui conserve l'heure même si l'ESP32 s'éteint. Les deux modules partagent la même ligne I2C (SDA/SCL), ce qui nous permet d'apprendre à contrôler plusieurs appareils avec seulement deux fils de signal. Vous decouvrirez ainsi le protocole I2C et le fonctionnement des modules RTC en pratique.

Horloge et calendrier matriciel (MAX7219, DS1307)
Un panneau lumineux pour ton bureau ou ton mur, qui affiche l'heure et la date en texte défilant. Sur l'écran LED 8x32, une horloge à gros chiffres fait clignoter ses deux points chaque seconde ; au d

Horloge matricielle, calendrier et station météo (MAX7219, DS1307)
Un panneau à texte défilant pour ton bureau ou ton mur, qui affiche tour à tour l'heure, la date et la météo de la pièce. Sur l'écran LED 8x32 apparaissent d'abord la température en Celsius et en Fahr

Enregistreur de Température ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
Construis un enregistreur de température horodaté avec ESP32 ! Lis la température/humidité du DHT22 chaque minute, obtiens l'heure réelle du DS1307 RTC et enregistre sur carte microSD au format CSV. L'OLED affiche en direct la température (grande police), le pourcentage d'humidité, l'horodatage et le compteur. Le fichier `/temp_log.csv` sur la carte SD s'ouvre dans Excel, Google Sheets ou Python pandas pour analyse — parfait pour surveillance de serre, suivi de température à domicile, c

ESP32 : heure réelle depuis Internet via NTP
L'ESP32 se connecte au Wi-Fi et récupère l'heure réelle avec une précision de la milliseconde depuis des serveurs NTP (Network Time Protocol). Grâce à `configTzTime()`, le fuseau horaire de la Turquie (TRT, UTC+3) est appliqué automatiquement et le passage DST est géré via la chaîne POSIX TZ. L'heure est affichée sur le moniteur série et sur un écran LCD I2C en option. `configTzTime()` démarre le service SNTP ; des resynchronisations périodiques ont lieu tant que l'accès au réseau est disponible

Horloge numérique avec afficheur 7 segments à 4 chiffres
Une horloge numérique lumineuse à quatre chiffres, comme celle du four de la cuisine. Le module horloge DS1302 garde l'heure, et chaque seconde l'Arduino lit les heures et les minutes et les affiche s
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 160 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

