// Avatar Uhr v2.00.00 (Begonnen am 12.12.2025)
// Anleitung: https://www.instructables.com/Berlin-Clock-Arduino-Nano-DS1307-Real-Time-Clock-7/
// DCF-77: https://wolles-elektronikkiste.de/dcf77-funkuhr
// sprintf(buf, "%02d:%02d:%02d",p.hour, p.minute, p.second);
// Rot = 0
// Orange = 35
// Gelb = 50
// Grün = 130
// Blau = 240
// LCD.display() / LCD.noDisplay() // Display ein. ausschalten
// SAT Antenne wird nur angezeigt, wenn Synchonistion erfolgreich war.
// Synchronisierung nachts um 3:00 Uhr. Wenns nich klappt, alle 10 Minuten, 1h lang.
// Bei Fehlschlag, Antenne ausblenden und Sekunden LED auf rot wechseln.
#include <Wire.h> // I²C einbinden
#include <TimeLib.h> // Zeit- und Datumsfunktionen einbinden
#include <RTClib.h> // RTC 3231 einbinden
#include <LiquidCrystal_I2C.h> // I2 LCD Display einbinden
#include <Adafruit_NeoPixel.h> // LED Stripes (WS2812B) ansteuern
#include <EEPROM.h> // EEprrom einbinden
#define prgVersion "2.00.00" // Programmversion
#define prgDate "19.12.25" // Programm Erstellungsdatum
#define author " Gucky"
#define lcdAddress 0x27 // I²C Adreresse der RTC
#define rtcAddress 0x30 // I²C Adresse des LCD Displays
#define lcdCols 16 // 16 Zeichen pro LCD Zeile
#define numLed 24
#define numLight 10
#define lcdRows 2
#define pinInterrupt 2
#define pinMotion 3
#define pinBeeper 5 // Piepser Pin
#define pinStripeTime 6
#define pinStripeLight 7
#define pinEnter 8
#define pinValDown 9
#define pinValUp 10
#define pinkeySelect 11
#define pinMenuUp 12
#define pinLED 13
#define pinLDR A0
#define eeUseLDR 0x01
#define eeUseMotion 0x02
#define eeUseBeeper 0x03
#define eeSyncHour 0x11
#define eeSyncMin 0x12
#define eeRGBMode 0x21
#define eeRGBSpeed 0x22
const byte rot = 0;
const byte glb = 40;
const byte ora = 25;
const byte grn = 130;
const byte bla = 240;
byte rgbCol = 0;
byte rgbSat = 255;
byte rgbVal = 255;
byte light;
byte valueLDR = 1023; // Aktuelle Raumhelligkeit
byte val;
// Einstellungen & Menü
bool useMotion = false;
bool useLDR = true;
bool useBeeper = true;
byte rgbMode = 0;
byte rgbSpeed = 0;
byte tempValue;
unsigned long firstPixelHue = 0;
byte timeHour;
byte timeMin;
byte timeSec;
byte timeDay;
byte timeMonth;
byte timeYear;
byte timeWeekDay;
byte syncHour = 0;
byte syncMin = 0;
byte timeUpdated = 0;
// Variablen für DCF-77
volatile unsigned long lastInt = 0;
volatile unsigned long currentBuf = 0;
volatile unsigned long nextBuf = 0;
//volatile bool newMinute = false;
//volatile bool timeValid = false;
volatile byte bufCounter;
byte signal = 0;
bool rtcUpdated = false; // Wird true, wenn Zeit synchronisiert wurde.
// Variablen für Tasten
bool keySelect = HIGH;
bool keyMenu = HIGH;
bool keyValDown = HIGH;
bool keyValUp = HIGH;
bool keyEnter = HIGH;
bool keySelectOld = HIGH;
bool keyMenuOld = HIGH;
bool keyValDownOld = HIGH;
bool keyValUpOld = HIGH;
bool keyEnterOld = HIGH;
unsigned long menuTimeout;
byte menuPage = 0;
const byte menuPageMax = 11;
unsigned long keyPressTime;
bool editMode = false;
byte editValue = 0;
byte valueChanged = 0;
// Wchentagsnamen
char const PROGMEM day01[] = "So";
char const PROGMEM day02[] = "Mo";
char const PROGMEM day03[] = "Di";
char const PROGMEM day04[] = "Mi";
char const PROGMEM day05[] = "Do";
char const PROGMEM day06[] = "Fr";
char const PROGMEM day07[] = "Sa";
char* const PROGMEM days[] = { day01, day02, day03, day04, day05, day06, day07 };
char dayName[2];
char const PROGMEM month01[] = "Jan";
char const PROGMEM month02[] = "Feb";
char const PROGMEM month03[] = "Mär";
char const PROGMEM month04[] = "Apr";
char const PROGMEM month05[] = "Mai";
char const PROGMEM month06[] = "Jun";
char const PROGMEM month07[] = "Jul";
char const PROGMEM month08[] = "Aug";
char const PROGMEM month09[] = "Sep";
char const PROGMEM month10[] = "Okt";
char const PROGMEM month11[] = "Nov";
char const PROGMEM month12[] = "Dez";
char* const PROGMEM months[] = { month01, month02, month03, month04, month05, month06, month07, month08, month09, month10, month11, month12 };
char monthName[3];
const byte haken[] = { B00000, B00000, B00001, B00011, B10110, B11100, B01000, B00000 };
const byte signal1[] = { B00000, B00000, B00000, B00000, B00000, B00000, B11000, B11000 };
const byte signal2[] = { B00000, B00000, B00000, B00000, B00011, B00011, B11011, B11011 };
const byte signal3[] = { B00000, B00000, B11000, B11000, B11000, B11000, B11000, B11000 };
const byte signal4[] = { B00011, B00011, B11011, B11011, B11011, B11011, B11011, B11011 };
const byte c[] = { B01110, B10001, B10111, B11001, B11001, B10111, B10001, B01110 };
const byte akku[] = { B01110, B11111, B10001, B10001, B11111, B11111, B11111, B11111 };
const byte antenna[] = { B10001, B01001, B00110, B00110, B11001, B00011, B00111, B00111 };
const byte summerr[] = { B01110, B11111, B11001, B10111, B11011, B11101, B10011, B01110 };
LiquidCrystal_I2C LCD(lcdAddress , lcdCols , lcdRows);
Adafruit_NeoPixel stripeTime (numLed , pinStripeTime , NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripeLight(numLight, pinStripeLight, NEO_GRB + NEO_KHZ800);
RTC_DS3231 RTC;
void setup()
{
pinMode(pinInterrupt, INPUT);
pinMode(pinMenuUp , INPUT_PULLUP);
pinMode(pinkeySelect , INPUT_PULLUP);
pinMode(pinValUp , INPUT_PULLUP);
pinMode(pinValDown , INPUT_PULLUP);
pinMode(pinMotion , INPUT_PULLUP);
pinMode(pinEnter , INPUT_PULLUP);
pinMode(pinLED , OUTPUT);
Serial.begin(115200);
LCD.init();
LCD.createChar(0, haken);
LCD.createChar(1, signal1);
LCD.createChar(2, signal2);
LCD.createChar(3, signal3);
LCD.createChar(4, signal4);
LCD.createChar(5, c);
LCD.createChar(6, antenna);
LCD.createChar(7, akku);
if(!RTC.begin())
{
while(1)
{
digitalWrite(pinLED, HIGH);
delay(50);
digitalWrite(pinLED, HIGH);
delay(950);
}
}
//RTC.adjust(DateTime(2000, 1, 1, 0, 0, 0));
stripeTime.begin();
stripeLight.begin();
LCD.clear();
LCD.backlight();
digitalWrite(pinLED, HIGH);
LCD.print(F(" DCF-77 "));
LCD.setCursor(0, 1);
LCD.print(F(" PANGEA CLOCK "));
tone(pinBeeper, 2000, 20);
delay(2000);
stripeTime.clear();
stripeLight.clear();
stripeTime.show();
stripeLight.show();
for(byte x = 0; x <= numLed; x++)
{
stripeTime.setPixelColor(x - 1, stripeTime.ColorHSV( 0, 0, 0));
stripeTime.setPixelColor( x, stripeTime.ColorHSV( 130, 255, 255));
stripeTime.show();
stripeLight.setPixelColor(x/2 - 1, stripeLight.ColorHSV( 0, 0, 0));
stripeLight.setPixelColor( x/2, stripeLight.ColorHSV( 130, 255, 255));
stripeLight.show();
delay(30);
}
LCD.clear();
LCD.print(F("Version "));
LCD.print(prgVersion);
LCD.setCursor(0, 1);
LCD.write(5);
LCD.print(prgDate);
LCD.print(author);
delay(2000);
LCD.clear();
digitalWrite(pinLED, LOW);
readPrefs();
attachInterrupt(digitalPinToInterrupt(pinInterrupt), DCF77_Interrupt, CHANGE);
}
/*
void checkAdj()
{
if (digitalRead(changeTime) == HIGH)
{
if (digitalRead(setHourPos) == HIGH)
{
unsigned long v = RTC.get();
v = v + 3600;
RTC.set(v);
}
if (digitalRead(setMinPos) == HIGH)
{
unsigned long v = RTC.get();
v = v + 60;
RTC.set(v);
}
if (digitalRead(setHourNeg) == HIGH)
{
unsigned long v = RTC.get();
v = v - 3600;
RTC.set(v);
}
if (digitalRead(setMinNeg) == HIGH)
{
unsigned long v = RTC.get();
v = v - 60;
RTC.set(v);
}
i = (tm.Minute);
k = (tm.Hour);
obtainNo();
obtainRunning();
compileRegs();
sendToRegs();
delay(300);
}
}
*/
void loop()
{
unsigned long t = millis();
DateTime now = RTC.now(); // RTC auslesen
valueLDR = map(analogRead(pinLDR), 0, 1023, 255, 50);
if(timeUpdated != now.second()) // Nur jede Sekunde die Anzeigen aktualisueren
{ // LDR Wert auslesen und in Werte zwischen 50 und 255 umrechnen
val = (!useLDR? rgbVal:valueLDR);
timeHour = now.hour(); // Zeitvariablen für die Verwendung in Subroutinen speichern
timeMin = now.minute();
timeSec = now.second();
timeDay = now.day();
timeMonth = now.month();
timeYear = now.year() - 2000;
timeWeekDay = now.dayOfTheWeek();
if(useBeeper && !timeMin && !timeSec) // Stundensignal ausgeben, wenn Beeper an, Minute = 0 und Sekunde = 0 sind
{
for(byte x = 0; x <= numLight; x++) // Licht LEDs flackern jede Stunde flackern lassen
stripeLight.setPixelColor(x, stripeLight.ColorHSV(0, 255, useLDR == false? rgbVal:valueLDR));
stripeLight.show();
tone(pinBeeper, 2000, 20); // Piepston ausgeben
for(byte x = 0; x <= numLight; x++)
stripeLight.setPixelColor(x, stripeLight.ColorHSV(0, 0, 0));
stripeLight.show();
delay(80);
for(byte x = 0; x <= numLight; x++)
stripeLight.setPixelColor(x, stripeLight.ColorHSV(0, rgbSat, useLDR == false? rgbVal:valueLDR));
stripeLight.show();
tone(pinBeeper, 2000, 100);
}
if(digitalRead(pinMotion) == LOW && millis() > 15000 && useMotion) // Wenn keine Bewegung, Timeout abgelaufen und LCD ein eschaltet sind, ...
{
LCD.clear(); // ... Display ausschaslten.
LCD.noBacklight();
}
else
{
if(!menuPage)
updateDisplay(); // LCD Display aktualisieren
}
updateStripe(); // LED Stripe aktualisieren
timeUpdated = now.second(); // Neue Sekunde speichern
}
updateLight();
checkKeys(); // Tasten abfragen
//LCD.setCursor(13,1);
//LCD.print(millis() - t);
}
// LCD aktualisieren
void updateDisplay()
{
LCD.backlight(); // Hintergrundbeleuchtung einschalten.
char day; // Für Wochentagsanzeige.
char tm[9];
LCD.setCursor(4, 0); // Cursor in Zeile 1, Position 5.
sprintf(tm,"%02d:%02d %02d",timeHour, timeMin, timeSec);
LCD.print(tm);
LCD.setCursor(9, 0);
LCD.print(timeSec % 2 == 0? ":":" ");
LCD.setCursor(1, 1); // Cursor in Zeile 2,Position 2.
strcpy_P(dayName, (char*)pgm_read_word(&(days[timeWeekDay]))); // Wochentag (Name) ermitteln und...
LCD.print(dayName); // ausgeben.
LCD.print(F(", ")); // Komma anhängen.
LCD.print(timeDay < 10? "0":""); // Wenn TagSekunde kleiner als 10 ist, eine 0 voarnstellen, sonst nichts.
LCD.print(timeDay); // Tag ausgeben.
LCD.print(F(". ")); // Gefilgt von einem .
strcpy_P(monthName, (char*)pgm_read_word(&(months[timeMonth - 1]))); // Wochentag (Name) ermitteln.
LCD.print(monthName); // Wochentag ausgeben.
LCD.print(F(" ")); // Gefolgt von einem Leerzeichen.
LCD.print(timeYear); // Jahreszehl ausgeben (2000 werden in loop von now.year() abgezogen).
// Empfangsstärke anzeigen.
LCD.setCursor(0, 0);
LCD.print(F(" "));
signal = random(0, 4);
if(signal > 0) // Empfangsanzeige oben links und rechts.
{
LCD.setCursor(0, 0); // Cursor nach oben Links setzen (Empfangsstärke).
LCD.write(signal < 2? 1:2); // Wenn signal 1 oder 2 ist, nur das 1.Symbol entsprechend anzeigen
if(signal > 2) // Wenn signal größer als 2 ist (nur dann, um 2 Symbol auszublenden/anzuzeigen), ...
LCD.write(signal > 3? 4:3); // ... und 3 oder 4 ist, 2. Symbol entsprechend anzeigen.
}
LCD.setCursor(15, 0); // Cursor nach oben rechts setzen.
LCD.write(signal < 1? 32:6); // Wenn signal 0 ist, Leerzeichen anzeigen, sonst das Antennensymbol.
}
void updateStripe()
{
// Sekunden
stripeTime.setPixelColor( 0, stripeTime.ColorHSV( editMode == false? glb * 256:bla * 256, rgbSat, timeSec % 2? 0:val)); // Letzer Wert (v) = LDR Wert, wenn Helligkeitsregelung
stripeTime.setPixelColor( 20, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin % 5 >= 1? val:0));
stripeTime.setPixelColor( 21, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin % 5 >= 2? val:0));
stripeTime.setPixelColor( 22, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin % 5 >= 3? val:0));
stripeTime.setPixelColor( 23, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin % 5 >= 4? val:0));
stripeTime.setPixelColor( 9, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 5? val:0));
stripeTime.setPixelColor( 10, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 10? val:0));
stripeTime.setPixelColor( 11, stripeTime.ColorHSV( rot * 256, rgbSat, timeMin >= 15? val:0));
stripeTime.setPixelColor( 12, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 20? val:0));
stripeTime.setPixelColor( 13, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 25? val:0));
stripeTime.setPixelColor( 14, stripeTime.ColorHSV( rot * 256, rgbSat, timeMin >= 30? val:0));
stripeTime.setPixelColor( 15, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 35? val:0));
stripeTime.setPixelColor( 16, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 40? val:0));
stripeTime.setPixelColor( 17, stripeTime.ColorHSV( rot * 256, rgbSat, timeMin >= 45? val:0));
stripeTime.setPixelColor( 18, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 50? val:0));
stripeTime.setPixelColor( 19, stripeTime.ColorHSV( ora * 256, rgbSat, timeMin >= 55? val:0));
stripeTime.setPixelColor( 5, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour % 5 >= 1? val:0));
stripeTime.setPixelColor( 6, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour % 5 >= 2? val:0));
stripeTime.setPixelColor( 7, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour % 5 >= 3? val:0));
stripeTime.setPixelColor( 8, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour % 5 >= 4? val:0));
// 5´er Stunden
stripeTime.setPixelColor( 1, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour >= 5? val:0));
stripeTime.setPixelColor( 2, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour >= 10? val:0));
stripeTime.setPixelColor( 3, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour >= 15? val:0));
stripeTime.setPixelColor( 4, stripeTime.ColorHSV( rot * 256, rgbSat, timeHour >= 20? val:0));
stripeTime.show();
}
void updateLight()
{
for(int currentLED = 0; currentLED <= numLight; currentLED++)
{
long unsigned pixelHue = firstPixelHue - (currentLED * 65536 / numLed);
stripeLight.setPixelColor(currentLED, stripeLight.gamma32(stripeLight.ColorHSV(pixelHue, 255, useLDR? valueLDR:val))); // Letzer Wert = LDR, wenn Helligkeitsregelung
}
firstPixelHue += 8;
if(firstPixelHue > 65535)
firstPixelHue = 0;
stripeLight.show();
}
void checkKeys()
{
// menuTimeout
// showMenu
if(millis() >= menuTimeout + 10000 + (editMode * 50000) && menuPage) // && !editMode)
{
menuPage = 0;
editMode = false;
valueChanged = 0;
LCD.clear();
LCD.noBlink();
updateDisplay();
}
keyMenu = digitalRead(pinMenuUp);
keySelect = digitalRead(pinkeySelect);
keyValUp = digitalRead(pinValUp);
keyValDown = digitalRead(pinValDown);
keyEnter = digitalRead(pinEnter);
if(keyMenu != keyMenuOld)
{
keyMenuOld = keyMenu;
delay(5);
digitalWrite(pinLED, !keyMenu);
if(keyMenu == LOW)
{
if(menuPage >= menuPageMax)
menuPage = 1;
else
menuPage++;
editMode = false;
showMenu();
}
menuTimeout = millis();
}
if(keySelect != keySelectOld)
{
keySelectOld = keySelect;
delay(5);
digitalWrite(pinLED, !keySelect);
if(keySelect == LOW)
{
if(menuPage > 1)
{
editMode = !editMode;
if(editMode)
LCD.blink();
else
LCD.noBlink();
//(editMode? "LCD.blink()":"LCD.noBlink()");
}
if(editMode)
{
//switch(menuPage)
//{
// default:
// break;
//}
}
showMenu();
}
menuTimeout = millis();
}
if(keyValDown != keyValDownOld)
{
keyValDownOld = keyValDown;
delay(5);
menuTimeout = millis();
}
if(keyValUp != keyValUpOld)
{
keyValUpOld = keyValUp;
delay(5);
if(editMode)
valueChanged = true;
menuTimeout = millis();
}
if(keyEnter != keyEnterOld)
{
keyEnterOld = keyEnter;
delay(5);
digitalWrite(pinLED, !keyEnter);
if(keyEnter == LOW)
{
}
menuTimeout = millis();
}
}
void showMenu()
{
LCD.setCursor(0, 0);
// LCD.print(menuPage);
// delay(500);
char tm[17];
switch(menuPage)
{
case 1:
LCD.print(F("Version "));
LCD.print(prgVersion);
LCD.print(F(" "));
LCD.write(126);
LCD.setCursor(0, 1);
LCD.write(5);
LCD.print(prgDate);
LCD.print(author);
break;
case 2:
LCD.write(127);
LCD.print(F(" Uhr stellen "));
LCD.write(126);
LCD.setCursor(0, 1);
sprintf(tm, " Zeit: %02d:%02d ",timeHour, timeMin);
LCD.print(tm);
LCD.setCursor(menuPage == 2? 9:12 , 1);
//if(editMode)
// LCD.blink();
break;
default:
LCD.clear();
LCD.print(menuPage);
break;
/*
case 3:
LCD.write(127);
LCD.print(F(" Datum stell. "));
LCD.write(126);
LCD.setCursor(0, 1);
break;
case 3:
LCD.write(127);
LCD.print(F(" DCF-77 Sync. "));
LCD.write(126);
LCD.setCursor(0, 1);
LCD.print(F("Sync.Zeit: : "));
LCD.setCursor(11, 1);
LCD.print(syncHour < 10? "0":"");
LCD.print(syncHour);
LCD.setCursor(14, 1);
LCD.print(syncMin < 10? "0":"");
LCD.print(syncMin);
if(editMode)
{
LCD.setCursor(11 + editValue * 4, 1);
LCD.blink();
}
break;
case 4:
LCD.write(127);
LCD.print(F(" DCF-77 Sync. "));
LCD.write(126);
LCD.setCursor(0, 11);
LCD.print(F("Jetzt synchron."));
break;
case 5:
LCD.write(127);
LCD.print(F(" LED Beleucht "));
LCD.write(126);
LCD.setCursor(0, 1);
if(rgbVal < 10) LCD.print(F("00"));
if(rgbVal > 9 && rgbVal < 100) LCD.print(F("0"));
LCD.print(rgbVal);
LCD.print(": ");
LCD.print(bar(rgbVal, 16, 12));
break;
case 6:
LCD.write(127);
LCD.print(F(" LDR Sensor "));
LCD.write(126);
useLDR = true;
LCD.setCursor(0, 1);
LCD.print(F("Aktiv: Aus Ein"));
LCD.setCursor(useLDR == false? 7:12, 1);
LCD.write(0);
break;
case 7:
LCD.write(127);
LCD.print(F(" IR Sensor "));
LCD.write(126);
LCD.setCursor(0, 1);
LCD.print(F("Aktiv: Aus Ein"));
LCD.setCursor(useMotion == false? 7:12, 1);
LCD.write(0);
break;
case 8:
LCD.write(127);
LCD.print(F(" Tonsignal "));
LCD.write(126);
LCD.setCursor(0, 1);
LCD.print(F("Aktiv: Aus Ein"));
LCD.setCursor(useBeeper == false? 7:12, 1);
LCD.write(0);
break;
case 9:
LCD.write(127);
LCD.print(F(" RGB Modus "));
LCD.write(126);
LCD.setCursor(0, 1);
LCD.print(F("#"));
LCD.print(rgbMode < 10? "0":"");
LCD.print(rgbMode);
LCD.print(":");
LCD.print("Regenbogen");
break;
case 10:
LCD.write(127);
LCD.print(F(" RGB Tempo "));
LCD.write(126);
LCD.setCursor(0, 1);
LCD.print(F("Tempo:"));
LCD.setCursor(7, 1);
LCD.print(rgbSpeed < 10? "0":"");
LCD.print(rgbSpeed);
break;
case 11:
LCD.write(127);
LCD.print(F(" Speichern "));
LCD.setCursor(0, 0);
LCD.print(F(" Einstellungen "));
LCD.setCursor(0, 1);
LCD.print(F(" gespeichert. "));
//savePrefs();
break;
*/
}
if(useBeeper)
tone(pinBeeper, 1000, 20);
}
void savePrefs()
{
EEPROM.update(eeUseLDR , useLDR);
EEPROM.update(eeUseMotion, useMotion);
EEPROM.update(eeUseBeeper, useBeeper);
EEPROM.update(eeSyncHour , syncHour);
EEPROM.update(eeSyncMin , syncMin);
EEPROM.update(eeRGBMode , rgbMode);
EEPROM.update(eeRGBSpeed , rgbSpeed);
editMode = 0;
}
void readPrefs()
{
EEPROM.write(eeUseLDR , true);
EEPROM.write(eeUseMotion, false);
EEPROM.write(eeUseBeeper, true);
EEPROM.write(eeSyncHour , 4);
EEPROM.write(eeSyncMin , 56);
EEPROM.write(eeRGBMode , 1);
EEPROM.write(eeRGBSpeed , 0);
useLDR = EEPROM.read(eeUseLDR);
useMotion = EEPROM.read(eeUseMotion);
useBeeper = EEPROM.read(eeUseBeeper);
syncHour = EEPROM.read(eeSyncHour);
syncMin = EEPROM.read(eeSyncMin);
rgbMode = EEPROM.read(rgbMode);
rgbSpeed = EEPROM.read(rgbSpeed);
}
void DCF77_Interrupt()
{
unsigned int signalDuration = 0;
signalDuration = millis() - lastInt;
digitalWrite(pinLED, digitalRead(pinInterrupt));
if(digitalRead(pinInterrupt))
{
if(signalDuration > 1500) // Wenn Signaldauer > 1500 mS, dann neue Sekunde.
{
if(bufCounter == 59)
{
//timeValid = true;
if(signal < 4)
signal++;
currentBuf = nextBuf;
}
else
{
if(signal > 0)
signal--;
//timeValid = false;
}
nextBuf = 0;
//newMinute = true;
bufCounter = 0;
}
}
else
{
if(signalDuration > 150)
nextBuf |= ((unsigned long long)1 << bufCounter);
bufCounter++;
}
lastInt = millis();
}
String bar(float val, float max, byte len)
{
val = 25;
int pro = floor((len / max) * val);
int y;
String txt = "";
for(y = 0; y < len; y++)
txt += char(255);
return txt;
}
//void evaluateSequence() // Evtl. überflüssig?
//{
// byte dcf77Year = (currentBuf >> 50) & 0xFF; // year = bit 50-57
// byte dcf77Month = (currentBuf >> 45) & 0x1F; // month = bit 45-49
// byte dcf77DayOfWeek = (currentBuf >> 42) & 0x07; // day of the week = bit 42-44
// byte dcf77DayOfMonth = (currentBuf >> 36) & 0x3F; // day of the month = bit 36-41
// byte dcf77Hour = (currentBuf >> 29) & 0x3F; // hour = bit 29-34
// byte dcf77Minute = (currentBuf >> 21) & 0x7F; // minute = 21-27
// bool parityBitMinute = (currentBuf >> 28) & 1;
// bool parityBitHour = (currentBuf >> 35) & 1;
// bool parityBitDate = (currentBuf >> 58) & 1;
// if((parity_even_bit(dcf77Minute)) == parityBitMinute)
// {
// if((parity_even_bit(dcf77Hour)) == parityBitHour)
// {
// if(((parity_even_bit(dcf77DayOfMonth) + parity_even_bit(dcf77DayOfWeek) + parity_even_bit(dcf77Month) + parity_even_bit(dcf77Year))%2) == parityBitDate)
// RTC.adjust(DateTime(rawByteToInt(dcf77Year) + 2000, rawByteToInt(dcf77Month), rawByteToInt(dcf77DayOfMonth), rawByteToInt(dcf77Hour), rawByteToInt(dcf77Minute), 0));
// }
// }
//}
//unsigned int rawByteToInt(byte raw)
//{
// return ((raw >> 4) * 10 + (raw & 0x0F));
//}
//bool parity_even_bit(byte val)
//{
// val ^= val >> 4;
// val ^= val >> 2;
// val ^= val >> 1;
// val &= 0x01;
// return val;
//}
G
O
R
R
R
R
R
R
R
R
R
R
R
Sekunde
Stunde x 5
Stunde 1-4
Minute x 5
Minute 1-4
DCF-77
Signal
O
O
O
O
O
O
O
O
O
O
O
Nur ein LDR, kein Modul.
Motion HC SR-501
Piezo
Piepser
24 x WS-2812WS
10 x WS-2812WS
LCD 16x2 I²C
RTC 1307
Menu
Select
Val+
Val-
Enter