Comment obtenir une heure précise?

16

J'ai fabriqué une horloge en utilisant un Arduino, mais le temps semble dériver. Je suis conscient du problème de roulement ; l'horloge semble dériver d'environ 15 minutes au cours d'une semaine.

J'utilise un PCB personnalisé avec ce résonateur de Digi-key. Le code lit la fonction millis () au début de chaque boucle et fonctionne à partir de cette valeur.

Ma question est: comment puis-je mesurer le temps avec un Arduino, assez précisément pour faire une horloge de bureau passable?

John Walthour
la source
3
La fonction milliseconde est fournie avec les données d'une interruption, ce qui prend quelques cycles d'horloge pour s'exécuter. Cela ajoute un temps minuscule à chaque tick.
TheDoctor
3
@TheDoctor: C'est incorrect. L'interruption ne ralentit pas le minuteur matériel qui pilote millis().
Edgar Bonet

Réponses:

15

Remarque: bien que ma réponse ait été acceptée et ait un score de vote plus élevé, assurez-vous de lire la grande réponse d'Edgar Bonet sur la façon de faire en sorte que votre Arduino garde le temps sans RTC.

J'ai réussi à utiliser l'horloge en temps réel DS1307. Voici un lien vers sa fiche technique .

Voici quelques-unes de ses fonctionnalités:

  • Il utilise une interface IC pour la communication avec Arduino, ce qui facilite la programmation en utilisant les bonnes bibliothèques (disponibles sur le Net).

  • Il est connecté à Arduino via les broches SCL et SDA (analogiques A4 et A5 respectivement), n'utilisant ainsi que 2 broches.

  • Il nécessite très peu de composants externes pour fonctionner.

  • L'informatique peut être connectée à une pile bouton pour garder le temps même lorsque l'Arduino est éteint. Dans son mode basse consommation, la pile bouton dure des années.

  • Il dérive très peu (dans mon cas il ne dérive que quelques secondes par semaine).

  • Ce n'est pas tres cher.

Si vous n'avez pas l'intention d'utiliser un RTC, vous pouvez remplacer le cristal qui est couramment utilisé pour fournir une horloge à Arduino pour un module oscillateur à cristal comme celui-ci de Farnel ou cet autre . Ils viennent en paquets de 4 broches comme dans les images ci-dessous. Ils généreront une horloge beaucoup plus précise pour votre arduino.

Image de l'oscillateur à cristal Image de l'oscillateur à cristal Image de l'oscillateur à cristal

Les deux modules mentionnés ont des tolérances de 50 ppm et fonctionnent à 5V.

Encore une fois, pour être clair, ces modules d'oscillateur à cristal ne doivent pas être confondus avec le cristal ordinaire à 2 broches comme ci-dessous. Celles-ci font partie du circuit des horloges externes pour les microcontrôleurs, par exemple.

Oscillateur à cristal

Ricardo
la source
Le DS1302 est-il assez bon ou dois-je passer au DS1307?
Kelly S. French
14

Vous n'avez pas besoin d'un RTC pour construire une horloge: la puce ATmega possède tout le matériel nécessaire pour effectuer les tâches du RTC lui-même. Voici comment:

  1. Obtenez un cristal de montre à 32768 Hz: achetez-le ou démontez une vieille horloge. Ces cristaux, spécialement conçus pour garder le temps, ont une dérive de température extrêmement faible. Vous en auriez également besoin si vous vouliez utiliser une puce RTC.

  2. Configurez les fusibles de votre ATmega pour fonctionner avec l'oscillateur RC 8 MHz. Cela rendra votre millis()fonction horriblement inexacte et libérera également les broches XTAL1 et XTAL2.

  3. Connectez le cristal de la montre aux broches TOSC1 et TOSC2. Ce sont les mêmes broches que XTAL1 et XTAL2 (9 et 10 sur le 328P). Les différents noms sont utilisés pour signifier différentes fonctions.

  4. Configurez le temporisateur / compteur 2 pour un fonctionnement asynchrone, un mode de comptage normal, un pré-échelle réglé sur 128 et activez l'interruption de dépassement de temporisation.

Vous obtiendrez maintenant une interruption TIMER2_OVF à un rythme très régulier d'une fois par seconde. Il vous suffit de faire avancer l'affichage de l'horloge d'une seconde dans l'ISR. Entre les interruptions, vous pouvez mettre le MCU en veille très profonde (mode veille à économie d'énergie: rien ne fonctionne que Timer / Counter 2) et fonctionner pendant des années sur quelques cellules AA. À moins que l'écran ne soit énergivore, évidemment.

J'ai fait exactement cela pour construire mon horloge murale à une main de 24 heures . Ce lien pointe maintenant vers la traduction anglaise de la documentation originale en français.

Étalonnage du quartz

Si vous ne calibrez pas votre quartz, vous pouvez vous attendre à une dérive importante, généralement quelques secondes par semaine . Le taux de dérive dépend de la capacité parasite des traces qui connectent le cristal au MCU. En principe, il pourrait être supprimé en ajoutant une capacité supplémentaire finement réglée. Il convient de noter que vous auriez le même problème de dérive avec un RTC.

Si vous êtes satisfait de ce type de précision, alors vivez avec et soyez heureux. Cependant, si vous souhaitez mesurer la dérive, vous remarquerez qu'elle est très stable. Vous pouvez ensuite facilement le compenser dans le logiciel et atteindre une précision de quelques secondes par an .

