TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: esperanzachat en 19 de Mayo de 2019, 19:01:21

Título: Reloj se adelanta solo
Publicado por: esperanzachat en 19 de Mayo de 2019, 19:01:21
Hola, hice un temporizador basado en un DS1307 y el tema que tengo es que, estando alimentado, la hora, una vez ajustada. se adelanta, es  decir se adelanta unos 2 min cada 10 a 15 dias y no se porque, ya que no uso ningun comando que la pueda modificar. use la libreria de redpic
Código: [Seleccionar]
///////////////////////////////////////////////////////////////////////////////////////
///                               DS1307.C                                           ///
///                     Driver for Real Time Clock                                   ///
///                     modified by Redpic 08/2006                                   ///
///                  http://picmania.garcia-cuervo.com                               ///
///                                                                                  ///
/// void ds1307_init(val)                                                            ///
///                  - Enable oscillator without clearing the seconds register       ///
///                    used when PIC loses power and DS1307 run from 3V BAT          ///
///                  - Config Control Register with next parameters:                 ///
///                     DS1307_ALL_DISABLED          All disabled                    ///
///                     DS1307_OUT_ON_DISABLED_HIHG  Out to Hight on Disable Out     ///
///                     DS1307_OUT_ENABLED           Out Enabled                     ///
///                     DS1307_OUT_1_HZ              Freq. Out to 1 Hz               ///
///                     DS1307_OUT_4_KHZ             Freq. Out to 4.096 Khz          ///
///                     DS1307_OUT_8_KHZ             Freq. Out to 8.192 Khz          ///
///                     DS1307_OUT_32_KHZ            Freq. Out to 32.768 Khz         ///
///                                                                                  ///
///                     Example init:                                                ///
///                     ds1307_init(DS1307_ALL_DISABLED);                            ///
///                     ds1307_init(DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);           ///
///                                                                                  ///
/// void ds1307_set_date_time(day,mth,year,dow,hour,min,sec) - Set the date/time     ///
///                                                                                  ///
/// void ds1307_get_date(day,mth,year,dow)                   - Get the date          ///
///                                                                                  ///
/// void ds1307_get_time(hr,min,sec)                         - Get the time          ///
///                                                                                  ///
/// char ds1307_read_nvram_byte(char addr)                   - Read byte in address  ///
///                                                                                  ///
/// void ds1307_write_nvram_byte(char addr, char value)      - Write byte in address ///
///                                                                                  ///
/// void ds1307_get_day_of_week(char* ptr)                   - Get string Day Of Week///
///                                                                                  ///
/// If defined USE_INTERRUPTS all functions disable Global Interrupts on starts and  ///
///                           enable Global on ends else usar can do it hiself       ///
///                                                                                  ///
///////////////////////////////////////////////////////////////////////////////////////

#ifndef RTC_SDA
#define RTC_SDA  PIN_A1
#define RTC_SCL  PIN_A0
#endif

#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)

#define DS1307_ALL_DISABLED         0b00000000 // All disabled
#define DS1307_OUT_ON_DISABLED_HIHG 0b10000000 // Out to Hight on Disable Out
#define DS1307_OUT_ENABLED          0b00010000 // Out Enabled
#define DS1307_OUT_1_HZ             0b00000000 // Freq. Out to 1 Hz
#define DS1307_OUT_4_KHZ            0b00000001 // Freq. Out to 4.096 Khz
#define DS1307_OUT_8_KHZ            0b00000010 // Freq. Out to 8.192 Khz
#define DS1307_OUT_32_KHZ           0b00000011 // Freq. Out to 32.768 Khz

#define Start_user_address_nvram    0x08
#define End_user_address_nvram      0x3f

char days_of_week[7][11]={"Lunes\0","Martes\0","Miércoles\0","Jueves\0","Viernes\0","Sábado\0","Domingo\0"};

byte ds1307_bin2bcd(byte binary_value);
byte ds1307_bcd2bin(byte bcd_value);

