A quoi ça sert… un module RTC ?

horloge RTC

Un Arduino Uno et son micro-contrôleur ATmega328P ne possèdent pas d’horloge interne. Ils ne sont donc capables de retourner ni l’heure ni la date courante. C’est le rôle d’un composant appelé « RTC » qui signifie « Real Time Clock », ou HTR en français qui signifie « horloge temps réel ».

Les composants DS1302 et DS1307

Un exemple de composant utilisé fréquemment comme RTC est le DS1302. Il nécessite un oscillateur externe de fréquence 32.768 kHz relié à ses broches 2 et 3. Afin de conserver l’heure et la date courante, une alimentation par pile est prévue sur ce composant.

Le micro-contrôleur communique avec ce composant par un lien série via les broches CE, I/O et SCLK. Il existe plusieurs librairies dans l’IDE Arduino utilisables pour ce composant, par exemple « Rtc by Makuna » qui est assez complète.

Le composant DS1307 reprend les mêmes principes que le DS1302 mais communique avec le micro-contrôleur par bus I2C (via ses broches SCL et SDA).

Remarque importante : Si vous n’utilisez pas de batterie il faut relier la broche VBAT à la masse, sinon le composant ne fonctionnera pas correctement.

DS1307 relié à un Arduino
Le DS1307 avec son oscillateur 32.768 kHz relié en I2C à l’Arduino Uno

Utilisation d’un module RTC

L’utilisation de modules basés sur ce composant est assez pratiques, car ils incluent généralement le composant, un oscillateur externe et le support pour la pile. Ils communiquent généralement avec l’Arduino via le bus I2C.

Exemple de module basé sur le composant DS1307

Le câblage de ce type de module est extrêmement simple. Il suffit de relier l’alimentation 5 V et les 2 fils du bus I2C.

Par contre j’ai observé des comportements étranges sur certains modules. Lorsque la pile n’était pas insérée dans le support l’Arduino avait des difficultés à reconnaître le module lors de la phase d’initialisation lors de l’appel de la fonction rtc.begin(). C’est très probablement lié au fait que sans pile le VBAT du DS1307 doit être relié à la masse, et certains modules ne doivent pas bien gérer ce cas.

Schéma du montage

Schéma câblage module RTC Arduino Uno
Schéma de câblage du module RTC avec l’Arduino Uno
Module RTC Arduino Uno

Programme de l’Arduino Uno

Je recommande d’utiliser librairie « RTClib » de Adafruit pour votre programme.

// Utilisation d'un module RTC avec un Arduino Uno
// https://tutoduino.fr/
// Copyleft 2020

#include "RTClib.h"

RTC_DS1307 rtc;

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

  // Attente de la connection serie avec l'Arduino
  while (!Serial);

  // Lance le communication I2C avec le module RTC et 
  // attend que la connection soit operationelle
  while (! rtc.begin()) {
    Serial.println("Attente du module RTC...");
    delay(1000);
  }

  // Mise à jour de l'horloge du module RTC avec la date et 
  // l'heure courante au moment de la compilation de ce croquis
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  Serial.println("Horloge du module RTC mise a jour");
}

void loop () {
    DateTime now = rtc.now();
    char heure[10];

    // Affiche l'heure courante retournee par le module RTC
    // Note : le %02d permet d'afficher les chiffres sur 2 digits (01, 02, ....)
    sprintf(heure, "Il est %02d:%02d:%02d", now.hour(), now.minute(), now.second());
    Serial.println(heure);
    
    delay(5000);
}

Affichage sur le moniteur série

affichage module rtc
Affichage de l’heure retournée par le module RTC sur le moniteur série

Dérive de l’horloge

On remarque qu’au démarrage du programme, l’heure du moniteur série et l’heure retournée par le module RTC diffèrent de quelques secondes. C’est normal et vous le comprenez facilement à la lecture du programme. En effet nous mettons à jour l’heure du module RTC dans notre programme avec l’heure de compilation du programme et non l’heure à laquelle le programme démarre sur l’Arduino Uno. Dans la capture d’écran ci-dessus, vous voyez que le module RTC affiche 17:12:23 alors que le moniteur série affiche 17:12:45. L’horloge du module RTC est en retard de 22 secondes par rapport à l’heure du PC. Ce retard correspond au temps de compiler le programme, le téléverser et le démarrer sur l’Arduino. Mais il ne s’agit en aucun cas d’une dérive de l’horloge du module RTC.

La dérive est quand à elle liée à la précision de l’horloge du module RTC. Le constructeur de ce module annonce une dérive de 2 secondes par jour, ce qui veut dire que l’horloge peut avoir un retard ou une avance de 2 secondes par jour. L’horloge aura potentiellement un retard ou une avance d’environ 5 minutes par mois, ce qui est acceptable pour un petit montage électronique.

