DCF 77-Signale dekodieren

Nachdem ich im ersten Beitrag zu diesem Thema einen Sketch zum Analysieren der DCF77-Signale beschrieben habe,möchte hier nun zwei Sketche beschreiben, mit denen sich die Signale des DCF77 Senders dekodieren lassen.

dcf77_impulsdauern
Bild 1

Mit dem ersten Sketch beschreibe ich noch eher eine andere Form der Analyse, die aber den ersten Einstieg in die Dekodierung bietet. Mit dem Arduino wird die Zeitdauer zwischen der ansteigenden und abfallenden Flanke des Signals gemessen. Diese beschreibt dann die Impulslänge des im Sendesignal enthaltenen Zeitsignals.

Die Ausgabe erfolgt wie gehabt wieder über den seriellen Monitor der Arduino Entwicklungsumgebung. Es wird die gemessene Länge einer Sekunde in ms ausgegeben. Zusätzlich dann die noch wichtigere Information über die Dauer des Impulses. Die Ausgabe sieht dann wie in Bild 1 aus. Zum Vergrößern des Screenshots einfach die Grafik anklicken.

Hier der dazu gehörende Sketch:

/*================================================================================
  Einfaches Programm zum Einlesen von digitalen Signalen eines DCF77 Empfängers
  Die Zeit zwischen zwei Sekundenimpulsen wird gemessen
  Die Länge des '1' Signals wir gemessen
  Ausgabe der Sekundenimpulse auf eine LED
  Ausgabe der gemessenen Zeidauern auf den seriellen Monitor der Arduino IDE
==================================================================================*/


#define DCF77Pin 2                                                // An diesen Pin wird der DCF77 Empfänger angeschlossen
#define LEDPin 13                                                 // Eingelesene Impulse des Empfängers werden hier ausgegeben
int vorheriger_DCF_Wert = 0;                                      // Zwischenspeicher für vorherigen Impulswert (dient zur Flankenerkennung)
int DCF77Pegel;                                                   // aktuell erkannter Wert am DCF77Pin
int Flanke_hoch;                                                  // Zeitpunkt in millis an dem die ansteigende Flanke erkannt wurde
int Dauer_Eins = 0;                                               // Dauer des '1' Signals
int Dauer_Sekunde = 0;                                            // Impulslänge der Sekunde

void setup() {
  Serial.begin(9600);
  pinMode(DCF77Pin, INPUT);                                       // DCF77PIN für Eingabe setzen
  pinMode(LEDPin, OUTPUT);                                        // LEDPin für Ausgabe setzen
}

void loop() {
  DCF77Pegel = digitalRead(DCF77Pin);                             // Wert am DCF77Pin einlesen und in DCF77Pegel speichern
  if (DCF77Pegel == 1 && vorheriger_DCF_Wert == 0) {              // prüfen ob der aktuelle Wert = 1 ist und der vorherige 0 war = aufsteigende Flanke erkannt
  Dauer_Sekunde = millis() - Flanke_hoch;                         // Impulslänge der Sekunde ist die Zeitdauer seit der letzten aufsteigenden Flanke  
  Flanke_hoch = millis();                                         // Zeitpunkt in millis der aktuellen aufsteigenden Flanke
  vorheriger_DCF_Wert = 1;                                        // aktueller Wert des erkannten Impulses
  digitalWrite(LEDPin, DCF77Pegel);                               // LEDPin auf aktuell erkannten Wert nach Flanke setzen
  Serial.print("Dauer Sekundenimpuls = ");                        // Ausgabe der erkannten Zeitdauern auf den seriellen Monitor
  Serial.print(Dauer_Sekunde);
  Serial.print(" ms  --> Dauer '1' Signal = ");
  Serial.print(Dauer_Eins);
  Serial.println(" ms");
  }
  if (DCF77Pegel == 0 && vorheriger_DCF_Wert == 1) {              // prüfen ob der aktuelle Wert = 0 ist und der vorherige 1 war = absteigende Flanke erkannt
  Dauer_Eins = millis() - Flanke_hoch;                            // Dauer des '1' Signals = Zeit von aufsteigender bis abfallender Flanke
  vorheriger_DCF_Wert = 0;                                        // aktueller Wert des erkannten Impulses
  digitalWrite(LEDPin, DCF77Pegel);                               // LEDPin auf aktuell erkannten Wert nach Flanke setzen
  }
  delay(3);                                                       // ein bischen warten wegen unsauberer Flanke
}  

dcf77_binaerwerte
Bild 2

