Autor Tema: Precisión del reloj  (Leído 10757 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Precisión del reloj
« Respuesta #15 en: 05 de Diciembre de 2003, 11:28:00 »
Aquí tienes el reloj totalmente acabado, cortesía de Diegonet: http://miarroba.com/foros/ver.php?temaid=665952&foroid=46840

Desconectado PabloFiscella

  • PIC16
  • ***
  • Mensajes: 154
RE: Precisión del reloj
« Respuesta #16 en: 05 de Diciembre de 2003, 12:09:00 »
Pareceria ser que en Argentina no se consigue nada.
El 3,2768 tampoco lo consigo. Encotre alguien que vende el 4,096 a  U$s7, un poco caro no?
Luego les cuento porque lo voy a comprar.
Para poder hacer el temporizador.

Saludos a todos.
Pablo

achamber2k3

  • Visitante
RE: Precisión del reloj
« Respuesta #17 en: 10 de Diciembre de 2003, 17:53:00 »
Bueno, en mi pais ahora tenemos control de cambio y es un poco dificil conseguir cualquier cosa, asi que aplico un metodo que llame "del año bisiesto" para resolver esto con un común cristal de 4MHz exactos, lo que hice fue lo siguiente:

1.- considere el preescaler en 256 y la fcristal obviamente en 4MHz

2.- Construi una tabla en excel para calcular con valores de recarga desde  0 hasta 255 la siguiente formula:

nciclos = 1seg/( (256-recarga)*256*(4/4000000) )

Esto me da el numero de ciclos necesarios del lazo externo (que en un ejemplo dado por ustedes era de 20) para contar aproximadamente un segundo. Por supuesto me dan todos con decimales, pero bueno ahi esta el truco de la cosa.

3.- Tomo el valor de nciclos que menos decimales tenga y por supuesto sea menor a 255 en este caso tengo que con un valor de recarga de 6 el cual tiene un valor de nciclos de 15,625 con una interrupcion por timer cada 64ms bien veamos que nuestra diferencia con un numero entero es de 0,625 para el valor de nciclos, pues tratamos de encontrar el primer numero que multiplicado por 0,625 nos de un entero, en este caso es 8 - > 8*0.625 = 5 esto significa que cada 8 ejecuciones del contador cargado con 15 debemos cargarlo con 15+5 = 20 para de esta forma corregir los decimales.

4.- Asi pues usariamos dos contadores uno que llevaria la cuenta de ajuste y otro que llevaria la cuenta de cuando se cumple un segundo. Este metodo pienso aplicarlo proximamente en un control de luces, ya lo simule y funciona perfectamente, una salida alternativa al problema de los cristales.

Saludos a todos y Exitos

AChamber

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Precisión del reloj
« Respuesta #18 en: 11 de Diciembre de 2003, 06:27:00 »
Hola Alfredo, no lo acabo de entender y creo que esto que tú planteas nos interesa a todos.

Siguiendo tu razonamiento:

Cargando el TMR0 con 6 y usando un Preescaler=256 (fosc=4MHz) sale que cada 64ms se producirá una interrupción.

¿Puedes poner como cargarías los 2 contadores externos para conseguir el deseado segundo?

Un saludo

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Precisión del reloj
« Respuesta #19 en: 11 de Diciembre de 2003, 10:31:00 »
Hola Cuca, estaba contestando antes y se ha ido la luz ... dita sea.

Vamos a hacer algunos números.

Cargando el TMR0 con 6 y usando un Preescaler=256 (fosc=4MHz) sale que cada 64ms se producirá una interrupción.

Si usamos un Contador cargado con 15 y realizamos 15 interrupciones saldría un tiempo de 15 · 64ms = 960ms.

Si esto se repite 8 veces saldría un tiempo de 8 · 960ms = 7680ms

Si ahora hacemos la corrección cargando el registro Contador con 5 (en lugar de 15) el tiempo empleado en estas 5 pasadas será: 5 · 64ms = 320ms.

Es decir los 8 primeros segundos los ha realizado en 7680ms más la corrección que es 320ms.

Si sumamos ambos tiempos salen un total de 7680 + 320ms = 8000ms = 8s

Creo que la precisión se obtiene cada 8s, no cada 9s.

¡¡¡Muy buena explicación Cucaracha!!!

Desconectado cucaracha

  • PIC24H
  • ******
  • Mensajes: 1409
    • CUCAWEB
RE: Precisión del reloj
« Respuesta #20 en: 11 de Diciembre de 2003, 10:57:00 »
...y esos 5 "añadidos" en que segundo entran pocher...

Saludos!
Saludos desde Huelva (ESPAÑA)

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Precisión del reloj
« Respuesta #21 en: 11 de Diciembre de 2003, 11:16:00 »
Ya estoy otra vez aquí.

Los 320ms son los que le faltan para completar los 8s, por lo tanto entran en el transcurso del 7º segundo.

Un saludo

Desconectado cucaracha

  • PIC24H
  • ******
  • Mensajes: 1409
    • CUCAWEB
RE: Precisión del reloj
« Respuesta #22 en: 11 de Diciembre de 2003, 11:35:00 »
Jeje... pues mirándolo de nuevo creo que ni tú ni yo...
En el 8º se deben de contar 20 en lugar de 15. Se ha de cambiar una vez concluido el 7º paso. Ya que si cargas luego de 8 el contador con 5, cuando se cumplan incrementará también los segundos, osea que serían ya 9.
No?

Saludos!!
Saludos desde Huelva (ESPAÑA)

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Precisión del reloj
« Respuesta #23 en: 11 de Diciembre de 2003, 12:17:00 »
Vamos a darle más caña:

- Según el primer desarrollo numérico (7680ms + 320ms), la corrección, que son los 320ms se empieza a hacer cuando han pasado 7680ms , es decir cuando han pasado 7,68s y cuando termina la corrección han pasado los 8s.

- Según tu segundo desarrollo numérico (el de 20), la corrección se empieza a hacer cuando han pasado 960ms · 7 = 6720ms, es decir cuando han pasado 6.72s y el resultado de la corrección es: 20 · 64ms = 1280ms. Si sumamos los 6720ms + 1280ms = 8s

CONCLUSIÓN: bien de una manera, bien de otra se llega al mismo resultado.

Un saludo

Desconectado cucaracha

  • PIC24H
  • ******
  • Mensajes: 1409
    • CUCAWEB
RE: Precisión del reloj
« Respuesta #24 en: 11 de Diciembre de 2003, 13:13:00 »
Más marcha!!

Si te fijas, el segundo desarrollo está basado en el primero. Cuando han pasado esos 7,68seg es al octavo paso. Ahora le sumas los 320mseg que faltan y listo. Sobre papel muy bien, pero como lo haces en el micro. Para llevar a cabo el primer desarrollo, tienes que hacer lo que viene en el segundo.
Porque como sumas esos 320ms (los cinco ciclos)?? Habría que hacerlo con otra rutina que los contara y no incrementara los segundo al final.
Microcontroladormente hablando esos 7,68 seg, en realidad es como si fueran los 8 seg con un error de 320ms (por el cristal), entonces se hace la treta de la correción. Pero eso, esos 7,68seg son 8seg con un error de 320ms. Entiendes mi razonamiento

No?

Saludos!!
Saludos desde Huelva (ESPAÑA)

achamber2k3

  • Visitante
RE: Precisión del reloj
« Respuesta #25 en: 11 de Diciembre de 2003, 13:53:00 »
Carambas he entrado por curiosidad desde el trabajo y Dios Mio! que interesante se ha puesto esto, jaja, pues si, ambos tienen razon, yo lo que hago originalmente es cargar con 15 durante siete veces y con 20 la octava vez, y obtengo el ajuste de error cada 8 segundos, le he llamado metodo del a~no bisiesto porque asi se hace en el calendario, el a~no solar tiene algo asi como 365.25 dias, ese error se suma y cada 4 a~nos tenemos un 29!

En la noche al llegar a la casa les cuelgo el programa para que lo vean y comentemos.

Saludos y Exitos

Achamber

Desconectado PabloFiscella

  • PIC16
  • ***
  • Mensajes: 154
RE: Precisión del reloj
« Respuesta #26 en: 12 de Diciembre de 2003, 07:30:00 »
Lo probe y funciona perfecto.

Son unos capos.
Muchas gracias. Saludos
Pablo

achamber2k3

  • Visitante
RE: Precisión del reloj
« Respuesta #27 en: 12 de Diciembre de 2003, 18:25:00 »
Perdonen la demora aqui esta lo prometido, un poco tarde pues ya medio foro sabe como es, gracias por sus comentarios muchachos:

////                     INICIALIZAR                                 ////

void inicializar() {

      set_tris_a(0x00);                //Todo puerto A Salidas
      set_tris_b(0xF0);                //RB0-3 Salidas RB4-7 Entradas

      port_b = 0x00;                   //Inicializa señales de control
      port_a = 0x0c;                   //Inicializa señales de control

      init_lcd();

      setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
      set_rtcc(6);
      enable_interrupts(INT_RTCC);
      enable_interrupts(GLOBAL);

}

////                     RUTINAS DE INTERRUPCION                     ////

#INT_RTCC
void cada64ms()  {

   disable_interrupts(GLOBAL);

   set_rtcc(6);
   contemp1 = contemp1 - 1;

   if (contemp1==0) {

         contemp2 = contemp2 - 1;
         contemp1 = 15;

         if (contemp2==0){

            contemp1 = contemp1 + 5;
            contemp2 = 8;

         }

         // Rutina Aprox cada segundo - Exacta cada 8 seg.
         // contemp1 se carga con 15, 15, 15, 15, 15, 15, 15, 20, 15, 15...

         segundos = segundos + 1;
         if (segundos==60){
            minutos = minutos + 1;
            segundos = 0;
         }
         if (minutos==60){
            horas = horas + 1;
            minutos = 0;
         }
         if (horas==13){ horas = 1; }
         bampm = 0;

   }

   enable_interrupts(GLOBAL);

}


Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Precisión del reloj
« Respuesta #28 en: 13 de Diciembre de 2003, 05:29:00 »
achanver2k3 faltan bastantes cosas (definición de variables, el include de la LCD, el main ... )

¿Que te parece si pones el programa completo, incluida la visualización sobre la LCD?

Un saludo

achamber2k3

  • Visitante
RE: Precisión del reloj
« Respuesta #29 en: 13 de Diciembre de 2003, 10:05:00 »
Bueno alli va el programa, solo maneja el LCD, porque al hacer el control para todo lo demas que queria pues me quede sin memoria y ahora estoy trabajando en el diseño con un 876. Cuando lo tenga listo, con control de teclado, dimmer para las luces que controla e interfaz para el PC pues subo todo el proyecto.

Espero les sea útil.

Saludos a todos.

Alfredo

/////////////////////////////////////////////////////////////////////////
////                     PROYECTO DE DOMOTICA                        ////
/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////
////                     COMANDOS DEL PREPROCESADOR                  ////
/////////////////////////////////////////////////////////////////////////

#if defined(__PCM__)
#include <16F84A.h>
#fuses XT,NOWDT,NOPROTECT,PUT
#use delay(clock=4000000)

#bit lcd_rs = 5.0
#bit lcd_e = 5.1
#bit latch_ck = 5.2
#bit temp_cs = 5.3
#bit buzzer = 5.4

#byte port_a = 5
#byte port_b = 6
#byte lcd_data = 6

/////////////////////////////////////////////////////////////////////////
////                     DEFINICION DE VARIABLES                     ////
/////////////////////////////////////////////////////////////////////////

char string[16];
int estado_control;
int horas = 12;
int minutos = 00;
int segundos = 00;
short bampm = 0;
int contemp1 = 15;         // Contador Interno 15 o 20
int contemp2 = 8;         // Contador Ajuste hasta 8
float temp = 26.36;

/////////////////////////////////////////////////////////////////////////
////                     DEFINICION DE FUNCIONES                     ////
/////////////////////////////////////////////////////////////////////////

void inicializar();
void init_lcd();
void write_lcd_nibble(BYTE);
void write_lcd(SHORT, BYTE);
void lcd_gotoxy(BYTE,BYTE);
void lcd_putc(char);
void pantallaespera();
void lcd_putc(char);
void goto_lcd(BYTE,BYTE);

/////////////////////////////////////////////////////////////////////////
////                     RUTINA DE INICIALIZACION                    ////
/////////////////////////////////////////////////////////////////////////

void inicializar() {

      set_tris_a(0x00);                //Todo puerto A Salidas
      set_tris_b(0xF0);                //RB0-3 Salidas RB4-7 Entradas

      port_b = 0x00;                   //Inicializa señales de control
      port_a = 0x0c;                   //Inicializa señales de control

      init_lcd();

      setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
      set_rtcc(6);
      enable_interrupts(INT_RTCC);
      enable_interrupts(GLOBAL);

}

/////////////////////////////////////////////////////////////////////////
////                     PROGRAMA PRINCIPAL                          ////
/////////////////////////////////////////////////////////////////////////

main()   {

   inicializar();

   while(TRUE){

      pantallaespera();

   }

}

/////////////////////////////////////////////////////////////////////////
////                     RUTINAS DE INTERRUPCION                     ////
/////////////////////////////////////////////////////////////////////////

#INT_RTCC
void cada64ms()  {

   disable_interrupts(GLOBAL);

   set_rtcc(6);
   contemp1 = contemp1 - 1;

   if (contemp1==0) {

         contemp2 = contemp2 - 1;
         contemp1 = 15;

         if (contemp2==0){

            contemp1 = contemp1 + 5;
            contemp2 = 8;

         }

         // Rutina Aprox cada segundo - Exacta cada 8 seg.
         // contemp1 se carga con 15, 15, 15, 15, 15, 15, 15, 20, 15, 15...

         segundos = segundos + 1;
         if (segundos==60){
            minutos = minutos + 1;
            segundos = 0;
         }
         if (minutos==60){
            horas = horas + 1;
            minutos = 0;
         }
         if (horas==13){ horas = 1; }
         bampm = 0;

   }

   enable_interrupts(GLOBAL);

}

/////////////////////////////////////////////////////////////////////////
////                     RUTINAS DE MENU                             ////
/////////////////////////////////////////////////////////////////////////

void pantallaespera(){

      write_lcd (0, 0x80);
      printf(lcd_putc, "%02u:%02u:%02u%c %02.2fC", horas, minutos, segundos, bampm, temp);
      write_lcd (0, 0xc0);
      printf(lcd_putc, " * * O O      * ";

}

/////////////////////////////////////////////////////////////////////////
////                     RUTINAS DE MANEJO DE LCD                    ////
/////////////////////////////////////////////////////////////////////////

void init_lcd() {

   write_lcd_nibble(0x02);
   write_lcd(0, 0x0c);
   write_lcd(0, 0x01);
   write_lcd(0, 0x06);

}

void write_lcd_nibble(BYTE n) {

      lcd_data = n;
      delay_ms(1);
      lcd_e = 1;
      delay_ms(1);
      lcd_e = 0;
      delay_ms(1);

}

void write_lcd(SHORT nocom, BYTE dato) {

      lcd_rs = nocom;
      delay_ms(1);
      write_lcd_nibble(dato >> 4);
      write_lcd_nibble(dato & 0xf);
      lcd_rs = 0;

}

void lcd_putc( char c) {

   write_lcd(1,c);     break;

}

/////////////////////////////////////////////////////////////////////////
// FIN