J’ai réalisé le tuto « Mesure de la dérive d’un module RTC » dans lequel j’explique comment mesurer cette dérive et je compare la dérive du module RTC DS1307 avec celui du DS3231.

Problème lors du reset de l’Arduino

Dans le programme ci-dessus, il y a un piège auquel il faut faire attention. L’horloge du module RTC est en effet mise à jour à chaque redémarrage de l’Arduino avec l’heure et la date de compilation du programme. Après un reset de l’Arduino le module RTC n’indique plus du tout l’heure courante… 😉

Reset de l'Arduino

Pour éviter ce problème, il faut mettre à jour l’horloge du module RTC uniquement si le module indique que cette horloge n’est pas réglée. Afin de savoir si l’horloge a déjà été réglée nous utilisons la fonction isrunning().

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

  // Attente de la connection serie avec l'Arduino
  while (!Serial);

  // Lance le communication I2C avec le module RTC et 
  // attend que la connection soit operationelle
  while (! rtc.begin()) {
    Serial.println("Attente du module RTC...");
    delay(1000);
  }

  // Mise a jour de l'horloge du module RTC si elle n'a pas
  // ete reglee au prealable
  if (! rtc.isrunning()) {
    // La date et l'heure de la compilation de ce croquis 
    // est utilisee pour mettre a jour l'horloge
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  
    Serial.println("Horloge du module RTC mise a jour");
  }
}

Une pile c’est utile…

Mais lorsque le montage n’est plus alimenté, l’horloge du composant DS1307 est réinitialisée. Et au redémarrage du système la fonction isrunning() retournera FALSE. Le programme de l’Arduino réglera alors l’horloge avec l’heure de la compilation, qui ne sera plus du tout l’heure courante.

Aussi pour éviter ce problème, il faut que l’horloge du DS1307 ne soit pas réinitialisée en cas de perte d’alimentation. Pour cela une alimentation par pile est prévue sur ce composant et il continue à compter les tics du quartz et donc à conserver l’heure courante lorsqu’il est alimenté sur pile. Lorsque le circuit sera de nouveau alimenté, le programme n’aura pas besoin de mettre à jour l’horloge du module RTC.

Ajoutez un écran et vous avez une horloge

Pour finir cet article, ajoutons un petit écran OLED 0.96″ afin d’afficher l’heure, juste pour le fun 🙂

Voici le code correspondant qui utilise la librairie décrite dans mon autre article à propos des écrans OLED.

// Horloge sur afficheur OLED avec un module RTC et un Arduino Uno
// https://tutoduino.fr/
// Copyleft 2020

#include "RTClib.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
 
#define I2C_ADDRESS 0x3C

SSD1306AsciiAvrI2c oled;

RTC_DS1307 rtc;

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

  // Attente de la connection serie avec l'Arduino
  while (!Serial);

  // Lance le communication I2C avec le module RTC et 
  // attend que la connection soit operationelle
  while (! rtc.begin()) {
    Serial.println("Attente du module RTC...");
    delay(1000);
  }

  // Mise a jour de l'horloge du module RTC si elle n'a pas
  // deja ete reglee
  if (! rtc.isrunning()) {
    // La date et l'heure de la compilation de ce croquis 
    // est utilisee pour mettre a jour l'horloge
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  
    Serial.println("Horloge du module RTC mise a jour");
  }

  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(Adafruit5x7);  
  oled.clear();
  oled.set2X();
  oled.println("Tutoduino");
  oled.set1X();
  oled.println("Apprendre");
  oled.println("l'electronique");
  oled.println("avec un Arduino");
}

void loop () {
  DateTime now = rtc.now();
  char heure[10];
  
  // Affiche l'heure courante retournee par le module RTC
  // Note : le %02d permet d'afficher les chiffres sur 2 digits (01, 02, ....)
  sprintf(heure, "Il est %02d:%02d:%02d", now.hour(), now.minute(), now.second());
  Serial.println(heure);
  
  oled.clear();
  oled.set2X();
  oled.println("Tutoduino");
  oled.set1X();
  oled.println();
  oled.println(heure);
    
  delay(1000);
}

Influence de la température sur l’oscillateur

La température influence les oscillation du quartz et donc la dérive de l’horloge temps réel. En général un oscillateur résonne à une fréquence dont la précision est optimale pour une température de 25 °C. Lorsqu’il est utilisé avec une température différente ou qui varie, sa fréquence ne sera pas aussi précise.

Il existe des composants comme le DS3231 qui inclus un oscillateur compensé en température (TCXO) . La précision est bien meilleure que pour le DS1307, avec une dérive de quelques minutes au maximum par an.

DS3231
Module à base de DS3231