Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Arduino Nano Echtzeituhr (RTC) mit DS1307 – Präzise Zeitmessung

Komponenten und Materialien

Bauteil Menge Hinweise
Arduino Nano R3 1
Real Time Clock (RTC) Modul DS1307 1 Modul auf DS1307-Basis erleichtert den Aufbau erheblich. Selbstbau ist aber auch einfach möglich.
4-stelliges 7-Segment-LED-Display 1 Common Anode (gemeinsame Anode)
Female Header Single Row 3
Lochrasterplatine (Perforated Board) 1 Für sauberes Löten empfohlen. Am besten eine Platine mit Breadboard-ähnlichen Leiterbahnen.
Jumper-Kabel (generisch) 25
Male Header 40-polig 1 Reihe (2,54 mm) 1

Benötigte Werkzeuge und Maschinen

Apps und Online-Dienste

Über dieses Projekt

Dies ist eine wirklich einfache, leicht aufzubauende Digitaluhr mit dem RTC-Baustein DS1307. Sie zeigt die Zeit auf einem 4-stelligen 7-Segment-Display an. Der Code lässt sich leicht erweitern – z. B. um eine Weckfunktion – alles was du brauchst, ist etwas Fantasie und Einfallsreichtum. Das Projekt diente als Sprungbrett für komplexere Vorhaben, außerdem wollte ich etwas Cooles für mein Zimmer bauen.

Ich werde jedes Detail dokumentieren, inklusive der Probleme beim Löten auf der Platine und deren Lösungen.

Schritt 1: Komponenten

RTC-Modul (DS1307)

Arduino Nano Echtzeituhr (RTC) mit DS1307 – Präzise Zeitmessung

Der DS1307-Chip ist hervorragend, da er die Zeit auch bei Stromausfall behält (Pufferbatterie). Die Anbindung an den Arduino ist einfach, es gibt viele Libraries. Die Kommunikation läuft über I²C-Protokoll – auf dem Arduino Nano sind das Pins A4 (SDA) und A5 (SCL). Den DS-Pin benötigen wir nicht.

Nachteil: Die Genauigkeit ist nicht optimal. Der Chip neigt zu Zeitabweichungen (Drift), stark temperaturabhängig.

WICHTIG: Achte auf korrekte Polung von GND und Vcc. Auf dem Modul liegt Vcc vor GND. Ich habe mehrmals versehentlich vertauscht – der Chip wird extrem heiß. Tipp: Beim Einschalten die Knopfzelle berühren und sofort ausschalten, wenn sie warm wird.

Schieberegister (74HC595)

Arduino Nano Echtzeituhr (RTC) mit DS1307 – Präzise Zeitmessung

Hinweis: Die Chips sind generell zuverlässig, aber ich hatte mehrere defekte Exemplare: Q0/Q1 funktionsunfähig, Q3 intern auf GND gezogen (Fertigungsfehler). Meine aktuellen Chips sind auch nicht perfekt – einer hat defektes Q7. Exaktes Verdrahten und Durchgangsprüfung mit dem Multimeter sind Pflicht. Alles Teil des Lernprozesses.

4-stelliges 7-Segment-Display

Arduino Nano Echtzeituhr (RTC) mit DS1307 – Präzise Zeitmessung
Arduino Nano Echtzeituhr (RTC) mit DS1307 – Präzise Zeitmessung

Verwendetes Display: Generisches 4-stelliges Common Anode (gemeinsame Anode). 12 Pins, Nummerierung von links unten nach links oben. Jedes Segment zeigt eine Ziffer und einen Dezimalpunkt. Da kein Doppelpunkt (typisch für Uhren) vorhanden ist, nutze ich den Dezimalpunkt der zweiten Ziffer als Blinktrenner. Ideal für reine Ziffernanzeige.

WICHTIG: Für Anfänger knifflig, da Segmente a–g nicht linear angeordnet sind. Vorsicht beim Anschließen – niemals direkt an 5 V ohne Vorwiderstand!

Ein Schaltplan ist enthalten und selbsterklärend. Da der Schaltplan ein anderes Display zeigt, hier meine Pin-Belegung Schieberegister → Display:

Segment Display Pin Schieberegister Pin
A1115 (1. 595)
B71 (1. 595)
C42 (1. 595)
D23 (1. 595)
E14 (1. 595)
F105 (1. 595)
G56 (1. 595)
Dezimal37 (1. 595)
D1 (Ziffer 1)1215 (2. 595)
D2 (Ziffer 2)91 (2. 595)
D3 (Ziffer 3)82 (2. 595)
D4 (Ziffer 4)63 (2. 595)

Das Projekt ist günstig und einfach, erfordert aber Geduld und Ausdauer (besonders beim Löten auf der Platine). Zum reinen Ausprobieren auf dem Steckbrett brauchst du kaum 2 Stunden.

Feedback zur Verbesserung oder unklaren Stellen ist willkommen!

Code

Hauptprogramm – Clock Code (Arduino)

Benötigt die RTC-Library und die I²C-Library (Wire.h). Für Common Anode Displays.

#include <Wire.h>
#include <EEPROM.h>
#include <RTClib.h>

RTC_DS1307 RTC;

int temp, inc, hours1, minut, add = 11;
int HOUR, MINUT, SECOND;
int latchPin = 3;   // Pin 12 am 595 (OE)
int dataPin  = 4;   // Pin 14 am 595 (DS)
int clockPin = 2;   // Pin 11 am 595 (SH_CP)
int shift = 256;
int units, tens, hundreds, thousands;
int x, y;
const int alarmHour = 17;
const int alarmMinute = 26;

void setup() {
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(13, OUTPUT); // Alarm-LED
  Wire.begin();
  RTC.begin();
  if (!RTC.isrunning()) {
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}

void loop() {
  int temp = 0, val = 1, temp4;
  DateTime now = RTC.now();
  HOUR = now.hour();
  MINUT = now.minute();

  // Stunden aufsplitten
  if (HOUR < 10) {
    hundreds = HOUR;
    thousands = HOUR / 10;
  } else {
    hundreds = HOUR % 10;
    thousands = HOUR / 10;
  }
  // Minuten aufsplitten
  if (MINUT <= 9) {
    units = MINUT;
    tens = MINUT / 10;
  } else {
    units = MINUT % 10;
    tens = MINUT / 10;
  }

  // Ziffer 1: Einer Minuten (units) - 2. 595, Q0-Q7
  writeDigit(units, shift * 8);
  delay(1);
  // Ziffer 2: Zehner Minuten (tens) - 2. 595, Q0-Q7
  writeDigit(tens, shift * 4);
  delay(1);
  // Ziffer 3: Einer Stunden (hundreds) - 2. 595, Q0-Q7
  writeDigit(hundreds, shift * 2);
  delay(1);
  // Ziffer 4: Zehner Stunden (thousands) - 2. 595, Q0-Q7
  writeDigit(thousands, shift);
  delay(1);

  // Alarm-Sektion
  if (HOUR == alarmHour && MINUT == alarmMinute) {
    digitalWrite(13, HIGH);
  } else {
    digitalWrite(13, LOW);
  }
}

// Hilfsfunktion: Ziffer auf 7-Segment ausgeben (Common Anode)
void writeDigit(int digit, int digitSelect) {
  // Segment-Codes für Common Anode (LOW = an)
  const uint8_t seg[10] = {
    0b11000000, // 0
    0b11111001, // 1
    0b10100100, // 2
    0b10110000, // 3
    0b10011001, // 4
    0b10010010, // 5
    0b10000010, // 6
    0b11111000, // 7
    0b10000000, // 8
    0b10010000  // 9
  };
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, digitSelect >> 8);  // 2. 595: Ziffer wählen
  shiftOut(dataPin, clockPin, MSBFIRST, seg[digit]);        // 1. 595: Segmente
  digitalWrite(latchPin, HIGH);
}

Hinweis: Der ursprüngliche Code enthielt repetitive switch-case-Blöcke für jede Ziffer. Die obige Version nutzt eine kompakte Hilfsfunktion writeDigit() mit Lookup-Tabelle für bessere Lesbarkeit und Wartbarkeit.

Zeit einstellen – Set the time (Arduino)

Da der DS1307 zur Drift neigt, erlaubt dieses Programm die Zeiteinstellung über den Serial Monitor. RTC-Modul anschließen, Programm hochladen, Serial Monitor öffnen, korrektes Datum/Uhrzeit eingeben. Danach das Hauptprogramm (Clock Code) hochladen – die korrekte Zeit wird angezeigt.

/* RealTimeClockDS1307 Library - Beispiel zum Setzen der Zeit */
#include <Wire.h>
#include <RealTimeClockDS1307.h>

RealTimeClockDS1307 RTC;
#define DISPLAY_EVERY_N_SECONDS 1
#define HELP_EVERY_N_SECONDS 25
int count = 0;
char formatted[] = "00-00-00 00:00:00x";

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) processCommand();
  delay(1000);
  RTC.readClock();
  count++;
  if (count % DISPLAY_EVERY_N_SECONDS == 0) {
    Serial.print(count); Serial.print(": ");
    RTC.getFormatted(formatted);
    Serial.print(formatted); Serial.println();
  }
  if (count % HELP_EVERY_N_SECONDS == 0) {
    Serial.println("Send ? for a list of commands.");
  }
}

void processCommand() {
  if (!Serial.available()) return;
  char cmd = Serial.read();
  int in, in2;
  switch (cmd) {
    case 'h': case 'H': in = SerialReadPosInt(); RTC.setHours(in); RTC.setClock(); Serial.print("Setting hours to "); Serial.println(in); break;
    case 'i': case 'I': in = SerialReadPosInt(); RTC.setMinutes(in); RTC.setClock(); Serial.print("Setting minutes to "); Serial.println(in); break;
    case 's': case 'S': in = SerialReadPosInt(); RTC.setSeconds(in); RTC.setClock(); Serial.print("Setting seconds to "); Serial.println(in); break;
    case 'y': case 'Y': in = SerialReadPosInt(); RTC.setYear(in); RTC.setClock(); Serial.print("Setting year to "); Serial.println(in); break;
    case 'm': case 'M': in = SerialReadPosInt(); RTC.setMonth(in); RTC.setClock(); Serial.print("Setting month to "); Serial.println(in); break;
    case 'd': case 'D': in = SerialReadPosInt(); RTC.setDate(in); RTC.setClock(); Serial.print("Setting date to "); Serial.println(in); break;
    case 'W': Serial.print("Day of week is "); Serial.println((int)RTC.getDayOfWeek()); break;
    case 'w': in = SerialReadPosInt(); RTC.setDayOfWeek(in); RTC.setClock(); Serial.print("Setting day of week to "); Serial.println(in); break;
    case 't': case 'T': 
      if (RTC.is12hour()) { RTC.switchTo24h(); Serial.println("Switching to 24-hour clock."); }
      else { RTC.switchTo12h(); Serial.println("Switching to 12-hour clock."); }
      RTC.setClock(); break;
    case 'a': case 'A': if (RTC.is12hour()) { RTC.setAM(); RTC.setClock(); Serial.println("Set AM."); } else Serial.println("(Set hours only in 24-hour mode.)"); break;
    case 'p': case 'P': if (RTC.is12hour()) { RTC.setPM(); RTC.setClock(); Serial.println("Set PM."); } else Serial.println("(Set hours only in 24-hour mode.)"); break;
    case 'q': RTC.sqwEnable(RTC.SQW_1Hz); Serial.println("Square wave output set to 1Hz"); break;
    case 'Q': RTC.sqwDisable(0); Serial.println("Square wave output disabled (low)"); break;
    case 'z': RTC.start(); Serial.println("Clock oscillator started."); break;
    case 'Z': RTC.stop(); Serial.println("Clock oscillator stopped."); break;
    case '>': in = SerialReadPosInt(); in2 = SerialReadPosInt(); RTC.writeData(in, in2); Serial.print("Write to register "); Serial.print(in); Serial.print(" value "); Serial.println(in2); break;
    case '<': in = SerialReadPosInt(); in2 = RTC.readData(in); Serial.print("Read from register "); Serial.print(in); Serial.print(" value "); Serial.println(in2); break;
    default:
      Serial.println("Unknown command. Try:");
      Serial.println(" h## - set Hours   d## - set Date");
      Serial.println(" i## - set Minutes m## - set Month");
      Serial.println(" s## - set Seconds y## - set Year");
      Serial.println(" w## - set Day of Week");
      Serial.println(" t - toggle 12/24h  a - AM  p - PM");
      Serial.println(" z - start clock  Z - stop clock");
      Serial.println(" q - SQW 1Hz  Q - stop SQW");
      Serial.println(" >##,### - write register  <## - read register");
  }
}

int SerialReadPosInt() {
  int i = 0; boolean done = false;
  while (Serial.available() && !done) {
    char c = Serial.read();
    if (c >= '0' && c <= '9') i = i * 10 + (c - '0');
    else done = true;
  }
  return i;
}

Library-Dateien

Für die Nutzung werden zwei Libraries benötigt. Erstelle im Arduino libraries-Ordner folgende Ordnerstruktur und kopiere die Dateien hinein:

1. RealTimeClockDS1307 Library

Ordner: RealTimeClockDS1307

In der Arduino IDE: Sketch → Bibliothek einbinden → .ZIP-Bibliothek hinzufügen → Ordner auswählen.

2. RTClib Library (Adafruit/JeeLabs Fork)

Ordner: RTClib

Diese Library unterstützt DS1307, DS3231, PCF8523 und mehr. Kompatibel mit AVR, SAMD, ESP8266, ESP32 etc. Siehe Adafruit Guide.

Schaltplan

Der Schaltplan des Projekts (Fritzing-Datei):

7segmentClock.fzz

Herstellungsprozess

  1. Bügelbrett-Fertigung: Design, Materialien und Produktionsprozess
  2. Kuckucksuhr: Geschichte, Handwerkskunst und moderne Evolution
  3. Leiterplatten (PCB): Design, Fertigung und Zukunftstrends
  4. Surfboard-Konstruktion und Design: Von polynesischen Wurzeln zur modernen Innovation
  5. Arduino-Roboter mit Raspberry Pi bauen: Schritt-für-Schritt-Anleitung
  6. RasPiRobot Board V2: Raspberry Pi zum leistungsstarken Roboter-Controller erweitern
  7. Arduino POV-Uhr: Persistence-of-Vision LED-Display selbst bauen
  8. Infinity Mirror Clock: Endlose Eleganz trifft präzise Zeitanzeige
  9. Die Bedeutung einer fehlerfreien Leiterplatte
  10. Motorkonfiguration: Umfassender Leitfaden zu Typen und Merkmalen