Arduino Echtzeituhr LED-Uhr: Zuverlässige Zeitanzeige selbst bauen
Komponenten und Zubehör
| Arduino UNO | × | 1 |
| RTC-Modul (DS1307 / DS3231) | × | 1 |
| Widerstand 1 kΩ | × | 15 |
| Widerstand 120 Ω | × | 15 |
| Spannungsregler 7805 (5 V) | × | 1 |
| Keramik-Kondensator 22 pF | × | 1 |
| Quarz 16 MHz | × | 1 |
| Elektrolytkondensator 10 µF | × | 1 |
| Knopfzelle CR2032 + Halter | × | 1 |
| 5 mm LED grün | × | 190 |
| NPN-Transistor (z. B. 2N2222) | × | 10 |
| PNP-Transistor (z. B. 2N2907) | × | 12 |
| Taster (4 Stück) | × | 4 |
| Netzteil 12 V / 5 A | × | 1 |
Benötigte Werkzeuge
- Lötkolben + Lötzinn (bleifrei)
- Digitales Multimeter
Über dieses Projekt
Zuerst folgende Bibliotheken herunterladen:
Wire.h(bereits in Arduino IDE enthalten)RTClib.h(von Adafruit / GitHub)
Video ansehen
Im Video wird der Aufbau Schritt für Schritt gezeigt.
RTC-Verdrahtung
Das RTC-Modul (DS1307/DS3231) wird über I2C (A4=SDA, A5=SCL) an den Arduino angeschlossen. Die Knopfzelle CR2032 sichert die Uhrzeit bei Stromausfall.
RTC-Schalter / Taster
Vier Taster dienen der Zeiteinstellung (Stunden, Minuten, 12/24h-Modus, Bestätigung).
Anode und Kathode identifizieren
Die 7-Segment-Anzeigen sind als Common Anode ausgeführt. Bei Common Cathode müssen die Logikpegel im Code invertiert werden (siehe unten).
Schaltplan (Common Anode)
Die 6-stellige 7-Segment-Anzeige wird multiplexet: 6 Ziffern (Digit 1–6) und 8 Segmente (A–G, DP) werden über Transistoren (NPN für Ziffern, PNP für Segmente) angesteuert.
Änderungen für Common Cathode
Im Code die Definitionen SEGMENT_ON / SEGMENT_OFF und DIGIT_ON / DIGIT_OFF vertauschen.
Netzteil
Ein 7805-Regler wandelt 12 V auf 5 V für Arduino und Logik. Die LEDs werden direkt aus der 12-V-Versorgung (über Vorwiderstände) gespeist, um Strom zu sparen.
Code
LED-Uhr Code (Arduino)
/* 4-stellige 7-Segment-Anzeige, multiplexed auf 6 Stellen Basierend auf SparkFun / niq_ro / BMIAK Basnayaka */ #include#include "RTClib.h" RTC_DS1307 RTC; // Pin-Belegung Segmente int segA = 0, segB = 1, segC = 2, segD = 4; int segE = 7, segF = 8, segG = 12, segDP = 13; // Ziffern-Pins (Common Anode -> HIGH = aus, LOW = an über PNP) int digit1 = 11, digit2 = 10, digit3 = 9; int digit4 = 6, digit5 = 5, digit6 = 3; // Taster byte SW0 = A0, SW1 = A2, SW2 = A1, SWT = A3; int Adhr = 0, Admnt = 0, D = 0, Z = 0; long zh, uh, ore, zm, um, miniti; void setup() { Wire.begin(); RTC.begin(); // RTC.adjust(DateTime(F(__DATE__), F(__TIME__))); // Einmalig zum Stellen aktivieren // SQW auf 1 Hz konfigurieren Wire.beginTransmission(0x68); Wire.write(0x07); Wire.write(0x10); // 1 Hz Square Wave Wire.endTransmission(); // Pins als Output for (int p : {segA, segB, segC, segD, segE, segF, segG, segDP, digit1, digit2, digit3, digit4, digit5, digit6}) { pinMode(p, OUTPUT); } // Taster mit Pullups for (byte sw : {SW0, SW1, SW2, SWT}) { pinMode(sw, INPUT); digitalWrite(sw, HIGH); } digitalWrite(segDP, LOW); } void loop() { DateTime now = RTC.now(); long HR = now.hour() * 1000; long timp = HR * 10 + now.minute() * 100 + now.second(); Adhr = now.hour(); Admnt = now.minute(); if (timp >= 250000) timp -= 240000; // 12/24h-Umschaltung per Taster SWT if (digitalRead(SWT) == 0) { delay(300); D = (D == 0) ? 1 : 0; } if (D == 0) { // 24h-Modus if (timp >= 130000) { timp -= 120000; digitalWrite(segDP, HIGH); // PM-Indikator } } else { // 12h-Modus if (timp >= 130000) digitalWrite(segDP, LOW); } // Zeit einstellen per SW0 (gedrückt halten) if (digitalRead(SW0) == 0) { delay(100); Z = 1; set_time(); } // Multiplexing: 6 Stellen nacheinander anzeigen for (int i = 100; i > 0; i--) { if (timp >= 100000) displayNumber01(timp); else displayNumber02(timp); } for (int i = 100; i > 0; i--) { if (timp >= 100000) displayNumber03(timp); else displayNumber04(timp); } for (int i = 100; i > 0; i--) { if (timp >= 100000) displayNumber05(timp); else displayNumber06(timp); } } void set_time() { byte hours = Adhr, minutes = Admnt; // BCD-Korrektur if ((hours & 0x0F) > 9) hours += 6; if (hours > 0x24) hours = 1; if ((minutes & 0x0F) > 9) minutes += 6; if (minutes > 0x59) minutes = 0; while (Z) { // Stunden einstellen (SW2) while (digitalRead(SW2) == 0) { hours++; if ((hours & 0x0F) > 9) hours += 6; if (hours > 0x24) hours = 1; // Anzeige aktualisieren... for (int i = 400; i > 0; i--) displayNumber01(/* berechneter Wert */); } // Minuten einstellen (SW1) while (digitalRead(SW1) == 0) { minutes++; if ((minutes & 0x0F) > 9) minutes += 6; if (minutes > 0x59) minutes = 0; for (int i = 400; i > 0; i--) displayNumber01(/* berechneter Wert */); } // In RTC schreiben Wire.beginTransmission(0x68); Wire.write(0); Wire.write(0x00); // Sekunden Wire.write(minutes); // Minuten Wire.write(0x80 | hours); // Stunden (24h, Bit7=1) Wire.write(0x06); Wire.write(0x01); Wire.write(0x05); Wire.write(0x09); // Tag, Datum, Monat, Jahr Wire.write(0x10); // Control: 1 Hz SQW Wire.endTransmission(); delay(100); if (digitalRead(SW0) == 0) Z = 0; delay(300); } } // Anzeigefunktionen für jede Ziffer (multiplexed) // displayNumber01 bis displayNumber06 steuern jeweils eine Ziffer // lightNumber(ziffer) setzt die Segmente (0-9, 10=aus) // Common Anode: SEGMENT_ON = HIGH, SEGMENT_OFF = LOW // DIGIT_ON = HIGH (PNP-Basis), DIGIT_OFF = LOW void displayNumber01(long toDisplay) { /* ... */ } void displayNumber02(long toDisplay) { /* ... */ } void displayNumber03(long toDisplay) { /* ... */ } void displayNumber04(long toDisplay) { /* ... */ } void displayNumber05(long toDisplay) { /* ... */ } void displayNumber06(long toDisplay) { /* ... */ } void lightNumber(int numberToDisplay) { #define SEGMENT_ON HIGH #define SEGMENT_OFF LOW // Für Common Cathode: #define SEGMENT_ON LOW / #define SEGMENT_OFF HIGH switch (numberToDisplay) { case 0: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_OFF); break; case 1: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; case 2: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break; case 3: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break; case 4: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 5: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 6: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 7: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; case 8: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 9: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 10: // Alle aus digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; } }
Schaltplan

Herstellungsprozess
- Arduino POV-Uhr: Persistence-of-Vision LED-Display selbst bauen
- DIY Arduino Word Clock – Elegante Wortuhr mit RTC & Schieberegistern
- 20-kHz-Arduino-Oszilloskop mit Nokia 5110 LCD – Einfacher DIY-Bau
- Einen eigenen LED-Master-Clock mit Alarm bauen – aus 12 Metern Entfernung ablesbar
- Intelligente Jalousien: Automatische Lichtsteuerung mit Arduino & Solarenergie
- Italienische Word Clock mit Arduino Nano, NeoPixel, LCD & RTC
- LED per Bluetooth mit Arduino steuern – Einfache DIY-Anleitung
- Intelligenten Arduino-Vierbeiner-Roboter bauen: Schritt-für-Schritt-Anleitung
- Präzise 7-Segment-Uhr mit Arduino Pro Mini & DS1302 RTC – Selbstbau
- Isolierter Analogeingang für Arduino: Spannung/Strom galvanisch trennen