DS3231 - Ausgabefehler bei Zeit und Datum

Hallo !

Ich habe ein Problem mit meinem DS3231 Modul, ich möchte mir mal die aktuelle Zeit und das Datum im Serial Monitor anzeigen lassen, aber es kommt nur Müll raus :confused:

Der Output im Monitor:

2165.25.165 165:165:165

Hier stimmt irgendwas stark nicht. Ich habe bereits die Batterie getauscht, aber ohne Erfolg.

Der Code (Datum und Uhrzeit sind falsch):

Dieser ist eigentlich nur aus der zugehörigen Biblo genommen.

#include <Wire.h>
#include "ds3231.h"
#include "rtc_ds3231.h"

#define BUFF_MAX 128

uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 5000;

void setup()
{
    Serial.begin(9600);
    Wire.begin();
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);
    Serial.println("GET time");

  //  Serial.println("Setting time");
  //  parse_cmd("T300608330032016",16);
  //           TssmmhhWDDMMYYYY
    
}

void loop()
{
    char in;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // show time once in a while
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t);

        // there is a compile time option in the library to include unixtime support
#ifdef CONFIG_UNIXTIME
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d %ld", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec, t.unixtime);
#else
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
#endif

        Serial.println(buff);
        prev = now;
    }

    if (Serial.available() > 0) {
        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {
            parse_cmd(recv, recv_size);
            recv_size = 0;
            recv[0] = 0;
        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]
        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
            // drop
            recv_size = 0;
            recv[0] = 0;
        } else if (recv_size < BUFF_MAX - 2) {
            recv[recv_size] = in;
            recv[recv_size + 1] = 0;
            recv_size += 1;
        }

    }
}

void parse_cmd(char *cmd, int cmdsize)
{
    uint8_t i;
    uint8_t reg_val;
    char buff[BUFF_MAX];
    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time
    if (cmd[0] == 84 && cmdsize == 16) {
        //T355720619112011
        t.sec = inp2toi(cmd, 1);
        t.min = inp2toi(cmd, 3);
        t.hour = inp2toi(cmd, 5);
        t.wday = cmd[7] - 48;
        t.mday = inp2toi(cmd, 8);
        t.mon = inp2toi(cmd, 10);
        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
        DS3231_set(t);
        Serial.println("OK");
    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        Serial.print("aging reg is ");
        Serial.println(DS3231_get_aging(), DEC);
    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        uint8_t flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
        //BMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
        }
        uint8_t flags[5] = { 0, 0, 0, 0 };
        DS3231_set_a2(time[0], time[1], time[2], flags);
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
        Serial.print("temperature reg is ");
        Serial.println(DS3231_get_treg(), DEC);
    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
        reg_val = DS3231_get_sreg();
        reg_val &= B11111100;
        DS3231_set_sreg(reg_val);
    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
        reg_val = DS3231_get_addr(0x5);
        Serial.print("orig ");
        Serial.print(reg_val,DEC);
        Serial.print("month is ");
        Serial.println(bcdtodec(reg_val & 0x1F),DEC);
    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3231_set_aging(0);
    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
        Serial.print("status reg is ");
        Serial.println(DS3231_get_sreg(), DEC);
    } else {
        Serial.print("unknown command prefix ");
        Serial.println(cmd[0]);
        Serial.println(cmd[0], DEC);
    }
}

Hier stimmt irgendwas stark nicht

Ja, die Uhr antwortet überhaupt nicht.

165 = 15 * 10 + 15, d.h. alle Bit gesetzt, d.h. gar nichts empfangen.

Wenn du ohne Uhrenbibliothek, nur mit Wire.h arbeitest, könntest du das leicht sehen.

Hast du die Uhr jemals gestellt? Falls ja, ist es vermutlich ein generelles I2C Problem.

Der I2C-Scanner findet deinen Uhrenmodul vermutlich auch nicht.

Wieso eigentlich 2 Bibliotheken?

Speedcore016: Der Output im Monitor:

2165.25.165 165:165:165

Hier stimmt irgendwas stark nicht.

Ja.

