RTC-Bibliotheken- dem Wahnsinn nahe

Hallochen. Meine Uhr ist kaputt. Nein: kaputt stimmt nicht, aber ich habe wohl etwas unvorsichtig mit dem Modul gespielt und dabei die gespeicherte Zeit verstellt. Und: ich bekomme sie einfach nicht wieder eingestellt. Ursache: irgendwelche Fehlermeldungen, die vermuten lassen, dass ich nicht die richtigen Bibliotheken benutze.

Hat irgend jemand hier ein Programm, mit dem ich die RTC (1307) stellen kann samt Links zu sämtlichen, damit auch funktionierenden Bibliotheken? Leider scheint es nämlich besonders von RTC.H, DS1307.h usw. schier unendliche Versionen zu geben, ich dreh bald durch. :(

Rück mal den genutzten Sketch raus und die Fehlermeldung

Rabenauge:
Hat irgend jemand hier ein Programm, mit dem ich die RTC (1307) stellen kann samt Links zu sämtlichen, damit auch funktionierenden Bibliotheken?

Ich habe einen Sketch, der funktioniert OHNE spezielle Bibliotheken und ermöglicht Dir das Stellen von Datum und Zeit über den seriellen Monitor.

#include <Wire.h>
// I2C Adresse der RTC ist 0x68 für DS1307 und DS3231
#define RTC_I2C_ADDRESS 0x68

int jahre,monate,tage,stunden,minuten,sekunden;
// wochentag bleibt in diesem Test-Sketch unberücksichtigt

void rtcReadTime(int &jahre, int &monate, int &tage, int &stunden, int &minuten, int &sekunden)
// aktuelle Zeit aus RTC auslesen
{
// Reset the register pointer
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  sekunden    = bcdToDec(Wire.read() & 0x7f);
  minuten     = bcdToDec(Wire.read());
  stunden     = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  /*wochentag   = */bcdToDec(Wire.read());
  tage        = bcdToDec(Wire.read());
  monate      = bcdToDec(Wire.read());
  jahre       = bcdToDec(Wire.read())+2000;  
}

void rtcWriteTime(int jahre, int monate, int tage, int stunden, int minuten, int sekunden)
// aktuelle Zeit in der RTC speichern
{
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(sekunden));    // 0 to bit 7 starts the clock
  Wire.write(decToBcd(minuten));
  Wire.write(decToBcd(stunden));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
                                  
  Wire.write(decToBcd(0)); // Wochentag unberücksichtigt
  Wire.write(decToBcd(tage));
  Wire.write(decToBcd(monate));
  Wire.write(decToBcd(jahre-2000));
  Wire.endTransmission();  
}

byte decToBcd(byte val) // Hilfsfunktion zum Lesen/Schreiben der RTC
// Convert decimal number to binary coded decimal
// Hilfsfunktion für die Echtzeituhr
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  // Hilfsfunktion zum Lesen/Schreiben der RTC
// Convert binary coded decimal to decimal number
// Hilfsfunktion für die Echtzeituhr
{
  return ( (val/16*10) + (val%16) );
}


int getIntFromString (char *stringWithInt, byte num)
// input: pointer to a char array
// returns an integer number from the string (positive numbers only!)
// num=1, returns 1st number from the string
// num=2, returns 2nd number from the string, and so on
{
  char *tail; 
  while (num>0)
  {
    num--;
    // skip non-digits
    while ((!isdigit (*stringWithInt))&&(*stringWithInt!=0)) stringWithInt++;
    tail=stringWithInt;
    // find digits
    while ((isdigit(*tail))&&(*tail!=0)) tail++;
    if (num>0) stringWithInt=tail; // new search string is the string after that number
  }  
  return(strtol(stringWithInt, &tail, 10));
}  


void setup()
{
  Wire.begin();       // initialisiert die Wire-Library
  Serial.begin(9600); // Serielle Kommunikation starten
  while (!Serial);    // wait for serial port to connect. Needed for Leonardo only
  Serial.println("\r\nRTC Demo Sketch by jurs for German Arduino Forum");
  Serial.println("Dieser Sketch zeigt die aktuelle Zeit alle 10 Sekunden im 'Serial Monitor'.");
  Serial.println("Du kannst die Zeit mit einem 'set' Befehl im 'Serial Monitor' neu setzen.");
  Serial.println("\r\nBeispiel:");
  Serial.println("set 28.08.2013 10:54\r\n");
}


