Domanda su replica Tix Led Clock

Buona domenica a tutti!!! Anni fa, insieme al mitico Uwe e grazie al codice iniziale di SilverCG sono riuscito a mettere in piedi una replica del Tix Led Clock, venduto su thinkgeek ed altri siti di accessori strani, qua potete vedere il mio risultato: tix led clock replica - YouTube

La domanda che vorrei porre è: (sia ad Uwe che a tutti voi!!) Come mai mi perde quasi un minuto al giorno!?!? Posto il codice qua:

/*#################################################
###           ---- Tix LED Clock ----           ###
###Copyright 2010 - Dave Johnson - SilverCG.com ###
### --- this code includes 3 rows of multiplexed###
### leds to display a clock                     ###
#################################################*/

#include <DateTime.h>
#include <DateTimeStrings.h>
#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  255   // Header tag for serial time sync message

int colpins[] = {2,3,4,5,6,7,8,9,10};
int rowpins[] = {12, 11, 13};
char top;
long timer;
const long muxInterval = 20;
int mux = 0;
int x;
int timesync;
int hourlist2[3];
int hourlist[9];
int minlist2[6];
int minlist[9];
int oldminute;


void setup() {
  Serial.begin(19200);
  for (int pin=0; pin<9; pin++) {
    pinMode( colpins[pin], OUTPUT );
  }
  for (int pin=0; pin<3; pin++) {
    pinMode( rowpins[pin], OUTPUT );
  }
  DateTime.sync(DateTime.makeTime(0, 34, 12, 10, 4, 2010));;

}

/* void hoursplit(){
  */