Entweder hast Du die Uhr seit dem letzten Total-Power-Off (keine Versorgung der Uhr mit VCC bei gleichzeitigem Ausfall von VBat) nicht mehr gestellt), oder die I2C-Schnittstelle ist nicht funktionsfähig, z.B. wegen fehlerhafter Verkabelung.

Soll die Uhr noch mehr machen, als nur die Zeit anzeigen ? Dafür, dass es ein Beispielsketch aus der Library sein soll, finde ich den sehr unübersichtlich und umfangreich.

Und wie Scherheinz schon schrieb, du brauchst nur eine RTC Library.

Wenn du nicht unbedingt auf deinem Sketch beharren musst, habe ich hier einen simplen Sketch, der dir die Zeit und das Datum auf dem seriellen Monitor anzeigt.

Die Uhr kannst du stellen, in dem du die Funktion “setDateTimeDS3231();” im Setup beim ersten Upload frei gibst und für den nächsten Upload wieder sperrst. Sonst wird die RTC bei jedem Neustart wieder gestellt. Die Zeit musst du anpassen.

Beispiel (getestet und funktioniert):

#include <DS3232RTC.h>                  //https://github.com/JChristensen/DS3232RTC
#include <Time.h>
#include <Wire.h>

void setup() {
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC

  // Zeit und Datum stellen, nur zum Stellen beim Flashen freigeben ---------------------------------------
  //setDateTimeDS3231();    // nach dem ersten Flashen wieder rausnehmen "//"
}

void loop() 
{
  serial_Display();
  delay(1000);
}

void serial_Display(void)
{
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(day());
  Serial.print(' ');
  Serial.print(month());
  Serial.print(' ');
  Serial.print(year());
  Serial.println();
}


void printDigits(int digits)    // 1.Stelle auffüllen SerialMonitor
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

//############################## Uhr stellen ###########################################
// Function to set the current time, change the second&minute&hour to the right time
void setDateTimeDS3231()                
{
  //this example first sets the system time (maintained by the Time library) to
  //a hard-coded date and time, and then sets the RTC from the system time.
  //the setTime() function is part of the Time library.
  //setTime(hr,min,sec,day,month,yr);
  setTime(9, 44, 00, 8, 8, 2016);   //set the system time to 23h31m30s on 13Feb2009
  RTC.set(now());
}
//--------------------------------------------------------------------------------------

Wenn du ohne RTC - Bibliothek so primitiv wie möglich sehen willst, was deine Uhr macht,
probier mal diesen Minimal-Sketch:

#define RTC_I2C_ADDRESS 0x68 // // I2C adress of DS1307 or DS3231
#include <Wire.h>

boolean RTCinit()
{
  Wire.begin();
  delay(10); // small delay to stabilize I2C bus voltage
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  return (Wire.endTransmission()==0);
}

char HIGHDIGIT ( byte b ) {
   return '0' + (b>>4);  
}
char LOWDIGIT ( byte b ) {
   return '0' + (b&0x0F);  
}

byte bcdSec, bcdMin, bcdHr;

void setup() {
  Serial.begin(9600);
  if (RTCinit()) Serial.println(F("RTC OK"));
  else { 
    Serial.println(F("RTC/I2C ERROR"));
    while (true) { ; } // Useless to continue 
  }
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 1);
  if (Wire.read() & 0x80) {
    Serial.println(F("RTC WAS STOPPED, STARTING AT 00:00"));
    Wire.beginTransmission(RTC_I2C_ADDRESS);
    Wire.write(0);
    Wire.write(bcdSec);
    Wire.write(bcdMin);
    Wire.write(bcdHr);
    Wire.endTransmission();  
  }
}

void loop() {
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 3);
  bcdSec = Wire.read();
  bcdMin = Wire.read();
  bcdHr = Wire.read();
  Serial.write(HIGHDIGIT(bcdHr));
  Serial.write(LOWDIGIT(bcdHr));
  Serial.write(':');
  Serial.write(HIGHDIGIT(bcdMin));
  Serial.write(LOWDIGIT(bcdMin));
  Serial.write(':');
  Serial.write(HIGHDIGIT(bcdSec));
  Serial.write(LOWDIGIT(bcdSec));
  Serial.println();
  delay(1000);
}

Ich würde sagen erstmal alles rausschmeissen, immerhin sind da 2 importierte Librarys..

Eine richtige Library über den Library MAnager installieren.. Dort ist eine verfügbar.

Zweitens, bei normalen Librarys Fragt man den Init auf True ab um nicht in einer Falschverdrahtung zu landen..

z.B.

if(!DS3231_init(DS3231_INTCN)) Serial.println("Verdrahtungsfehler");

Ich würde von vorne anfangen und ein Beispielsketch ausprobieren oder das ganze direkt selbst aufsetzen!

Hallo,
“if(!DS3231_init(DS3231_INTCN))”

Das kannte ich noch nicht- will ich aber auch nicht recht glauben.
Stellt das nun einen VerdrahtungsFehler fest, oder stellt es fest- das keine Daten ankommen?
Das sind doch zwei verschiedene Dinge!?
Gruß und Spaß
Andreas

Naja..

Zur Info:

Wenn man den DS3231 VCC,GND,SDA und SCL richtig verdrahtet liefert der Init immer True, solange der DS3231 nicht selbst kaputt ist und antwortet! (Das True oder False zurückgeliefert wird hatte bisher jede Lib die ich nutzte)

Wenn der Init True zurückliefert und trotzdem Nix ankommt könnte die Uhr im auslieferungszustand gestoppt sein.. Auch dazu hat jede Lib eine Funktion, wenn diese das nicht automatisch überprüft!

EDIT: Wenn Du Deine Librarys/Quelle/Version outen würdest könnte man sich die aufgerufenen Funktionen mal anschauen und nicht nur vermutungen anstellen. Habe selbst mal geschaut.. Dein Init liefert garnix zurück.. also fällt das weg. Prüfe einfach ein register auf Plausibilität,das ist das einfachste, Beispiele wurden heir gepostet.

Gruß.

Dein Init liefert garnix zurück

Zum prüfen, ob eine Uhr da ist und auf I2C antwortet, braucht man überhaupt keine RTC Library.
Schon gar nicht eine, die solch einen Fehler ignoriert.

Es gibt fast unendlich viele RTC Libraries.
Die meisten machen viel zu viel Schnickschnack, und zu wenig an grundlegenden Aufgaben.

@HotSystem: Wenn die Uhr nur zum Anzeigen der Uhrzeit dient, ist z.B.#include <Time.h>total overkill, sorry.

michael_x:
@HotSystem: Wenn die Uhr nur zum Anzeigen der Uhrzeit dient, ist z.B.#include <Time.h>total overkill, sorry.

Ok, das mag für dein Beispiel ohne RTC-Library stimmen, aber einige RTC-Libs (z.B. die von mir verwendete) verlangen die Lib. Daher kann ich die nicht einfach ohne Änderung der Lib weglassen.

Somit sehe ich es nicht als “overkill” sondern hier notwendig.

HotSystems: Wenn du nicht unbedingt auf deinem Sketch beharren musst, habe ich hier einen simplen Sketch, der dir die Zeit und das Datum auf dem seriellen Monitor anzeigt.

Dafür ist dieser Sketch optimal: http://tronixstuff.com/2014/12/01/tutorial-using-ds1307-and-ds3231-real-time-clock-modules-with-arduino/

Das schöne ist, dass er keine Fremdlibraries braucht. Wire gehört zur IDE, so dass solange die IDE ordnungsgemäß installiert ist, das Sketch auch funktioniert. Liefert es keine sinnvolle Uhrzeit zurück, muss man nach einem Hardwarefehler suchen.

Hey Leute !

Der Fehler war simple und zwar hatte ich einen zweiten Sensor am I2C Bus, welcher die selbe Adresse wie die Uhr bezieht. Habe einfach die Adresse des zweiten Sensors geändert und nun funktioniert alles. =)

Vielen Dank für die Hilfe!

LG

Prima dass du Fehler gefunden hast. Da hätten wir lange weiter raten können. ;)