void ds1307_init(int val){

   byte seconds = 0;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_start();
   i2c_write(0xD1);
   seconds = ds1307_bcd2bin(i2c_read(0));
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_write(ds1307_bin2bcd(seconds));
   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x07);
   i2c_write(val);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_set_date_time(byte day, byte mth, byte year, byte dow, byte hr, byte min, byte sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_write(ds1307_bin2bcd(sec));
  i2c_write(ds1307_bin2bcd(min));
  i2c_write(ds1307_bin2bcd(hr));
  i2c_write(ds1307_bin2bcd(dow));
  i2c_write(ds1307_bin2bcd(day));
  i2c_write(ds1307_bin2bcd(mth));
  i2c_write(ds1307_bin2bcd(year));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_date(byte &day, byte &mth, byte &year, byte &dow){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);
  i2c_start();
  i2c_write(0xD1);
  dow  = ds1307_bcd2bin(i2c_read() & 0x7f);
  day  = ds1307_bcd2bin(i2c_read() & 0x3f);
  mth  = ds1307_bcd2bin(i2c_read() & 0x1f);
  year = ds1307_bcd2bin(i2c_read(0));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_time(byte &hr, byte &min, byte &sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_start();
  i2c_write(0xD1);
  sec = ds1307_bcd2bin(i2c_read() & 0x7f);
  min = ds1307_bcd2bin(i2c_read() & 0x7f);
  hr  = ds1307_bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}


char ds1307_read_nvram_byte(char addr){

   char retval;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);

   i2c_start();
   i2c_write(0xD1);
   retval = i2c_read(0);
   i2c_stop();

   return(retval);

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_write_nvram_byte(char addr, char value){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);
   i2c_write(value);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_day_of_week(char* ptr){

   byte lday;
   byte lmonth;
   byte lyr;
   byte ldow;
   ds1307_get_date(lday,lmonth,lyr,ldow);
   sprintf(ptr,"%s",days_of_week[ldow]);
}

///////////////////////////////////////////////////////////////////////////////

byte ds1307_bin2bcd(byte binary_value){

  byte temp;
  byte retval;

  temp = binary_value;
  retval = 0;
  while(1){
    if(temp >= 10){
      temp -= 10;
      retval += 0x10;
    }else{
      retval += temp;
      break;
    }
  }
  return(retval);
}

byte ds1307_bcd2bin(byte bcd_value){

  byte temp;

  temp = bcd_value;
  temp >>= 1;
  temp &= 0x78;
  return(temp + (temp >> 2) + (bcd_value & 0x0f));
}

///////////////////////////////////////////////////////////////////////////////
Título: Re:Reloj se adelanta solo
Publicado por: KILLERJC en 19 de Mayo de 2019, 19:26:10
Tu problema no esta en el programa, sino en la alimentacion del DS1307 y/o el cristal del DS1307, sea layout,etc

Tuve un compañero que hizo un proyecto con el mismo, Y luego de renegar y pasarle lo mismo, con un mejor filtrado y un mejor layout del oscilador (como lo pide el datasheet del DS1307) ademas de poner a GND el encapsulado del cristal logro una muy buena mejoria. Paso de unos minutos cada 10 dias a segundos al mes.
Título: Re:Reloj se adelanta solo
Publicado por: Robert76 en 19 de Mayo de 2019, 20:31:12
De cualquier forma, un cristal de cuarzo tiene pequeños corrimientos de su fcia. nominal.
Así que es de esperarse algo cómo ésto.
No pienses que un DS1307 sea un reloj atómico.
Las pequeñas diferencias las corrijes por soft, por ejem. a cada hora adelantas o retrasas la diferencia en una hora.
Por ejem si dices que adelanta 2' en 15 días, es decir adelanta aprox .33333 segundos por hora.
Entonces restas .33333 a cada hora, o mejor restas un segundo cada tres horas.
Título: Re:Reloj se adelanta solo
Publicado por: KILLERJC en 19 de Mayo de 2019, 21:21:55
Mi compañero tambien intento arreglarlo asi... no pudo... El error no era constante. Por lo tanto no funciono de esa forma.

Ademas 0.33s por HORA es una locura de error. Y tenes un reloj super chino que mantiene mejor el horario con componentes mucho mas baratos :3
Título: Re:Reloj se adelanta solo
Publicado por: Robert76 en 19 de Mayo de 2019, 21:30:08
El detalle de que el corrimiento no es cte. es debido al factor temperatura, entre otros.
Yo utilizo ese método y el error lo he reducido a prácticamente algunos segundos de corrimiento por año.
En el propio programa que realicé, me permite modificar el valor de una variable que se traduce a sumar o restar X segundos por día.

Por otro lado .333" por hora puede resultar una locura de error, pero ese es el cálculo que da en función de los datos que expuso el compañero.
Título: Re:Reloj se adelanta solo
Publicado por: Picuino en 20 de Mayo de 2019, 05:52:21
Un buen reloj mecánico adelanta o atrasa como máximo 5 segundos/día.

Un oscilador de cuarzo barato puede darte esa misma precisión, pero se puede compensar para mejorarlo. Si está bien compensado debería darte unos 5 segundos/mes de error máximo.
Título: Re:Reloj se adelanta solo
Publicado por: Picuino en 20 de Mayo de 2019, 07:11:08
Hola, hice un temporizador basado en un DS1307 y el tema que tengo es que, estando alimentado, la hora, una vez ajustada. se adelanta, es  decir se adelanta unos 2 min cada 10 a 15 dias y no se porque, ya que no uso ningun comando que la pueda modificar. use la libreria de redpic

Si el cristal tiene una exactitud de 100ppm, eso significa que va a tener un error máximo de = 0.000100 * (24 *60 * 60) = 8,6 segundos/dia
En 15 días el error máximo será de 2 minutos.

Si compras un cristal mejor (de 30 ppm) y tienes suerte, el error no será mayor de 10ppm y mejorará mucho la exactitud.
Título: Re:Reloj se adelanta solo
Publicado por: AleSergi en 20 de Mayo de 2019, 08:46:51
por ahi lei gente quejandose de la falta de presición del ds1307, y que existe un tal ds3231 modulo arduinero que mejora muchisimo el problema respecto al primero.... 
Título: Re:Reloj se adelanta solo
Publicado por: esperanzachat en 20 de Mayo de 2019, 09:27:47
Gracias a todos por responder. Yo uso un modulo "tiny rtc" ó similar, por lo que tendria que descartar a priori errores por el tema de la placa. Sin embargo ya me pasaba con otra placa que tuve que dejar de producir porque no le encontre el defecto. Esta placa es un diseño nuevo.Lo otro raro es que como dije, la hora varia independientemente de que yo consulte la hora o no, incluso si dejo el reloj desenchufado, alimentado solo por la pila.Les pasare una foto de la placa. (http://www.todopic.com.ar/foros/imgtiny/33v1du1.jpg)
La placa tiene un modulo bluetooth y le puse un capacitor de filtrado en la alimentacion del reloj. Ademas funciona a 12V.
Título: Re:Reloj se adelanta solo
Publicado por: Robert76 en 20 de Mayo de 2019, 09:33:30
Obviamente que la hora seguirá sufriendo corrimiento independientemente de si consultas la hora o no, de si está energizado o no. Ya que la base de tiempo trabaja independiente.
Título: Re:Reloj se adelanta solo
Publicado por: remi04 en 20 de Mayo de 2019, 14:03:20
Yo utilizo muchisimo el DS1307 por que tengo un proyecto en la calle funcionando con mas de 100 unidades vendidas y no tengo esos problemas.  Atrasa o adelanta lo normal que hace cualquier reloj casio o reloj de pared, etc..

De modulos RTC decirte que el único que mejores resultados me ha dado ha sido el de robotdyn, mas caro, no trae memoria eeprom como el de tiny pero no importa..

  De todas formas, en mis diseños para el ds1307 uso este resonador:

 https://lcsc.com/product-detail/SMD-Crystals_SHENZHEN-CRYSTAL-TECH-7MC32768F12UC_C252400.html

 Este encapsulado va metalizado internamente y conectado al plano de tierra " Sin tocar lo que es el cuarzo" al cual hay que hacerle un layout totalmente separado de tierra. Algunos diseños sueldan el cuarzo al plano de tierra y eso he comprobado que no les sienta muy bien.

Este que os pongo es complicado de soldar pero es el que mejor resultado me da.

  Por otro lado hay que asegurarle al integrado una buena alimentación constante de 5V. Al pin de la batería Backup hay que colocarle un diodo 4147 en inverso se instale o no se instale la pila. He comprobado que la precisión mejora mucho con el diodo, especialmente cuando el integrado conmuta al perder la alimentación y pasa a usar la batería backup.

 Por ultimo, utilizar las referencias del chip con certificado industrial.  Es mucho mas estable con los cambios de temperatura.

 Saludos.



 
Título: Re:Reloj se adelanta solo
Publicado por: Picuino en 20 de Mayo de 2019, 14:39:04
El DS3231 lleva un cristal integrado y compensación de temperatura.
https://datasheets.maximintegrated.com/en/ds/DS3231.pdf
El error es menor de 30 segundos al año.
Puedes encontrar módulos por 1€, a mi me parece mejor opción.
Título: Re:Reloj se adelanta solo
Publicado por: esperanzachat en 21 de Mayo de 2019, 10:45:29
De nuevo, gracias a todos. Como uso el tiny RTC o similares, no puedo agregarle el diodo. Creo que lo mejor será usar el ds3231. Tengo una libreria, voy a ver si la puedo hacer andar. Ya voy a pedir ayuda con eso si no la puedo hacer andar. Gracias a todos.
Título: Re:Reloj se adelanta solo
Publicado por: planeta9999 en 21 de Mayo de 2019, 11:43:11

Si buscas precisión y tener el reloj siempre al segundo por mucho tiempo que pase, puedes probar con un módulo DCF77. Estos relojes se ajustan periódicamente de manera automática, por radio (onda larga), creo que con un reloj atómico. Hay varias emisoras en los distintos continentes, en Europa tenemos la de Alemania con un alcance de 1500Km.

Así te desentiendes por completo, sabes que el reloj siempre estará al segundo.
Título: Re:Reloj se adelanta solo
Publicado por: Picuino en 21 de Mayo de 2019, 13:39:43


Si buscas precisión y tener el reloj siempre al segundo por mucho tiempo pase, puedes probar con un módulo DCF77. Estos relojes se ajustan periódicamente de manera automática, por radio (onda larga), creo que con un reloj atómico. Hay varias emisoras en los distintos continentes, en Europa tenemos la de Alemania con un alcance de 1500Km.

Así te desentiendes por completo, sabes que el reloj siempre estará al segundo.

Otra alternativa es un módulo GPS, que también está sincronizado con relojes atómicos. Un módulo barato de unos 10 € te dará un error máximo de 100ns.
https://www.ebay.es/itm/Modulo-arduino-GPS-GY-NEO6MV2-nano-UNO-MEGA/252266235582?hash=item3abc3d46be:g:iycAAOSwhfRcOIvD


Ambos tienen el problema de necesitar recibir la señal de radio de onda larga o de los satélites gps y en muchas ocasiones esto no es nada fácil.

Saludos.
Título: Re:Reloj se adelanta solo
Publicado por: moduled en 06 de Junio de 2021, 13:10:26
Ha pasado bastante tiempo que se publicó este asunto, yo he tenido ese problema desde hace tiempo, el problema es la marca o el fabricante del DS1307, al principio utilicé DS1307 de Maxim (Dallas Semi..) durante años la hora ha sido precisa, ultimamente compré DS1307 por aliexpress, ya que cuestan 10 por $0.81 desde ese momento empezaron mis dolores de cabeza, se adelanta 4 a 5 min cada 7 dias, con lo cual tuve que detener la producción y equipos devueltos. Volví a comprar los Maxim originales (Digikey, Mouser etc. a $3.5) y volvió la precisión. Comprobado!
Título: Re:Reloj se adelanta solo
Publicado por: allennet en 21 de Junio de 2021, 04:56:20
Los cristales con menos ppm son los de placas madre, comprate de las antiguas q esten malogradas y pruebas, tambien hay veces q las golpean y se aumentan su ppm  :?