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.
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 }
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 }