[Gelöst] DS1307 New Lib Problem mit fillbytime2000

Hallo,
ich versuche verzweifelt meinen RTC mit der Lib langfristig zu stellen. Ich hole mir die Zeit per NTP und dann wird auch die Zeit im RTC korrekt gestellt. Ich befülle den RTC mit der “fillByTime2000” Funktion. Leider ist die Zeit wieder nach einem Hard Reset weg. Wenn ich die epoch Zeit nicht als Variable übergebe, sondern über die Zahl, also statt fillByTime2000(timeNow) mit fillByTime2000(1392023633) dann geht es. Ebenso gilt es für fillByHMS. Wenn ich die Variable übergebe geht’s nicht, wenn ich (10,2,10) eingebe funktioniert es wieder. Ich lasse mir die Variable auf dem Serial Monitor ausgeben. Die Variablen sind korrekt befüllt. Arduino IDE ist 1.0.5 Lib ist Version 1.24

Was kann ich da jetzt machen?

//####################################################################//
//                    Uhrzeit und Datumsanzeige                       //
//####################################################################//

void Clock() // Uhrzeit Ausgabe auf LCD
{     
  RTC.getTime(); // RTC Zeit holen
  if (RTC.hour < 10){ // Wenn RTC Stunde < 10 dann
    lcd.setCursor(7,1); // Cursorbeginn auf Zeichen 7, Zeile 2
  } 
  else { // sonst
    lcd.setCursor(6,1); // Cursorbeginn auf Zeichen 6, Zeile 2
  }
  lcd.print(RTC.hour); // Stunden anzeigen
  printDigits(RTC.minute); // : Minuten anzeigen
  printDigits(RTC.second); // : Sekunden anzeigen
  lcd.setCursor(3,2); // Cursorbeginn auf Zeichen 1, Zeile 2
  switch (RTC.dow) { // Prüfe welcher Wochentag ist und dann Ausgabe als Text
  case 0:    // Wenn RTC.dow = 0
    lcd.print(F("So.")); // Wochentag "Sonntag"
    break; // fertig
  case 1:    // Wenn RTC.dow = 1
    lcd.print(F("Mo.")); // Wochentag "Montag"
    break; // fertig
  case 2:    // Wenn RTC.dow = 2
    lcd.print(F("Di.")); // Wochentag "Dienstag"
    break; // fertig
  case 3:    // Wenn RTC.dow = 3
    lcd.print(F("Mi.")); // Wochentag "Mittwoch"
    break; // fertig
  case 4:    // Wenn RTC.dow = 4
    lcd.print(F("Do.")); // Wochentag "Donnerstag"
    break; // fertig
  case 5:    // Wenn RTC.dow = 5
    lcd.print(F("Fr.")); // Wochentag "Freitag"
    break; // fertig
  case 6:    // Wenn RTC.dow = 6
    lcd.print(F("Sa.")); // Wochentag "Samstag"
    break; // fertig
  } 
  if (RTC.day < 10 && RTC.month < 10){ // Wenn Tag < 10 und Monat < 10  
    lcd.setCursor(9,2); // Cursorbeginn auf Zeichen 9, Zeile 3 
  } 
  else if (RTC.day >= 10 && RTC.month < 10 || RTC.day < 10 && RTC.month >= 10 ){ // Wenn Tag > 10 und Monat < 10 oder Tag < 10 und Monat > 10
    lcd.setCursor(8,2); // Cursorbeginn auf Zeichen 8, Zeile 3
  } 
  else { // alles andere
    lcd.setCursor(7,2); // Cursorbeginn auf Zeichen 7, Zeile 3
  }
  lcd.print(RTC.day); // Tag anzeige
  lcd.print(F(".")); // Text "."
  lcd.print(RTC.month); // Monat anzeige
  lcd.print(F(".")); // Text "."
  lcd.print(RTC.year); // Jahr anzeige
}

//####################################################################//
//         Führende Null bei der Uhrzeit wenn kleiner 10              //
//####################################################################//

void printDigits(int digits) // Funktion um die : zwischen Std. / Min. / Sek. darzustellen 
{
  lcd.print(F(":")); // Text ":"
  if(digits < 10) // Wenn Stunden weniger 10
      lcd.print(F("0")); // setzte 0 voran
  lcd.print(digits); // Ausgabe Digits
}

//####################################################################//
//              NTP Zeit mit RTC Zeit synchronisieren                 //
//####################################################################//

void NTPSyncUpdate()
{
  if((millis() - prev_NTPSyncUpdate) > interval_NTPSyncUpdate) { // Delay mit Millis damit der µC nach andere Dinge paralell abarbeiten kann   
    prev_NTPSyncUpdate = millis(); // Aktuelle millis Zeit in "NTPSyncUpdate" speichern
    NTPSync(); // Funktion NTPSync aufrufen
  }
} 

