Hallo zusammen, ich wollte Fragen, wie es genau mit den Impulsen vom DCF 77 Empfänger aussieht. Wenn das Signal 100 ms lang ist, ist es eine logische 0. Anschliessend folgt eine Pause von 900 ms. Wenn das Signal 200 ms lang ist, ist es eine logische 1. Anschliessend folgt eine Pause von 800 ms. Wenn die 58 Sekunde gesendet wurde, folgt eine Pause von 1800 ms bzw. 1900 ms. Anhand dieses Pausensignals, lässt sich die Funkuhr synchronisieren. Nun meine Frage: Liegt bei einem Signal von 100 oder 200 ms eine Spannung am Ausgang des DCF77 an und liegt bei einer Pause von 800,900,1800, 1900 ms keine Spannung an. Wäre für jede Hilfe dankbar, denn dann könnte ich endlich das Programm für den DCF77 Empfänger schreiben.
Liegt bei einem Signal von 100 oder 200 ms eine Spannung am Ausgang des DCF77 an und liegt bei einer Pause von 800,900,1800, 1900 ms keine Spannung an. Antwort: kommt auf den Empfänger an! den den ich habe der kann beides.
Es gibt verschiedene Module, das Signal ist ggf. invertiert. Aber Deine Annahme ist richtig. guck mal: DCF77
Also stimmt meine Annahme.... Was bedeutet aber: invertiert Normalerweise wird bei 100 oder 200 ms eine Spannung angelegt Bei der Pause, liegt dann keine Spannung an. Bedeutet invertiert: Das es dann umgedreht ist?
Gast wrote: > Also stimmt meine Annahme.... > Was bedeutet aber: invertiert > > Normalerweise wird bei 100 oder 200 ms eine Spannung angelegt > Bei der Pause, liegt dann keine Spannung an. > > Bedeutet invertiert: Das es dann umgedreht ist? Riiiichtig!
Das Zeitverhalten hast Du in der ersten Nachricht genau beschrieben. Da das Zeitsignal, abhängig vom Empfänger, als "1" oder als "0" ausgegeben wird, bietet es sich an, das Empfangsprogramm unabhängig von der Signalpolarität zu schreiben. Damit kann dann das DCF-Signal von jedem Empfänger dekodiert werden. Gruß Joachim
<klugschiss> An DCF77 liegt immer Spannung an, aber innerhalb der Sekunde entweder 800 ms oder 900 ms ne höhere als in den verbleibenden 100 ms bzw. 200 ms :) </klugschiss> Hendi
Das ist gut, denn mit diesen Informationen kann ich nun ohne weiteres in einen Atmel programmieren. Das bedeutet, das ich ein Datensignal und Pausensignal "nicht invertiert, oder invertiert" von einem Dateneingang lesen kann. Liegt dort eine Spannung an: Variable 1 solange addieren, bis die Spannung abfällt. Fällt die Spannung ab: Variable 2 solange addieren, bis die Spannung wieder anliegt. Liegt die Spannung wieder an, werden die Werte von Variable 1 u. Variable 2 ausgewertet und in die entsprechenden Variablen abgelegt. Auswerten bedeutet: Anhand des Wertes von Variable 1 u. Variable 2, lässt sich ermitteln, ob eine logische 1 oder 0 gesendet wurde. Hierzu wird auch pro so einem Durchlauf in die Variable 3 immer der Wert 1 hinzuaddiert. Das ist nötig, denn nur so weiss man, bei was für einen Sekundensignal man sich gerade befindet und wie man den zusätzlich gesendeten Digitalcode "0 oder 1" zu speichern hat. Anschliessend werden die Variable 1 u. Variable 2 wieder auf den Wert 0 gesetzt, so dass man dort wieder neue Wert addieren kann. Darauffolgend beginnt wieder alles von vorne...... Wird das 58 Sekundensignal mit einer Pause von 1800 ms bzw. 1900 ms gesendet, dann werden entsprechende Variablen wieder gelöscht. Die entsprechend ausgewerteten Daten, wie Datum u. Uhrzeit wird dann über 7 Segmentanzeigen ausgegeben.
Einige DCF-Empfäger haben aber auch einen Open Kolektor Ausgang. Dann kommt da keine Spannung raus.
Dann braucht man eine Pullup nach Vcc. Diesen kann man im Layout sicherheitshalber vorsehen. Der interne im Atmel ist für diesen Zweck zu hchohmig, da kann es zu Störungen kommen. Im Übrigen sind die DCF-Pulse nicht supergenau, sondern schwanken -je nach Empfänger- so um +-20% um den Idealwert. Im Programm müssen also Fenster für die jeweiligen "1" und "0" Pulse vorgesehen werden, die diese Toleranzen berücksichtigen und "Ausreißer" ausmaskieren.
Einfach die Bits addieren geht leider auch nicht, ich benutze dafür eine Look-up Tabelle, in der stehen die Wertigkeiten der einzelnen Bits (Quasi-BCD). Auch die Prüfbits (Paritätsbits) sollten ausgewertet werden um den Empfang sicherer zu machen.
>Einige DCF-Empfäger haben aber auch einen Open Kolektor Ausgang. Dann >kommt da keine Spannung raus. Spannung kann nirgends rauskommen. Die kann nur anliegen bzw. sie kann dafür sorgen, dass Strom fliesst (irgendwo heruaskommt...).
Du arbeitest besser mit Signalwechseln, nicht mit Logikpegeln, wie es Joachim Börke schon ganz richtig angedeutet hat; erzeuge doch mit jedem Signalwechsel einen Interrupt (geht bei den AVR's ganz leicht) und lese dort einen Timer aus; die "0" und "1" ergibt sich dann durch die aufgelaufenen Zeiten; dazu kann man Konsistenztests machen (nach einer 100ms-Zeit muß eine 900ms-Zeit kommen, nach einer 200ms-Zeit muß eine 800ms-Zeit kommen, oder es kommt die 1800ms- oder die 1900ms-Zeit); und die Zeitfenster beachten (Toleranzen, wurde auch schon angesprochen).
In der Codesammlung gibts auch sehr effizienten Beispielcode: Beitrag "DCF77 Uhr in C mit ATtiny26" Peter
Das mit dem Auslösen eines Interrupts bewerkstellige ich dann folgendermasen: Liegt eine Spannung an, dann wird eine Funktion ausgeführt. Diese Funktion addiert pro Schleifendurchlauf einen Wert bei einer Variable hinzu. Fällt nun diese Spannung ab, dann hört diese Funktion auf zu arbeiten. Das bedeutet, dass dann diese Variable einen Wert hat und dieser Wert der Variable sagt dann einem, wie lange das Signal war. Bei 100 ms = .... Bei 200 ms = .... Da nun die Spannung abgefallen ist, wird eine andere Funktion aufgerufen. Diese Funktion addiert nun pro Schleifendurchlauf einen Wert bei einer Variable hinzu. Hiermit weiss man dann, ob das Pausensignal 800,900,1800 oder 1900 ms lang war. Wenn nun wieder eine Spannung anliegt, hört das Zählen dieser Variable auf. Nun werden diese Werte ausgewertet u. dann die Variablen von der Funktion 1 und Funktion 2 auf den Wert 0 gesetzt. Anschliessend beginnt wieder alles von vorne. Wie weiss ich aber, was für Wertigkeiten diese Variablen haben, schliesslich werden ja diese Werte intern im Mikrocontroller gespeichert. Ich dachte, dass ich die Werte der Variablen über Schieberegister über Leds ausgebe u. dann mit einer Webcam aufzeichne. Nun kann man die Bilder der Webcam auswerten u. anschliessend das Programm im Atmel dementsprechend umändern. Wüsstet ihr eine andere Möglichkeit, dann lasst es mich bitte wissen.
Deine Beschreibungen lesen sich so, als ob du noch ein paar Vorübungen brauchen würdest, bevor es Sinn macht sich an einer DCF-77 zu versuchen. Du fängst mal damit an, dir eine Zeitbasis zu schaffen. Dazu nimmst du einen Timer und stellst den so ein, dass du alle paar ms einen Interrupt kriegst. In der Interruptfunktion (von der du nun weist, in welchem Zeitraster sie aufgerufen wird) überprüfst du den jetzigen Zustand des Eingangspins an dem der Empfänger hängt und vergleichst ihn mit dem Zustand, den er beim letzten Aufruf der Interrupt Funktion hatte: * Sind die beiden gleichen, dann hat sich am Signal nichts getan und du zählst einfach nur eine Variable um 1 höher (die kommt später noch ins Spiel und misst einfach nur, wie lange das Signal war). * Sind die beiden aber ungleich, dann hast du eine Flanke gefunden. Die kann von 0 nach 1 oder von 1 nach 0 sein. Das interessiert aber nicht weiter, denn jetzt kommt obige Variable ins Spiel. Diese Variable ist ja ein Mass für die Zeit, die von einem Flankenwechsel zum nächsten Flankenwechsel vergangen ist (dazu wird sie am Ende dieser Behandlung auf 0 gesetzt, um dann wieder langsam hochgezählt zu werden). Entscheidend ist: Diese Zeitdauer kann nicht beliebig sein. Sie kann nur sein: * 100 ms * 200 ms * 800 ms * 900 ms * 1800 ms * 1900 ms (mit entsprechenden kleinen Variationen versteht sich). Die Fälle 800ms und 900ms interessieren nicht weiter. Interessanter sind die Fälle 100 bzw. 200 ms. Je nachdem was vorliegt, hast du entweder eine 0 oder eine 1 empfangen. Die Fälle 1800 ms bzw. 1900 ms sind nur deswegen interessant, weil sie signalisieren, dass jetzt ein neues Pulstelegramm anfängt. Irgendwo werden ja die 0 und 1 von den 100 bzw. 200ms gespeichert. Das wird fürs erste wahrscheinlich ein Array sein. Und ein Auftreten von 1800 bzw. 1900 ms bedeutet lediglich, das der Schreibindex in das Array wieder auf 0 gesetzt werden soll. Zusammengefasst: Zeitdauer < 150 ms ? Eine 0 speichern else Zeitdauer < 250 ms ? Eine 1 speichern else Zeitdauer > 1500 ms ? Neues Telegramm beginnt In Pseudo-Code uint8_t EingangVorher; uint8_t Telegramm[60]; utin8_t NextIndex; ISR( ... ) { uint8_t EingangJetzt; EingangJetzt = PIN .... if( EingangJetzt == EingangVorher ) PulsZeit++; else { EingangVorher = EingangJetzt; if( PulsZeit < 150 ) // 100 ms Telegramm[NextIndex++] = 0; else if( PulsZeit < 250 ) // 200 ms Telegramm[NextIndex++] = 1; else if( PulsZeit > 1500 ) { NextIndex = 0; // Werte das Telegramm aus } PulsZeit = 0; } } Für eine erste Version sollte das so in etwa reichen. Fang erst mal damit an, dir einen Timer aufzusetzen um damit die Zeitbasis für den Interrupt hinzukriegen. Also erste Übung könntest du ja mal mit dem Timer eine blinkende LED machen. Ach ja: In deinem Programm werden da natürlich nicht die Zahlenwerte 150, 250 und 1500 auftauchen. Die korrekten Werte hängen davon ab, wie du den Timer konfigurierst und in welchen Zeitabständen ein Interrupt generiert wird.
Die Strategie macht ein gutes Programm aus. Im ersten Schritt haben wir festgestellt, dass es besser ist, Pulslängen zu bestimmen und daraus die Datenbits zu ermitteln, als auf eine "1" oder eine "0" zu warten und darüber zu grübeln ob der Empfänger die richtige Signalpolarität hat. Die Idee, solange zu zählen, wie Spannung anliegt, ist sicher zum funktionieren zu bringen. Es ist wesentlich besser, statt dessen mit einem Timer des Controllers definierte Zeitimpulse zu erzeugen und diese zu zählen. (Wenn man mit der Armbanduhr in der Hand eine Zeit mißt, macht man das ähnlich) Die Idee, mit dem (unbekannten) DCF-Signal Interupts auszulösen, führt dann zu Problemen, wenn Störimpulse vorhanden sind. Das ist dann aufwendig zu umschiffen. Es ist sicher eine gute Idee, den von Karl Heinz vorgeschlagenen Weg zu verfolgen und zum funktionieren zu bringen. Viel Erfolg Joachim
Zitat: Die Idee, solange zu zählen, wie Spannung anliegt, ist sicher zum funktionieren zu bringen. Es ist wesentlich besser, statt dessen mit einem Timer des Controllers definierte Zeitimpulse zu erzeugen und diese zu zählen. (Wenn man mit der Armbanduhr in der Hand eine Zeit mißt, macht man das ähnlich) Diese Idee habe ich jetzt wiegesagt auch in Basic umgesetzt. Wenn die entsprechenden Bauteile für die Schaltung bei mir sind und ich alles miteinander verschaltet habe und ich den entsprechenden Programmiercode in das Flash-Rom des Atmel übertragen habe, werde ich bei erfolgreichem Lauf der Funkuhr den Basic-Programmiercode hier veröffentlichen. Wiegesagt baut diese Funktionsart auf einer anderen Idee auf "und theoretisch sehe ich in diesem Programmiercode auch keine Probleme" Bis dann
frank wrote:
> in bascom basic genügt ein befehl.
Kann man auch den Quelltext sehen, der hinter diesem Befehl steckt ?
Wäre nämlich sehr wichtig, um festzustellen, ob und wie fehlertolerant
dieser Befehl ist (Parity-Check, Timingcheck, Störungsüberbrückung
usw.).
Peter
alle checks werden gemacht kannst dir ja das lib file anschauen habe schon eine uhr am laufen mit uhr und wecker + temperaturanzeige und funkübertragen mit Kaffeemascine an.
frank wrote:
> alle checks werden gemacht kannst dir ja das lib file anschauen
Welches Lib-File ?
Kannst Du es schicken ?
Natürlich nur, wenn es auch Quelltext ist, im Objektformat kann man ja
nichts erkennen.
Peter
Ich glaub, ich habs gefunden: http://www.roboternetz.de/wissen/index.php/DCF77-Decoder_als_Bascom-Library#Software Ist aber alles in Assembler, da braucht man ne Weile zum Durchsteigen. Peter
dcf77.lib ist im copiler verbaut den dcf77.bas code habe ich aus irgent einem forum gesaugt mist muss mal meine favorieten checken.
Den Programmiercode werde ich erst dann veröffentlichen, wenn dieser auch läuft......... Aber zu 99,99% ist er lauffähig.
frank wrote: > dcf77.lib ist im copiler verbaut den dcf77.bas code habe ich aus irgent > einem forum gesaugt mist muss mal meine favorieten checken. Ist Dein Programm ähnlich sorgfältig geschrieben wie Dein Posting?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.