
Ziele des Projekts
Die Weckzeit wird zusammen mit Wochentag, Datum und Uhrzeit auf dem 4-zeiligen LCD-Display mit I²C-Schnittstelle angezeigt. Die Einstellungen können mit Tastern oder einer Fernbedienung vorgenommen werden.
Außerdem wird die mit dem RTC-Modul gemessene Temperatur angezeigt. Für die Aktivierung des Wecksignals wird die ⇒Alarmfunktion des RTC-Moduls DS3231 genutzt.
Anwendungsbeispiel (Danke an Norbert Schrills)




Die Weckmelodie wird mit RTTTL abgespielt.
RTTTL (Ring Tone Text Transfer Language) sind Klingeltöne, die ursprünglich von Nokia für ihre Mobiltelefone entwickelt wurden. Ein Klingelton muss drei Bestandteile haben:
- den Namen des Klingeltons
- die Standardvorgaben: die Dauer der Noten und die verwendete Oktave
- die durch Kommata getrennten Noten (internationale Notenbezeichnung c, d, e, f, g, a, b) alle Teile sind durch einen Doppelpunkt getrennt
Beispiel Te Deum:
TeDeum:d=4,o=5,b=63:8c,8f,16f,16g,8a
d=4: Standardnotenlänge Viertelnote
o=5: Angabe der Oktave
b=63: Abspielgeschwindigkeit 63 Schläge pro Minute
8c: Note C als Achtelnote gespielt
Als Wecksignal stehen verschiedene Melodien zur Verfügung.
Das Programm spielt die Melodien:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#include "PlayRtttl.hpp" int Lautsprecher = 5; char TeDeum[] = "Te_Deum:d=4,o=5,b=63:8c,8f,16f,16g,8a,8f,c6,8a,8a,8a#,16c6,16a#,16a,16a#,8c6,16g,16f,16g,16a,8g"; char Elise[] = "Elise:d=8,o=5,b=125:32p,e6,d#6,e6,d#6,e6,b,d6,c6,4a.,32p,c,e,a,4b.,32p,e,g#,b,4c.6,32p,e,e6,d#6,e6,d#6,e6,b,d6,c6,4a"; char Ode[] = "Ode:d=4,o=6,b=100:a5,a5,a_5,c,c,a_5,a5,g5,f5,f5,g5,a5,a.5,8g5,2g5,"; char Bolero[] = "Bolero:d=4,o=5,b=80:c6,8c6,16b,16c6,16d6,16c6,16b,16a,8c6,16c6,16a,c6,8c6,16b,16c6,16a,16g,16e,16f,2g"; char Fuenfte[] = "Fuenfte:d=4,o=5,b=180:8f,8f,8f,1c#,8p,8d#,8d#,8d#,1c,8p,8f,8f,8f,8c#,8f#,8f#,8f#,8f,8c#6,8c#6,8c#6,2a#,8p"; void setup() { playRtttlBlocking(Lautsprecher, TeDeum); delay(1000); playRtttlBlocking(Lautsprecher, Elise); delay(1000); playRtttlBlocking(Lautsprecher, Ode); delay(1000); playRtttlBlocking(Lautsprecher, Bolero); delay(1000); playRtttlBlocking(Lautsprecher, Fuenfte); } void loop() { // bleibt leer, Programm läuft nur einmal } |
Weitere Klingeltöne zum Download bei 🔗PICAXE
Wecker mit Tastern
- linker Taster: eine Stunde vorwärts
- mittlerer Taster: eine Minute weiter
- rechter Taster: Wecker ein- oder ausschalten

Die zuvor eingestellte Zeit und der Zustand des Weckers (ein/aus) werden auf dem internen Speicher (⇒EEPROM) eines Arduinos gespeichert.
Benötigte Bauteile
- 3 Taster
- ⇒4-zeiliges LCD mit I²C-Schnittstelle
- ⇒RTC-Modul DS3231
- Lautsprecher
- Leitungsdrähte

Die Laustärke des Lautsprechers kannst du mit einem vorgeschalteten Widerstand regulieren.

Der Schaltplan
(Fahre mit der Maus über das Bild, um die Bezeichnungen der Bauteile zu sehen)
Das Programm
Bibliotheken und Variablen

![]() | ![]() |

Einstellungen:
- Uhrzeiten, in denen das Display dunkel geschaltet werden kann
ZeitBeleuchtungAus/ZeitBeleuchtungEin
Angabe einer Uhrzeit ohne vorangestellte 0 - Anzeige der Sekunden ein/aus
SekundenAnzeigen true/false - Anzeige der Temperatur ein/aus
AnzeigeTemperatur true/false - KorrekturTemperatur
Die integrierte Messung der Temperatur des DS3231 ist nicht sehr genau (+/- 3°) und wird zusätzlich durch die Wärme in einem Gehäuse beeinflusst. Der festgelegt Wert wird nach der Messung mit 0.25 multipliziert. - Auswahl der Melodie:
0: TeDeum
1: Elise
2: Ode
3: Bolero
4: Fuenfte - Licht beim Wecksignal ein/aus
Lichtwecker true/false

