Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Über mich
  • Deutsch
  • English
Menu

Zeitmessung per Funk: DCF77-Empfangsmodul mit Arduino

Posted on 25. September 20246. Januar 2025 by Stefan Draeger

Mit einem DCF77-Empfangsmodul lassen sich exakte Zeitdaten von einem Funksender wie dem DCF77 empfangen. Diese präzisen Zeitsignale sind ideal für Projekte mit einem Arduino, bei denen eine genaue Uhrzeit erforderlich ist, etwa für zeitgesteuerte Schaltungen oder Datenerfassungssysteme. Das DCF77-Signal wird von der Physikalisch-Technischen Bundesanstalt (PTB) über eine Sendeanlage in Mainflingen ausgestrahlt und stellt eine zuverlässige Quelle für die Mitteleuropäische Zeit (MEZ) sowie die mitteleuropäische Sommerzeit (MESZ) dar.

Zeitmessung per Funk: DCF77-Empfangsmodul mit Arduino
Dieses Video auf YouTube ansehen.

In diesem Beitrag zeige ich dir, wie du ein DCF77-Empfangsmodul mit dem Arduino verbindest, die empfangenen Daten dekodierst und für dein Projekt weiterverarbeitest. Statt vorgefertigte Bibliotheken zu verwenden, biete ich dir einen einfachen Code, den du direkt in dein eigenes Projekt einfügen kannst. Dadurch behältst du die volle Kontrolle über die Signalverarbeitung und kannst die Daten flexibel an deine spezifischen Anforderungen anpassen.

Dieses Projekt eignet sich sowohl für Einsteiger als auch für Fortgeschrittene, die präzise Zeitsteuerungen oder Datenerfassungen umsetzen möchten.

Inhaltsverzeichnis

  • Wozu dient das DCF77-Empfangsmodul?
    • Sender DCF77 in Mainflingen
  • Technische Daten vom DCF77 Empfangsmodul
  • Bezug
    • Lieferumfang
  • Aufbau der Schaltung
  • Programmieren
    • Schritt 1 – Initialisieren der Bibliotheken und Definitionen
    • Schritt 2 – Definieren der Hardware-Pins und globalen Variablen
    • Schritt 3 – Setup des Arduino und LCD-Displays
    • Schritt 4 – Hauptprogramm zur Zeitabfrage und Anzeige
    • Schritt 5 – Interrupt zur Verarbeitung des DCF77-Signals
    • Schritt 6 – Zeitstempel erstellen und zurückgeben
    • Schritt 7 – Hilfsfunktion zur Konvertierung von BCD nach Dezimal

Wozu dient das DCF77-Empfangsmodul?

Das DCF77-Empfangsmodul dient dazu, über Funk genaue Zeit- und Datumsinformationen zu empfangen, die von der DCF77-Sendeanlage ausgestrahlt werden. Diese Informationen werden mit einer hohen Genauigkeit über eine Langwelle (77,5 kHz) gesendet und sind besonders nützlich für Anwendungen, bei denen eine präzise Zeit erforderlich ist, wie etwa bei Funkuhren, Zeiterfassungssystemen oder zeitgesteuerten Schaltungen. In Arduino-Projekten ermöglicht das DCF77-Modul, die empfangenen Zeitdaten in Echtzeit zu verarbeiten, ohne auf externe Zeitserver oder manuelle Einstellungen angewiesen zu sein. Dadurch wird es zu einer idealen Komponente für Automatisierungen, bei denen eine verlässliche Zeitsynchronisierung entscheidend ist.

Sender DCF77 in Mainflingen

Der Sender DCF77 überträgt die Daten dabei mit einer Frequenz von 77.5kHz und einer Leistung von 50kW.

DCF77 Zeitzeichensender bei Mainflingen (Frankfurt am Main)
DCF77 Zeitzeichensender bei Mainflingen (Frankfurt am Main)

Zu diesem Sender gibt es einen Ausführlichen Wikipedia Artikel, welchen ich hier nun gerne verlinken möchte:

Seite „DCF77“. In: Wikipedia, Die freie Enzyklopädie. Bearbeitungsstand: 6. September 2019, 12:10 UTC. URL: https://de.wikipedia.org/w/index.php?title=DCF77&oldid=192027822 (Abgerufen: 13. September 2019, 19:15 UTC)

Technische Daten vom DCF77 Empfangsmodul

  • Betriebsspannung: min. 1,2V – max. 3,3V
  • Stromaufnahme: <90 µA (max. 120µA)
  • Empfangsfrequenz: min. 40 kHz, max. 100 kHz
  • Arbeitstemperatur: -40 °C bis +85 °C
  • Lagertemperatur: -55 °C bis +85 °C

Bezug