void loop(){
  int hour = (DateTime.Hour);
  int minute = (DateTime.Minute);
  int seconds = (DateTime.Second);
  int newhour = 0;

  if (seconds == 0 || timesync == 1) {
    Serial.println(seconds);
   // reset
    for (int i = 0; i < 9; i++){
      minlist[i] = 0;
      hourlist[i] = 0;
    }
    for (int i = 0; i < 6; i++) {
      minlist2[i] = 0;
    }  
    for (int i = 0; i < 3; i++) {
      hourlist2[i] = 0;
    }   
  
  
   //math 
   //------------- start new code ---- july 22 2010 ---
   if (hour == hour){
//    if (hour > 12){
//      newhour = hour - 12;
//    }
//    if (hour < 12) {
//      newhour = hour;
//    }
//    if (newhour == newhour){
//      if (newhour == 0) {
//        hourlist2[0] = 1;
//        hourlist[0] = 1;
//        hourlist[1] = 1;
//      }
//      if (newhour == 12){
//        hourlist2[0] = 1;
//        hourlist[0] = 1;
//        hourlist[1] = 1;
//      }
//      if (newhour == 11){
//        hourlist2[0] = 1;
//        hourlist[0] = 1;
//      }
//      if (newhour == 10){
//        hourlist2[0] = 1;
//        hourlist2[1] = 0;
//        hourlist2[2] = 0;
//        for (int i = 0; i < 9; i++){
//          hourlist[i] = 0;
//        }
//      }
    if (hour > 19 && hour < 24) {
      hourlist2[0] = 1;
      hourlist2[1] = 1;

      int subhour = hour - 20;
      for (int i = 0; i < subhour; i++){
        hourlist[i] = 1;
      }
    }
    if (hour > 9 && hour < 20) {
      hourlist2[0] = 1;
      int subhour = hour - 10;
      for (int i = 0; i < subhour; i++){
        hourlist[i] = 1;
      }
    }
      
    if (hour > 0 && hour < 10) {
      for (int i = 0; i < hour; i++){
        hourlist[i] = 1;
      }
    }
    if (hour == 0){  
    }
//--------------------end new code 
    if (minute >= 0 and minute < 10) {
      minlist2[0] = 0;
      minlist2[1] = 0;
      minlist2[2] = 0;
      minlist2[3] = 0;
      minlist2[4] = 0;
      minlist2[5] = 0;
      minute -= 0;
      for (int i = 0; i < minute; i++){
        minlist[i] = 1;
      }
    }
    if (minute >= 10 and minute < 20) {
      minlist2[0] = 1;
      minlist2[1] = 0;
      minlist2[2] = 0;
      minlist2[3] = 0;
      minlist2[4] = 0;
      minlist2[5] = 0;
      minute -= 10;
      for (int i = 0; i < minute; i++){
        minlist[i] = 1;
      }
    }
    if (minute >= 20 and minute < 30) {
      minlist2[0] = 1;
      minlist2[1] = 1;
      minlist2[2] = 0;
      minlist2[3] = 0;
      minlist2[4] = 0;
      minlist2[5] = 0;
      minute -= 20;
      for (int i = 0; i < minute; i++){
        minlist[i] = 1;
      }
    }
    if (minute >= 30 and minute < 40) {
      minlist2[0] = 1;
      minlist2[1] = 1;
      minlist2[2] = 1;
      minlist2[3] = 0;
      minlist2[4] = 0;
      minlist2[5] = 0;
      minute -= 30;
      for (int i = 0; i < minute; i++){
        minlist[i] = 1;
      }
    }
    if (minute >= 40 and minute < 50) {
      minlist2[0] = 1;
      minlist2[1] = 1;
      minlist2[2] = 1;
      minlist2[3] = 1;
      minlist2[4] = 0;
      minlist2[5] = 0;
      minute -= 40;
      for (int i = 0; i < minute; i++){
        minlist[i] = 1;
      }
    }
    if (minute >= 50 and minute < 60) {
      minlist2[0] = 1;
      minlist2[1] = 1;
      minlist2[2] = 1;
      minlist2[3] = 1;
      minlist2[4] = 1;
      minlist2[5] = 0;
      minute -= 50;
      for (int i = 0; i < minute; i++){
        minlist[i] = 1;
      }
    }
  }
timesync = 0;
}

// Random function
if (seconds == 0 || seconds ==  5 || seconds ==  10 || seconds == 15 || seconds ==  20 || seconds ==  25 || seconds == 30 || seconds ==  35 || seconds ==  40 || seconds ==  45 || seconds ==  50 || seconds == 55){
  if (x == 1){
    x = 0;
    for (int a=0; a<9; a++){
      int r = random(a,9); 
      int temp = minlist[a];
      minlist[a] = minlist[r];
      minlist[r] = temp;
 
    }
    for (int a=0; a<9; a++){
      int r = random(a,9);
      int temp = hourlist[a];
      hourlist[a] = hourlist[r];
      hourlist[r] = temp;
      }
    for (int a=0; a<6; a++){
      int r = random(a,6);
      int temp = minlist2[a];
      minlist2[a] = minlist2[r];
      minlist2[r] = temp;
    }
    for (int a=0; a<3; a++){
      int r = random(a,3);
      int temp = hourlist2[a];
      hourlist2[a] = hourlist2[r];
      hourlist2[r] = temp;
    }
  }
}
// random off for 10 seconds
if (seconds == 1 || seconds == 6 || seconds == 11 || seconds ==  16 || seconds == 21 || seconds == 26 || seconds == 31 || seconds == 36 || seconds == 41 || seconds == 46 || seconds == 51 || seconds == 56){
  x = 1;
}

// draw 



int rowone[] = {hourlist2[0], hourlist[0], hourlist[1], hourlist[2], minlist2[0], minlist2[1], minlist[0], minlist[1], minlist[2]};
int rowtwo[] = {hourlist2[1], hourlist[3], hourlist[4], hourlist[5], minlist2[2], minlist2[3], minlist[3], minlist[4], minlist[5]};
int rowthree[] = {hourlist2[2], hourlist[6], hourlist[7], hourlist[8], minlist2[4], minlist2[5], minlist[6], minlist[7], minlist[8]};
 
if (millis() - timer < muxInterval)
  {
    timer = millis();
    mux++;
    if (mux > 2){
      mux = 0;
    }
    for (int i = 0; i <=8; i++){
      digitalWrite(colpins[i], LOW);

    }
    digitalWrite(rowpins[0], LOW);
    digitalWrite(rowpins[1], LOW);
    digitalWrite(rowpins[2], LOW);
    
      
   if (mux == 0) {
      for (int i = 8; i >= 0; i--) {
        if (rowone[i] == 1){
          digitalWrite(colpins[i], HIGH);
          digitalWrite(rowpins[0], HIGH);
        }
      }
    }
  

  if (mux == 1) {
    for (int i = 8; i >= 0; i--) {
      if (rowthree[i] == 1){
        digitalWrite(colpins[i], HIGH);
        digitalWrite(rowpins[2], HIGH);
      }
    }
  }

  if (mux == 2) {
    for (int i = 8; i >= 0; i--) {
      if (rowtwo[i] == 1){
        digitalWrite(colpins[i], HIGH);
        digitalWrite(rowpins[1], HIGH);
      }
    }
  }
}
  

// Time
unsigned long  prevtime;
  if( getPCtime()) {  // try to get time sync from pc
    Serial.print("Clock synced at: ");
    Serial.println(DateTime.now(),DEC);
  }
  if(DateTime.available()) { // update clocks if time has been synced
    digitalWrite(13,LOW);  // first flash the LED
    prevtime = DateTime.now();

    DateTime.available(); //refresh the Date and time properties


  }
}


