Forum: Mikrocontroller und Digitale Elektronik Atmega644 DCF77_Dekodierung


von Michael B. (michaelba)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

zur Messung des  High-Pegels des  DCF77-Signals  habe ich die im Anhang 
dargestellte Funktion geschrieben.

Das für viele mit Sicherheit sofort ersichtliche Problem ist,
dass die Variable array_count für die gesamte Zeitspanne, für die die 
if-Bedingung gilt immer wieder  inkrementiert wird, anstatt nur einmal.

Fixe Werte (nämlich 200 und 100) haben wenig Sinn, da diese so gut wie 
nie auf die ms genau zutreffen.

Die Stelle des Arrays soll den binären Wert 1 oder 0 zugewiesen 
bekommen, danach soll die Variable (einmal) inkrementiert werden.

Hat jemdand eine Lösung?

Gerne auch switch/ case oder Ähnliches.Andere Kritik ebenso erwünscht.

Vielen Dank im Voraus
Michael

von Peter D. (peda)


Lesenswert?

Quelltexte immer als *.c posten !!!

von Joachim B. (jar)


Lesenswert?

ich hatte Peter Danneggers DCF77 genommen
Beitrag "DCF77 Uhr in C mit ATtiny26" z.B.

auf Arduino und mega1284p in die IRQ zur Tastenentprellung portiert

war einfacher als meinen PC Code für lcc32 umzuschreiben

von Dominik B. (odysseus1710)


Lesenswert?

Du solltest vielleicht erstmal schildern, was dein Programm genau macht, 
das ist mir nicht ganz ersichtlich.
Vermutlich rufst du in einer Schleife immer wieder
1
dcf77_anlys
 auf und unterscheidest zuerst auf Low oder High Pegel.

Ich nehme an die Variable
1
dcf77_level_pw
 soll zählen, wie lange der High-Pegel ist, damit du zwischen '0' und 
'1' unterscheiden kannst ?

Wo wird diese denn inkrementiert? Gibt es ein Timer, der diese jede ms 
inkrementiert?

Und wie du bereits selbst festgestellt hast, wird das so nicht 
funktionieren, da
1
dcf77_anlys
 wohl andauernd aufgerufen wird.

Ein erster Schritt wäre ein PinChangeInterrupt für PD2, der nur 
aufgerufen wird, wenn ein Flankenwechsel an besagtem Pin auftritt. Damit 
erübrigt sich dein Problem.

von Maxx (Gast)


Lesenswert?

Am Einfachsten, wenn du nicht auf den Pegel reagierst, sondern auf die 
Änderung des Pegels. Da ich dir nicht empfehlen würde dies per Interrupt 
zu machen bedeutet das für deinen Code:

Speichere zwischen, wie der letzte Pegel war und werte bei jedem neuen 
Durchlauf aus, ob der Pegel im letzten Durchgang der gleiche war.



Nichtsdestotrotz solltest du dir vorher noch einige Gedanken machen:
- Dein DCF Signal ist ein Störbehaftetes Signal. Deine 100ms/200ms 
können von einzelnen Spitzen unterbrochen werden. (Stichwort 
Entprellung, welches auch Hinweis auf die konklrete Lösung deiner ersten 
Frage ist)
- Vielleicht macht es Sinn, nicht die 100ms/200ms der Austastlücke zu 
berechnen, sondern die 800,900 oder >=1800 ms des Signals.
- Gib Magic Numbers, wenn nötig namen und ein #define. Macht das 
"feintunen" einfacher, da du nur einen Wert anpassen musst.
- Sind die meisten Magic-Numbers überhaupt nötig?
- Was ist mit dem nicht abgedeckten Wertebereich?

Dominik B. schrieb:

> Ein erster Schritt wäre ein PinChangeInterrupt für PD2, der nur
> aufgerufen wird, wenn ein Flankenwechsel an besagtem Pin auftritt. Damit
> erübrigt sich dein Problem.

Bitte nicht. Bei jedem kleinen Empfangsproblem und Flackern am PIN hängt 
der uC dann nur noch im IRQ. Wenn IRQ, dann einen regelmäßigen Timer.

von Joachim B. (jar)


Lesenswert?

Maxx schrieb:
> Wenn IRQ, dann einen regelmäßigen Timer.

sag ich doch der 10ms Timer kann Tasten entprellen und noch Impulse vom 
DCF sammeln.

von Jakob (Gast)


Lesenswert?

Die Strategie, die empfangene Zeit der Trägerabsenkung
so genau auszuwerten, um zwischen Low und High zu
unterscheiden, macht "den Empfang" nicht besser, als die
simple Entscheidung, Trägerabsenkung kürzer, oder länger,
als 150 ms.

Für die Decodierung ist es vorteilhafter, den Beginn der
Trägerabsenkung zu betrachten:

Ist der Beginn einer Trägerabsenkung 970...1030 ms (oder auch
beim Minutenbeginn 1970...2030 ms) nach Beginn der vorigen
Trägerabsenkung, dürfte das Signal gültig sein.
Eine Abtastung 150 ms nach Beginn der Trägerabsenkung (noch
abgesenkt, oder nicht mehr abgesenkt) liefert den Bit-Wert.

Den Rest macht die Plausibilitätsprüfung des Auswerteprogramms.
- Parity-Check
- Logische Abfolge des Zeitablaufs:
  Dazu sollte dein Programm aber gut Bescheid wissen, wie die
  nächste Minute aussehen muss:
  Dass z.B. auf JJ-02-28 23:59 nur JJ-02-29 00:00 folgen kann,
  wenn JJ ohne Rest durch 4 teilbar ist...
  Das braucht 2 vollständig dekodierte Zeittelegramme.


Ob man den Beginn der Trägerabsenkung mit Interrupt, oder
Polling erfasst, ist wurscht, wenn das oben beschriebene
Abstandskriterium ausgewertet wird. (Auch wenn es in diesem
Forum verbale Glaubenskriege darum gibt...)

Ob die Trägerabsenkung aus deinem Empfänger als High-, oder
Low-Signal kommt, kannst du mit einer LED testen.
Absenkung 100...200 ms ist sichtbar kürzer, als der Rest von
800...900 ms.

Meine Experimente mit den billigsten Empfängermodulen in etwa
450 km Entfernung vom DCF lieferten mit dieser Strategie und mit
Interrupt, oder Polling immer (außer bei Gewitter) meist 3,
nur manchmal erst 5 Minuten nach dem Einschalten eine korrekte (!)
Zeitanzeige.

Das Empfangsmodul sollte nur nicht zu dicht an den üblichen
Störquellen platziert werden. (Dagegen hilft auch deine
Strategie nicht viel.)

von Michael B. (michaelba)


Angehängte Dateien:

Lesenswert?

Hallo an alle,

vielen Dank erstmal für die ausführlichen Kommentare und die Hilfe.
Hier die Details:
@ Peter Dannegger:
  siehe Anhang

@ Joachim B.:
  Danke, werde ich anschauen

@ Dominik B.:
Du hast es im Prinzip ohne genaue Erklärung schon erfasst.
Siehe main routine while(1).
Ja, es gibt einen Timer, der jede ms in die ISR hüpft und
dcf77_level_pw inkrementiert.

@Maxx:
Danke für den Hinweis. Ich verwende später den invertierten Ausgang des
Moduls, also mache ich im Prinzip das, was du meinst.
Danke für den #define-Tipp.

@ Jakob:
Danke Dir für den Hinweis/ Erfahrungsbericht/ die Überlegungen. Die 
Empfangsprobleme der Module sind mir bekannt, jedoch  betreibe ich die 
„Uhr“ gerade noch mit einem zweiten µC (Atmega8), dem ich eine 
„Beipielminute“ einprogrammiert habe, die er als Signal an einem Pin 
ausgibt. So möchte ich zunächst mal den Algorithmus des Atmega 644 
testen.


Freundliche Grüße
Michael

von Jakob (Gast)


Lesenswert?

EINE Beispielminute ist für den Test des Empfangsalgorithmus
nicht sonderlich hilfreich. Sooo schwer ist es auch nicht eine
DCF-Simulation zu programmieren: 1999 war das notwendig, um
die Reaktion schlechter Datums-Software auf den Jahrtausendwechsel
zu testen.

So einen Simulator mit beliebiger Startzeit und real ablaufender
Uhr + Kalender inklusive Sommerzeit und Schaltsekunde mitsamt 
Vorankündigungsbits kann man mit einem ATTiny-µC realisieren.

Aber - Super-Idee, werde mal versuchen, meinen Simulator um
die üblichen Funkweg-Probleme zu erweitern! ;-)  ;-)
- Also die Auswirkung von Fading und Laufzeit-Verschiebungen
  auf die Standard-Empfangsmodule.

Statische, oder gar pulsförmige Nahfeldstörungen sind aber
einfacher durch günstigere Positionierung der Antenne, bzw.
des Empangsmoduls zu minimieren.

Auch bei sehr schlechtem Empfang hilft die exakte Erkennung
der Trägerabsenkungsdauer nicht. Dagegen gibt es Programmansätze,
die sich aus einer längeren Abfolge von gestörten Telegrammen mit
logischer (!) Filterung die höchstwahrscheinliche DCF-Zeit
errechnen. Die längere Abfolge kann dann auch mal eine Stunde,
oder mehr umfassen.

Gut ist es, diesen Programmen die geschätzte Zeit als Startwert
vorzugeben...

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
Noch kein Account? Hier anmelden.