
Le coucou en question est une horloge née en 1989 à Triberg, en Forêt Noire (Allemagne).
Battant approximativement la demi-seconde, il n’a pas la stabilité d’un quartz oscillant à plusieurs kHz, voire MHz. De là à mettre un mouvement à quartz, il n’y a qu’un pas que les fabricants ont bien sûr déjà franchi. Mais l’âme d’un coucou étant son mouvement mécanique, il n’était pas question pour moi d’y toucher.
Donc le premier point du cahier des charges était de ne pas modifier le mécanisme d’origine, et de faire en sorte que ce dernier continue à fonctionner quand le dispositif de régulation est arrêté pour une raison quelconque.
Le deuxième point du cahier des charges portait sur la précision : une stabilisation du fonctionnement à 10 secondes près est largement suffisante ; par contre il est souhaitable qu’elle soit tenue aussi bien à long terme qu’à court terme, et c’est là que le problème se complique un peu.
Précision et stabilité
Assez sensible aux variations de température ou d’humidité, ainsi qu’aux mouvements d’air puisqu’il est proche de la porte d’entrée de la maison, ce coucou avait une tendance à dériver tranquillement de quelques minutes par mois. Rien de dramatique, mais la sonnerie des heures et de la demie finissait par devenir purement indicative, au point de nécessiter une intervention manuelle pour la recaler.
Pour autant, il est inutile de chercher la précision à la seconde près. D’abord parce que le coucou n’affiche pas les secondes (!), ensuite parce que l’instant auquel il sonne le premier coup de chaque heure ou la demie n’est calé qu’à quelques secondes près (ce qui est déjà bluffant s’agissant d’une mécanique aussi simple).
Pour ramener le problème à ce que je connais, j’ai choisi une solution électronique. Et comme je suis passé graduellement du fer à souder au clavier, je suis parti sur une solution Arduino (au sens large incluant les cartes à base de microcontrôleurs Atmel, mais aussi la gamme ESP8266 et les réalisations diverses la mettant en oeuvre).
Cette palette de solutions présente l’avantage d’un outil unique de développement. Et pour le sujet qui nous intéresse, fournit tout ce qu’il faut pour expérimenter, entre cartes et modules complémentaires divers.
S’agissant de réguler un mécanisme, il nous faudra forcément une horloge locale de référence permettant de mesurer et de corriger la dérive constatée du coucou.
Si l’horloge de référence est précise (elle est presque à la bonne fréquence) et stable (elle y reste), tout va bien. Si elle est décalée en fréquence, mais stable, on peut faire avec car un décalage (donc une erreur systématique) peut toujours se corriger par soft. Si elle est instable et fluctue de façon aléatoire en fonction de la température ou autres paramètres, le cas est désespéré.
L’horloge de référence toute désignée est celle du microprocesseur. Pas l’horloge RC intégrée parce ce que la carte utilisée, quelle qu’elle soit, propose mieux.
Premier type de solution : une carte Arduino Uno chinoise ou autre similaire. L’utilisation d’une résonateur céramique conduit à une stabilité de l’ordre de 3 pour 1000, mais disons 1 pour 1000 dans la plage de température réduite qui est celle d’une habitation. A raison de 86400 secondes par jour, on peut dériver de plus d’une minute par jour : ce n’est pas franchement mieux que le coucou sans assistance…
Avec la carte Arduino Uno « officielle », le quartz améliore la stabilité à court terme. Dans la même plage de température, on peut tabler sur une stabilité de 30 ppm (0,030 pour mille). Il faut alors près de 4 jours pour atteindre une variation de 10s.
Pour une meilleure stabilité à court terme, et une stabilité acceptable à long terme, on peut, pour quelques Euros, utiliser un TCXO (oscillateur compensé en température), par exemple un module DS3231 dit RTC (horloge temps réel) qui apporte une stabilité de l’ordre de 2 ppm. Il faudra alors 2 mois pour constater une dérive de 10 s.
Ou encore mieux, pour un coût du même ordre de grandeur, on peut profiter des services d’une horloge atomique (externe…). Il suffit d’ajouter une interface Wifi qui, une ou deux fois par jour, donne accès à un serveur NTP.
Là, c’est l’arme absolue, la dérive de moins de 10s se maintiendra toute l’année… C’est la solution que j’ai finalement retenue.
Voilà donc maintenant un coucou mécanique bien entouré : entre l’électronique de régulation et les deux ressources proches de lui dont il bénéficie (la box ADSL avec réseau WiFi, et un onduleur initialement ajouté pour l’alimentation de cette box) il est raisonnablement à l’abri des coupures du réseau électrique, et remis à l’heure exacte aussi fréquemment qu’on le souhaite.
Couplage mécanique entre l’électronique et le coucou
Il reste à préciser le mode d’interaction de l’électronique sur le coucou.
Le balancier est constitué d’une tige en bois sur laquelle est placée une masselotte (coulissante) de réglage. Le plus simple est d’intervenir directement sur ce balancier.
Les plus férus de pneumatique pourront envoyer un jet d’air vers le balancier en mouvement (!) mais de mon côté j’ai choisi une solution magnétique, avec la mise en place, sur la face cachée de la tige du balancier, d’un aimant néodyme (petit aimant très puissant, de forme cylindrique de diamètre 6mm et de hauteur 3mm) collé à chaud sur sa tranche.