Der Schritt zur Dekodierung der empfangenen Signale ist nun nicht mehr weit. Aus der gemessenen Impulslänge lässt sich ermitteln, ob eine „1“ oder eine „0“ empfangen wurde. Eine Impulsbreite von 100 ms entspricht dabei einer „0“ und 200 ms stellen eine „1“ dar.

Für die Dekodierung darf man allerdings nicht so „scharf“ herangehen. Ich habe daher im Sketch festgelegt, dass ein Impuls länger als 150 ms einer „1“ entspricht. Die übrigen Impulse, sofern sie länger als 50 ms sind, entsprechen dann einer „0“.

Bild 2 zeigt die Ausgabe auf dem seriellen Monitor. Zum Vergrößern bitte wieder auf die Grafik klicken.

Der Code ist wieder gut dokumentiert und sollte sich daher von selbst erklären.

/*================================================================================
  Einfaches Programm zum Einlesen von digitalen Signalen eines DCF77 Empfängers
  Die Zeit zwischen zwei Sekundenimpulsen wird gemessen
  Die Länge des '1' Signals wir gemessen
  Daraus wird errechnet ob eine logische 1 oder 0 erkannt wurde
  Ausgabe der Sekundenimpulse auf eine LED
  Ausgabe der erkannten Binaerwerte auf den seriellen Monitor der Arduino IDE
==================================================================================*/


#define DCF77Pin 2                                                // An diesen Pin wird der DCF77 Empfänger angeschlossen
#define LEDPin 13                                                 // Eingelesene Impulse des Empfängers werden hier ausgegeben
int vorheriger_DCF_Wert = 0;                                      // Zwischenspeicher für vorherigen Impulswert (dient zur Flankenerkennung)
int DCF77Pegel;                                                   // aktuell erkannter Wert am DCF77Pin
int Flanke_hoch;                                                  // Zeitpunkt in millis an dem die ansteigende Flanke erkannt wurde
int Dauer_Eins = 0;                                               // Dauer des '1' Signals
int Dauer_Sekunde = 0;                                            // Impulslänge der Sekunde
int Binaerwert;

void setup() {
  Serial.begin(9600);
  pinMode(DCF77Pin, INPUT);                                       // DCF77PIN für Eingabe setzen
  pinMode(LEDPin, OUTPUT);                                        // LEDPin für Ausgabe setzen
}

void loop() {
  DCF77Pegel = digitalRead(DCF77Pin);                             // Wert am DCF77Pin einlesen und in DCF77Pegel speichern
  if (DCF77Pegel == 1 && vorheriger_DCF_Wert == 0 && (millis()-Flanke_hoch) > 50) {              // prüfen ob der aktuelle Wert = 1 ist und der vorherige 0 war = aufsteigende Flanke erkannt
  Dauer_Sekunde = millis() - Flanke_hoch;                         // Impulslänge der Sekunde ist die Zeitdauer seit der letzten aufsteigenden Flanke  
  Flanke_hoch = millis();                                         // Zeitpunkt in millis der aktuellen aufsteigenden Flanke
  vorheriger_DCF_Wert = 1;                                        // aktueller Wert des erkannten Impulses
  digitalWrite(LEDPin, DCF77Pegel);                               // LEDPin auf aktuell erkannten Wert nach Flanke setzen
  if (Dauer_Sekunde > 1200) {                                     // Ausgabe des erkannten Binärwertes
    Serial.println("Beginn einer neuen Sekunde");                 // Alles größer 1200 ms muss dann die 59. Sekunde sein, die eine neue Minute anzeigt
    }
  else if (Dauer_Eins > 150) {                                    // Eine logische 1 dauert 200ms daher sollte eine Impulsdauer >150ms eine 1 sein (Reserve eingebaut)
    Serial.println("Binaerwert = 1");
    }
  else {
    Serial.println("Binaerwert = 0");                              // Eine logische 1 dauert 100ms. Wenn es keine 1 ist muss es eine 0 sein:-)
    }    
  }
  if (DCF77Pegel == 0 && vorheriger_DCF_Wert == 1) {              // prüfen ob der aktuelle Wert = 0 ist und der vorherige 1 war = absteigende Flanke erkannt
  Dauer_Eins = millis() - Flanke_hoch;                            // Dauer des '1' Signals = Zeit von aufsteigender bis abfallender Flanke
  vorheriger_DCF_Wert = 0;                                        // aktueller Wert des erkannten Impulses
  digitalWrite(LEDPin, DCF77Pegel);                               // LEDPin auf aktuell erkannten Wert nach Flanke setzen
  }
  delay(3);                                                       // ein bisschen warten wegen unsauberer Flanke
}  

 

Schreibe einen Kommentar

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