void NTPSync() 
{ 
  if(Udp.available()) {
    while (!Udp.parsePacket()) ;
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer
    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:
    highWord = word(packetBuffer[40], packetBuffer[41]);
    lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    secsSince1900 = highWord << 16 | lowWord;               
    // now convert NTP time into everyday time:
    seventyYears = 2208988800UL;     
    // subtract seventy years:
    epoch = secsSince1900 - seventyYears;       
    // print the hour, minute and second:
    // Unixtime(epoch) - Sek seit 2000(time_2000) 
    mesz = epoch - time_2000;
    timeNow = mesz + adjustDstEurope();
    // Set Time to RTC
    RTC.setRAM(0, (uint8_t *)&startAddr, sizeof(uint16_t));
    RTC.getRAM(55, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
    if (TimeIsSet != 0xaa55) {
      RTC.stopClock();
      // Setzt die Zeit und Datum als time2000
      RTC.fillByTime2000(timeNow);    
      RTC.setTime();
      TimeIsSet = 0xaa55;
      RTC.setRAM(5, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
      RTC.startClock();
    }
  }
}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 		   
  Udp.beginPacket(address, 123); // NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}

//####################################################################//
//              Berechnung der Sommer / Winterzeit                    //
//####################################################################//

int adjustDstEurope()
{
  // last sunday of march
  int beginDSTDate=  (31 - (5* year() /4 + 4) % 7);
  int beginDSTMonth=3;
  //last sunday of october
  int endDSTDate= (31 - (5 * year() /4 + 1) % 7);
  int endDSTMonth=10;
  // DST is valid as:
  if (((month() > beginDSTMonth) && (month() < endDSTMonth))
    || ((month() == beginDSTMonth) && (day() >= beginDSTDate))
    || ((month() == endDSTMonth) && (day() <= endDSTDate)))
    return 3600;  // DST europe = utc +1 hour
  else return 0; // nonDST europe = utc +0 hour
}

ht81: Die Variablen sind korrekt befüllt

Dein Programm verwendet aber auch Konstanten im Quellcode, die nicht zu vernachlässigen sind.

5 != 55

Hi, Du meinst bestimmt diese Stelle

 RTC.setRAM(0, (uint8_t *)&startAddr, sizeof(uint16_t));
    RTC.getRAM(55, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
    if (TimeIsSet != 0xaa55) {
      RTC.stopClock();
      // Setzt die Zeit und Datum als time2000
      RTC.fillByTime2000(timeNow);    
      RTC.setTime();
      TimeIsSet = 0xaa55;
      RTC.setRAM(5, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
      RTC.startClock();
    }

Ich hatte auch mal alles Auskommentiert, dies funktionierte aber ebenso wenig:

      RTC.stopClock();
      // Setzt die Zeit und Datum als time2000
      RTC.fillByTime2000(timeNow);    
      RTC.setTime();
      RTC.startClock();
    }

Wo ist der Link zur Bibliothek, die Du verwendest? Und poste den vollständigen Sketch, vieleicht liegt der Fehler ja ausserhalb des von Dir geposteten Bereich.

Hi,

im Anhang der Code. Hoffe irgendjemand findet den Fehler :slight_smile:

Forum.zip (4.08 KB)

Ich versuch's noch einmal:

Wo ist der Link zur Bibliothek, die Du verwendest?

Es gibt mindestens ein Dutzend Bibliotheken für den DS1307-Chip. Wir wollen nicht ständig unsere Zeit verschwenden, indem wir Deinen Code mit einer anderen Bibliothek abgleichen, als derjenigen, die Du verwendest.

Hallo Pylon,

sorry das war mein Fehler, habe eigentlich gedacht das ich den Link reinkopiert hätte. Habe ich wohl vergessen. Sorry nochmals.

Ich verwende die Version 1.24 von der Lib hier

http://code.google.com/p/ds1307new/downloads/list

Habe allerdings auch schon die 1.23 probiert. Arduino IDE ist die 1.05

Die Bibliothek prüft nicht, ob der Chip den Empfang der Daten bestätigt. Somit ist es relativ wahrscheinlich, dass Dich eine Eigenheit des DS1307 nervt: Wenn die Spannung auch nur leicht absinkt (was bei Dir mit Ethernet-Shield und angeschlossenem LCD nicht unwahrscheinlich ist), verweigert er die I2C-Kommunikation.

Messe mal die Spannung zwischen GND und 5V (im Betrieb) und auch die Spannung der Pufferbatterie und poste die Werte.

Wir hatten hier schon oft Werte von 4.6V für die Versorgung und 3.5V für die Batterie. Mit dem Scope betrachtet war dann die Versorgung noch etwas wellig und schon waren die 1.25 * Vbatt unterschritten, ab welcher der Chip die Kommunikation verweigert. Wenn dann die I2C-Acknowledges nicht geprüft werden, sucht man lange nach dem wahren Grund.

Hallo Pylon,

sorry für die späte Antwort. Habe jetzt mal die Spannung messen wollen und siehe da: 0V, 3,5V, 2,8V, 1,1V, 0V, 0,2V etc.... Ich könnt echt kotzen. Das Problem war / ist die kalte Lötstelle gewesen. Habe es jetzt nachgelötet und nun geht der Code. Es ist ein DS1307 aus China. Bei genauer Betrachtung sind alle Lötstellen beschi....en. Das kommt also sehr gut mit deiner Vermutung zusammen. Durch die "instabile" Spg. Versorgung macht er wohl Fehler beim schreiben. Meisten hielt ich das DS1307 in der Hand bzw. am Kabel. Deswegen hatte ich wohl meistens Glück als ich die Zeit "selber" befüllt hatte. Danke nochmals für deinen Wertvollen Tipp. So wäre ich nicht drauf gekommen XD