Página principal
Base de tiempo
1 Segundo
Arduino ATMEGA328

Después de haber realizado el Generador de DCF77 con el Arduino, me dí cuenta que algunos relojes no sincronizaba bien.
El caso es que debía tener una base de tiempos muy precisa, y con la función de delay
() no servía.
Pensando y mirando montajes anteriores míos, encontré entre mis montajes uno que utilizaba interrupciones internas mediante contadores.

Para este montaje se utilizan los contadores de 16bits, en modo CTC

19.9.2 -Modo de borrado del temporizador en comparación (CTC)
En los modos de borrado del temporizador en comparación (CTC) (modo 4 o 12, WGMn[3:0]=0x4 o 0xC), los registros OCRnA o ICRn se utilizan para manipular la resolución del contador: el contador se pone a CERO cuando el valor del contador (TCNTn) coincide con el OCRnA (si WGMn[3:0]=0x4) o el ICRn (WGMn[3:0]=0xC). El OCRnA o el ICRn definen el valor superior del contador, por lo tanto también su resolución. Este modo permite un mayor control de la frecuencia de salida de comparación. Simplifica la operación de conteo de eventos externos.
El valor del contador (TCNTn) aumenta hasta que se produce una comparación con OCRnA o ICRn, y luego se borra el TCNTn.


ISR(TIMER1_COMPA_vect)
{
  if(playRun==true)  rutina100();   
}


setup()
{
.............
.............
  // Interrupciones cada 0,1 Segundos
    cli();
    TCCR1A=0;
    TCCR1B=0;   
#if MODO_SEG == 0   // 0=999.762.128 nS 1=999.762.876
      OCR1A=1562; 
      TCCR1B |= (1<<WGM12);   //  0 1 0 0 CTC OCR1A Immediate MAX
      TCCR1B |= (1<<CS10);    // clk I/O /1024 (From prescaler)
      TCCR1B |= (1<<CS12);
#endif
#if MODO_SEG == 1   // 1=1.000.081.262 nS  0=1.000.0828
      OCR1A=6253;   //6252 DIV-256
      TCCR1B |= (1<<WGM12);   //  0 1 0 0 CTC OCR1A Immediate MAX
      TCCR1B |= (1<<CS12); // clk I/O /256 (From prescaler)
#endif  
#if MODO_SEG == 2   // DIV-64
      OCR1A=25031;
                      // 25020    1.000.282.772 nS
                      // 25015    1.000.082.800 nS
                      // 25013 DIV-64   1.000.003.00 nS
                      // 25013 DEDO     1.000.241.871
                      //       DEDO     1.000.121.011
                      // 25013 otro reloj 999.289.372 nS
                      // 25032 otro reloj 1.000.052.634 nS
                      // 25031 otro reloj 1.000.012.119 nS
      TCCR1B |= (1<<WGM12);   //  0 1 0 0 CTC OCR1A Immediate MAX
      TCCR1B |= (1<<CS10); // clk I/O /64 (From prescaler)
      TCCR1B |= (1<<CS11);
#endif
  TIMSK1=(1<<OCIE1A);     // Timer/Counter1, Output Compare A Match Interrupt Enable 
  sei(); 
}

En el código se crea un a interrupción cada 0.1 Segundos.
Con un contador hasta 10, se crea un incremento de 1 Segundo.
Al utilizar los prescaler de   /1024, /265, /64 , podemos aumentar la resolución.
La mejor resolución la conseguimos al utilizar la división 64 , o eso debería ocurrir.





DIV 1024 16000000/1024=15625/10=1562 999.762.128 nS
DIV 256 16000000/256=62500/10=6250 1.000.081.262
DIV 64 16000000/64=250000/10=25000 25020    1.000.282.772 nS
25015    1.000.082.800 nS
25013    1.000.003.000 nS
25013    1.000.241.871 ns    DEDO    
25013    1.000.121.011 ns   DEDO2    

25013    999.289.372 nS    otro reloj
25032   1.000.052.634 nS  otro reloj
25031   1.000.012.119 nS  otro reloj

Todos los tiempos de este montaje dependen de la precisión del cristal de cuarzo a 16 MHz.
Es claro que para el circuito del Arduino nano, no creo que empleen un cristal demasiado exacto.

Entre dos Arduinos nano existe una variación de 14 microsegundos.

Con el mismo módulo nano, si colocamos el dedo sobre el cristal de cuarzo, la variación llega alcanzar 118 microsegundos.
Esto puede ser debido al aumento de temperatura y a la variación de capacidad que induce el dedo.

Vamos a realizar unos cálculos sobre la variación de tiempo en un reloj después de 3 meses, en el caso de 1.000.003.000 nS.

1 Segundo ->3 microSegundos
1h -> 10800 uS
1 dia ->259200 uS   (0.259 S.)
3 meses->23 Segundos

Conclusión:
Se puede y no se puede utilizar el ATMEGA328 como base de tiempos de un reloj.
Lo primero que debemos hacer es ajustar el temporizador para cada circuito nano, y obtener la la mejor precisión, o tener un cristal de 16MHz muy preciso.
También tenemos que tener cuidado la temperatura del entorno del Arduino nano.
Para las medidas he utilizado un analizador de señal Saleae Logic , y no estoy seguro de su precisión, creo que es alta.

Programa Arduino

Espero que os haya gustado este pequeño análisis.

Saludos.
Juan Galaz