prec home dir suiv

CHOUR - Horloge DCF77 sur processeur MSP430

img

Présentation

J'ai plein d'horloges et de montres mécaniques, électriques ou électroniques mais je ne suis jamais sûr qu'elles soient à l'heure. Il me fallait donc une petite horloge de confiance. Et je voulais qu'elle fonctionne sur piles sans avoir à les changer trop souvent. Et puis, ça m'amusait...

Donc voici la présentation de cette horloge synchronisé sur le signal DCF77 ainsi que son programme qui tourne sur un processeur Texas Instrument (TI) MSP430F449 qui comme toute la série des processeurs MSP430, est réputé pour sa très faible consommation tout en étant capable de gérer en permance un afficheur LCD. Et c'est le gros avantage de cette horloge par rapport à un smartphone : pas besoin de la recharger tous les jours. Normalement, un changement de pile toutes les X années suffit (X de l'ordre de 5 à 7 ans).

Pour ceux qui ont parcouru ce site, vous avez pu voir tout une série de compteurs geiger-muller de ma conception qui utilisent ce processeur ou d'autres de la même famille et dont la consommation moyenne est de l'ordre de 20 à 60µA selon les versions.

Pour terminer cette introduction, vous trouverez pléthore d'horloges synchronisées sur le signal DCF77 à des prix très raisonnables (une vingtaine d'euro ou moins) et qui font beaucoup plus de chose que celle présentée ici. Cette horloge n'a ni réveil matin, ni réglage de l'heure (elle ne fonctionne donc que dans certains pays d'Europe) et n'a aucune autre prétention que de permettre d'expérimenter et d'avoir la satisfaction de l'avoir faite soit même.

Et vous trouverez également, outre les programmes sources, quelques réflexions sur la façon de traiter le signal DCF77.

Spécifications

Les spécifications sont les suivantes :

L'afficheur est le seul interface disponible (avec éventuellement, les boutons poussoirs)

img

Affichage de l’heure

Entre deux mise à l’heure à partir du signal DCF77, l’horloge fonctionne « en roue libre » sur sa propre base de temps interne.

Elle resynchronise sa base de temps interne et se remet à l’heure lorsqu’un signal DCF77 correct est reçu.

Affichage de la date

L’affichage de la date se fait sur l’afficheur en haut à gauche. Il affiche alternativement (chaque seconde) l’année (exemple : 2023) ou le jour et le mois (exemple : 23:08 pour le 23 août).

Cette date se resynchronise tous les jours (ou à la demande) lorsqu’un signal DCF77 correct est reçu.

Indicateurs

4 indicateurs sont présents sur l’afficheur :

Matériel

Le processeur utilisé est donc un MSP430 disponible sur un petit circuit de développement conçu par Olimex. Il dispose d'un afficheur (que j'avais cassé il y a plusieurs années. Je l'ai remplacé par un autre modèle d'où les fils un peu partout pour relier l'afficheur à la carte de développement), 4 boutons poussoirs et d'autres bricoles que j'ai viré (prise V24, buzzer...).

img
MSP430-449STK2

Pour le module DCF77, j’en ai pris un tout fait sur Aliexpress (environ 3€ port compris en 2023). Il est donné pour avoir une consommation maximum de 85µA ce qui est assez élevé. Mais en mode « désactivé », sa consommation est imperceptible.

img
Module RCC02C03A

Pour ceux qui auraient du mal à trouver la spécification, voici quelques indications utiles :

Réalisation

Ci-après, la réalisation matérielle (avec l'afficheur qui n'est pas d'origine !). On y trouve la connexion du module DCF77 sur un connecteur de la carte de développement avec son alimentation, le signal d'activation sur le port GPIO P2.1 et le signal démodulé sur le port GPIO P2.0. L'autre connexion est celle du porte pile qui fournit l'alimentation de 3V.

img

On peut mettre tout ça dans un petit boitier imprimé en 3D, ici, en ASA (sans le capôt qui ferme le tout).

img

img

Boitier qui présente une légère rétractation des bords, problème malheureusement courant avec le ASA.

Logiciel

La partie la plus complexe mais la plus intéressante concerne le logiciel. Celui-ci est téléchargeable pour le cas (improbable) où quelqu'un voudrait réaliser cette horloge ou le cas (plus probable) où quelqu'un voudrait des tuyaux sur la programmation du MSP430.

La partie concernant l'affichage de l'heure, de la date et des indicateurs n'appelle pas d'attention particulière et je ne la détaillerai pas.

La partie réellement intéressante concerne le décodage du signal DCF77 et la gestion de la basse consommation. C'est ce qui est expliqué ci-après.

Réception du signal DCF77

La réception du signal se fait donc via un module spécialisé qui peut être activé ou non. Il n’est activé que lorsque l’horloge le demande (soit lors d’une mise à l’heure automatique à 00:00:00, soit lors d’une demande manuelle). Si au bout de 10mn, l’horloge n’a pas reçu de trame correcte, le module DCF77 est désactivé et l’horloge continue de fonctionner en roue libre. Un indicateur permet de savoir si la dernière tentative de réception à 00:00:00 a fonctionné ou pas.

Rappel sur le signal DCF77

On trouve une spécification du signal DCF77 sur le site Wikipedia. Les explications qui suivent résument les points importants de cette spécification.

Le signal DCF77 est constitué d’une porteuse à 77,5kHZ. La modulation de cette porteuse code l’information à transmettre (un bit) sous forme temporelle.

Cette modulation se retrouve sur une sortie du module spécialisée sous la forme d’un 0 (tension nulle) ou d’un 1 (tension d’alimentation du module).

On retiendra que si on reçoit un signal à 1 pendant plus de 200ms ou si l'on reçoit un signal à 0 pendant plus de 1900ms, on a soit un gros problème de réception, soit un module en panne.

img

Donc, chaque seconde, on doit recevoir un signal à 1 (dont la durée donne la valeur du bit), puis après 100ms (respectivement 200ms), un signal à 0 pendant 900ms (respectivement 800ms), puis de nouveau, un signal à 1, etc.

On appelle « trame » l'ensemble des bits du signal horaire émis périodiquement.

La trame comporte 59 bits utiles véhiculés à raison d'un bit par seconde (donc 59 secondes). La 60ème seconde sert à la synchronisation et vaut 0 pendant une seconde (pas de modulation). Elle marque la fin de la trame courante et le premier front montant qui suit détermine le début de la trame suivante. Il détermine également le moment où les signaux reçus de la trame précédente peuvent être utilisés.

Dit autrement, l’heure reçue dans une trame est valide lorsqu’on reçoit le début de la trame suivante. En supposant que l'heure reçue soit 09:56, le front montant du début de la trame suivante (qui code 09:57) permettra de mettre une horloge à l'heure avec l'heure (09:56:00. Il y a un cas particulier, voir la spécification sur Wikipédia)

img

La durée du signal de synchronisation permet de faire sans difficulté le décodage des informations reçues afin d’être prêt à les utiliser lors de l’apparition de la trame suivante. Pour la signification des bits reçus, voir sur Wikipedia.

Stratégie de synchronisation

Une stratégie de synchronisation (trouver le début d'une trame) peut être la suivante :

Cette recherche peut se faire par test d'état (déconseillé) ou en utilisant des interruptions sur fronts montants et descendants. Un front descendant déclenche une mesure de durée que l'on arrête sur le prochain front montant. Si cette durée est entre 1800ms et 1900ms, on a trouvé le début d'une trame.

Sauf que si l'on procède ainsi, ça ne fonctionne pas bien parce que le signal est très sensible au bruit et qu'il y a souvent des impulsions parasites.

Il faut donc filtrer ces parasites ce qui implique de mesurer la durée entre chaque front (front montant ou front descendant) pour savoir si l’on doit prendre en compte le signal ou pas. Mais on se heure à un autre problème qui est de savoir si l’impulsion parasite était en fait le début d’un signal valide ou pas. On doit donc aussi mesurer la temps dans le signal auquel s’est produite cette impulsion pour lever le doute.

On a bien sûr le même problème pour la détection des signaux codant les bits. Mais en supposant que l'on a trouvé le début d'une trame (je vous rassure, c'est faisable), on peut procéder plus simplement que pour le signal de synchronisation.

L'idée est d'échantillonner (par exemple, toute les millisecondes) le signal pendant une certaine durée (pendant par exemple 50ms) autour du centre supposé de sa durée.

Pour ce faire, on utilise un compteur initialisé à 0, et à chaque fois que l'on détecte un signal à 1, on fait +1 dans le compteur et pour un signal à 0, -1.

Si la somme est positive, on considère que l’on a reçu un 1 sur la période de mesure, sinon, on a reçu un 0 (pour un compteur nul, il y a une incertitude mais cela veut dire que le signal est particulièrement brouillé).

Cette approche permet d’éviter de mesurer la durée des impulsions parasites et permet de rejeter les signaux trop brouillés : Si on obtient 0 alors qu’on devait avoir 1 (par exemple lors des 100 premières milliseconde du codage d'un bit) ou un 1 alors qu'on devait avoir un 0 (pendant les 800 dernières millisecondes du codage d'un bit), le plus prudent est de reprendre toute la mesure.

img

Mais on peut faire encore plus simple en échantillonnant que le signal présent entre 100ms et 200ms. S’il est présent, on a un 1, sinon, un 0. Le seul inconvénient potentiel est qu’on fait moins de contrôle sur la forme du signal donc on est moins susceptible de détecter certaines erreurs dans un environnement très bruité.

Idéalement, il faudrait pouvoir détecter le front montant de chaque nouveau signal codant un bit afin d'être certain d'échantilloner au bon endroit dans le signal. Mais on se retrouve de nouveau avec le problème d'éliminer les signaux parasites comme dans le cas du signal de synchronisation.

Une autre solution consiste à disposer d'une horloge suffisamment stable et précise sur 60 secondes que l'on déclenche au début du signal de synchronisation. Puis toutes les 1000ms, on passe à l'échantillonnage du bit suivant.

C'est l'approche adoptée dans la présente implémentation et l'on utilise pour cette horloge le quartz à 8MHz disponible sur la carte de développement que l'on divise jusqu'à avoir un top toutes les millisecondes pour l'échantillonnage.

Cette méthode est très similaire à celle d’une classique réception asynchrone.

Petit test de culture réseau : indiquez le débit en baud et le débit en bits par seconde (bps) de la communication (si vous regardez les définitions que l'on trouve de bauds et bps sur le net, vous avez toutes les chances de donner une réponse fausse).

Implémentation retenue

Pour cette horloge, l’implémentation retenue est un mixte entre la détection de fronts et la mesure temporelle de la valeur du signal.

Algorithme pour la synchronisation :

Une fois que la synchronisation a été trouvée, le programme mesure le valeur du signal entre 140ms et 170ms de la même façon que pour la mesure de la synchronisation. Si le cumul est positif, le signal code un bit à 1. Sinon, il code un bit à 0.

Cette façon de procéder permet de filtrer les éventuels parasites sans mesures compliquées.

Décodage

Le décodage consiste à interpréter les bits reçus. Certains contrôles (parité, cohérence) permettent de valider que la trame est correcte ou pas (note : la numérotation des bits de la trame commence à 0).

Parité : elle concerne les minutes, les heures, la date.

Valeurs fixes : elles concernent le bit 0 (toujours à 0) et le bit 20 (toujours à 1).

Cohérence : certaines valeurs doivent se trouver dans des limites connues (heures, minutes, secondes, dates, jour de la semaine).

Qualité du signal

La réception du signal DCF77 peut être assez problématique. Surtout que les environnements actuels sont très bruités du fait des alimentations à découpage présentes dans de nombreux appareils ou des éclairages à LED. La simple proximité d'un appareil d'éclairage allumé peut empêcher toute réception.

Selon les fréquences et la modulation utilisée, la réception peut être meilleure à certaines heures, en particulier, la nuit.

L’afficheur indique la qualité du signal reçu en affichant de 0 à 3 barres à côté de l’antenne. L’algorithme est le suivant :

Sauf lorsqu’il n’y a pas de réception du tout (0 barre), la modification du nombre de barres est mise à jour toutes les secondes.

Une impulsion est définie ici comme parasite si sa durée est inférieure ou égale à 50ms.

Stratégie pour une basse consommation

4 mode de basse consommation sont disponibles. LPM4 est exclu d’office dans la mesure où il désactive toutes les horloges et attend un événement externe pour réveiller le processeur. Reste donc LPM0 à LPM3.

Pour une basse consommation, on doit viser une utilisation maximale de LPM3.

En roue libre, le programme est réveillé par le Watchdog (WDT) toutes les secondes pour mettre l’heure et la date à jour.

WDT peut être piloté par un oscillateur interne au processeur (moyennement précis) ou par un quartz sur XT1 (très précis).

En roue libre, la consommation de l’horloge est de l’ordre de 45µA avec XT1 et 40µA avec l'oscillateur interne. Cette consommation passe à environ 400µA en recherche de signal et à environ 650µA une fois la synchronisation trouvée quelque soit la source de l'horloge.

Du fait de la faible différence entre les deux modes, l’implémentation utilisant XT1 a été retenue moyennant une consommation moyenne supérieure de 5µA.

Le mode basse consommation LPM3 est activé dès que les différentes routines ont terminé leur traitement.

Une journée fait 1440 minutes. Chaque jour, l'horloge fonctionne en roue libre entre 99,3% (elle n'arrive pas à se synchroniser) et 99,9% du temps (elle arrive à se synchroniser en 2 minutes ou moins). La consommation est essentiellement due à l’affichage, à l’entretien de XT1 et au traitement qui doit s’exécuter la plupart du temps en moins d’1ms à 1MHz de fréquence d’horloge.

La documentation du mode LPM3 est un peu imprécise sur certains points mais des recherches sur le forum de Texas Instrument (TI) permettent de lever certaines ambiguïtés.

Ainsi, on apprend que LPM3 n’arrête pas les quartz (c’est heureux) et n’arrête pas SMCLK s’il est utilisé par un périphérique ce qui est le cas du timer A0 qui utilise XT2 (8MHz) et qui est actif lorsque l’horloge recherche le signal DCF77.

Pour le reste, il y a les nécessaires initialisations des différents périphériques pour limiter la consommation. Par défaut, ils sont désactivés. Un problème se pose néanmoins pour les GPIO.

En général, on conseille de configurer les GPIO en entrée avec une résistance de polarisation active (il y a des débats sur le niveau (bas ou haut) d'activation de ces résistances). Sauf que le MSP439F449 ne dispose pas de résistances de polarisation.

J'ai lu quelque part que TI conseillait de configurer les GPIO en sortie. Cela parait logique : sans résistances de polarisation, les entrées sont en l'air et il y a un risque de voir les GPIO commuter en permanence ce qui consomme de l'énergie.

j'ai fait plusieurs essais et pour le moment, les meilleurs résultats ont été obtenus en mettant P1 et P2 en sortie (sauf les GPIO explicitement déclarées en entrées) et les autres ports dans leur configuration par défaut à la mise sous tension sachant que la plupart d'entre-eux sont initialisés par la suite lors de la configuration de l'écran LCD.

Selon Wikipédia, les piles AA Alcalines ont une capacité de l'ordre de 2850mAh.

Si l’on utilise deux piles en série pour obtenir 3V (capacité toujours de 2850mAh), l’autonomie sera de l’ordre de 7 ans pour une consommation moyenne de 45µA.

Avec le processeur piloté uniquement par sa base de temps interne, l’autonomie serait de l’ordre de 8 ans.

Chargement du logiciel

Le logiciel a été développé en langage C avec l'environnement Code Composer Studio (Eclipse pour MSP430).

Chargement Logiciel

Août 2023

sommaire