void machsAlle10Sekunden(){
  static unsigned long prevMillis=-20000;
  char linebuf[30];
  if (millis()-prevMillis<10000) return; // Zeit noch nicht erreicht, Funktion abbrechen
  prevMillis=millis();
  // RTC Uhr auslesen
  rtcReadTime(jahre,monate,tage,stunden,minuten,sekunden);
  // Zeit für Ausgabe formatieren
  snprintf(linebuf,sizeof(linebuf),"%02d.%02d.%04d %02d:%02d:%02d Uhr",tage,monate,jahre,stunden,minuten,sekunden);
  // Zeit auf serieller Schnittstelle ausgeben
  Serial.println(linebuf);
}

void behandleSerielleBefehle()
{
  char linebuf[30];
  byte counter;
  if (Serial.available())
  {
    delay(100); // Warte auf das Eintreffen aller Zeichen vom seriellen Monitor
    memset(linebuf,0,sizeof(linebuf)); // Zeilenpuffer löschen
    counter=0; // Zähler auf Null
    while (Serial.available())
    {
      linebuf[counter]=Serial.read(); // Zeichen in den Zeilenpuffer einfügen
      if (counter<sizeof(linebuf)-1) counter++; // Zeichenzähler erhöhen
    }
    // Ab hier ist die Zeile eingelesen
    if (strstr(linebuf,"set")==linebuf) // Prüfe auf Befehl "set" zum Setzen der Zeit
    { // Alle übermittelten Zahlen im String auslesen
      tage=getIntFromString (linebuf,1);
      monate=getIntFromString (linebuf,2);
      jahre=getIntFromString (linebuf,3);
      stunden=getIntFromString (linebuf,4);
      minuten=getIntFromString (linebuf,5);
      sekunden=getIntFromString (linebuf,6);
    }
    else
    {
      Serial.println("Befehl unbekannt.");
      return;
    }
    // Ausgelesene Werte einer groben Plausibilitätsprüfung unterziehen:
    if (jahre<2000 || monate<1 || monate>12 || tage<1 || tage>31 || (stunden+minuten)==0)
    {
      Serial.println(linebuf);
      Serial.println("\r\nFehlerhafte Zeitangabe im 'set' Befehl");
      Serial.println("\r\nBeispiel:");
      Serial.println("set 28.08.2013 10:54\r\n");
      return;
    }
    rtcWriteTime(jahre, monate, tage, stunden, minuten, sekunden);
    Serial.println("Zeit und Datum wurden auf neue Werte gesetzt.");
  }
}


void loop()
{ 
  machsAlle10Sekunden();
  behandleSerielleBefehle();
}

Hallo Rabenauge,

ich stelle meine DS1307 mit diesen Dateien ein. http://code.google.com/p/ds1307new/ vielleicht sind die richtig.

Gruß Heinz

@ sschultewolter: ich hab diverse versucht, mit diversen Methoden, nix hat geklappt. Einige liessen sich problemlos compilieren und übertragen, liefen auch aber das stellen hat eben nie funktioniert. Insbesondere die Methode, die einige benutzen, bei der die Uhr auf die Zeit der Compilierung gestellt wird, versagten schon in der Vergangenheit durchweg kläglich.

@jurs: du bist mein Held. Danke- das hat super funktioniert.

Rabenauge: Danke- das hat super funktioniert.

Kleiner Nachtrag: Da meine Routinen zum Stellen und Auslesen der Uhr den Wochentag unberücksichtig lassen, manchmal aber doch ein Wochentag benötigt wird: Den Wochentag kann man sich jederzeit nach dem Auslesen selbst ausrechnen, falls man ihn benötigt. Code dazu:

int dayOfWeek(int year, int month, int day)
/* Calculate day of week in proleptic Gregorian calendar. Sunday == 0. */
{
  int adjustment, mm, yy;
  adjustment = (14 - month) / 12;
  mm = month + 12 * adjustment - 2;
  yy = year - adjustment;
  return (day + (13 * mm - 1) / 5 + yy + yy / 4 - yy / 100 + yy / 400) % 7;
}

hi,

ich finde es auch am einfachsten und resourcenschonendsten, ohne bibliothek zu arbeiten. gerade bei einer uhr, wo man kein datum mit sommerzeitumschaltung braucht, genügen die wire und ein paar zeilen.

gruß stefan