Invisible en fonctionnement normal du coucou, son faible poids ne génère qu’une légère perturbation de la fréquence naturelle d’oscillation du balancier, facilement rattrapée par un décalage de quelques millimètres de la masselotte de réglage.
Juste à hauteur de cet aimant et placée horizontalement à l’arrière du coucou ( contre le mur), j’ai ajouté d’une baguette en bois (un couvre-joint en l’occurrence) collée à chaud par les extrémités aux deux flasques latérales.

Sur cette baguette, également collés à chaud, sont placés un électroaimant (à gauche sur la photo) et (à droite) un capteur magnétique genre capteur à effet hall, mais en l’occurrence il s’agit d’une magnétorésistance.
La photo ci-dessous montre le résultat de cette modification :

Une fois en place, la baguette se voit peu. Voici une vue de l’arrière du coucou, avec la baguette positionnée entre les flasques et son câble qui rejoint l’électronique placée en partie haute du coucou :

L’électroaimant auquel on applique l’impulsion électrique « qui va bien » (quelques dizaines de ms) peut soit l’attirer soit repousser l’aimant et ainsi modifier la période d’oscillation du balancier.
Quant au capteur qui détecte chaque passage de l’aimant à sa proximité, il remplit un triple rôle :
- Il permet de mesurer la durée de chaque période (on n’en fait strictement rien, à part l’afficher pour information)
- Il fournit la synchronisation (par rapport au battement du balancier) du moment où on envoie une impulsion à l’électroaimant pour corriger le mouvement.
- Il permet de compter le nombre de battements du balancier pendant une durée donnée.
On peut imaginer des variantes (surtout pour le placement du capteur magnétique), mais là j’ai tout simplement placé le capteur et l’électroaimant chacun à environ 15mm au-delà de la course de l’aimant.
C’est très simple, mais ça fonctionne très correctement pour peu qu’on gère bien le timing de l’impulsion (comme une balançoire que l’on doit pousser ou retenir à bon escient).
Aux essais, on constate que si l’impulsion est trop longue et/ou mal calée dans le temps, il est facile de retenir l’aimant pour qu’il ne soit même plus vu par le capteur, ou de le pousser assez fort pour qu’il survole le capteur et, au retour, finisse par se coller carrément sur l’électroaimant (qui non alimenté est un bête barreau de fer que l’aimant ne doit donc pas approcher de trop près).
Mais avec une impulsion d’une durée de 40 à 80 ms et décalée de quelques dizaines de ms de l’instant de passage de l’aimant au plus près de l’électroaimant, on obtient rapidement des résultats convaincants (si l’électroaimant était une bougie de moteur à essence, on parlerait de calage de l’allumage par rapport au point mort haut…).
Pour être plus précis, le capteur magnétique est un 2SS52M. Comme il est omnipolaire, peu importe s’il fait face au pôle nord ou au pôle sud de l’aimant.

