// https://www.rc-modellbau-portal.de/index.php?threads/arduino-mit-dcf77-modul-und-rtc-echtzeituhr-ds3231.8278/
// ################################
// kein Antennensymbol, neue Aufteilung der Zeilen
// ################################
//Code um einen Arduino Nano Clone mit DCF77 Modul von ELV zu verbinden und Zeit auszulesen.
//Zur Überbrückung von Empfangsstörungen, bzw. wenn die DCF-Signalauswertung deaktiviert wird,
//steht eine RTC DS3231 parat, die parallel läuft
//DCF77.h und TimeLib.h wurden ohne Anpassungen verwendet.
//DCF77 Bibliothek wurde von hier erhalten: http://thijs.elenbaas.net/downloads/?did=1
//TimeLib.h Bibliothek wurde von hier erhalten: https://github.com/PaulStoffregen/Time
//Die Sketch-Vorlage wurde von hier geladen (hier werden auch andere Module behandelt): https://www.issb.de/mw/index.php/Test_elektronischer_Funkuhren-Module_(DCF77)_am_Mikroconcroller
// Librarys für DCF77 Funkuhrmodul
#include "DCF77.h" //Alle DCF77 Funktionen laufen ueber diese Bibliothek.
#include "TimeLib.h" //Time.h hat bei mir nie funktioniert, habe TimeLib.h eingebunden, dann gehts.
//#include <DS1307RTC.h>
#include "RTClib.h"
// Librarys für LCD-Display
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define DCF_PIN 2 // Verbindung zum DCF77 Arduino UNO PIN
#define DCF_INTERRUPT 0 // Interrupt number associated with pin
#define PIN_LED 13 // Status von der Verbindung an LED-PIN 13
bool g_bDCFTimeFound = false; // wurde ein gueltiges DCF77 Signal gefunden?
/*uint8_t ant[] = {
B00100,
B01010,
B10001,
B00100,
B00100,
B00100,
B00100,
B00100
};
*/ //####################### kann entfallen
// Variablen für die Auswertung und den Abgleich der Zeiten
byte ErstStart = 1;
byte DCFaktiv = 0;
byte DCFZeitOK = 0;
long Intervall = 120000; // Abfrageintervall 2 Minuten
long UpdateTimer = 0; // Zwischenspeicher für die Wartezeit
int belpin=9; // Pin für die PWM-Steuerung der Hintergrundbeleuchtung
int zeichenPos = 11;
int laengeWochentag;
int laengeMonat;
char nameMonat[10];
DCF77 DCF = DCF77(DCF_PIN, DCF_INTERRUPT); // Dieser Eintrag sollte für andere Module aktiviert werden...
// für das DCF-Modul von ELV muss das Signal invertiert werden, deshalb so:
// DCF77 DCF = DCF77(DCF_PIN, DCF_INTERRUPT, false); // false für invertiertes Signal
LiquidCrystal_I2C lcd(0x27, 20, 4); //Hier wird festgelegt um was für einen Display es sich handelt.
// RTC_DS3231 rtc; // Es wird eine Objekt rtc aus der Klasse RTC_3231 der RTClib.h erstellt
RTC_DS1307 rtc;
void setup()
{
pinMode(belpin, OUTPUT); // PWM Pin ist ein Ausgang
pinMode(PIN_LED, OUTPUT);
//Serial.begin(9600); // Seriellen Monitor starten
DCF.Start(); // DCF Uhr starten
DCFaktiv=1; // Merker, dass das DCF77 Signal ausgerwetet wird, man kann das mit DCF.Stop(); anhalten
rtc.begin(); // RTC starten
// Voreinstellung von RTC
rtc.adjust(DateTime(2020, 10, 28, 13, 26, 30));
lcd.init(); //Im Setup wird der LCD gestartet
lcd.backlight(); //Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus).
// lcd.createChar(0, ant);//####################### kann entfallen
lcd.setCursor(0, 3); // Spalte, Zeile, 0, 0 entspricht 1. Spalte oder 1. Zeile
lcd.print("DCF77 V2.6 aktiv: "); lcd.print(DCFaktiv);
}
void loop()
{
// das Signal wird nur alle 5 Sekunden abgefragt
delay(1000);
digitalWrite(PIN_LED, HIGH);
delay(50);
digitalWrite(PIN_LED, LOW);
DCFZeitOK = 0; // noch kein gültiges DCF-Telegramm empfangen
time_t DCFtime = DCF.getTime(); // Prüfen ob eine neue DCF77 Zeit verfügbar ist
if (DCFtime != 0)
{
// Serial.println("Aktuelle Zeit wurde empfangen!");
setTime(DCFtime);
g_bDCFTimeFound = true;
DCFZeitOK=1;
}
// die Uhrzeit wurde gesetzt, also LED nach kurzer Zeit ein
if (g_bDCFTimeFound)
{
delay(50);
digitalWrite(PIN_LED, HIGH);
}
if ((DCFZeitOK=1)&&(year()>2019)&&(((millis()-UpdateTimer) > Intervall)) )
{
ErstStart = 0;
// Wenn eine gültige DCF77 Zeit vorliegt, das DCF Jahr > 2019 und Intervall vergangen ist, die RTC aktualisieren
RTCUpdate();
UpdateTimer = millis();
// LCD-Zeile 3 vollständig löschen
int neuZeile = 0;
lcd.setCursor(0, 3);
while (neuZeile <= 20){
lcd.print(" ");
neuZeile++;
}
// Zeitpunkt des letzten Sync anzeigen
lcd.setCursor(2, 3); // Spalte, Zeile, 0, 0 entspricht 1. Spalte oder 1. Zeile
lcd.print("Last Sync: ");
DateTime aktuell = rtc.now();
//Stunde = (aktuell.hour()); Minute = (aktuell.minute()); Sekunde = (aktuell.second());
if (aktuell.hour() <10){lcd.print("0");} lcd.print(aktuell.hour()); lcd.print(":");
if (aktuell.minute() <10){lcd.print("0");} lcd.print(aktuell.minute());// lcd.print(":");
// if (aktuell.second() <10){lcd.print("0");} lcd.print(aktuell.second()); lcd.print(" ");
}
// Hintergrundbeleuchtung in Abhängigkeit der Uhrzeit (Stunde)
// Zwischen 21 Uhr abends und 7 Uhr morgens abdunkeln
if(hour() > 21 || hour() < 7)
{
analogWrite(belpin, 10); // Beleuchtung 255(hell) - 0(dunkel)
}
else
{
analogWrite(belpin, 250); // Beleuchtung 255(hell) - 0(dunkel)
}
// Ende Dimmersteuerung
digitalClockDisplay(); // DCF77 Zeit anzeigen
RTCClockDisplay(); // DCF77-Zeit für RTC- Zeit übernehmen
}
void RTCUpdate()
{
// Datum und Uhrzeit der DCF77 in RTC übertragen
rtc.adjust(DateTime(year(), month(), day(), hour(), minute(), second()));
}
void RTCClockDisplay()
{
// Anzeigen der RTC-Zeit auf dem 20x4 LCD-Display
int Stunde; int Minute; int Sekunde;
int Tag; int Monat; int Jahr;
DateTime aktuell = rtc.now();
Stunde = (aktuell.hour()); Minute = (aktuell.minute()); Sekunde = (aktuell.second());
Jahr = (aktuell.year()); Monat = (aktuell.month()); Tag = (aktuell.day());
// LCD-Zeile 2 vollständig löschen
int neuZeile = 0;
lcd.setCursor(0, 1);
while (neuZeile <= 20){
lcd.print(" ");
neuZeile++;
}
char dayName[7][12] = {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"};
// Textlänge für zentrierte Anzeige des Wochentags
laengeWochentag = strlen(dayName[aktuell.dayOfTheWeek()]);
lcd.setCursor(9 - laengeWochentag / 2, 1);
lcd.print(dayName[aktuell.dayOfTheWeek()]);
char nameMonat[13][10] = {"k.a.", "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"};
// Textlänge des Monatsnamens für zentrierte Anzeige des Datums mit ausgeschriebenen Monatsnamen
laengeMonat = strlen(nameMonat[Monat]);
lcd.setCursor(5 - laengeMonat / 2, 2);
if (Tag <10){lcd.print("0");} lcd.print(Tag); lcd.print(". ");
lcd.print(nameMonat[Monat]);
lcd.print(" ");
lcd.print(Jahr);
}
void digitalClockDisplay()
{
// Anzeigen der Zeit auf dem 20x4 LCD-Display
lcd.setCursor(6, 0);
if (hour()<10){lcd.print("0");} lcd.print(hour()); lcd.print(":");
if (minute()<10){lcd.print("0");} lcd.print(minute()); lcd.print(":");
if (second()<10){lcd.print("0");}lcd.print(second()); lcd.print(" ");
}