Solange die Weckmelodie abgespielt wird, bleibt der Sekundenzeiger stehen. Anschließend wird wieder der aktuelle Wert angezeigt.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#include "RTClib.h" #include "LCDIC2.h" #include "EEPROM.h" #include "Bounce2.h" #include "PlayRtttl.hpp" // 4-zeiliges LCD LCDIC2 lcd(0x27, 20, 4); // Name des RTC-Moduls RTC_DS3231 rtc; #define AlarmInterruptPin 2 // Alarm beim Start auf false setzen volatile bool Alarm = false; #define Lautsprecher 5 #define LED 6 #define TasterLinks 9 #define TasterMitte 10 #define TasterRechts 11 // Standardwerte werden teilweise später durch EEPROM überschrieben int StundeWeckzeit = 7; int MinuteWeckzeit = 0; bool SekundenAnzeigen = true; bool WeckerEinAus = true; bool LichtWecker = true; bool AnzeigeTemperatur = true; int KorrekturTemperatur = 0; bool LichtEinschalten = true; int Weckmelodie = 4; int Schlummerzeit = 1; int ZeitBeleuchtungAus = 22; int ZeitBeleuchtungEin = 7; // Tasten Bounce zuordnen Bounce WeckzeitStunde = Bounce(); Bounce WeckzeitMinute = Bounce(); Bounce StatusWecker = Bounce(); // 0 char TeDeum[] = "Te_Deum:d=4,o=5,b=63:8c,8f,16f,16g,8a,8f,c6,8a,8a,8a#,16c6,16a#,16a,16a#,8c6,16g,16f,16g,16a,8g"; // 1 char Elise[] = "Elise:d=8,o=5,b=125:32p,e6,d#6,e6,d#6,e6,b,d6,c6,4a.,32p,c,e,a,4b.,32p,e,g#,b,4c.6,32p,e,e6,d#6,e6,d#6,e6,b,d6,c6,4a"; // 2 char Ode[] = "Ode:d=4,o=6,b=100:a5,a5,a_5,c,c,a_5,a5,g5,f5,f5,g5,a5,a.5,8g5,2g5,"; // 3 char Bolero[] = "Bolero:d=4,o=5,b=80:c6,8c6,16b,16c6,16d6,16c6,16b,16a,8c6,16c6,16a,c6,8c6,16b,16c6,16a,16g,16e,16f,2g"; // 4 char Fuenfte[] = "Fuenfte:d=4,o=5,b=180:8f,8f,8f,1c#,8p,8d#,8d#,8d#,1c,8p,8f,8f,8f,8c#,8f#,8f#,8f#,8f,8c#6,8c#6,8c#6,2a#,8p,8f,8f,8f,8c,8f#,8f#,8f#,8f,8d#6,8d#6,8d#6,1c6"; |
Der setup-Teil
Nachdem die Zeit mit dem Zeitpunkt des Kompilierens gesetzt wurde, musst du vor einem erneutem Hochladen die Zeile 32 mit // versehen, ansonsten stimmt nach einem Stromausfall oder einem erneutem Einstecken der Stromzufuhr die Zeit nicht mehr.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
void setup() { pinMode(TasterLinks, INPUT_PULLUP); pinMode(TasterMitte, INPUT_PULLUP); pinMode(TasterRechts, INPUT_PULLUP); // Instanzen des Objekts Bounce für jede Taste zuordnen // Zeitintervall einstellen WeckzeitStunde.attach(TasterLinks); WeckzeitStunde.interval(20); WeckzeitMinute.attach(TasterMitte); WeckzeitMinute.interval(20); StatusWecker.attach(TasterRechts); StatusWecker.interval(20); Serial.begin(9600); // auf serielle Verbindung warten while (!Serial) {;} delay(1000); rtc.begin(); /* wenn Datum und Zeit nicht korrekt -> Datum/Zeit setzen Jahr, Monat, Tag, Stunde, Minute, Sekunde keine führende 0 setzen rtc.adjust(DateTime(2025, 4, 14, 16, 42, 30)); */ rtc.adjust(DateTime(2025, 4, 14, 16, 42, 30)); // Zeitpunkt des Kompilierens als aktuelle Zeit setzen rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // 32K-Pin am DS3231 deaktivieren rtc.disable32K(); // Pin 2 als Interrupt-Pin pinMode(AlarmInterruptPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(AlarmInterruptPin), Wecken, FALLING); // Alarme löschen und deaktivieren rtc.clearAlarm(1); rtc.clearAlarm(2); rtc.disableAlarm(1); rtc.disableAlarm(2); // LCD starten lcd.begin(); // Cursor "verstecken" lcd.setCursor(false); // Weckzeit Stunde/Minute aus EEPROM lesen StundeWeckzeit = EEPROM.read(0); MinuteWeckzeit = EEPROM.read(2); // Status der Weckzeit lesen ein/aus WeckerEinAus = EEPROM.read(4); // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Alarm setzen DateTime alarmTime (aktuell.year(), aktuell.month(), aktuell.dayOfTheWeek(), StundeWeckzeit, MinuteWeckzeit, 0); rtc.setAlarm1(alarmTime, DS3231_A1_Hour); } |
Der loop-Teil
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
void loop() { String Stunde, Minute, Weckzeit; int CursorPosition = 0; // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Stunde einstellen if (WeckzeitStunde.update()) { if (WeckzeitStunde.read() == LOW) { if (StundeWeckzeit >= 23) StundeWeckzeit = 0; else StundeWeckzeit ++; } } // Minute einstellen if (WeckzeitMinute.update()) { if (WeckzeitMinute.read() == LOW) { if (MinuteWeckzeit >= 59) MinuteWeckzeit = 0; else MinuteWeckzeit ++; } } // Wecker ein/aus if (StatusWecker.update()) { if (StatusWecker.read() == LOW) { WeckerEinAus = !WeckerEinAus; // Status Wecker schreiben if(WeckerEinAus) EEPROM.update(4, 1); else EEPROM.update(4, 0); } } // Weckzeit und Alarm neu setzen DateTime AlarmWecker (aktuell.year(), aktuell.month(), aktuell.day(), StundeWeckzeit, MinuteWeckzeit, 0); rtc.setAlarm1(AlarmWecker, DS3231_A1_Hour); // Schlummerzeit setzen DateTime AlarmSchlummerZeit (aktuell.year(), aktuell.month(), aktuell.day(), StundeWeckzeit, MinuteWeckzeit + Schlummerzeit, 0); rtc.setAlarm2(AlarmSchlummerZeit, DS3231_A2_Hour); // Wochentag, Datum und Zeit anzeigen lcd.setCursor(0, 0); /* Wochentag anzeigen 0 = Sonntag 1 = Montag ... 6 = Samstag */ switch (aktuell.dayOfTheWeek()) { case 0: lcd.print("Sonntag "); break; case 1: lcd.print("Montag "); break; case 2: lcd.print("Dienstag "); break; case 3: lcd.print("Mittwoch "); break; case 4: lcd.print("Donnerstag"); break; case 5: lcd.print("Freitag "); break; case 6: lcd.print("Samstag "); break; } lcd.print(" "); if(AnzeigeTemperatur) { lcd.setCursor(15, 0); // Temperatur ermitteln -> ggfs. KorrekturTemperatur nach oben korrigieren // 0 -> nur ganzzahlige Werte, 1 -> eine Nachkommastelle String Temperatur = String(rtc.getTemperature() - 0.25 * KorrekturTemperatur, 0); Temperatur.replace(".", ","); lcd.print(Temperatur + "\337C "); } lcd.setCursor(0, 1); lcd.print(String(aktuell.day()) + "."); // Cursorposition verschieben CursorPosition += 3; // Monatsnamen anzeigen lcd.print(" "); switch (aktuell.month()) { case 1: lcd.print("Januar"); CursorPosition += 6; break; case 2: lcd.print("Februar"); CursorPosition += 7; break; case 3: lcd.print("M\341rz"); CursorPosition += 4; break; case 4: lcd.print("April"); CursorPosition += 5; break; case 5: lcd.print("Mai"); CursorPosition += 3; break; case 6: lcd.print("Juni"); CursorPosition += 4; break; case 7: lcd.print("Juli"); CursorPosition += 4; break; case 8: lcd.print("August"); CursorPosition += 6; break; case 9: lcd.print("September"); CursorPosition += 9; break; case 10: lcd.print("Oktober"); CursorPosition += 7; break; case 11: lcd.print("November"); CursorPosition += 8; break; case 12: lcd.print("Dezember"); CursorPosition += 8; break; } lcd.print(" "); lcd.print(String(aktuell.year())); // Jahreszahl + Leerzeichen CursorPosition += 5; // mit Leerzeichen auffüllen for(int i = CursorPosition; i < 19; i++) { lcd.print(" "); } lcd.setCursor(0, 2); // wenn Stunden < 10 -> führende 0 setzen if (aktuell.hour() < 10) lcd.print("0"); lcd.print(String(aktuell.hour())); lcd.print(':'); // wenn Minuten < 10 -> führende 0 setzen if (aktuell.minute() < 10) lcd.print("0"); lcd.print(String(aktuell.minute())); if(SekundenAnzeigen) { lcd.print(':'); // wenn Sekunden < 10 -> führende 0 setzen if (aktuell.second() < 10) lcd.print("0"); lcd.print(String(aktuell.second())); } // Steuerung der Hintergrundbeleuchtung if(aktuell.hour() == ZeitBeleuchtungAus) lcd.setBacklight(false); if(aktuell.hour() == ZeitBeleuchtungEin) lcd.setBacklight(true); if (WeckerEinAus) lcd.print(" Wecker ein"); else lcd.print(" Wecker aus"); /* Weckzeit formatieren -> führende 0 ergänzen 4 mögliche Fälle Stunde < 10 Minute < 10 Stunde < 10 Minute > 9 Stunde > 10 Minute < 10 Stunde > 10 Minute > 9 */ if (StundeWeckzeit < 10 && MinuteWeckzeit < 10) { Weckzeit = "0" + String(StundeWeckzeit) + ":0" + String(MinuteWeckzeit); } if (StundeWeckzeit < 10 && MinuteWeckzeit > 9) { Weckzeit = "0" + String(StundeWeckzeit) + ":" + String(MinuteWeckzeit); } if (StundeWeckzeit > 9 && MinuteWeckzeit < 10) { Weckzeit = String(StundeWeckzeit) + ":0" + String(MinuteWeckzeit); } if (StundeWeckzeit > 9 && MinuteWeckzeit > 9) { Weckzeit = String(StundeWeckzeit) + ":" + String(MinuteWeckzeit); } lcd.setCursor(0, 3); lcd.print("Weckzeit " + Weckzeit); lcd.setCursor(15, 3); if(LichtWecker) lcd.print("L"); else lcd.print(" "); lcd.setCursor(17, 3); if(WeckerEinAus) { if (Schlummerzeit > 9) lcd.print("S" + String(Schlummerzeit)); else lcd.print("S " + String(Schlummerzeit)); } else lcd.print(" "); // String zusammensetzen String aktuelleZeit = Stunde + ":" + Minute; if(WeckerEinAus) { if (Alarm && rtc.alarmFired(1)) { // 255 = maximaler Wert if (LichtWecker) analogWrite(LED, 255); WeckmelodieSpielen(); rtc.clearAlarm(1); analogWrite(LED, 0); } if(Alarm && rtc.alarmFired(2)) { if (LichtWecker) analogWrite(LED, 255); WeckmelodieSpielen(); rtc.clearAlarm(2); rtc.disableAlarm(2); analogWrite(LED, 0); } Alarm = false; } } |
Die Funktion Wecken setzt die Variable Alarm auf true:
|
1 2 3 4 |
void Wecken() { Alarm = true; } |
Die Variable Weckmelodie bestimmt, welche Melodie gespielt wird:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
oid WeckmelodieSpielen() { switch(Weckmelodie) { case 0: playRtttlBlocking(Lautsprecher, TeDeum); break; case 1: playRtttlBlocking(Lautsprecher, Elise); break; case 2: playRtttlBlocking(Lautsprecher, Ode); break; case 3: playRtttlBlocking(Lautsprecher, Bolero); break; case 4: playRtttlBlocking(Lautsprecher, Fuenfte); break; default: break; } } |
Wecker mit Fernbedienung
Die Fernbedienung bietet die Möglichkeit die Einstellungen im laufenden Betrieb zu ändern, die neuen Einstellungen zu speichern und auf dem LCD anzuzeigen.


Beispiele für Fernbedienungen
| Taste | bewirkt | Speichern im EEPROM | Anzeige im Display |
|---|---|---|---|
| Pfeil oben | eine Stunde vorwärts | ja | ja |
| Pfeil unten | eine Stunde zurück | ja | ja |
| Pfeil rechts | eine Minute weiter | ja | ja |
| Pfeil links | eine Minute zurück | ja | ja |
| OK | Wecker ein- oder ausschalten | ja | ja |
| 1 | Melodie ändern (1 .. 5) 1: Te Deum 2: Für Elise 3: Ode an die Freude 4: Bolero 5: Beethovens Fünfte | ja | ja Name der Melodie |
| 2 | Temperaturanzeige ein/aus | ja | ja |
| 6 | Wecksignal mit Licht ein/aus | ja | ja (L) |
| 7 | Schlummerzeit verringern | ja | S + Anzahl Minuten |
| 8 | Schlummerzeit vergößern | ja | S + Anzahl Minuten |
| 9 | Anzeige der Sekunden ein/aus | nein | ja |
| 0 | Licht ein-/ausschalten | nein | nein |
| * | Hintergrundbeleuchtung einschalten | nein | ja |
| # | Hintergrundbeleuchtung ausschalten | nein | ja |

Benötigte Bauteile
- ⇒Infrarot-Empfänger mit Fernbedienung
- ⇒4-zeiliges LCD mit I²C-Schnittstelle
- ⇒RTC-Modul DS3231
- Lautsprecher
- Leitungsdrähte
Der Schaltplan
(Fahre mit der Maus über das Bild, um die Bezeichnungen der Bauteile zu sehen)
Die weiße LED ist optional.
Das Programm
Einstellungen
Wenn du das Programm zum ersten Mal startest, sind alle Werte im EEPROM auf 0 gesetzt. Mit diesem Programm kannst du die Werte anzeigen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "EEPROM.h" void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial); delay(1000); for (int i = 0; i < 14; i++) { Serial.println(EEPROM.read(i)); } } void loop() { // bleibt leer, Programm wird nur einmal ausgeführt } |
Mit diesem Programm kannst du alle Werte auf 0 setzen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include "EEPROM.h" void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial); delay(1000); for (int i = 0; i < 14; i++) { EEPROM.write(i, 0); } // geschriebene Zahlen lesen for (int i = 0; i < 12; i++) { Serial.println(EEPROM.read(i)); } } void loop() { // bleibt leer, Programm wird nur einmal ausgeführt } |
Bibliotheken und Variable

