DCF77 über Digitalpin?

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.

OK, dann verstehe ich jetzt auch, was die einzelnen Funktionen so machen. Was mir an readTime() nicht so gefällt, ist dass sie den kompletten Programmablauf unterbricht. Die Uhr sollte aber eigentlich kontinuierlich weiterlaufen, dafür habe ich den DS1307 ja schließlich eingebaut.
Wenn ich diese Woche Zeit habe, werde ich mal sehen, ob sich eine Funktion einbauen lässt, die wie scanSignal() ständig aufgerufen wird und zurückgibt, ob die Uhrzeit korrekt empfangen wurde. (Und die Veränderungen natürlich auch hier reinstellen)

Ich weiss garnicht mehr genau wie ich das gemacht hatte bei meiner Uhr.
Soweit ich mich erinnern kann hatte ich auch das Problem das dimyDCF.scanSignal(); regelmäßig aufgerufen werden musste.
Je nach dem was ich drum herum noch so gemacht hatte (z.B. Serial.prints) wurde das zu langsam.
Ich hatte dann noch in der Lib was verändert um festzustellen ob das Signal richtig war.
Über myDCF.valid konnte ich das auslesen
-1 = Empfangsfehler
1 = OK
Musste dann aber noch mal zusätzlich ne abfrage machen ob die Werte für Sekunden usw. auch Plausibel sind.
Weil ab und zu kam von der Auswertung ein OK aber die Werte waren völlig falsch.

Und soweit ich mich erinnern kann hat das ganz gut funktioniert.
Leider nur auf dem Breadboard, nachher in meiner Holzuhr nicht mehr.
Aber das hatte auch andere Gründe.

And1G:
OK, dann verstehe ich jetzt auch, was die einzelnen Funktionen so machen. Was mir an readTime() nicht so gefällt, ist dass sie den kompletten Programmablauf unterbricht. Die Uhr sollte aber eigentlich kontinuierlich weiterlaufen, dafür habe ich den DS1307 ja schließlich eingebaut.
Wenn ich diese Woche Zeit habe, werde ich mal sehen, ob sich eine Funktion einbauen lässt, die wie scanSignal() ständig aufgerufen wird und zurückgibt, ob die Uhrzeit korrekt empfangen wurde. (Und die Veränderungen natürlich auch hier reinstellen)

Hast Du eine Funkuhr?
Die ermitteln das DCF Signal in der Regel (mag durchaus Ausnahmen geben) Nachts zwischen 2 und 4 Uhr. Und was machen die Zeiger in dieser Zeit? Sie bleiben stehen.
Ich will damit sagen: es ist im Prinzip wurscht, ob mitten in der Nacht für ein paar Minuten die Uhr stehenbleibt.

@MaFu: Ich denke, das kann man nicht so verallgemeinern. Ich habe mich ja in letzter Zeit etwas ausführlicher mit dem DCF77-Empfang und dessen Auswertung beschäftigt. Im Prinzip könnte jede Funkuhr das Signal kontinuierlich einlesen und auswerten. Ist die Uhr jedoch auf Stromsparen ausgelegt, trifft deine Aussage durchaus zu. Funkuhren mit Wetteranzeige (Auswertung der Bits 1-14), Bahnhofsuhren und viele Uhren mit "dicken" Batterien :wink: lesen aber das Signal kontinuierlich ein.
Wenn man jetzt nur einmal am Tag das DCF-Signal aufschnappt, muss im Hintergrund die Zeit mitlaufen, das über die verstrichenen Millisekunden zu machen wäre über 24 Stunden reichlich ungenau, ohne eine RTC würde ich das nicht machen. Da bleibt dann nur das permanente Einlesen.

And1G hat geschrieben, dass er eine DS1307 dranhängen hat. Und da reicht es ja wohl, wenn einmalig in der Nacht aktualisiert wird.

Ansonsten geb ich Dir recht.
Aber selbst wenn ich das weiterzählen ausschließlich über millis() machen würde brauche ich nicht permanent auslesen. Einmal pro Stunde würde reichen, so ungenau ist der ATmega nun auch wieder nicht.

Hallo wie kann ich die Stunden in 12 stunden ausgeben.
Analoge anzeige in 24 stunden ist etwas doof.
Gruß

#include <DCF77.h>

int DCF77Pin=2;
int blinkPin=13;
int seconds=0;
int previousSecond=0;
int minutes=0;
int hours=0;
DCF77 myDCF=DCF77(DCF77Pin);
int SZ;
//int stdPin=10;
//int minuPin=12;
float value;
float value1;
float value3;
//int std1;
//int minu1;



void setup(void) 
{
  pinMode(blinkPin, OUTPUT);
  pinMode(4, OUTPUT);
  digitalWrite(2, LOW);
  // open the serial port at 9600 bps:
  Serial.begin(57600);
}

void loop(void) 
{
  int DCFsignal = myDCF.scanSignal();
  if (DCFsignal) {
    digitalWrite(blinkPin, HIGH);
  } else {
    digitalWrite(blinkPin, LOW);
  }
  hours=myDCF.hh;
  minutes=myDCF.mm;
  seconds=myDCF.ss;
  if (seconds != previousSecond) 
    myDCF.serialDumpTime();
  delay(20);
  previousSecond = seconds;
  {
 //   minu1=minutes;
   // std1=hours;
    value = hours;//std1;
    value1 =minutes;//minu1;
    value3=seconds; 
   analogWrite(9, value*10);//Stunden 24*10 = 240
  analogWrite(10, value1*4);//Minuten 60*4 = 240
 analogWrite(11, value3*4); //Sekunden 60*4 = 240
 // Serial.println(value*10);
 // Serial.println(value1*4);
  }
  {
     SZ = hours*60+minutes;

 if (SZ >= 1095 && SZ <= 1200 ) 
{pinMode(4, OUTPUT); 
  digitalWrite(4, HIGH);} 
else 
  {digitalWrite(4, LOW);}
  }
}
hours = hours - (hours > 11)?11:0;

Zieht, wenn hours>11 ist 12 ab, ansonsten 0, sollte funktionieren, wenn ich da nicht noch etwas übersehen hab :smiley:

An der Erkennung, ob die Zeit richtig ermittelt wurde bin ich gerade noch am tüfteln.

And1G wenn ich denn code nehme wird mir immer die Zeit angezeigt die nach dem ? steht.

hours = hours % 12; // Mudulo Division durch 12, Ergebnis ist der Rest und liegt somit immer zwischen 0 und 11

Danke MaFU werde es gleich probieren

Ich habe ein bisschen gebastelt aber das Ergebnis sagt mir noch nicht so ganz zu:

bool DCF77::checkTime(void)
{
	scanSignal();
	return(ready && finalized);
}

Funktioniert bei gutem Empfang bestens, gibt beim Minutenwechsel True aus. Bei schlechten Empfang bleibt allerdings die Zeit stehen, es wird aber trotzdem True zurückgegeben. Als Folge wird dann im Minutentakt so lange bis wieder Empfangen wurde eine alte Uhrzeit ausgegeben:

Time: 16:10:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:11:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:11:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:11:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:14:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:14:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:14:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:17:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:18:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:18:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:20:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:20:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:22:0 Date: Sa, 18.2.2012 (Winterzeit)
Time: 16:23:0 Date: Sa, 18.2.2012 (Winterzeit)

Hier ist die loop-Funkion:

	if (myDCF.checkTime())
	{
		myDCF.serialDumpTime();
		digitalWrite(LEDPin, !digitalRead(LEDPin) );
	}

Hat jemand eine Idee? Eigentlich hätte ich erwartet, dass finalized nur true ist, wenn die Uhrzeit auch wirklich zusammengesetzt werden konnte, das scheint aber nicht der Fall zu sein...

Hi,
kann es sein, dass der CODE mit der Array Lösung, nicht mit Arduino 1.0 läuft?
Es passiert im Serial Monitor einfach nichts.