¿Cómo obtengo una hora precisa?

16

He hecho un reloj usando un Arduino, pero el tiempo parece ir a la deriva. Soy consciente del problema de reinversión ; el reloj parece moverse unos 15 minutos en el transcurso de una semana.

Estoy usando una PCB personalizada con este resonador de Digi-key. El código lee la función millis () al comienzo de cada ciclo y funciona a partir de ese valor.

Mi pregunta es: ¿cómo puedo medir el tiempo con un Arduino, con la precisión suficiente para hacer un reloj de escritorio aceptable?

John Walthour
fuente
3
La función de milisegundos se suministra con datos de una interrupción, que tarda un par de ciclos de reloj en ejecutarse. Esto agrega una cantidad minúscula de tiempo a cada tic.
TheDoctor
3
@TheDoctor: Esto es incorrecto. La interrupción no ralentiza el temporizador de hardware que conduce millis().
Edgar Bonet

Respuestas:

15

Nota: aunque mi respuesta fue aceptada y tiene una puntuación de voto más alta, asegúrese de leer la excelente respuesta de Edgar Bonet sobre cómo hacer que su Arduino mantenga el tiempo sin un RTC.

He tenido bastante éxito en el uso del reloj de tiempo real DS1307. Aquí hay un enlace a su hoja de datos .

A continuación se presentan algunas de sus características:

  • Utiliza la interfaz IC para la comunicación con Arduino, lo que facilita la programación utilizando las bibliotecas correctas (disponibles en la red).

  • Está conectado a Arduino a través de los pines SCL y SDA (analógico A4 y A5 respectivamente), por lo que solo usa 2 pines.

  • Requiere muy pocos componentes externos para funcionar.

  • Se puede conectar a una batería de celda de moneda para que mantenga el tiempo incluso cuando el Arduino está apagado. En su modo de bajo consumo, la batería de celda de moneda dura años.

  • Se desplaza muy poco (en mi caso solo se desplaza unos segundos por semana).

  • No es muy costoso.

Si no tiene la intención de usar un RTC, puede reemplazar el cristal que se usa comúnmente para proporcionar reloj a arduino para un módulo oscilador de cristal como este de Farnel o este otro . Vienen en paquetes de 4 pines como en las imágenes a continuación. Generarán un reloj mucho más preciso para tu arduino.

Imagen del oscilador de cristal Imagen del oscilador de cristal Imagen del oscilador de cristal

Ambos módulos mencionados tienen tolerancias de 50 ppm y funcionan a 5V.

Nuevamente, para ser claros, estos módulos osciladores de cristal no deben confundirse con el cristal normal de 2 pines como se muestra a continuación. Esos son parte de los circuitos de relojes externos para MCU, por ejemplo.

Oscilador de cristal

Ricardo
fuente
¿El DS1302 es lo suficientemente bueno o debería pasar al DS1307?
Kelly S. French
14

No necesita un RTC para construir un reloj: el chip ATmega tiene todo el hardware necesario para realizar las tareas del RTC. Aquí es cómo:

  1. Obtenga un reloj de cristal de 32768 Hz: cómprelo o desarme un reloj antiguo. Estos cristales, diseñados específicamente para mantener el tiempo, tienen una deriva de temperatura extremadamente pequeña. También necesitarías uno de esos si quisieras usar un chip RTC.

  2. Configure los fusibles de su ATmega para funcionar con el oscilador RC de 8 MHz. Esto hará que su millis()función sea terriblemente inexacta, y también liberará los pines XTAL1 y XTAL2.

  3. Conecte el cristal de reloj a los pines TOSC1 y TOSC2. Estos son los mismos pines que XTAL1 y XTAL2 (9 y 10 en el 328P). Los diferentes nombres se usan para significar diferentes funciones.

  4. Configure el Temporizador / Contador 2 para operación asíncrona, modo de conteo normal, preescalador configurado en 128 y habilite la interrupción de desbordamiento del temporizador.

Ahora obtendrá una interrupción TIMER2_OVF a una velocidad muy constante de una vez por segundo. Solo necesita avanzar la pantalla del reloj un segundo en el ISR. Entre las interrupciones, puede poner el MCU en modo de suspensión muy profundo (modo de suspensión de ahorro de energía: nada funciona más que Temporizador / Contador 2) y funcionar durante años en un par de celdas AA. A menos que la pantalla tenga mucha energía, obviamente.

Hice exactamente esto para construir mi reloj de pared con una mano las 24 horas . Este enlace apunta ahora a la traducción al inglés de la documentación original en francés.

Calibración de cuarzo

Si no calibra su cuarzo, puede esperar una deriva significativa, generalmente unos segundos por semana . La tasa de deriva depende de la capacitancia parásita de las trazas que conectan el cristal a la MCU. En principio, podría eliminarse agregando un poco de capacitancia extra finamente ajustada. Vale la pena señalar que tendría el mismo problema de deriva con un RTC.

