Überblick

Der Arduino kann nur ab dem Zeitpunkt des Einschaltens die Zeit messen. Das aktuelle Datum und die Zeit kann nur mit einem RTC-Modul (RealTimeClock) gesetzt und gelesen werden. Beim ersten Start muss das aktuelle Datum und die aktuelle Zeit manuell gesetzt werden, anschließend läuft die Zeit mit Hilfe der Batterie weiter. Das hier verwendete Modul DS3231 misst zusätzlich die Temperatur.
Angeschlossen wird das Modul über ⇒I²C. Wird der SQW-Pin mit einem Interrupt-Pin verbunden können Alarmfunktionen genutzt werden.

Wenn das Modul nicht mit Strom versorgt ist, kann die Batterie (C2032) die Uhrzeit bis zum nächsten Einschalten puffern. Allerdings verfügt das DS3231-Modul über eine Ladefunktion für die Batterie. Wenn das Modul mit Strom versorgt wird, sollte die Batterie entfernt oder eine wieder aufladbare Knopfzelle verwendet werden.
Der Schaltplan
Benötigte Bibliothek
Sketch -> Bibliothek einbinden -> Bibliotheken verwalten

Funktionen der Bibliothek Adafruit RTClib DS3231
| Schlüsselwort | Anzeige/Parameter |
|---|---|
| begin() | Modul initialisieren |
| now() | aktuelle Zeit holen |
| adjust(DateTime(Jahr Monat, Tag, Stunde, Minute, Sekunde) | Beispiel: rtc.adjust(DateTime(2025, 4, 17, 10, 31, 30)); |
| dayOfTheWeek() | Nummer des Wochentages 0 = Sonntag 1 = Montag . . . 6 = Samstag |
| day() | Tag |
| month() | Monat 1 = Januar 2 = Februar ... 12 = Dezember |
| year() | Jahr |
| hour() | Stunde |
| minute()) | Minute |
| second()) | Sekunde |
| Uhrzeit als Array definieren: char Zeit[] = "Uhrzeit: hh:mm:ss" print(aktuell.toString(Zeit)) | hh = Stunden mm = Minuten ss = Sekunden |
| Datum als Array definieren: char Datum[] = "DD.MM.YYYY" print(aktuell.toString(Datum)) | DD = Tag MM = Monat YYYY = 4-stelliges Jahr |
| getTemperature() | Temperatur ermitteln |
| lostpower() | untersucht, ob das Modul zwischenzeitlich nicht mit Strom versorgt wurde |
| disableAlarm(1) disableAlarm(2) | Alarm 1/2 deaktivieren |
| disable32K(); | 32K-Pin am DS3231 deaktivieren |
| setAlarm1() setAlarm2() | Alarm (1/2) setzen |
| alarmFired(1) alarmFired(2) | Status des Alarms (1/2) ermitteln |
| writeSqwPinMode(DS3231_OFF) | SQW Pin-Mode setzen |
Die Zeit kann mit unterschiedlichen Methoden gesetzt werden, leider sind beide nicht genau:
- mit der Angabe von Datum und Uhrzeit:
rtc.adjust(DateTime(2025, 4, 17, 10, 30, 30));
Format: Jahr, Monat, Tag, Stunde, Minute, Sekunden
Man muss dann sofort nach der Festlegung das Programm kompilieren, die Uhr wird vermutlich etwas vor- oder nachgehen, je nachdem wie gut die Zeit zwischen der Änderung und dem Abschluss der Kompilierung geschätzt wurde.
Vor der nächsten Kompilierung muss die Zeile entfernt werden. - mit der Zeit zu der das Programm kompiliert wurde:
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
Solange die Zeit des Computers mit einem Zeitserver synchronisiert wurde, wird die Uhrzeit lediglich ein wenig nachgehen.
Zeit anzeigen

