DS3231 RTC Echtzeituhr mit Arduino: Weckalarm & Datenlogger mit Zeitstempel
Der interne Timer des Arduino ist ungenau und vergisst nach jedem Stromausfall die Uhrzeit komplett. Das DS3231 RTC-Modul (Real Time Clock) löst beide Probleme: Ein Quarzoszillator mit Temperaturkompensation hält die Zeit auf ±2 Minuten pro Jahr genau, und eine kleine Pufferbatterie sorgt dafür, dass die Uhr auch ohne Strom weiterläuft. In diesem Tutorial stellst du die Uhr, baust einen Weckalarm per Interrupt und erweiterst deinen SD-Karten-Logger um echte Zeitstempel.
Warum eine externe Echtzeituhr?
Der Arduino selbst hat keine "Ahnung" von der Uhrzeit – millis() zählt nur die Millisekunden seit dem letzten Reset und läuft nach rund 50 Tagen über. Für alles, was ein echtes Datum und eine echte Uhrzeit braucht (Datenlogger mit Zeitstempel, Wecker, Zeitschaltuhren, Zutrittskontrollen mit Protokoll), reicht das nicht aus.
Das DS3231 ist dafür der Quasi-Standard unter den Maker-RTCs: Anders als das ältere DS1307 hat es einen eingebauten, temperaturkompensierten Quarz direkt im Chip integriert – keine externe Bauteiltoleranz, keine Nachjustierung nötig. Zusätzlich bringt das Modul einen AT24C32 EEPROM-Baustein (32Kbit freier Speicher) und einen eingebauten Temperatursensor mit, den du kostenlos mitnutzen kannst.
Über den Programmierbaren Interrupt-Pin (SQW) kann das DS3231 sogar den Arduino aus dem Sleep-Modus wecken oder zu einer festgelegten Uhrzeit ein Signal auslösen – ganz ohne dass der Mikrocontroller die ganze Zeit mitzählen muss.
Was du brauchst
| Bauteil | Menge | ca. Preis | Link |
|---|---|---|---|
| DS3231 RTC-Modul mit AT24C32 EEPROM | 1x | ab 2,49 € | Zum Produkt |
| UNO R3 Board | 1x | ab 4,99 € | Zum Produkt |
| Micro SD Card Reader Modul (für Logger-Projekt) | 1x | ab 1,19 € | Zum Produkt |
| Breadboard 400 Kontakte | 1x | ab 3,49 € | Zum Produkt |
Installiere zusätzlich über den Bibliotheksverwalter der Arduino IDE die Bibliothek RTClib von Adafruit – sie deckt DS3231, DS1307 und weitere RTC-Chips mit einer einheitlichen API ab.
Schaltungsaufbau
| DS3231 Pin | UNO R3 Pin | Funktion |
|---|---|---|
| VCC | 5V | Spannungsversorgung |
| GND | GND | Masse |
| SDA | A4 | I2C Datenleitung |
| SCL | A5 | I2C Taktleitung |
| SQW | Pin 2 (für Interrupt-Beispiel) | Alarm-/Interrupt-Signal |
Das Modul spricht I2C und teilt sich die Pins A4/A5 problemlos mit anderen I2C-Sensoren wie dem BMP280 oder OLED-Display – alle Geräte hängen einfach parallel an derselben Datenleitung, solange sie unterschiedliche I2C-Adressen haben.
Code 1: Uhrzeit setzen und auslesen
Beim allerersten Programmlauf stellst du die Uhr auf die Kompilierzeit deines Sketches. Danach läuft sie eigenständig weiter, auch nach einem Reset oder Stromausfall.
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
void setup() {
Serial.begin(9600);
if (!rtc.begin()) {
Serial.println("DS3231 nicht gefunden - Verkabelung pruefen!");
while (true) delay(100);
}
if (rtc.lostPower()) {
Serial.println("RTC hat Zeit verloren, stelle auf Kompilierzeit...");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
DateTime jetzt = rtc.now();
Serial.print(jetzt.year());
Serial.print("-");
Serial.print(jetzt.month());
Serial.print("-");
Serial.print(jetzt.day());
Serial.print(" ");
Serial.print(jetzt.hour());
Serial.print(":");
Serial.print(jetzt.minute());
Serial.print(":");
Serial.println(jetzt.second());
delay(1000);
}
So funktioniert's
rtc.lostPower() prüft, ob die Pufferbatterie leer war oder das Modul frisch angeschlossen wurde – nur dann wird die Uhr neu gestellt. So verhinderst du, dass jeder Neustart des Arduino die Uhrzeit versehentlich zurücksetzt.
Code 2: Weckalarm per Interrupt (SQW-Pin)
Statt ständig rtc.now() abzufragen, kann das DS3231 selbst zu einer festgelegten Uhrzeit den SQW-Pin auf LOW ziehen und so einen Hardware-Interrupt auf dem Arduino auslösen – ideal für stromsparende Wecker- oder Zeitschaltuhr-Projekte.
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
const int PIN_SQW = 2;
volatile bool alarmAusgeloest = false;
void alarmInterrupt() {
alarmAusgeloest = true;
}
void setup() {
Serial.begin(9600);
pinMode(PIN_SQW, INPUT_PULLUP);
if (!rtc.begin()) {
Serial.println("DS3231 nicht gefunden!");
while (true) delay(100);
}
rtc.clearAlarm(1);
rtc.writeSqwPinMode(DS3231_OFF); // SQW-Pin fuer Alarm freigeben statt Rechtecksignal
// Alarm auf eine feste Uhrzeit setzen, z.B. 07:30:00 taeglich
rtc.setAlarm1(DateTime(0, 0, 0, 7, 30, 0), DS3231_A1_Hour);
attachInterrupt(digitalPinToInterrupt(PIN_SQW), alarmInterrupt, FALLING);
Serial.println("Alarm scharf - wartet auf 07:30 Uhr");
}
void loop() {
if (alarmAusgeloest) {
Serial.println("ALARM! Es ist 07:30 Uhr");
rtc.clearAlarm(1);
alarmAusgeloest = false;
}
}
Die Interrupt Service Routine (ISR) setzt bewusst nur ein volatile bool-Flag, statt direkt Serial.println() aufzurufen – seriellen Output innerhalb einer ISR auszuführen kann zu Instabilität führen. Die eigentliche Reaktion erfolgt sicher im normalen loop().
Code 3: Datenlogger mit echtem Zeitstempel
Kombiniere das DS3231 mit dem Micro-SD-Kartenmodul aus unserem Datenlogger-Tutorial, um jede Messung mit echtem Datum und Uhrzeit statt einer bloßen Zählernummer zu protokollieren.
#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>
#define SD_CHIP_SELECT 4
RTC_DS3231 rtc;
void setup() {
Serial.begin(9600);
if (!rtc.begin()) {
Serial.println("DS3231 nicht gefunden!");
while (true) delay(100);
}
if (!SD.begin(SD_CHIP_SELECT)) {
Serial.println("SD-Karte nicht gefunden!");
while (true) delay(100);
}
if (!SD.exists("zeit_log.csv")) {
File datei = SD.open("zeit_log.csv", FILE_WRITE);
if (datei) {
datei.println("Datum,Uhrzeit,Sensorwert");
datei.close();
}
}
Serial.println("Logger mit Zeitstempel bereit");
}
void loop() {
DateTime jetzt = rtc.now();
float platzhalterWert = rtc.getTemperature(); // eingebauter Temperatursensor als Beispielwert
File datei = SD.open("zeit_log.csv", FILE_WRITE);
if (datei) {
char zeile[64];
sprintf(zeile, "%04d-%02d-%02d,%02d:%02d:%02d,%.2f",
jetzt.year(), jetzt.month(), jetzt.day(),
jetzt.hour(), jetzt.minute(), jetzt.second(),
platzhalterWert);
datei.println(zeile);
datei.close();
Serial.println(zeile);
} else {
Serial.println("Fehler beim Schreiben auf SD-Karte!");
}
delay(60000); // jede Minute eine Zeile
}
rtc.getTemperature() nutzt den im DS3231-Chip eingebauten Temperatursensor, der eigentlich zur internen Quarzkompensation dient – als grober Zusatzwert (±3°C Genauigkeit) taugt er aber durchaus für einfache Übersichten, ersetzt jedoch keinen dedizierten Sensor wie den DS18B20 oder BMP280.
Praxistipps
🔋 Pufferbatterie prüfen: Die meisten Module kommen mit einer CR2032-Knopfzelle. Miss sie mit einem Multimeter, falls rtc.lostPower() nach jedem Neustart true zurückgibt – oft ist einfach die Batterie leer oder von Werk aus nicht kontaktiert.
🌐 Sommerzeit selbst behandeln: Das DS3231 kennt keine Zeitzonen oder Sommerzeit-Umstellung. Für Projekte, die das brauchen, rechnest du die Umstellung in Software oder synchronisierst stattdessen per NTP über WLAN (z. B. mit einem ESP32).
📅 Zweiten Alarm nutzen: Das DS3231 hat zwei unabhängige Alarme (Alarm 1 und Alarm 2) – praktisch, um z. B. einen täglichen Weckalarm und einen wöchentlichen Erinnerungsalarm parallel zu verwalten.
Troubleshooting
⚠️ "DS3231 nicht gefunden": Prüfe zuerst SDA/SCL auf Vertauschung – das ist der häufigste Verkabelungsfehler bei I2C-Modulen. Ein I2C-Scanner-Sketch (im Internet leicht zu finden) zeigt dir die tatsächlich erkannte Adresse (normalerweise 0x68).
⚠️ Uhrzeit setzt sich bei jedem Start zurück: Das rtc.adjust() im obigen Code sollte nur einmalig laufen, wenn lostPower() wahr ist. Falls du es versehentlich unbedingt aufrufst, wird die Uhr bei jedem Reset auf die Kompilierzeit des Sketches zurückgesetzt.
⚠️ Interrupt löst nie aus: Kontrolliere, dass rtc.writeSqwPinMode(DS3231_OFF) gesetzt ist – solange der SQW-Pin im Standard-Rechtecksignal-Modus läuft, kann er keine Alarme auslösen. Prüfe außerdem, dass der SQW-Pin per INPUT_PULLUP konfiguriert ist, da er als Open-Drain-Ausgang arbeitet.
⏱️ Baue dein Zeit-Projekt
Alle Bauteile für dieses Tutorial findest du bei MAKEROO.
- Sensoren & Module – DS3231, SD-Kartenmodul & mehr
- Mikrocontroller-Boards – UNO R3, Nano V3 und ESP32
Kombiniere das DS3231 mit unserem Datenlogger-Tutorial für lückenlose Zeitstempel.
Fazit
Das DS3231 macht aus jedem Arduino-Projekt eine zuverlässige Uhr mit Batteriepufferung – ohne Nachjustieren, ohne Zeitverlust nach einem Stromausfall. Von der einfachen Zeitanzeige über den interruptbasierten Weckalarm bis zum zeitgestempelten Datenlogger deckt dieses Tutorial die wichtigsten Anwendungsfälle für präzises Zeitmanagement in deinen eigenen Projekten ab.