boolean getPCtime() {
  // if time sync available from serial port, update time and return true
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    if( Serial.read() == TIME_HEADER ) {        
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        char c= Serial.read(); 
        top = c;        
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
        }
      } 
      timesync = 1;  
      DateTime.sync(pctime);   // Sync Arduino clock to the time received on the serial port
      return true;   // return true if time message received on the serial port
    }  
  }
  return false;  //if no message return false
}

La parte rtc è un ds1302 con relativo quarzo e batteria tampone, che ne dite?

Ciao nytro81 Non mi sono ancora preso il tempo di analizzare il Tuo sketch, ma presumo che non abbia nessun errore. Posso dirti che il DS1302 sopratutto col quarzo sbaglaiato puó essere cosí impreciso. Dei quarzi da 32 kHz esistono con 2 capacitá sostitutive. Se si mette quello sbaglaito sul DS1302 quello va leggermente sbaglaito. Ci sono RTC piú precisi oppure se sincronizzate con GPS, DCF77, RDS o NTP anche un ds1302 puó diventare piú preciso. Purtroppo questo significa che si deve aggiungere altroa elettronica e che quella costa.

Ciao Uwe

Proverò a mettere sotto test la sola parte rtc e vedere quanto perde magari

Lo sketch che ho ripostato, ogni quanto farebbe il controllo sull'rtc? ogni minuto?

DS1302 :The internal oscillator is designed for operation with a crystal having a specified load capacitance of 6pF

Pero’ la maggioranza dei quarzi che si trovano in giro hanno una capacita’ doppia. Quindi visto che l’errore è esagerato ti conviene sostituire il quarzo con uno piu’ adatto

Ti ringrazio per l'appunto, anche se in verità mi ero già informato su questa cosa e mi pare (dico mi pare perchè sono passati anni e non ne sono certo) che avevo già provato ad ordinare e sostituire con quarzi da 6! Cmq proverò per sicurezza, grazie!

Modifico il problema, l'orologio va avanti, non perde minuti.... oggi ho tenuto tutto il pomeriggio attaccato il solo rtc e messo a paragone con l'orologio di windows, da terminale ho verificato che in meno di 5 ore ha guadagnato tipo 5 secondi... quindi il problema è confermato che sia sul solo circuito rtc... proverò a rifarlo con un quarzo da 6, oppure prendo un modulo rtc già pronto, magari è più affidabile del mio fatto in casa! Grazie

Se lo cambi, prendi almeno un DS3231

Più affidabile? Confermo la mostruosa sprecisione dell'attuale, guadagnato 6 secondi in 24 ore

http://datasheets.maximintegrated.com/en/ds/DS3231.pdf

2ppm, decisamente piu preciso di quello che stai usando ... in piu, usa un quarzo interno compensato in temperatura ... ed ultimo, ma non per questo secondario, costa giusto un paio di Euro ;)