![]() | ![]() |


Wenn Tasten auf der Fernbedienung gedrückt werden, kann es zu kurzen zeitlichen Verzögerungen kommen. Diese werden aber bei der nächsten Abfrage des RTC-Moduls korrigiert.

Solange die Weckmelodie abgespielt wird, bleibt die Sekundenanzeige stehen. Anschließend wird wieder der aktuelle Wert angezeigt.
Du musst die Variablen für die Tasten der jeweiligen Fernbedienung anpassen. ⇒Hier kannst du die Tastencodes herausfinden.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#include "RTClib.h" #include "LCDIC2.h" #include "EEPROM.h" #include "IRremote.hpp" #include "PlayRtttl.hpp" // Interruptpin des Infrarot-Empfängers #define EmpfaengerPin 3 #define Lautsprecher 5 #define LED 6 // 4-zeiliges LCD LCDIC2 lcd(0x27, 20, 4); // Name des RTC-Moduls RTC_DS3231 rtc; // Interrupt-Pin -> Alarm auslösen #define AlarmInterruptPin 2 // Alarm beim Start auf false setzen volatile bool Alarm = false; volatile bool IRAktiv = false; // Tasten Fernbedienung Pfeile oben #define Licht_ein 82 #define Melodie_aendern 22 #define Temperatur_Anzeige_umschalten 25 #define Licht_Wecker_umschalten 94 #define Schlummern_minus 8 #define Schlummern_plus 28 #define Sekunden_Anzeige_umschalten 90 #define Beleuchtung_ein 66 #define Beleuchtung_aus 74 #define Wecker_Status 64 #define Stunde_plus 70 #define Minute_minus 68 #define Minute_plus 67 #define Stunde_minus 21 // Tasten Fernbedienung Pfeile unten /* #define Licht_ein 25 #define Melodie_aendern 69 #define Temperatur_Anzeige_umschalten 70 #define Licht_Wecker_umschalten 67 #define Schlummern_minus 7 #define Schlummern_plus 21 #define Sekunden_Anzeige_umschalten 9 #define Beleuchtung_ein 22 #define Beleuchtung_aus 13 #define Wecker_Status 28 #define Stunde_plus 24 #define Minute_minus 8 #define Minute_plus 90 #define Stunde_minus 82 */ // Standardwerte werden teilweise später durch EEPROM überschrieben int StundeWeckzeit = 7; int MinuteWeckzeit = 0; bool SekundenAnzeigen = true; bool WeckerEinAus = true; bool LichtWecker = true; bool LichtEinschalten = true; bool AnzeigeTemperatur = true; int KorrekturTemperatur = 5; int Weckmelodie = 0; int Schlummerzeit = 1; // 0 char TeDeum[] = "Te_Deum:d=4,o=5,b=63:8c,8f,16f,16g,8a,8f,c6,8a,8a,8a#,16c6,16a#,16a,16a#,8c6,16g,16f,16g,16a,8g"; // 1 char Elise[] = "Elise:d=8,o=5,b=125:32p,e6,d#6,e6,d#6,e6,b,d6,c6,4a.,32p,c,e,a,4b.,32p,e,g#,b,4c.6,32p,e,e6,d#6,e6,d#6,e6,b,d6,c6,4a"; // 2 char Ode[] = "Ode:d=4,o=6,b=100:a5,a5,a_5,c,c,a_5,a5,g5,f5,f5,g5,a5,a.5,8g5,2g5,"; // 3 char Bolero[] = "Bolero:d=4,o=5,b=80:c6,8c6,16b,16c6,16d6,16c6,16b,16a,8c6,16c6,16a,c6,8c6,16b,16c6,16a,16g,16e,16f,2g"; // 4 char Fuenfte[] = "Fuenfte:d=4,o=5,b=180:8f,8f,8f,1c#,8p,8d#,8d#,8d#,1c,8p,8f,8f,8f,8c#,8f#,8f#,8f#,8f,8c#6,8c#6,8c#6,2a#,8p"; |
Der setup-Teil
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
void setup() { // Infrarot-Empfänger starten IrReceiver.begin(EmpfaengerPin); rtc.begin(); // Zeitpunkt des Kompilierens als aktuelle Zeit setzen rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // 32K-Pin am DS3231 deaktivieren rtc.disable32K(); // Pin 2 als Interrupt-Pin pinMode(AlarmInterruptPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(EmpfaengerPin), IRAbfragen, FALLING); attachInterrupt(digitalPinToInterrupt(AlarmInterruptPin), Wecken, FALLING); // Alarme löschen und deaktivieren rtc.clearAlarm(1); rtc.clearAlarm(2); rtc.disableAlarm(1); rtc.disableAlarm(2); rtc.writeSqwPinMode(DS3231_OFF); // LCD starten lcd.begin(); // Cursor "verstecken" lcd.setCursor(false); // Einstellungen aus EEPROM lesen StundeWeckzeit = EEPROM.read(0); MinuteWeckzeit = EEPROM.read(2); WeckerEinAus = EEPROM.read(4); Weckmelodie = EEPROM.read(6); SekundenAnzeigen = EEPROM.read(8); Schlummerzeit = EEPROM.read(10); LichtWecker = EEPROM.read(12); AnzeigeTemperatur = EEPROM.read(14); // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Alarm setzen DateTime alarmTime (aktuell.year(), aktuell.month(), aktuell.day(), StundeWeckzeit, MinuteWeckzeit, 0); rtc.setAlarm1(alarmTime, DS3231_A1_Hour); } |
Der loop-Teil

Wenn der Druck auf die Taste der Fernbedienung zu schnell hintereinander registriert wird, kannst du in Zeile 15 die Zeit für delay etwas erhöhen.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
void loop() { String Stunde, Minute, Weckzeit; // aktuelle Zeit lesen DateTime aktuell = rtc.now(); if (IRAktiv && IrReceiver.decode()) { // resume -> nächsten Wert lesen IrReceiver.resume(); if (IrReceiver.decodedIRData.command >= 0 && IrReceiver.decodedIRData.command < 95) { delay(200); // Stunden ++ if (IrReceiver.decodedIRData.command == Stunde_plus) { if (StundeWeckzeit >= 23) StundeWeckzeit = 0; else StundeWeckzeit ++; // Weckzeit Stunde an Position 0 in EEPROM schreiben EEPROM.update(0, StundeWeckzeit); } // Stunden -- if (IrReceiver.decodedIRData.command == Stunde_minus) { if (StundeWeckzeit == 0) StundeWeckzeit = 23; else StundeWeckzeit --; // Weckzeit Stunde an Position 0 in EEPROM schreiben EEPROM.update(0, StundeWeckzeit); } // Minuten ++ if (IrReceiver.decodedIRData.command == Minute_plus) { if (MinuteWeckzeit >= 59) { MinuteWeckzeit = 0; StundeWeckzeit ++; EEPROM.update(0, StundeWeckzeit); } else MinuteWeckzeit ++; // Weckzeit Stunde an Position 0 in EEPROM schreiben EEPROM.update(2, MinuteWeckzeit); } // Minuten -- if (IrReceiver.decodedIRData.command == Minute_minus) { if (MinuteWeckzeit == 0) { MinuteWeckzeit = 59; StundeWeckzeit --; EEPROM.update(0, StundeWeckzeit); } else MinuteWeckzeit --; // Weckzeit Stunde an Position 2 in EEPROM schreiben EEPROM.update(2, MinuteWeckzeit); } // Wecker ein/aus if (IrReceiver.decodedIRData.command == Wecker_Status) { WeckerEinAus = !WeckerEinAus; // Status Wecker an Position 4 in EEPROM schreiben if(WeckerEinAus) EEPROM.update(4, 1); else EEPROM.update(4, 0); } // Hintergrundbeleuchtung aus if (IrReceiver.decodedIRData.command == Beleuchtung_aus) lcd.setBacklight(false); // Hintergrundbeleuchtung ein if (IrReceiver.decodedIRData.command == Beleuchtung_ein) lcd.setBacklight(true); // Melodie ändern if (IrReceiver.decodedIRData.command == Melodie_aendern) { if(Weckmelodie >= 0 && Weckmelodie < 4) Weckmelodie ++; else Weckmelodie = 0; lcd.setCursor(13, 1); // Name der Melodie anzeigen switch (Weckmelodie) { case 0: lcd.print("Te Deum"); break; case 1: lcd.print(" Elise"); break; case 2: lcd.print(" Ode"); break; case 3: lcd.print(" Bolero"); break; case 4: lcd.print(" F\365nfte"); break; } EEPROM.update(6, Weckmelodie); } // Temperaturanzeige aus/ein if (IrReceiver.decodedIRData.command == Temperatur_Anzeige_umschalten) { AnzeigeTemperatur = !AnzeigeTemperatur; EEPROM.update(14, AnzeigeTemperatur); } // Wecken mit Licht if (IrReceiver.decodedIRData.command == Licht_Wecker_umschalten) { LichtWecker = !LichtWecker; if(LichtWecker) EEPROM.update(12, 1); else EEPROM.update(12, 0); } // Schlummern - if (IrReceiver.decodedIRData.command == Schlummern_minus) { if(WeckerEinAus) { if (Schlummerzeit > 0) Schlummerzeit --; EEPROM.update(10, Schlummerzeit); lcd.setCursor(17, 3); if (Schlummerzeit > 9) lcd.print("S" + String(Schlummerzeit)); else lcd.print("S " + String(Schlummerzeit)); } } // Schlummern + if (IrReceiver.decodedIRData.command == Schlummern_plus) { if(WeckerEinAus) { Schlummerzeit ++; EEPROM.update(10, Schlummerzeit); lcd.setCursor(17, 3); if (Schlummerzeit > 9) lcd.print("S" + String(Schlummerzeit)); else lcd.print("S " + String(Schlummerzeit)); } } // Licht ein/aus if (IrReceiver.decodedIRData.command == Licht_ein) { if (LichtEinschalten) { analogWrite(LED, 200); LichtEinschalten =!LichtEinschalten; } else { analogWrite(LED, 0); LichtEinschalten =!LichtEinschalten; } } // Sekunden anzeigen ein/aus // Status Sekundenzeiger an Position 8 in EEPROM schreiben if (IrReceiver.decodedIRData.command == Sekunden_Anzeige_umschalten) { SekundenAnzeigen = !SekundenAnzeigen; if(SekundenAnzeigen) EEPROM.update(8, 1); else EEPROM.update(8, 0); } } } // Weckzeit und Alarm neu setzen DateTime AlarmWecker (aktuell.year(), aktuell.month(), aktuell.day(), StundeWeckzeit, MinuteWeckzeit, 0); rtc.setAlarm1(AlarmWecker, DS3231_A1_Hour); // Schlummerzeit setzen DateTime AlarmSchlummerZeit (aktuell.year(), aktuell.month(), aktuell.day(), StundeWeckzeit, MinuteWeckzeit + Schlummerzeit, 0); rtc.setAlarm2(AlarmSchlummerZeit, DS3231_A2_Hour); // Wochentag, Datum und Zeit anzeigen lcd.setCursor(0, 0); /* Wochentag anzeigen 0 = Sonntag 1 = Montag ... 6 = Samstag */ switch (aktuell.dayOfTheWeek()) { case 0: lcd.print("Sonntag "); break; case 1: lcd.print("Montag "); break; case 2: lcd.print("Dienstag "); break; case 3: lcd.print("Mittwoch "); break; case 4: lcd.print("Donnerstag"); break; case 5: lcd.print("Freitag "); break; case 6: lcd.print("Samstag "); break; } lcd.print(" "); lcd.setCursor(13, 1); if (WeckerEinAus) { switch (Weckmelodie) { case 0: lcd.print("Te Deum"); break; case 1: lcd.print(" Elise"); break; case 2: lcd.print(" Ode"); break; case 3: lcd.print(" Bolero"); break; case 4: lcd.print(" F\365nfte"); break; } } else lcd.print(" "); if(AnzeigeTemperatur) { lcd.setCursor(16, 0); // Temperatur ermitteln -> ggfs. KorrekturTemperatur nach oben korrigieren // 0 -> nur ganzzahlige Werte, 1 -> eine Nachkommastelle String Temperatur = String(rtc.getTemperature() - 0.25 * KorrekturTemperatur, 0); Temperatur.replace(".", ","); lcd.print(Temperatur + "\337C"); } else { lcd.setCursor(16, 0); lcd.print(" "); } lcd.setCursor(0, 1); char Datum[] = "DD.MM.YYYY"; lcd.print(aktuell.toString(Datum)); lcd.setCursor(0, 2); // wenn Stunden < 10 -> führende 0 setzen if (aktuell.hour() < 10) lcd.print("0"); lcd.print(String(aktuell.hour())); lcd.print(':'); // wenn Minuten < 10 -> führende 0 setzen if (aktuell.minute() < 10) lcd.print("0"); lcd.print(String(aktuell.minute())); if(SekundenAnzeigen) { lcd.print(':'); // wenn Sekunden < 10 -> führende 0 setzen if (aktuell.second() < 10) lcd.print("0"); lcd.print(String(aktuell.second())); } else lcd.print(" "); lcd.setCursor(8, 2); if (WeckerEinAus) lcd.print(" Wecker ein"); else lcd.print(" Wecker aus"); lcd.setCursor(0, 3); // Wenn Wecker ein -> Status anzeigen if(WeckerEinAus) { /* Weckzeit formatieren -> führende 0 ergänzen 4 mögliche Fälle Stunde < 10 Minute < 10 Stunde < 10 Minute > 9 Stunde > 10 Minute < 10 Stunde > 10 Minute > 9 */ if (StundeWeckzeit < 10 && MinuteWeckzeit < 10) { Weckzeit = "0" + String(StundeWeckzeit) + ":0" + String(MinuteWeckzeit); } if (StundeWeckzeit < 10 && MinuteWeckzeit > 9) { Weckzeit = "0" + String(StundeWeckzeit) + ":" + String(MinuteWeckzeit); } if (StundeWeckzeit > 9 && MinuteWeckzeit < 10) { Weckzeit = String(StundeWeckzeit) + ":0" + String(MinuteWeckzeit); } if (StundeWeckzeit > 9 && MinuteWeckzeit > 9) { Weckzeit = String(StundeWeckzeit) + ":" + String(MinuteWeckzeit); } lcd.print("Weckzeit " + Weckzeit); lcd.setCursor(15, 3); if(LichtWecker) lcd.print("L"); else lcd.print(" "); lcd.setCursor(17, 3); if (Schlummerzeit > 9) lcd.print("S" + String(Schlummerzeit)); else lcd.print("S " + String(Schlummerzeit)); } // Wecker aus -> Status verbergen else lcd.print(" "); /* Weckzeit erreicht -> Alarm auslösen -> Melodie abspielen -> wenn Variable Lichtwecker gesetzt: LED einschalten -> LCD-Hintergrundbeleuchtung einschalten -> Alarm2 -> Schlummern */ if(WeckerEinAus) { if (Alarm && rtc.alarmFired(1)) { // 255 = maximaler Wert if (LichtWecker) analogWrite(LED, 255); WeckmelodieSpielen(); rtc.clearAlarm(1); analogWrite(LED, 0); IrReceiver.begin(EmpfaengerPin); } if(Alarm && rtc.alarmFired(2)) { if (LichtWecker) analogWrite(LED, 255); WeckmelodieSpielen(); rtc.clearAlarm(2); rtc.disableAlarm(2); analogWrite(LED, 0); IrReceiver.begin(EmpfaengerPin); } Alarm = false; } } |
Die über den Interruptpin ausgelöste Funktion IRAbfragen() setzt die Variable IRAktiv auf true:
|
1 2 3 4 |
void IRAbfragen() { IRAktiv = true; } |
Die Funktion Wecken setzt die Variable Alarm auf true:
|
1 2 3 4 |
void Wecken() { Alarm = true; } |
Die Variable Weckmelodie bestimmt, welche Melodie gespielt wird:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void WeckmelodieSpielen() { switch(Weckmelodie) { case 0: playRtttlBlocking(Lautsprecher, TeDeum); break; case 1: playRtttlBlocking(Lautsprecher, Elise); break; case 2: playRtttlBlocking(Lautsprecher, Ode); break; case 3: playRtttlBlocking(Lautsprecher, Bolero); break; case 4: playRtttlBlocking(Lautsprecher, Fuenfte); break; default: break; } } |
Ähnliche Projekte
- Analoge Uhr mit TFT 240×240 Pixeln und RTC-Modul
- Datum und Zeit mit ESP und time.h anzeigen
- Datum und Zeit mit dem NTP-Protokoll anzeigen
- DHT – Messdaten und Zeit auf TFT anzeigen
- Stoppuhr
- Analoge Uhr mit TFT 240×240 Pixeln und WiFi
- Uhrzeit auf LED-Matrix anzeigen
- Zeit mit time.h auf einem TFT anzeigen
- Zeit im Seriellen Monitor mit ESP-Mikrocontroller anzeigen
- Datum, Uhrzeit und Temperatur auf einem LCD mit einem RTC-Modul anzeigen
Letzte Aktualisierung:




