DCF77 über Digitalpin?

Hallo!

Für meine Uhr habe ich den DCF77-Empfänger von Conrad geholt. Nun war ich am Wochenende etwas im Stress und habe den Datenpin von dem Gerät auf einen Digitaleingang am Arduino gelegt, um dann mit Schrecken festzustellen, dass die Bibliothek, die ich verwende [1] das Teil gerne an einem Analogeingang hätte.

Im Quellcode wird an einer einzigen Stelle dieser Analogeingang abgefragt und dann mit dem Wert 200 verglichen, woraus wie ich das sehe ermittelt wird, ob es sich um eine 0 oder 1 handelt.

Diesen Teil habe ich dann mit einer Abfrage auf einen Digitalpin ersetzt... Sieht jemand eine Chance, dass die Bibliothek trotzdem noch funktioniert? Die Uhr liegt jetzt seit einer Stunde auf der Fensterbank und synchronisiert bis jetzt nicht. Was allerdings nichts heißen muss, da entweder das Modul nicht besonders toll ist oder ich hier schlechten Empfang habe, denn auch beim Testen am Analogpin hatte ich manchmal über Stunden kein anständiges Signal bekommen.

Oder kennt jemand eine alternative Bibliothek, die mit Digitalpins zurechtkommt?

[1] ~~http://gonium.net/md/2007/01/06/arduino-dcf77-v02-released/~~
http://arduino.cc/forum/index.php?topic=52841.0

In seiner v 0.2 benutzt er Pin 2, in v 0.1 Pin 7. Die v 0.2 hat überhaupt keine Library, nur die v 0.1 - und weder in der Library noch dem Code zu 0.1 + 0.2 finde ich einen Vergleich zu 200, nicht mal die Zahl 200 kommt irgendwo vor. Kann es sein das Du einen falschen Link gepostet hast?

Der Empfang ist sehr ortsabhängig, verändere mal die Position der Antenne, wenn Du ewig kein brauchbares Signal bekommst.

Oh wie peinlich, da habe ich mir wohl den falschen Link gespeichert und nicht richtig überprüft. Und dann ist der richtige auch noch aus dem gleichen Forum, das passiert mir nicht noch einmal :blush:

Im Moment steht die Uhr auf der Fensterbank und der Empfänger ist auch in Richtung Frankfurt ausgerichtet. Bis jetzt kein Empfang... Ich werde den Laptop mal über Nacht laufen lassen und über USB loggen, ob irgendetwas empfangen wird.
Morgen werde ich noch ein paar andere Orte testen, obwohl ich eigentlich dort wo sie jetzt steht schon minütlich ein Signal empfangen habe.

Kennt jemand vielleicht eine gute andere Bibliothek?

Dann poste ich doch mal einfach meinen Text aus einem anderen Thread hier noch einmal:

Ich habe auch den Conrad Empfänger. Zum Auslesen verwende ich die DCF77 Library von Mathias Dalheimer. Da ich damit aber große Probleme beim Auslesen hatte, habe ich sie modifiziert/erweitert. Diese erweiterte Version kann hier heruntergeladen werden: http://www.mafu-foto.de/elektronik/arduino/108-arduino-library-fuer-dcf77-funkuhrempfaenger

Bei mir funktioniert es damit.

Schön, dass sich noch mehr Leute mit dem DCF77-Empfang beschäftigen.
Ein Grund, warum oft der analoge Eingang verwendet wird, liegt meines Erachtens an der Art bzw. die Spannung des Ausgangssignals. Die Module von Pollin laufen zum Beispiel mit 3,3V, daher hat das Signal auch nur diesen Pegel bzw. knapp darunter. In der Theorie sollte das noch als High-Pegel am digitalen Eingang durchgehen, ob das in der Praxis immer so ist?
Wie hast du denn das Modul angeschlossen? Hast du daran gedacht, einen Widerstand gegen die positive Versorgungsspannung zu schalten, weil es sich beim Conrad-Modul um einen Open-Collector-Ausgang handelt?

Ich würde mich freuen, wenn du diesen Code mal testen und das Resultat (bzw. nur den Ausschnitt zwischen den Synchronisationen) posten könntest:

int DCFPin = A0; 
int val = 0;   
unsigned long zeit;

void setup(){
  delay (2000);
  Serial.begin(115200);  
  for (int i=1; i<=12000; i++){
    zeit=millis();
    val = analogRead(DCFPin);
    if (val>1000){
      Serial.print("_");
    } else {
      Serial.print("-");
    }  
    if (i%100==0){
      Serial.print (" ");
      Serial.println (i/100);
    }  
    while (millis()-zeit<10) {} 
  }  
}

void loop(){}

Die Resultate meiner Ansätze findest du in diesem Thread ab Seite 2: http://arduino.cc/forum/index.php/topic,88238.0.html

Na dann mal mehrgleisig :

Hier das Pollin Modul aber inmitten einer Messumgebung. Die LED geht etwa alle 10-15 sec unregelmäßig (EDIT) auf high, aber an den Stunden / Minuten / Sekunden Werten erst mal keine Veränderung.
Das spräche aber dafür dass das 3.3 V Eingangssignal dedektiert wird.

Ich lasse das heute morgen mal laufen.


Habe die Routine mal isoliert, dann schafft es die Sekunden zu synchronisieren. Sieht danach aus dass dieser Vorgang ganz alleine laufen sollte. :wink: Ich habe da noch I2C Übertragungen dazwischen, das ist nix.

Das Pollin Modul funktioniert perfekt mit dieser Libray.

sth77:
Die Zeile while (millis()-start<10) {} müsste eigentlich while (millis()-zeit<10) {} heißen, kann das sein?
Die Ergebnisse gibt es hier: DCF77 - Pastebin.com
Habe während es lief auch die Antenne etwas herumgeschwenkt, im Bereich der Richtung, in der Frankfurt liegen sollte :wink: Bin übrigens so runde 160km entfernt, falls das wichtig ist.
Angeschlossen ist es so:

|-------------------------------|
|                               |
|                               |
| _____________                 |
| |D-|D+|5V|GND|                |
|-------------------------------|

D+ ist an für deinen Sketch jetzt an A0 gewandert, sonst habe ich es an D2. Über einen Pull-Up Widerstand von 10kOhm mit 5V verbunden
D- ist der invertierende Ausgang und überhaupt nicht angeschlossen.

Ich habe deinen Sketch auch mal so verändert, dass er den Pin D2 abfragt. Mit meinen ungeübten Augen sieht das Resultat doch zumindest sehr ähnlich aus: DCF77 an D2 - Pastebin.com

MaFu:
Danke, deine Bibliothek werde ich gleich ausprobieren!
Habe ich einen anderen Thread hier übersehen?

Meine Uhr lief jetzt die ganze Nacht durch seit etwa 1 Uhr. In 14 Stunden nicht ein mal synchronisiert :frowning:

Ja, mit den Variablen start und zeit ist mir ein Fehler unterlaufen, die Variable hieß ursprünglich startzeit und wurde dann gekürzt. Gut aufgepasst, ich habs hier im Codeschnipsel verbessert.
Dein Resultat sieht auch prima aus, daraus sollte sich die richtige Uhrzeit berechnen lassen.

Bei deinem Sketch entspricht _ einer 1 und - einer 0, richtig? Dann müsste ich mir doch eigentlich daraus eine Uhrzeit auch "von Hand" zum Testen ermitteln können, oder?

MaFu:
Deine Bibliothek läuft perfekt! Werde mein Projekt am Wochenende mal drauf umstellen! Danke euch!

Es gibt lange und kurze Absenkungen des Signals, wobei lange Absenkungen für eine 1 stehen, kurze für eine 0. Jede Sekunde kommt ein neues Bit herein. Eine Auswertung meines Signalverlaufs habe ich hier beschrieben:

http://arduino.blogger.de/stories/1993353/

Ah ja natürlich, ein Bit pro Sekunde... Ja, dann ist die Sache klar!
Finde ich klasse, dass du dir so eine Mühe machst, das so super zu erklären!

MaFu:
Ich habe mich heute mal an deine Bibliothek drangesetzt.

    /**
    * Should be called every 15 ms in order to sample the DCF signal.
    * Returns the current state of the signal: 1 for HIGH, 0 for LOW.
    */
    bool readTime(unsigned char retries);
    int scanSignal(void);

Wie ist das zu Verstehen? Muss ich wirklich alle 15ms einmal die Funktion aufrufen?

Kann man das irgendwie in der Bibliothek automatisieren? Vielleicht mit einem Timer Interrupt?

Und gibt es irgendeine Möglichkeit, zu prüfen, ob erfolgreich synchronisiert wurde?

Hintergrund ist, dass ich noch ein DS1307 RTC-Modul am Laufen habe, was die Uhrzeit angibt. Da soll natürlich nur reingeschrieben werden, wenn die Synchronisation erfolgreich war.

Und dann sind mir noch ein Paar Dinge aufgefallen:

struct DCF77Buffer
{
  unsigned long long prefix     :15 ;
  unsigned long long Antenna    :1  ;   // wenn Bit gesetzt wird Reserveantenne benutzt
  unsigned long long DSTChange  :1  ;   // Bit wird eine Stunde vor Zeitumstellung gesetzt
  unsigned long long DST        :2  ;   // Sommer-/Winterzeit
  unsigned long long LeapSec    :1  ;   // Ank?ndigung einer bevorstehenden Schaltsekunde
  unsigned long long Start      :1  ;
  unsigned long long Min        :7  ;   // 7 Bits für die Minuten
  unsigned long long P1         :1  ;   // Parity Minuten
  unsigned long long Hour       :6  ;   // 6 Bits für die Stunden
  unsigned long long P2         :1  ;   // Parity Stunden
  unsigned long long Day        :6  ;   // 6 Bits für den Tag
  unsigned long long Weekday    :3  ;   // 3 Bits für den Wochentag
  unsigned long long Month      :5  ;   // 3 Bits für den Monat
  unsigned long long Year       :8  ;   // 8 Bits für das Jahr **eine 5 für das Jahr 2005**
  unsigned long long P3         :1  ;   // Parity von P2
};
struct DCF77Parity
{
   unsigned char parity_flag    :1;
   unsigned char parity_min     :1;
   unsigned char parity_hour    :1;
   unsigned char parity_date    :1;
};

Was bedeuten die Zahlen hinterm Doppelpunkt? Kann ich annehmen, dass damit die einzelnen Bits belegt werden? Gibt es zu dieser Syntax einen Namen? Sowas habe ich nämlich noch nie gesehen...
Ein long long hat 64 Bit, richtig?

Jedes Element im struct DCF77Buffer ist 64 bit groß, damit ist eine Instanz des struct fast 1KB groß. Ist das nicht ein wenig übertrieben für die 59 Bit die das Signal eigentlich hat?

Grad auf dem Weg nach Hause kam mir die zündende Idee: Da handelt es sich um Bitfelder, und die habe ich doch schon einmal gesehen :wink:
Die kamen nämlich bei uns in der Vorlesung zu Systemarchitektur (In der es leider ( :wink: ) um den MSP430 von TI geht) vor und es wurde uns schön davon abgeraten, diese zu benutzen. Ich habe dazu mal etwas aus dem Skript eingescant, leider durch Textmarker teilweise schlecht zu Lesen, aber ich denke es ist erkennbar, worauf es abzielt.
Das Beispielprogramm auf der rechten Seite oben hat mit Bitfeldern 402 Bytes und mit Maskenoperationen 202 Bytes an Größe. (Wobei sich in der Definition der Struktur so wie ich das grad sehe ein Fehler eingeschlichen hat...) Kann dazu hier jemand sagen, wie das auf dem Atmel aussieht?

Die Struktur ist daher auch insgesamt nur 64 Bit groß, also keine Verschwendung, lediglich 5 unvermeidbare überschüssige Bits :slight_smile:

mkl0815:
Jedes Element im struct DCF77Buffer ist 64 bit groß, damit ist eine Instanz des struct fast 1KB groß. Ist das nicht ein wenig übertrieben für die 59 Bit die das Signal eigentlich hat?

Eben nicht, dafür sorgt ja eben die Bitdefinition. Es wird nur ein einziges longlong verwendet, die Struktur ist somit nur 64 Bit groß.
Durch diese Definition kann man sich aber die ganze Bitschieberei sparen.
Ist einfach nur die Schmankerl von C ausgenutzt.

And1G:
MaFu:
Ich habe mich heute mal an deine Bibliothek drangesetzt.

    /**

* Should be called every 15 ms in order to sample the DCF signal.
    * Returns the current state of the signal: 1 for HIGH, 0 for LOW.
    */
    bool readTime(unsigned char retries);
    int scanSignal(void);



Wie ist das zu Verstehen? Muss ich wirklich alle 15ms einmal die Funktion aufrufen?

Kann man das irgendwie in der Bibliothek automatisieren? Vielleicht mit einem Timer Interrupt?

Und gibt es irgendeine Möglichkeit, zu prüfen, ob erfolgreich synchronisiert wurde?

Ehrlich gesagt, weiß ich nicht mehr was diese Anmerkung mit den 15ms zu bedeuten hat. Ist vermutlich noch ein Überbleibsel aus der Originalversion.

Schau Dir einfach mal das beiliegende Beispiel an.
Du brauchst nur einmal die Funktion scanSignal() aufrufen und kannst dann anschließend aus den Variablen der Klasse die Werte entnehmen.
Allerdings kann das natürlich auch in die Hose gehen. Daher ist die Funktion readTime() sinnvoller. Der Parameter von readTime() ist die Anzahl der Versuche, mit readTime(5) wird z.B. bis zu 5x versucht die Zeit zu ermitteln. Bei Erfolg wird true zurückgeliefert, ansonsten false.

Danke für die Aufklärung. Das wusste ich nicht (mehr), falls es mir jemals untergekommen ist/war.
Und wieder was gelernt....

Das beiliegende Beispiel (reduziert auf das wesentliche) sieht so aus:

#include <DCF77.h>

int DCF77Pin=11;
int seconds=0;
int previousSecond=0;
int minutes=0;
int hours=0;
DCF77 myDCF=DCF77(DCF77Pin);

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

void loop() {
  int DCFsignal = myDCF.scanSignal();
  hours=myDCF.hh;
  minutes=myDCF.mm;
  seconds=myDCF.ss;
  if (seconds != previousSecond) 
    myDCF.serialDumpTime();
  delay(20);       
  previousSecond = seconds;
}

scanSignal wird eben nicht nur einmal aufgerufen, sondern permanent in der Loop, allerdings verzögert durch ein delay(). Das ist im Prinzip die gleiche Herangehensweise, wie ich sie in meinem Sketch auf Seite 1 wählte. Das Signal wird gepollt, also in einem regelmäßigen Abstand abgefragt.

Natürlich wirds in den Beispielsketch immer wieder aufgerufen. Aber doch nur, weil das Beispiel sonst nichts anderes macht.

Ich würds so machen wie jede normale Funkuhr auch:
Einmal am Tag (sinnvollerweise in den Nachtstunden) mit readTime(5) die Uhrzeit ermitteln und wenn true zurückkommt die ermittelte Zeit übernehmen. Bei false kann man es ja ein paar mal alle 15 Minuten wiederholen bis es passt.