Quant à l’électroaimant, il provient d’un relais automobile 12V.
Pas beau, mais efficace…

Comme l’électroaimant doit opposer à l’aimant un pôle nord ou sud selon que l’on veut ralentir ou accélérer le balancier, il est commandé à l’aide d’un pont en H qui permet de l’alimenter dans les deux sens. Ce pont est en fait la « moitié d’un double pont » HG 7881 (qui contient deux circuits intégrés L9110S). Il fait parfaitement l’affaire, pour quelques Euros.
L’ensemble est alimenté sous 10V. Cette tension alimente le pont en H, le capteur magnétique, et l’entrée Vin de la carte électronique qui génère son propre 5V.
Pour limiter les pointes de courant dans le câble d’alimentation, un condensateur de 3300 µF (alimenté via une résistance de quelques ohms) est placé au plus près du pont en H.
Le pont en H est commandé par deux sorties logiques de l’Arduino. Et une entrée logique (avec résistance de pull-up) reçoit la sortie (collecteur ouvert) du capteur magnétique.
Voici à quoi ressemble la partie électronique du système:

On voit en haut le condensateur cité plus haut et à droite le double pont en H. Un connecteur 6 points (avec un point blanc pour le détrompage) permet le raccordement de l’ensemble capteur + électroaimant.
La carte utilisée (WeMos) est construire autour d’un ESP8266 (côté pont en H) dont on distingue l’antenne WiFi.
Le tout est collé par points de colle à chaud sur une planchette de bois qui loge très aisément dans la partie haute du coucou. Cette partie haute étant en creux, l’ensemble est invisible. Seul le câble d’alimentation en haut et la baguette en bas du coucou témoignent de la modification du coucou.
Autre vue avec, au premier plan, le connecteur 6 points et la prise châssis d’alimentation 10V :

