Vous le savez certainement, le raspberry, mini PC adapté aux systèmes embarqué, ne dispose pas d’horloge interne. Lors d’une utilisation « bureautique », il met son horloge à jour par internet grâce aux serveurs de temps et le protocole ntp.
Autrement dit, si vous utilisez un raspberry en tant que système embarqué, sans connexion internet, dès qu’il sera éteint, l’heure et la date se décaleront. On peut rapidement se retrouver avec une date système au 30 novembre 1999 , 00h00:00. Cela peut même empêcher un boot normal du système.
Dans cette situation, il faut lui ajouter une horloge RTC externe. Heureusement, aujourd’hui, cela ne coûte que quelques euros. Mais cela peut demander des heures de programmation en recherchant comment exploiter cette petite bête avec une pile.
Voici donc un exemple d’utilisation du modèle à base de DS1302 :
Ce circuit RTC est souvent utilisé sur les Arduino qui ont le mêmes problèmes (absence d’horloge interne autonome). Son utilisation sur Arduino est bien documenté mais ce n’est pas le cas dans le câdre d’une utilisation sur Raspberry : le code fournis en C est difficilement utilisable du fait qu’on ne sait sur quels PIN du raspberry il faut brancher la bête ou comment réattribuer les PIN. Il y a bien un code C avec un exemple de translation de PIN mais je n’ai jamais réussi à le faire fonctionner.
Le DS1302 possède 5 PIN : VCC (+3,3V) GND (la masse) et CLK (clock), RST (reset) et DAT (data)
Heureusement, il existe une classe en python écrite par Jason Birch, sous licence GNU qui permet de s’en sortir. Elle est télécharchable ici :https://github.com/BirchJD/RTC_DS1302 et ici RTC_DS1302.py
La page fournis la bibliothèque de classe principale (RTC_DS1302.py) et un exemple d’utilisation. Il faut tout d’abord adapter RTC_DS1302.py à votre cas :
Dans ce code, les correspondance sont les suivantes :
- SCLK désigne le PIN CLK (GPIO – BCM 2 par défaut)
- CE désigne le PIN RST (GPIO – BCM 3 par défaut)
- IO désigne le PIN DAT (GPIO – BCM 4 par défaut)
Pour adapter le code à votre cas, il faudra donc modifier ces 3 lignes (exemple dans le cas où on utilise les PIN 27,17 et 18 au lieu de 2,3,4) :
class RTC_DS1302: # RTC_DS1302_SCLK = 2 RTC_DS1302_SCLK = 27 # RTC_DS1302_CE = 3 RTC_DS1302_CE = 17 # RTC_DS1302_IO = 4 RTC_DS1302_IO = 18
Une fois fait, on a accès aux fonctionnalité de lecture et d’écriture dans le module RTC.
L’exemple fournis sur le site est assez pauvre (il ne fait que la mise à jour en du module RTC par une date codée en dur puis la lecture du contenu de la RAM du module).
Pour tester sereinement on a besoin au départ de deux programmes :
- l’un qui se contente de lire l’heure du module et l’affiche (que j’ai nommé getRTC.py)
- l’autre qui reçoit en entrée une date-heure fournis par l’utilisateur en argument pour mettre à jour l’heure du module RTC (que j’ai nommé setRTC.py)
Utilisation – Obtenir l’heure actuelle du module :
$ python getRTC.py Message: Message for RAM on RTC DS1302 Date/Time: Sunday 2019-03-03 21:09:29 Year: 2019 Month: 03 Day: 03 DayOfWeek: Sunday Hour: 21 Minute: 09 Second: 29
Utilisation – Mettre à l’heure l’horloge du module : set RTC.py SSAAMMJJHHMMSS (date heure concaténée) : le script met à jour l’heure puis relit le contenu de la RAM pour afficher la nouvelle heure
$ python setRTC.py 20190303211150 Message: Message for RAM on RTC DS1302 Date/Time: Sunday 2019-03-03 21:11:50 Year: 2019 Month: 03 Day: 03 DayOfWeek: Sunday Hour: 21 Minute: 11 Second: 50
Si vous obtenez des dates du type 30 novembre 1999 (ou 2000) à 00h00:00 cela signifie soit que le module est mal branché, soit que les PIN sont mal affectés dans le fichier RTC_DS1302.py.
A noter : il m’est arrivé de ne pas pouvoir mettre à jour le module bien que tout soit correct (la date et l’heure datait de la veille et ne changeait jamais), j’ai été obligé de lui retirer la pile puis de la remettre en place.
Une fois ces 2 programmes en place, vous avez la confirmation que tout fonctionne, on peut passer à l’étape suivante.
En effet, l’intérêt est de pouvoir mettre à jour le module à partir du Raspberry ou mettre à jour le Raspberry à partir du module.
Pour l’initialisation , je procède de la manière suivante :
- Le raspberry est connecté au web
- Son horloge système est à l’heure (elle s’est mise à l’heure grâce au service ntp)
- Je mets alors à jour le module rtc grâce au script updfromSYS.py
$ python updfromSYS.py Systeme date/time is 20190303212037 Message for RAM on RTC DS1302 Date/Time: Sunday 2019-03-03 21:20:37 Year: 2019 Month: 03 Day: 03 DayOfWeek: Sunday Hour: 21 Minute: 20 Second: 37
Vous pouvez relancer getRTC.py pou vous assurez que l’horloge RTC est à jour et tourne
$ python getRTC.py Message: Message for RAM on RTC DS1302 Date/Time: Sunday 2019-03-03 21:22:16 Year: 2019 Month: 03 Day: 03 DayOfWeek: Sunday Hour: 21 Minute: 22 Second: 16
Comme tout a fonctionné, je peux maintenant rendre le raspberry autonome (déconnexion su web) si à chaque démarrage je lance le script qui mettre le raspberry à jour à partir de l’heure du module RTC : updfromRTC.py
sudo python updfromRTC.py Date/Time from RTC : 20190303 21:24:58 Systeme date set to 20190303 Systeme time set to 21:24:58 date dimanche 3 mars 2019, 21:25:44 (UTC+0100)
Vous remarquerez que j’ai utilisé sudo, en effet pour mettre à jour la date système, il faut les autorisations de root
Il faut mettre en place cette routine à chaque démarrage du raspberry, une solution consiste à le mettre dans le fichier rc.local, une autre à créer un service « oneshot » mais qui ne peut être lancé » qu’après le service rc.local, sans quoi, vous aurez des surprises.
Attention : une mauvaise mise à l’heure peut empêcher le raspberry de booter normalement ou peut bloquer certains services. On n’a pas alors d’autre choix que se connecter en ssh si on le peut ou connecter clavier/souris/écran pour résoudre le problème. Dans certains cas, le reconnecter au web suffit à le remettre à l’heure mais ne résout pas le problème pour le prochain démarrage.
Une petite remarque : on ne sera jamais totalement à jour car le module ne donne pas accès à une précision supérieur à la seconde en lecture et en mise à jour mais est-ce grave ? au pire, vous aurez 0,99999999 secondes d’écart avec l’heure réelle.
De toute manière, le temps d’exécution (lecture du module et mis eà jour) n’est pas nulle donc il reste impossible d’avoir une mise à jour parfaite.
Si l’un d’entre vous a un script en C permettant de faire la même chose, y compris, choisir les PIN qu’on veut utiliser, je suis preneur.