Si está satisfecho con este tipo de precisión, viva con ella y sea feliz. Sin embargo, si desea medir la deriva, notará que es muy estable. Luego puede compensarlo fácilmente en el software y lograr una precisión de unos segundos por año .

El algoritmo para corregir la deriva es muy simple. A partir de la deriva medida, calcula el retraso preciso entre las interrupciones, que debería estar muy cerca de 10 9  nanosegundos, luego:

#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;
    }
}

En el ejemplo anterior, el cuarzo es un poco demasiado rápido, y el software lo compensa con un "tic" cada pocos días. Si el cuarzo fuera demasiado lento, el mismo código haría doble clic una vez cada pocos días.

Este tipo de calibración también podría realizarse para un RTC, pero sería significativamente más complejo porque el RTC informa el tiempo en una forma desglosada que no se presta naturalmente a operaciones aritméticas.

Edgar Bonet
fuente
¡Guau, ese es un diseño muy elegante! Realmente me gusta cómo has puesto suficientes fotos para aclarar el diseño, incluso para nosotros los tontos monoglot americanos :) ¡Realmente me encanta ver documentación de proyecto explícita como esta!
John Walthour
2
@ JohnWalthour: ¡Gracias! Ahora me estás animando a escribir una traducción. :-)
Edgar Bonet
2
@ JohnWalthour: ¡Listo! El enlace ahora apunta a la traducción al inglés.
Edgar Bonet
Para ser claros, cuando dices, "el chip ATmega tiene todo el hardware necesario", eso no es del todo cierto cuando tienes que obtener un nuevo cristal. Creo que su solución es ingeniosa y no estoy por encima de reemplazar el cristal, pero estaba un poco confundido cuando dice que no necesito hardware y luego me doy la vuelta y digo que necesito reemplazar una pieza de hardware.
Kelly S. French
@ KellyS.French: Mi frase fue "el chip ATmega tiene todo el hardware necesario para realizar las tareas del RTC " (énfasis agregado). Pero entonces es importante notar que la mayoría de los RTC, incluido el omnipresente DS1307, necesitan un cristal externo para funcionar. El ATmega no es diferente: tiene todo lo que se necesita para reemplazar el RTC en sí , pero no para reemplazar el cristal que de todos modos tendría que conectar al RTC. Tenga en cuenta que un módulo RTC es más que un RTC, ya que incluye el cristal.
Edgar Bonet
6

El resonador que especificó tiene una estabilidad del 0.3%, donde el cristal o el oscilador de cristal (como lo menciona Ricardo) es de 50 ppm. Muchas veces más estable. Sin mencionar que la deriva de la temperatura del resonador es horrible. El calentamiento por la luz solar lo cambiará. Por lo tanto, no debe usarse un resonador para mantener el tiempo durante largos períodos.

Por lo tanto, usar un cristal o un oscilador de cristal obtendrá lo que desea. Ya sea usándolo en el ATmega y configurando los fusibles respectivamente o usándonos uno conectado a un RTC.

mpflaga
fuente
¿Dónde 50 ppm es 0.005% de estabilidad?
Matthew G.
Generalizo sobre esa especificación, para mantener la respuesta breve. Tenga en cuenta la estabilidad a un lado Res. tienen una tolerancia mucho mayor y pueden estar bastante apagados. Como John W está experimentando. "la parte correcta para el trabajo correcto"
mpflaga
Oh, tenía curiosidad por la terminología @mpflaga ... nueva para mí.
Matthew G.
4

Si no desea utilizar hardware adicional, como un reloj de tiempo real (por ejemplo, DSDS1307), puede mejorar significativamente la precisión de la sincronización desactivando todas las interrupciones no utilizadas. Por defecto, los bocetos de Arduino vienen con varias rutinas de interrupción habilitadas y, a menudo, no se usan para su boceto. La forma más rápida de averiguar si puede prescindir de él para intentar deshabilitarlos emitiendonoInterrupts();

jippie
fuente
3
−1 (aunque esto merece −4) porque: 1. A menos que realmente los necesite, todas las interrupciones están deshabilitadas de forma predeterminada, con la única excepción de TIMER0_OVF, que es necesaria para mantener la hora. 2. La precisión de sincronización de los Arduinos está limitada principalmente por la calidad del resonador. 3. Las interrupciones no afectan la precisión de, a millis()menos que se las arregle para gastar más de un milisegundo a la vez en darles servicio, en cuyo caso tiene otros problemas ... 4. ¡Desactivar las interrupciones noInterrupts()evitará millis()perder tiempo!
Edgar Bonet
2

Entiendo que gran parte del espíritu con Arduino es ser frugal y ocasionalmente pasar por un problema. Utilizo Arduino (y ahora chipKIT, ya que tiene 10 veces la RAM y 10 veces la velocidad del reloj) para mi lugar de trabajo y necesito "funciones periféricas" para estar al día y trabajar lo más rápido posible.

Utilizo el reloj de tiempo real sparkfun en uno de mis proyectos y estoy muy contento con él. También tienen una variante "Dead on" .

Chris K
fuente