L'algorithme de correction de la dérive est très simple. A partir de la dérive mesurée, vous déterminez le délai précis entre les interruptions, qui devrait être très proche de 10 9  nanosecondes, puis:

#define ONE_SECOND    1000000000  // in nanoseconds
#define ONE_INTERRUPT  999993482  // for example

ISR(TIMER2_OVF_vect)
{
    static uint32_t unaccounted_time;

    unaccounted_time += ONE_INTERRUPT;
    while (unaccounted_time >= ONE_SECOND) {
        advance_display_by_one_second();
        unaccounted_time -= ONE_SECOND;
    }
}

Dans l'exemple ci-dessus, le quartz est légèrement trop rapide et le logiciel compense en «manquant» une tique tous les quelques jours. Si le quartz était trop lent, le même code doublerait plutôt une fois tous les quelques jours.

Ce type d'étalonnage pourrait également être effectué pour un RTC, mais il serait beaucoup plus complexe car le RTC rapporte l'heure sous une forme décomposée qui ne se prête pas naturellement aux opérations arithmétiques.

Edgar Bonet
la source
Wow, c'est un design vraiment lisse! J'aime vraiment la façon dont vous avez mis suffisamment de photos pour rendre le design clair, même pour nous, les stupides Américains monoglottes :) J'aime vraiment voir la documentation explicite du projet comme ça!
John Walthour
2
@JohnWalthour: Merci! Vous m'encouragez maintenant à écrire une traduction. :-)
Edgar Bonet
2
@JohnWalthour: Terminé! Le lien pointe maintenant vers la traduction anglaise.
Edgar Bonet
Juste pour être clair, quand vous dites: "La puce ATmega a tout le matériel nécessaire", ce n'est pas tout à fait vrai lorsque vous devez obtenir un nouveau cristal. Je pense que votre solution est lisse et ne remplace pas le cristal, mais j'étais un peu confus lorsque vous dites que je n'ai pas besoin de matériel, puis que je me retourne et que je dois remplacer un morceau de matériel.
Kelly S. French
@ KellyS.French: Ma phrase était «la puce ATmega a tout le matériel nécessaire pour effectuer les tâches du RTC lui-même» (non souligné dans l'original). Mais alors il est important de noter que la plupart des RTC, y compris l'omniprésent DS1307, ont besoin d'un cristal externe pour fonctionner. L'ATmega n'est pas différent: il a tout ce qu'il faut pour remplacer le RTC lui - même , mais pas pour remplacer le cristal que vous auriez de toute façon à connecter au RTC. Veuillez noter qu'un module RTC est plus qu'un simple RTC, car il inclut le cristal.
Edgar Bonet
6

Le résonateur que vous avez spécifié a une stabilité de 0,3%, où le cristal ou l'oscillateur à cristal (comme mentionné par Ricardo) est de 50 ppm. Plusieurs fois plus stable. Sans parler de la dérive de température du résonateur, c'est horrible. Le chauffage par la lumière du soleil le changera. Par conséquent, un résonateur ne doit pas être utilisé pour garder le temps sur de longues périodes.

Par conséquent, l'utilisation d'un cristal ou d'un oscillateur à cristal obtiendra ce que vous voulez. Soit en l'utilisant sur l'ATmega et en réglant les fusibles respectivement, soit en nous connectant à un RTC.

mpflaga
la source
Où 50ppm est 0,005% de stabilité?
Matthew
Je généralise sur cette spécification, pour garder la réponse brève. Notez la stabilité de côté Res. ont une tolérance beaucoup plus grande et peuvent être assez éloignées. Comme John W le vit. "la bonne pièce pour le bon travail"
mpflaga
Oh, j'étais simplement curieux de connaître la terminologie @mpflaga ... nouvelle pour moi.
Matthew G.12
4

Si vous ne souhaitez pas utiliser de matériel supplémentaire comme une horloge en temps réel (par exemple, DSDS1307), vous pouvez améliorer considérablement la précision de synchronisation en désactivant toutes les interruptions inutilisées. Par défaut, les croquis Arduino sont livrés avec diverses routines d'interruption activées et souvent, ils ne sont pas utilisés pour réellement votre croquis. Le moyen le plus rapide de savoir si vous pouvez vous en passer pour essayer de les désactiver en émettantnoInterrupts();

jippie
la source
3
-1 (bien que cela mérite -4) parce que: 1. Sauf si vous en avez réellement besoin, toutes les interruptions sont désactivées par défaut, à la seule exception de TIMER0_OVF, qui est nécessaire pour le chronométrage. 2. La précision de synchronisation des Arduinos est principalement limitée par la qualité du résonateur. 3. Les interruptions n'affectent pas la précision de millis()sauf si vous parvenez à passer plus d'une milliseconde à la fois à les entretenir, auquel cas vous avez d'autres problèmes ... 4. La désactivation des interruptions avec noInterrupts()empêchera millis()de garder du temps!
Edgar Bonet
2

Je comprends qu'une grande partie de l'esprit avec Arduino est d'être économe et parfois de contourner un problème. J'utilise Arduino (et maintenant chipKIT, car il a 10 fois la RAM et 10 fois la vitesse d'horloge) pour mon lieu de travail et j'ai besoin de "fonctions périphériques" pour être à jour et travailler le plus rapidement possible.

J'utilise l'horloge en temps réel sparkfun dans l'un de mes projets et j'en suis très content. Ils ont également une variante "Dead on" .

Chris K
la source