|
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 |
#include "RTClib.h" // Name des RTC-Moduls RTC_DS3231 rtc; void setup() { // Serial starten Serial.begin(9600); delay(1000); // RTC-Modul starten if (!rtc.begin()) { Serial.println("RTC nicht verbunden"); Serial.println("Programm wird beendet!"); while (1); } else Serial.println("RTC verbunden!"); // Zeitpunkt des Kompilierens als aktuelle Zeit setzen rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } void loop() { // aktuelle Zeit holen DateTime aktuell = rtc.now(); char Datum[] = "DD.MM.YYYY "; Serial.print(aktuell.toString(Datum)); // Jahr anzeigen Serial.print(String(aktuell.year())); char Zeit[] = " Uhrzeit: hh:mm:ss "; Serial.print(aktuell.toString(Zeit)); // gemessene Temperatur in String umwandeln // int -> nur ganzzahlige Werte String Temperatur = String(rtc.getTemperature()); Temperatur.replace(".", ","); // Temperatur anzeigen Serial.println("Temperatur: " + Temperatur + "°C "); delay(1000); } |
Erweiterte Version mit Anzeige der Namen der Wochentage und der Monatsnamen:

Das dazugehörige Programm:
|
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 |
#include "RTClib.h" // Name des RTC-Moduls RTC_DS3231 rtc; void setup() { Serial.begin(9600); delay(1000); // RTC-Modul starten if (!rtc.begin()) { Serial.println("RTC nicht verbunden"); Serial.println("Programm wird beendet!"); while (1); } else Serial.println("RTC verbunden!"); /* wenn Datum und Zeit nicht korrekt -> Datum/Zeit setzen Jahr, Monat, Tag, Stunde, Minute, Sekunde Beispiel: 2024 Mai 5. 10 Uhr 30 Minuten 30 Sekunden rtc.adjust(DateTime(2024, 5, 5, 10, 30, 30)); alternativ: rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); */ rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } void loop() { // aktuelle Zeit holen DateTime aktuell = rtc.now(); /* Wochentag anzeigen 0 = Sonntag 1 = Montag ... 6 = Samstag */ switch (aktuell.dayOfTheWeek()) { case 0: Serial.print("Sonntag"); break; case 1: Serial.print("Montag"); break; case 2: Serial.print("Dienstag"); break; case 3: Serial.print("Mittwoch"); break; case 4: Serial.print("Donnerstag"); break; case 5: Serial.print("Donnerstag"); break; case 6: Serial.print("Samstag"); break; } // Leerzeichen hinzufügen Serial.print(" "); // Datum anzeigen Serial.print(String(aktuell.day()) + "."); /* Monatsnamen anzeigen 1= Januar 2 = Februar ... 12 = Dezember */ Serial.print(" "); switch (aktuell.month()) { case 1: Serial.print("Januar"); break; case 2: Serial.print("Februar"); break; case 3: Serial.print("M\u00e4rz"); break; case 4: Serial.print("April"); break; case 5: Serial.print("Mai"); break; case 6: Serial.print("Juni"); break; case 7: Serial.print("Juli"); break; case 8: Serial.print("August"); break; case 9: Serial.print("September"); break; case 10: Serial.print("Oktober"); break; case 11: Serial.print("November"); break; case 12: Serial.print("Dezember"); break; } Serial.print(" "); Serial.print(String(aktuell.year()) + " "); // Zeitangabe in Zeichenkette (String) umwandeln und anzeigen char Zeit[] = "hh:mm:ss"; Serial.print("Uhrzeit: "); Serial.print(aktuell.toString(Zeit)); // Temperatur ermitteln String Temperatur = String(rtc.getTemperature(), 1); // Anzeige im angelsächsisches Zahlenformat // . durch , ersetzen Temperatur.replace(".", ","); Serial.println(" Temperatur: " + Temperatur + "°C"); delay(1000); } |
Alarmfunktion nutzen
Der DS3231 verfügt über eine Alarmfunktion und es können zwei Alarme konfiguriert werden:
A1 Alarmfunktion
| Parameter | Alarm wenn ... |
|---|---|
| DS3231_A1_PerSecond | jede Sekunde |
| DS3231_A1_Second | die Sekunden passen |
| DS3231_A1_Minute | Minuten und Sekunden passen |
| DS3231_A1_Hour | Stunden, Minuten und Sekunden passen |
| DS3231_A1_Date | Tag, Stunden, Minuteen und Sekunden passen |
| DS3231_A1_Day | Wochentag, Stunden, Minuteen und Sekunden passen |
Alarm zur vollen Minute
|
1 2 |
DateTime ZeitAlarm1 (aktuell.hour(), aktuell.minute(), 0); rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Second); |