Das DCF1 Modul bekommst du auf ebay.de für ca. 5 € inkl. Versandkosten*. 

Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!

Du bekommst dieses Modul auch auf aliexpress.com für deutlich unter einem Euro, jedoch musst du hier mit einer langen Lieferzeit sowie wenn mal was nicht so mit der Lieferung klappt, mit einem „holperigen Support“ rechnen.

Lieferumfang

Das kleine Modul war in meinem Fall komplett aufgebaut und ich konnte quasi mit der Programmierung direkt beginnen. In meinem Fall lag dem kleinen Päckchen ein Datenblatt bei und somit musste ich nicht viel im Internet recherchieren.

Aufbau der Schaltung

Für die Schaltung am Arduino benötigst du:

  • einen Arduino UNO* oder Arduino Nano*,
  • ein USB-Datenkabel*,
  • ein DCF77-Empfangsmodul*,
  • eine 5mm LED* mit 220 Ohm Vorwiderstand*,
  • ein LC-Display* (mit I2C Schnittstelle),
  • diverse Breadboardkabel*,
    • 10 cm, männlich – weiblich,
    • 10 cm, männlich – männlich
Schaltung - DCF77-Emfangsmodul am Arduino Nano V3

Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!

Das DCF77-Empfangsmodul besitzt vier Pins welche mit GND, VCC, PON & TCO beschriftet sind. Das mir vorliegende Modul darf mit maximal 3.3V betrieben werden! Es gibt auch Module welche mit 5V betrieben werden können, hier empfehle ich dir zunächst ein Blick in das Datenblatt.

Schaltung - Arduino Nano V3 - DCF77-Empfangsmodul - LCD-Display
Schaltung – Arduino Nano V3 – DCF77-Empfangsmodul – LCD-Display

Das LC-Display wird via I2C angeschlossen und du benötigst hier die beiden analogen Pin A4 für SDA und A5 für SDA.

Programmieren

Das DCF77-Empfangsmodul kannst du recht einfach am Arduino programmieren, du benötigst keine zusätzliche Bibliothek dafür. Auf der Seite https://de.wikipedia.org/wiki/DCF77#Amplitudenumtastung findest du eine Tabelle aus welchen du die Positionen der Daten aus dem Bitmuster entnehmen kannst.

Den nachfolgenden Code habe ich von der Seite https://wolles-elektronikkiste.de/dcf77-funkuhr entnommen und umgeschrieben, sodass dieser einfacher aber auch robuster ist.

Programm – DCF77-Empfangsmodul am Arduino Nano V3 & LCD-DisplayHerunterladen

Schritt 1 – Initialisieren der Bibliotheken und Definitionen

In diesem Abschnitt importierst du notwendige Bibliotheken und definierst grundlegende Strukturen und Variablen, die für das Projekt benötigt werden.

#include <util/parity.h>  // Kommentiere diese Zeile aus, wenn du keinen AVR Mikrocontroller verwendest
#include <LiquidCrystal_I2C.h>

// Initialisierung des LCD-Displays (I2C Adresse: 0x27, 20 Zeichen, 2 Zeilen)
LiquidCrystal_I2C lcd(0x27, 20, 2);

// Definition der Struktur für den Zeitstempel
struct Zeitstempel {
  bool isValid;
  int jahr, monat, tag, wochentagInt, stunde, minute;
  String wochentagStr;
};

Zeitstempel zeitstempel;

Schritt 2 – Definieren der Hardware-Pins und globalen Variablen

Hier werden die benötigten Pins und globale Variablen festgelegt, die später in der Signalverarbeitung verwendet werden.

int interruptPin = 3;   // Pin, der das DCF77-Signal empfängt
int ledPin = 4;         // Pin zur Steuerung einer Status-LED
volatile unsigned long lastInt = 0;
volatile unsigned long long currentBuf = 0;
volatile byte bufCounter;
String wochentage[] = { "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So" };

Schritt 3 – Setup des Arduino und LCD-Displays

Im setup()-Abschnitt initialisierst du das LCD-Display und richtest den Interrupt für das DCF77-Signal ein. Außerdem wird die Status-LED konfiguriert.

void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), DCF77_ISR, CHANGE);

  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Lese Zeitstempel");
  lcd.setCursor(0, 1);
  lcd.print("von DCF77 Modul");
}

Schritt 4 – Hauptprogramm zur Zeitabfrage und Anzeige

Die loop()-Funktion fragt den aktuellen Zeitstempel ab und gibt ihn auf dem LCD sowie über die serielle Schnittstelle aus. Die Status-LED blinkt in regelmäßigen Abständen zur Anzeige, dass der Arduino arbeitet.