Première étape : trouver la correspondance entre les battements du coucou et les secondes.
Je pensais benoitement trouver ça sur le web, mais non.
J’y ai trouvé une méthode appliquée à diverses horloges : compter les dents des divers rouages impliqués.
J’ai reculé devant la tâche, et préféré commencer par une simple fonction de comptage des tops du capteur pendant 24 h. Il s’agit de « 24h du coucou », donc peu importe qu’il soit bien réglé ou pas, ce qui compte est le nombre de coups mesurés entre deux sonneries espacées de 24h, par exemple de 19h30 à 19h30 le lendemain.
Si on tombe sur un nombre pas rond, il suffit de chercher un peu autour : on attend quelque chose de divisible par 24 (3 x 8) et par 60 (5 x 3 x 4). Donc (PPCM) multiple de 3 x 8 x 5 = 120. Si le résultat du comptage est par exemple de 89 263, la division par 120, donne en arrondissant 743,8. En prenant 744 x 120 = 89 280, on a, en divisant par 24, 3720 coups à l’heure (ie 3600 secondes). Or 3720 / 3600 = 31 / 30. Trop beau pour être un hasard, je suis parti sur 31 battements toutes les 30 secondes et aujourd’hui c’est ce qui tourne avec un résultat qui s’est révélé convaincant sur plusieurs jours.
On note que la période « normale » est de 30/31 = 0,968 s, et que l’impulsion de 40 à 80ms envoyée à l’électroaimant représente 4 à 8 % de cette période.
Deuxième étape : le logiciel
J’ai essayé d’en faire le plus possible (de ce qui prend peu de temps) dans des routines d’interruptions pour que tout ça coopère et tourne tout seul. La partie loop() ne gère que les tâches longues au timing peu critique.
Rien d’original en soi, mais il faut dire que l’ESP8266 permet, sur un seul timer (celui qui n’est pas mobilisé par le WiFi) de générer autant d’interruptions que voulu : 1ms, 10 ms, 1s, 30s, etc. On y arrive aussi avec un Arduino standard, mais en générant des flags à tout va dans une routine d’interruption unique.
La mesure de l’avance du coucou (ou du retard si le résultat est négatif) se fait à l’aide d’une variable entière « avance », incrémentée de 1 à chaque top du capteur et décrémentée de 31 (puis aussitôt mémorisée) toutes les 30 s. Comme toutes les 30 s on a normalement 31 tops du capteur, la variable « avance » compte de 1 à 31 les tops capteur successifs puis retombe à 0 au top 30s (et on mémorise alors cette valeur 0). Si le coucou avance (trop de tops capteurs), la valeur mémorisée croit graduellement du nombre de tops en trop. S’il retarde, la valeur mémorisée décroit graduellement du nombre de tops manquants.
C’est tellement simple que c’en est presque élégant…
La régulation se fait par paliers de 16 battements ; c’est totalement arbitraire, mais évite d’enchaîner précipitamment accélérations et freinages. Si au début d’un palier on constate un retard d’au moins 5 battements, on accélère le balancier durant tout le palier, si on constate une avance d’au moins 5 battements, on freine le balancier , et si on est dans une « plage neutre » avec une avance comprise entre +2 et -2 battements, on ne fait rien. Résultat : ça s’auto-débrouille à maintenir le retard ou l’avance à plus ou moins 4 battements le plus souvent, et moins par moments.
Les avantages du « coucou connecté »
L’interface WiFi du module ESP8266 permet facilement, grâce aux bibliothèques associées, de réaliser un client NTP pour la mise à l’heure et un serveur web pour l’affichage d’une page d’état du coucou.
La synchronisation sur un serveur NTP
A chaque connexion au serveur NTP, on note le timestamp (unix) [nombre de secondes écoulées depuis le 1er Janvier 1970 à minuit UTC] qu’il fournit.
Et entre deux mises à l’heure successives on compte les secondes fournies par l’horloge locale.
La comparaison entre d’une part ce total des secondes locales et d’autre part la différence entre le dernier timestamp et le précédent, indique de combien l’horloge locale a avancé ou retardé par rapport à celle de référence du serveur NTP.
On décale d’autant le comptage des 30 secondes pour le calcul de l’avance, et au prochain « top 30s » l’avance mémorisée intègrera le nombre de battements à rattraper. Trop simple !
Comme l’électronique ignore quelle heure affiche le coucou, elle n’a pas non plus à connaitre l’heure exacte et cela nous simplifie bien la tâche.
En réalité, on n’a vraiment à connaitre que les timestamps unix successifs et le nombre de battements du balancier du coucou. Mais on passe par l’intermédiaire des « secondes de l’horloge locale » pour faire une pré-correction dans le bon sens, au fil de l’eau, entre deux timestamps.
Si l’horloge locale dérive dans la journée, le coucou dérive d’autant. Mais à long terme, et en fait chaque jour, le coucou est toujours remis à l’heure exacte NTP. L’horloge locale n’est donc qu’un outil d’extrapolation entre deux mises à l’heure NTP. De ce fait, on peut même (si on a confiance dans la liaison WiFi…) utiliser comme horloge locale un simple résonateur céramique au lieu d’un quartz.
L’affichage sur smartphone
Pour les premiers essais de faisabilité, j’avais utilisé une carte Arduino complétée par un afficheur LCD pour indiquer l’état des paramètres. Mais un afficheur rétroéclairé en haut d’un coucou, c’est inesthétique. De plus, c’est peu lisible à distance, et ses deux lignes de 16 caractères sont vite insuffisantes.
Le serveur web embarqué maintenant dans le logiciel permet de tenir à jour en permanence une page contenant tous les paramètres que l’on veut suivre : période en ms, avance ou retard en nombre de battements du balancier, heure de la dernière connexion NTP et amplitude en secondes de l’écart mesuré, etc.
Conclusion
Il est grisant de lire très exactement 08:00 sur la montre connectée quand le coucou sonne. Mais il faut bien admettre qu’en dehors du plaisir d’y parvenir, c’est parfaitement inutile dans la vie de tous les jours.
Mais parvenir à l’inutile est indispensable…