Binär Uhr mit DS1307

Hallo,

ich Programmier gerade eine Binär Uhr, das wichtigste funktioniert auch. Das heißt der DS1307 wird ausgelesen und die LEDs zeigen alles richtig an.
Leider ist mir auf gefallen das der RTC nicht weiter Arbeiten wenn die Pufferbatterie aktiv ist, aber die Uhrzeit bleibt gespeichert.

Da mir keine Lib für den RTC gefallen hat, hab ich es ohne Lib gemacht. http://combustory.com/wiki/index.php/RTC1307_-_Real_Time_Clock
Könnte es daran liegen oder ist der RTC defekt?

/*********************************************************
* Binäre Uhr mit RTC DS1307 mit Shiftregister
*
* Beschreibung
*
*
*
*
*Hardware:  Arduino
*           RTC DS1703
*           Shiftregister 74HC595N   3x
*/

/************************Library*************************/

#include "Wire.h"

/*************************I/O****************************/

const int dataPin= 2;
const int latchPin = 3;
const int clockPin = 4;
const int buttonAdd = 12;
const int buttonDiv = 13;
const int batPin = A1;

/*********************I2C Adressen***********************/

#define RTC_I2C_ADDRESS 0x68

/***********************Variablen************************/

char buffer[20] = "";                                     //Speicherbereich für Datenkonvertierung
int date[10];

/***********************DEC to BCD***********************/

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

/***********************BCD to DEC***********************/

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

/******************Zeit Umformatierung*******************/

int calc(int time)
{
  int pin1;
  int pin2;
  int pin4;
  int pin8;
  int pin16;
  int pin32;
  int pin64;
  int t_unit;
  int result;
  
  t_unit = time%10;
  
  if(t_unit == 1 || t_unit == 3 || t_unit == 5 || t_unit == 7 || t_unit == 9)              { pin1 = 1;} else   { pin1 = 0;}
  if(t_unit == 2 || t_unit == 3 || t_unit == 6 || t_unit == 7)                             { pin2 = 2;} else   { pin2 = 0;}
  if(t_unit == 4 || t_unit == 5 || t_unit == 6 || t_unit == 7)                             { pin4 = 4;} else   { pin4 = 0;}
  if(t_unit == 8 || t_unit == 9)                                                           { pin8 = 8;} else   { pin8 = 0;}
  
  if((time >= 10 && time < 20) || (time >= 30 && time < 40) || (time >= 50 && time < 60))  { pin16 = 16;} else {pin16 = 0;}
  if(time >= 20 && time < 40)                                                              { pin32 = 32;} else {pin32 = 0;}
  if(time >= 40 && time < 60)                                                              { pin64 = 64;} else {pin64 = 0;}
  
  result =  pin1 + pin2;
  result = result + pin4;
  result = result + pin8;
  result = result + pin16;
  result = result + pin32;
  result = result + pin64;

  return result;
}

/***********************Last Timer***********************/

//int lastTimer (boolean x, int count, 

/************RTC auslesen und konvertieren***************/

void getDateRTC()
{
  Wire.beginTransmission(RTC_I2C_ADDRESS);                 //Öffnet Verbindung zu RTC 
  Wire.write(0x00);                                        //Setzt Pointer auf Byte0
  Wire.endTransmission();                                  //Schließt Verbindung zur RTC
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);                    //Forder 7 Bytes an
  
  date[ 0 ] = bcdToDec(Wire.read() & 0x7f);                //Sekunde
  date[ 1 ] = bcdToDec(Wire.read() );                      //Minute
  date[ 2 ] = bcdToDec(Wire.read() & 0x3f);              //Stunde
  date[ 3 ] = bcdToDec(Wire.read() );                      //Wochentag
  date[ 4 ] = bcdToDec(Wire.read() );                      //Tag
  date[ 5 ] = bcdToDec(Wire.read() );                      //Monat
  date[ 6 ] = bcdToDec(Wire.read() );                      //Jahr
}

/********************RTC Datum setzen********************/

void setDateRTC(int pointer, int date)
{
  Wire.beginTransmission(RTC_I2C_ADDRESS);                 
  Wire.write(pointer);                                     //Setzt Pointer
  Wire.write(decToBcd(date) );                             //Schreibt Konvertierter Wert
  Wire.endTransmission();
}

/*************************Setup**************************/

void setup()
{
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);  
  pinMode(buttonAdd, INPUT);
  pinMode(buttonDiv, INPUT);
  
  Wire.begin();
  Serial.begin(9600);
}

/*************************Loop***************************/

void loop()
{
  getDateRTC();
  
  int dataH = calc(date[2]);                              //Stunde Formatieren für Ausgabe
  int dataM = calc(date[1]);                              //Minute
  int dataS = calc(date[0]);                              //Sekunde

  digitalWrite(latchPin, LOW);                            //Daten Ausgabe Aktivieren
  shiftOut(dataPin, clockPin, MSBFIRST, dataS);           //Ausgabe
  shiftOut(dataPin, clockPin, MSBFIRST, dataM);           //
  shiftOut(dataPin, clockPin, MSBFIRST, dataH);           //
  digitalWrite(latchPin, HIGH);                           //Daten Ausgabe Schließen
  printDate();
 delay(500);
}



void printDate()
{
  Serial.print(date[2]); Serial.print(":");
  Serial.print(date[1]); Serial.print(":");
  Serial.println(date[0]);
}

Gruß Hirschi

hi,