|
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 |
#include "RTClib.h" // 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; void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial) {;} delay(1000); rtc.begin(); 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), AlarmStarten, FALLING); // Alarm1 löschen, Alarm2 deaktivieren rtc.clearAlarm(1); rtc.disableAlarm(2); rtc.writeSqwPinMode(DS3231_OFF); // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Alarm1 jede volle Minute (0 Sekunden) setzen DateTime ZeitAlarm1 (aktuell.hour(), aktuell.minute(), 0); // Alarm setzen rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Second); } void loop() { // aktuelle Zeit lesen DateTime aktuell = rtc.now(); char Zeit[] = "Uhrzeit: hh:mm:ss"; Serial.println(aktuell.toString(Zeit)); if (Alarm) { if(rtc.alarmFired(1)) { Serial.println("Alarm 1 ausgelöst"); // Alarm1 löschen rtc.clearAlarm(1); } } delay(1000); } void AlarmStarten() { Alarm = true; } |
Alarm stündlich alle 15 Minuten
|
1 2 |
DateTime ZeitAlarm1 (aktuell.year(), aktuell.month(), aktuell.day(), aktuell.hour(), 15, 0); rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Minute); |
|
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 |
#include "RTClib.h" // 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; void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial) {;} delay(1000); rtc.begin(); 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), AlarmStarten, FALLING); // Alarm1 löschen, Alarm2 deaktivieren rtc.clearAlarm(1); rtc.disableAlarm(2); rtc.writeSqwPinMode(DS3231_OFF); // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Alarm1 stündlich nach 15 Minuten setzen DateTime ZeitAlarm1 (aktuell.year(), aktuell.month(), aktuell.day(), aktuell.hour(), 15, 0); // Alarm setzen rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Minute); } void loop() { // aktuelle Zeit lesen DateTime aktuell = rtc.now(); char Zeit[] = "Uhrzeit: hh:mm:ss"; Serial.println(aktuell.toString(Zeit)); if (Alarm) { if(rtc.alarmFired(1)) { Serial.println("Alarm 1 ausgelöst"); // Alarm1 löschen rtc.clearAlarm(1); } } delay(1000); } void AlarmStarten() { Alarm = true; } |
Alarm an einem Tag des Monats
Der Alarm wird am aktuellen Tag ausgelöst. Wenn du einen anderen Tag festlegen willst, musst du aktuell.month() und aktuell.day() durch Zahlen ersetzen.
|
1 2 |
DateTime ZeitAlarm1 (aktuell.year(), aktuell.month(), aktuell.day(), 9, 0, 0); rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Date); |
|
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 |
#include "RTClib.h" // 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; void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial) {;} delay(1000); rtc.begin(); 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), AlarmStarten, FALLING); // Alarm1 löschen, Alarm2 deaktivieren rtc.clearAlarm(1); rtc.disableAlarm(2); rtc.writeSqwPinMode(DS3231_OFF); // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Alarm1 an bestimmten Datum setzen // aktueller Tag (oder bestimmter Tag), Stunden, Minuten, Sekunden DateTime ZeitAlarm1 (aktuell.year(), aktuell.month(), aktuell.day(), 9, 0, 0); // Alarm setzen rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Date); } void loop() { // aktuelle Zeit lesen DateTime aktuell = rtc.now(); char Zeit[] = "Uhrzeit: hh:mm:ss"; Serial.println(aktuell.toString(Zeit)); if (Alarm) { if(rtc.alarmFired(1)) { Serial.println("Alarm 1 ausgelöst"); // Alarm1 löschen rtc.clearAlarm(1); } } delay(1000); } void AlarmStarten() { Alarm = true; } |
Alarm täglich wiederholen
|
1 2 |
DateTime ZeitAlarm1 (aktuell.year(), aktuell.month(), aktuell.dayOfTheWeek(), 7, 0, 0); rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Hour); |
|
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 |
#include "RTClib.h" // 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; void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial) {;} delay(1000); rtc.begin(); 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), AlarmStarten, FALLING); // Alarm1 löschen, Alarm2 deaktivieren rtc.clearAlarm(1); rtc.disableAlarm(2); rtc.writeSqwPinMode(DS3231_OFF); // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Alarm1 täglich wiederholen DateTime ZeitAlarm1 (aktuell.year(), aktuell.month(), aktuell.dayOfTheWeek(), 7, 0, 0); // Alarm setzen rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Hour); } void loop() { // aktuelle Zeit lesen DateTime aktuell = rtc.now(); char Zeit[] = "Uhrzeit: hh:mm:ss"; Serial.println(aktuell.toString(Zeit)); if (Alarm) { if(rtc.alarmFired(1)) { Serial.println("Alarm 1 ausgelöst"); // Alarm1 löschen rtc.clearAlarm(1); } } delay(1000); } void AlarmStarten() { Alarm = true; } |
A2 Alarmfunktion
| Parameter | Alarm wenn ... |
|---|---|
| DS3231_A2_PerMinute | jwenn Sekunden = 0 jede Minute |
| DS3231_A2_Minute | die Minuten passen |
| DS3231_A2_Hour | Stunden und Minuten passen |
| DS3231_A2_Date | Tag, Stunden, Minuteen und Sekunden passen |
| DS3231_A2_Day | Wochentag, Stunden, Minuteen und Sekunden passen |
A1 und A2 gleichzeitig nutzen
Mit TimeSpan kann ein Alarm in der Zukunft definiert werden
|
1 2 3 4 5 |
// Alarm in 10 Sekunden (nur A1) rtc.setAlarm1(rtc.now() + TimeSpan(10), DS3231_A1_Second); // Alarm in 1 Minute (zur nächsten vollen Minute) rtc.setAlarm2(rtc.now() + TimeSpan(0, 0, 1, 0), DS3231_A2_Minute); |
|
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 |
#include "RTClib.h" // 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; void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial) {;} delay(1000); rtc.begin(); 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), AlarmStarten, FALLING); // Alarm1 löschen, Alarm2 deaktivieren rtc.clearAlarm(1); rtc.disableAlarm(2); rtc.writeSqwPinMode(DS3231_OFF); // aktuelle Zeit lesen DateTime aktuell = rtc.now(); // Alarm1 täglich wiederholen DateTime ZeitAlarm1 (aktuell.year(), aktuell.month(), aktuell.dayOfTheWeek(), 7, 0, 0); // Alarm setzen rtc.setAlarm1(ZeitAlarm1, DS3231_A1_Hour); } void loop() { // aktuelle Zeit lesen DateTime aktuell = rtc.now(); char Zeit[] = "Uhrzeit: hh:mm:ss"; Serial.println(aktuell.toString(Zeit)); if (Alarm) { if(rtc.alarmFired(1)) { Serial.println("Alarm 1 ausgelöst"); // Alarm1 löschen rtc.clearAlarm(1); } // nach 1 Minute rtc.setAlarm2(rtc.now() + TimeSpan(0,0,1,0), DS3231_A2_Minute); if(rtc.alarmFired(2)) { Serial.println("Alarm 2 ausgelöst"); rtc.clearAlarm(2); } } delay(1000); } void AlarmStarten() { Alarm = true; } |
Quelle
Letzte Aktualisierung: