Arduino - RTC DS1307 - 20x4 Serial LCD Display

Hallo,

hier eine kleine Doku für alle um den Start mit RTC’s zu vereinfachen.
Ich habe mir die letzten Tage schon ein paar Stunden aus verschiedenen Quellen die Infos zusammengesucht da ich nichts fertiges gefunden habe was einfach nur eine kleine “Uhr” darstellt.

Deshalb nun hier das (funktionierende) Ergebnis.

Benutzt wurden:
1x Arduino Duemilanove
1x Real Time Clock Module - RTC von Watterott
1x 20x4 Zeichen LED gelb/grün serielle Ansteuerung von Watterott
1x Proto-Board nebst einer Hand voll Kabel

Damit die Uhrzeit auf den Display auch “sinnvoll” nur dann erneuert wird, wenn auch wirklich eine neue Sekunde angängt, habe ich den “delay(1000);” (den ich in einigen Scripten gefunden habe) gegen einen Interrupt vom Sekundenausgang des RTC’s getauscht.
Und schon schaut das Ergebnis viel besser aus.

Andere Displays oder Zeigerausgaben mit Servo oder Schrittmotor sollten sich ohne größeren Aufwand in die Basis einbauen lassen.

Viel Spaß beim weiterentwickeln.
Ich würde mich freuen, wenn Ihr euere Ergebnisse auch hier rein Posten würdet. :slight_smile:

Grüße…
…eok

/*
 * DS1307 RealTimeClock
 * Serial LCD Display 20x4
 * Sekundenupdate per Interrupt
 *
 * zusammengesucht aus verschiedenen Quellen und noch ein wenig erweitert
 */

// SDA (data line) analog pin 4  - zum DS1307
// SCL (clock line) analog pin 5 - zum DS1307
// Am Arduino Mega, SDA ist digital pin 20 und SCL ist 21.

#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <NewSoftSerial.h>

int updateSec = 0;

NewSoftSerial mySerial(9, 10);  // Das LCD Display braucht nur einen Pin. LCD auf Pin 10

void setup()  {
  Serial.begin(9600);
  mySerial.begin(9600);
  backlightOn();
  clearLCD();
  // Interrupt um den Sekundenfortschritt mit zu bekommen
  // Arduino Pin 2 
  attachInterrupt(0, newSec, FALLING);

  // zum Zeit einstellen einkommentieren und einmalig laufen lassen
  // danach wieder auskommentieren nicht vergessen
  // format - setTime(hr,min,sec,day,month,yr);
  //
  // setTime(21,04,0,6,10,10);
  // RTC.set(now());
  //

  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet)
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");
}

void loop()
{
  if ( updateSec == 1 ) {
  digitalClockDisplay();
  updateSec = 0;
  }
}

void digitalClockDisplay(){

  // Da in dem vierzeiligen Display noch eine Zeile Platz hatte
  // hier eine Art von Sekundenzeiger
  goTo(0);
  mySerial.print("--------------------");
  goTo(second()/3);
  mySerial.print("#");

  goTo(26);
  // Uhrzeit anzeigen
  printDigits(hour());
  Serial.print(":");
  mySerial.print(":");
  printDigits(minute());
  Serial.print(":");
  mySerial.print(":");
  printDigits(second());

  Serial.print(" ");

  goTo(45);
  // Datum anzeigen
  printDigits(day());
  Serial.print(".");
  mySerial.print(".");
  printDigits(month());
  Serial.print(".");
  mySerial.print(".");
  Serial.print(year());
  mySerial.print(year());
  Serial.println();

  goTo(65);
  // Wochentag anzeigen
  switch(weekday()) {
  case 1:
    Serial.println("Sonntag");
    mySerial.print(" Sonntag  ");
    break;
  case 2:
    Serial.println("Montag");
    mySerial.print("  Montag  ");
    break;
  case 3:
    Serial.println("Dienstag");
    mySerial.print(" Dienstag ");
    break;
  case 4:
    Serial.println("Mittwoch");
    mySerial.print(" Mittwoch ");
    break;
  case 5:
    Serial.println("Donnerstag");
    mySerial.print("Donnerstag");
    break;
  case 6:
    Serial.println("Freitag");
    mySerial.print(" Freitag  ");
    break;
  case 7:
    Serial.println("Samstag");
    mySerial.print(" Samstag  ");
    break;
  }
}

void printDigits(int digits){
  // Einstellige Werte mit führender Null versehen
  if(digits < 10) {
    Serial.print('0');
    mySerial.print('0');
  }
  Serial.print(digits);
  mySerial.print(digits);
}

void newSec() {
  updateSec = 1;
}


// SerialLCD Functions
// hier sind mehr Befehle aufgeführt als aktuell benutzt werden,
// aber so hat man immer alles beisammen
// zum optimieren des Codes können hier die nicht benutzten
// Funktionen oder auskommentiert entfernt werden
void selectLineOne(){  //puts the cursor at line 0 char 0.
  mySerial.print(0xFE, BYTE);   //command flag
  mySerial.print(128, BYTE);    //position
}
void selectLineTwo(){  //puts the cursor at line 2 char 0.
  mySerial.print(0xFE, BYTE);   //command flag
  mySerial.print(192, BYTE);    //position
}
void selectLineThree(){  //puts the cursor at line 3 char 0.
  mySerial.print(0xFE, BYTE);   //command flag
  mySerial.print(148, BYTE);    //position
}
void selectLineFour(){  //puts the cursor at line 4 char 0.
  mySerial.print(0xFE, BYTE);   //command flag
  mySerial.print(212, BYTE);    //position
}
void goTo(int position) { //position = line 1: 0-19, line 2: 20-39, etc, 79+ defaults back to 0
if (position<20){ mySerial.print(0xFE, BYTE);   //command flag
             mySerial.print((position+128), BYTE);    //position
}else if (position<40){mySerial.print(0xFE, BYTE);   //command flag
             mySerial.print((position+128+64-20), BYTE);    //position
}else if (position<60){mySerial.print(0xFE, BYTE);   //command flag
             mySerial.print((position+128+20-40), BYTE);    //position
}else if (position<80){mySerial.print(0xFE, BYTE);   //command flag
             mySerial.print((position+128+84-60), BYTE);    //position
} else { goTo(0); }
}
void clearLCD(){
  mySerial.print(0xFE, BYTE);   //command flag
  mySerial.print(0x01, BYTE);   //clear command.
}
void backlightOn(){  //turns on the backlight
   mySerial.print(0x7C, BYTE);   //command flag for backlight stuff
   mySerial.print(157, BYTE);    //light level.
}
void backlightOff(){  //turns off the backlight
   mySerial.print(0x7C, BYTE);   //command flag for backlight stuff
   mySerial.print(128, BYTE);     //light level for off.
}
void backlight50(){  //sets the backlight at 50% brightness
   mySerial.print(0x7C, BYTE);   //command flag for backlight stuff
   mySerial.print(143, BYTE);     //light level for off.
}
void serCommand(){   //a general function to call the command flag for issuing all other commands
   mySerial.print(0xFE, BYTE);
}

Saubere Arbeit und gut dokumentiert. Ich hab vielleicht noch eine kleine Ergänzung für Dich, nämlich Sommer-/Winterzeitumschaltung. Hier ein Codeschnipsel:

void Sommerzeit() {

int Sommerzeit=255;

if (WoTag==7 && Tag>24) { if (Monat==3 && Stunde==2 && (!Sommerzeit || Sommerzeit==255)){ Sommerzeit=TRUE; Stunde=Stunde; Stunde++;

}

else if (Monat==10 && Stunde==3 && (Sommerzeit || Sommerzeit==255)){

Stunde=Stunde; Stunde--; Sommerzeit=FALSE;

} }

}

Ich denke, dass Du es mühelos bei Bedarf einarbeiten kannst.

Währe noch die Hinzufügung von Feiertagen möglich !

Z.B. Ostern: http://www.frankfurt-interaktiv.de/ostern/osterberechnung.html

Das Hinzufügen eines Temperatursensors könnte interesant sein !

Dann könnte man eine Uhrzeit, Jahreszahl, Wochentags, Feiertage und Raumtemperaturanzeige realisieren !

Hallo eok,

ich habe den oben geschriebenen Code auf meinen Arduino geladen. Normalerweise müsste man doch die Clock-Leitung des DS1307 mit dem Pin 2 (Digital) verbinden, damit das Display in sinnvollen Abständen upgedatet wird, oder? Bei mir funktioniert das ganze nur, wenn ich in Pin 2 einen Draht stecke, der vermutlich wie eine Antenne wirkt, absonsten bleibt das Display mit der Einschaltzeit stehen.

Viele Grüße Fantinel ;)

hi Fantinel...

guter punkt! ja, pin2 für die clock (oder besser gesagt 1 sekunden takt vom rtc modul) ist schon richtig. ich habe wo gelesen, dass man den 1sek takt in den modulen ein und aus schalten kann. ggf ist er bei dir ausgeschaltet, was erklären würde wieso du keine updates bekommst.

oder es ist... ich hab bei mir da noch ne led mit dran gehabt um zu sehen was passiert. vielleicht braucht der port nur nen pullup/pulldown widerstand? ohne led hab ichs nicht probiert fällt mir gerade auf.

also probiers mal mit nem pullup oder pulldown... vielleicht klappts ja dann.

ich hab die schaltung auch nicht mehr aufgebaut hier, so dass ich nun auch nicht mehr nachschauen kann. :-/

aber es ist sicher nur ne kleinigkeit.

viel spass noch.... grüße... ...eok

Erstmal Danke für die Umsetzung des Interrupts, hat bei mir für eine wesentlich bessere und weniger "sprunghafte" Anzeige gesorgt.

Ja, man kann den 1 HZ Output des DS1307 ein und ausschalten, bzw. kann er dort auch andere Frequenzen zur Verfügung stellen. Ich hatte auch das Problem, dass das Signal bei mir nicht aktiv war. Ich verzichte daher auf den Einsatz einer Library, um die Zeit auf dem Chip zu stellen und mache das zu Fuss, um das entsprechende Bit setzen zu können:

//Kein Einsatz der library hier, um das Bit für den 1HZ Output explizit setzen zu können
      Wire.beginTransmission(0x68);
      Wire.send(0);
      Wire.send(decToBcd(0)); // 0 to bit 7 (= Sekunden) starts the clock
      Wire.send(decToBcd(mm));
      Wire.send(decToBcd(hh));
      Wire.send(decToBcd(dow));
      Wire.send(decToBcd(day));
      Wire.send(decToBcd(mon));
      Wire.send(decToBcd(year));
      Wire.send(0x10); // Aktiviere 1 HZ Output des DS1307 auf Pin 7
      Wire.endTransmission();

Basierend auf den Erläuterungen hier: http://tronixstuff.wordpress.com/2010/05/20/getting-started-with-arduino-%E2%80%93-chapter-seven/ und diesem Codebeispiel (PDF): http://tronixstuff.files.wordpress.com/2010/05/example7p32.pdf

Daneben habe ich auch einen Pullup verbaut.