was meinst Du mit: nicht weiter arbeitet. stimmt die zeit nicht mehr, wenn er wieder mit ext. versorgung läuft? oder liefert er keine zeit an den arduino? das wäre, denke ich, verständlich, weil I²C nicht funktionieren wird, wenn der 1307 und der arduino nicht spannungsmäßig verbunden sind.
ohne gemeinsamen GND geht das nicht. ob nur GND in dem fall genügt, kann ich nicht sagen.

gruß stefan

Hi Eisbaer,

also, so ballt ich die ext. Spannung entferne gefriert die Uhrzeit ein.
Wenn ich die ext. Spannung um 17 Uhr entferne und eine halbe Stunde später wieder einschalte läuft die Uhr bei 17Uhr weiter.

Gruß Hirschi

Das ist nicht normal. Ein wichtiger Zweck einer RTC ist ja gerade dass die Uhr weiter läuft wenn das Gerät ausgeschaltet ist. z.B. die RTC im Computer.

hi,

das ist sehr seltsam. wenn die batterieversorgung ok ist, sollte die zeit normal weiterlaufen. wenn nicht, sollte er zurückgesetzt sein und nicht mehr laufen (und auch keine 17:00 anzeigen).

probier doch mal die DS1307new lib, um das verhalten zu prüfen. einfach den testsketch DS1307_Monitor aufspielen und serial monitor starten.

gruß stefan

Das war nicht die Frage, aber ich habe ein paar Kommentare bezueglich des Programms:

const int dataPin= 2;
const int latchPin = 3;
const int clockPin = 4;
const int buttonAdd = 12;
const int buttonDiv = 13;
const int batPin = A1;

Hier, "#define dataPin 2" usw. benutzen.
Es macht wenig Sinn, 2 bytes fuer diese Konstanten zu benutzen.

/***********************Variablen************************/

char buffer[20] = "";                                     //Speicherbereich für Datenkonvertierung
int date[10];

buffer[] scheint unbenutzt zu sein.
Fuer date[] wuerde ich char benutzen.

/******************Zeit Umformatierung*******************/

int calc(int time)
{
  int pin1;
  int pin2;
  int pin4;
  int pin8;
  int pin16;
  int pin32;
  int pin64;
  int t_unit;
  int result;
  
  t_unit = time%10;
  
  if(t_unit == 1 || t_unit == 3 || t_unit == 5 || t_unit == 7 || t_unit == 9)              { pin1 = 1;} else   { pin1 = 0;}
  if(t_unit == 2 || t_unit == 3 || t_unit == 6 || t_unit == 7)                             { pin2 = 2;} else   { pin2 = 0;}
  if(t_unit == 4 || t_unit == 5 || t_unit == 6 || t_unit == 7)                             { pin4 = 4;} else   { pin4 = 0;}
  if(t_unit == 8 || t_unit == 9)                                                           { pin8 = 8;} else   { pin8 = 0;}
  
  if((time >= 10 && time < 20) || (time >= 30 && time < 40) || (time >= 50 && time < 60))  { pin16 = 16;} else {pin16 = 0;}
  if(time >= 20 && time < 40)                                                              { pin32 = 32;} else {pin32 = 0;}
  if(time >= 40 && time < 60)                                                              { pin64 = 64;} else {pin64 = 0;}
  
  result =  pin1 + pin2;
  result = result + pin4;
  result = result + pin8;
  result = result + pin16;
  result = result + pin32;
  result = result + pin64;

  return result;
}

Diese Funktion scheint komplett überflüssig zu sein.
calc(5) = 5....

  int dataH = calc(date[2]);                              //Stunde Formatieren für Ausgabe
  int dataM = calc(date[1]);                              //Minute
  int dataS = calc(date[0]);                              //Sekunde

Diese temporären Variablen sind nicht notwendig.
Einfach shiftOut(..,...,..., date[x]) benutzen...

Danke für die Tipps

Hirschi:
Leider ist mir auf gefallen das der RTC nicht weiter Arbeiten wenn die Pufferbatterie aktiv ist, aber die Uhrzeit bleibt gespeichert.

Ist Dir vielleicht auch eine Unterspannung am Puffer-Akku aufgefallen oder bietet der Akku seine gefällige Nominalspannung von 3,6 Volt (oder sogar mehr) im Pufferbetrieb mit abgeklemmter Stromversorgung?

Die Fehlerbeschreibung klingt für mich stark danach, als wenn die Spannung des Puffer-Akkus auf der Platine so niedrig ist, dass zwar die Registerinhalte der Uhr bei Batteriepufferung noch erhalten bleiben, aber der Quarz nicht mehr schwingt.

Ich hatte genau dieses Problem mit meinen RTC´s. Mir scheint die mögen es nicht wenn Vcc schwankt bzw prellt wenn man irgendwo Spannung von hand Abzieht, bei mir half es einen 10µF Kondensator direkt an die RTC zu bringen, also an die IC Beinchen VCC und GND.
Probier es mal damit,
Gruß
Der Dani.

P.S.: Du bist dir sicher das du dir RTC startest du musst nämlich ein Bit in einem Steuerwort setzten damit du die RTC startest nach dem schreiben der Zeit.
Lass dich vom dem TinyWireM nicht stören hier habe ich die RTC an einem Attiny84 genutzte der genau die gleiche Konstellation (RTC und Schieberegister,aber an 10cm großen 7Segement anzeigen) hat wie deine Uhr nur nicht mit einem Mega328 sonder halt mit dem kleinen Bruder.

void RTC_Start(){
  TinyWireM.beginTransmission(RTC_ADDRESS);
  TinyWireM.send(0x00);
  TinyWireM.send(decToBcd(ss));    // 0 to bit 7 starts the clock
  TinyWireM.endTransmission();
}