void loop() {
  digitalWrite(ledPin, HIGH);
  delay(750);
  digitalWrite(ledPin, LOW);
  delay(750);

  zeitstempel = getZeitstempel();
  if (zeitstempel.isValid) {
    lcd.clear();
    Serial.println("Aktuelle Zeit:");
    Serial.println("Jahr: " + String(zeitstempel.jahr));
    Serial.println("Monat: " + String(zeitstempel.monat));
    Serial.println("Tag: " + String(zeitstempel.tag));
    Serial.println("Wochentag: " + zeitstempel.wochentagStr);
    Serial.println("Stunde: " + String(zeitstempel.stunde));
    Serial.println("Minute: " + String(zeitstempel.minute));

    char datum[30];
    sprintf(datum, "%02d.%02d.%4d", zeitstempel.tag, zeitstempel.monat, zeitstempel.jahr);
    String datum2 = zeitstempel.wochentagStr + " " + datum;

    char uhrzeit[30];
    sprintf(uhrzeit, "%02d:%02d Uhr", zeitstempel.stunde, zeitstempel.minute);

    Serial.println(datum2);
    Serial.println(uhrzeit);

    lcd.setCursor(0, 0);
    lcd.print(datum2);
    lcd.setCursor(0, 1);
    lcd.print(uhrzeit);
  }
}

Schritt 5 – Interrupt zur Verarbeitung des DCF77-Signals

Die DCF77_ISR()-Funktion wird jedes Mal ausgelöst, wenn eine Änderung im DCF77-Signal erkannt wird. Hier wird die Pulsbreite des Signals gemessen und die Daten in den Buffer geschrieben.

void DCF77_ISR() {
  unsigned int dur = millis() - lastInt;

  if (digitalRead(interruptPin)) {
    if (dur > 1500) {
      bufCounter = 0;
      currentBuf = 0;
    }
  } else {
    if (dur > 150) {
      currentBuf |= ((unsigned long long)1 << bufCounter);
    }
    bufCounter++;
  }
  lastInt = millis();
}

Schritt 6 – Zeitstempel erstellen und zurückgeben

Die getZeitstempel()-Funktion extrahiert die empfangenen Zeitinformationen aus dem Buffer und erstellt daraus einen gültigen Zeitstempel, der dann zurückgegeben wird.

Zeitstempel getZeitstempel() {
  Zeitstempel zeit;
  byte dcf77Year = (currentBuf >> 50) & 0xFF;
  byte dcf77Month = (currentBuf >> 45) & 0x1F;
  byte dcf77DayOfWeek = (currentBuf >> 42) & 0x07;
  byte dcf77DayOfMonth = (currentBuf >> 36) & 0x3F;
  byte dcf77Hour = (currentBuf >> 29) & 0x3F;
  byte dcf77Minute = (currentBuf >> 21) & 0x7F;

  int jahr = rawByteToInt(dcf77Year);
  int monat = rawByteToInt(dcf77Month);
  int tag = rawByteToInt(dcf77DayOfMonth);
  int wochentag = rawByteToInt(dcf77DayOfWeek);
  int stunde = rawByteToInt(dcf77Hour);
  int minute = rawByteToInt(dcf77Minute);

  if (jahr > 0 && monat > 0) {
    zeit.isValid = true;
    zeit.jahr = jahr + 2000;
    zeit.monat = monat;
    zeit.tag = tag;
    zeit.wochentagInt = wochentag;
    zeit.wochentagStr = (wochentag > 0) ? wochentage[wochentag - 1] : "";
    zeit.stunde = stunde;
    zeit.minute = minute;
  } else {
    zeit.isValid = false;
  }
  return zeit;
}

Schritt 7 – Hilfsfunktion zur Konvertierung von BCD nach Dezimal

Die Funktion unsigned int rawByteToInt(byte raw) wandelt ein einzelnes Byte, das im binär kodierten Dezimalformat (BCD) vorliegt, in eine dezimale Zahl um. Bei BCD werden die oberen 4 Bits des Bytes als Zehnerstelle und die unteren 4 Bits als Einerstelle interpretiert.

Die Funktionsweise im Detail:

  1. Mit raw >> 4 werden die oberen 4 Bits des Bytes nach rechts verschoben, sodass die Zehnerstelle isoliert wird.
  2. raw & 0x0F maskiert die oberen 4 Bits und behält nur die unteren 4 Bits, die die Einerstelle darstellen.
  3. Schließlich wird das Ergebnis als Dezimalzahl berechnet, indem die Zehnerstelle mit 10 multipliziert und die Einerstelle dazuaddiert wird.

So ergibt sich aus einem BCD-Wert wie 0x25 (Zehnerstelle 2, Einerstelle 5) die Dezimalzahl 25.

unsigned int rawByteToInt(byte raw) {
  return ((raw >> 4) * 10 + (raw & 0x0F));
}

Schreibe einen Kommentar Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen

Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}