[img]
http://www.mdcc-fun.de/k.helbing/DCF77/DCF77.jpg
[/img]
Der Eingangs-Widerstand sollte nicht kleiner als 1 MOhm sein, da der Ausgang des Moduls nur mit max. 5 µA belastet werden darf. Wird eine ungeregelte oder andere Versorgungs-Spannung verwendet, sollte die Spannung für das Modul z.B. mit einer Zener-Diode stabilisiert werden, max. sind 3,3 Volt zulässig.
Als Schnittstelle zum PC bietet sich der serielle Port an; wird von PB direkt unterstützt und der kleine Bastelfreund hat sicher an seinem PC sowas zumindest nachgerüstet.
Für die Abfrage habe ich RI (Ring-Indicator) verwendet (liegt so schön auffindbar direkt unter Masse).
Und hier der Code, der sicher noch verbessert werden kann:
Code: Alles auswählen
;- Dekodierung des DCF77-Signals
;- verwendete Hardware: DCF-Empfangsmodul DCF1 von Pollin
;- "Helle" Klaus Helbing, 27.06.2015, PB 5.31 (x64)
;- siehe auch: https://de.wikipedia.org/wiki/DCF77
Declare.l ReadValues()
Declare.l Fehler()
Global T1.q
Global T2.q
Global Sekunde.l
Global IsHigh.l
Global IsLow.l
Global Dim BCD.l(7)
BCD(0) = 1
BCD(1) = 2
BCD(2) = 4
BCD(3) = 8
BCD(4) = 10
BCD(5) = 20
BCD(6) = 40
BCD(7) = 80
Global Dim WTag.s(7)
WTag(0) = "Fehler!"
WTag(1) = "Montag"
WTag(2) = "Dienstag"
WTag(3) = "Mittwoch"
WTag(4) = "Donnerstag"
WTag(5) = "Freitag"
WTag(6) = "Samstag"
WTag(7) = "Sonntag"
Global Dim JMonat.s(12)
JMonat(0) = "Fehler!"
JMonat(1) = "Januar"
JMonat(2) = "Februar"
JMonat(3) = "März"
JMonat(4) = "April"
JMonat(5) = "Mai"
JMonat(6) = "Juni"
JMonat(7) = "Juli"
JMonat(8) = "August"
JMonat(9) = "September"
JMonat(10) = "Oktober"
JMonat(11) = "November"
JMonat(12) = "Dezember"
Global Dim TMonat.l(12)
TMonat(0) = 0
TMonat(1) = 31
TMonat(2) = 28 ;Schaltjahr wird extra ermittelt
TMonat(3) = 31
TMonat(4) = 30
TMonat(5) = 31
TMonat(6) = 30
TMonat(7) = 31
TMonat(8) = 31
TMonat(9) = 30
TMonat(10) = 31
TMonat(11) = 30
TMonat(12) = 31
Global Dim RI.l(59)
Global AktBitNeu$ = ""
Global AktBitAlt$ = ""
Global Verlauf$ = ""
Legende$ = "M Wetter-Daten RAZZAS Min. P St. P MTag WT Mon. Jahr P-"
;Sekunde Legende
;00 M: Beginn neue Minute, immer "0"
;01-14 Wetter-Daten: Wetterinformationen der Firma MeteoTime
;15 R: Rufbit
;16 A: Ankündigung Wechsel MEZ/MESZ bzw. MESZ/MEZ am Ende dieser Stunde
;17 Z: Zonenbit1 "0": MEZ, "1": MESZ
;18 Z: Zonenbit0 "0": MESZ, "1": MEZ
;19 A: Ankündigung Schaltsekunde am Ende dieser Stunde
;20 S: Startbit der Zeitinformation, immer "1"
;21-27 Min.: BCD-codierte Minute (7 Bits 1,2,4,8,10,20,40)
;28 P: Paritätsbit der Minute (even Parity, Sekunden-Bits 21-27
;29-34 St.: BCD-codierte Stunde (6 Bits 1,2,4,8,10,20)
;35 P: Paritätsbit der Stunde (even Parity, Sekunden-Bits 29-24)
;36-41 MTag: BCD-codierter Tag (6 Bits 1,2,4,8,10,20)
;42-44 WT: BCD-codierter Wochentag (3 Bits 1,2,4) 1=Montag 7=Sonntag
;45-49 Mon.: BCD-codierter Monat (5 Bits 1,2,4,8,10)
;50-57 Jahr: BCD-codierte Jahrzahl (8 Bits 1,2,4,8,10,20,40,80) ohne Jahrhundert, auf "20" gesetzt
;58 P: Paritätsbit des Datums (even Parity, Sekunden-Bits 36-57)
;59 -: keine Sekundenmarke
Trenner$ = "=--------------=-=-=-=======-======-======---=====--------="
For i = 1 To 256
If OpenSerialPort(0, "COM" + Str(i), 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 256, 256)
If IsSerialPort(0)
Port = i
CloseSerialPort(0)
Break
EndIf
CloseSerialPort(0)
EndIf
Next
If Port = 0
MessageRequester("Fehler!", "Kann keine verfügbare COM-Schnittstelle finden!")
End
EndIf
If OpenSerialPort(0, "COM" + Str(Port), 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 256, 256)
If OpenWindow(0, 0, 0, 500, 330, "Helles DCF77 PC: COM" + Str(Port), #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
StickyWindow(0, 1)
FontHigh = Int(10.0 / (GetDeviceCaps_(GetDC_(WindowID(0)), #LOGPIXELSY) / 96.0)) ;Font anpassen
LoadFont(0, "Courier New", FontHigh) ;proportional
TextGadget(1, 10, 5, 100, 15, "Stunde:")
TextGadget(2, 190, 5, 300, 15, "??")
TextGadget(3, 10, 20, 100, 15, "Minute:")
TextGadget(4, 190,20, 300, 15, "??")
TextGadget(5, 10, 35, 100, 15, "Wochentag:")
TextGadget(6, 190, 35, 300, 15, "??")
TextGadget(7, 10, 50, 100, 15, "Tag:")
TextGadget(8, 190, 50, 300, 15, "??.")
TextGadget(9, 10, 65, 100, 15, "Monat:")
TextGadget(10, 190, 65, 300, 15, "??")
TextGadget(11, 10, 80, 100, 15, "Jahr:")
TextGadget(12, 190, 80, 300, 15, "20" + "??")
TextGadget(13, 10, 100, 170, 15, "Umstellung MEZ/MESZ:")
TextGadget(14, 190, 100, 300, 15, "????")
TextGadget(15, 10, 115, 150, 15, "Aktuell MEZ/MESZ:")
TextGadget(16, 190, 115, 300, 15, "????")
TextGadget(17, 10, 130, 150, 15, "Schalt-Sekunde:")
TextGadget(18, 190, 130, 300, 15, "????")
TextGadget(19, 10, 155, 80, 15, "Status:")
TextGadget(20, 190, 155, 300, 15, "Warte auf Signal an RI")
TextGadget(21, 10, 180, 150, 15, "Low-Level-Zeit:")
TextGadget(22, 190, 180, 300, 15, "????ms")
TextGadget(23, 10, 195, 150, 15, "High-Level-Zeit:")
TextGadget(24, 190, 195, 300, 15, "????ms")
TextGadget(25, 10, 220, 480, 15, "0 1 2 3 4 5")
TextGadget(26, 10, 235, 480, 15, "012345678901234567890123456789012345678901234567890123456789")
TextGadget(27, 10, 250, 480, 15, AktBitNeu$)
TextGadget(28, 10, 265, 480, 15, AktBitAlt$)
TextGadget(29, 10, 280, 480, 15, Trenner$)
TextGadget(30, 10, 295, 480, 15, Legende$)
TextGadget(31, 10, 310, 480, 15, Verlauf$)
For i = 1 To 31
SetGadgetFont(i, FontID(0))
Next
AddWindowTimer(0, 0, 5)
While GetSerialPortStatus(0, #PB_SerialPort_RI) = 0 ;also RI = Low
If WaitWindowEvent() = #PB_Event_CloseWindow
CloseSerialPort(0) ;zur Sicherheit
End
EndIf
Delay(5)
Wend
SetGadgetText(20, "Anfang neue Minute wird gesucht")
IsHigh = 1
BindEvent(#PB_Event_Timer, @ReadValues())
T1 = ElapsedMilliseconds()
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
EndIf
CloseSerialPort(0)
Else
MessageRequester("Fehler!", "Kann die gewählte COM-Schnittstelle nicht öffnen!")
EndIf
End
Procedure.l ReadValues()
Port_Status_RI = GetSerialPortStatus(0, #PB_SerialPort_RI)
If Port_Status_RI And IsLow ;also RI = High. Praktisch steigende Flanke = Sekunden-Beginn
IsHigh = 1
IsLow = 0
If Sekunde > 59
SetGadgetText(20, "Fehler. Suche Anfang neue Minute")
Verlauf$ + "Ü" ;Überlauf
Fehler()
ProcedureReturn
EndIf
T2 = ElapsedMilliseconds()
RI_Status_Dauer = T2 - T1
If RI_Status_Dauer > 750 And RI_Status_Dauer < 850
SetGadgetText(22, "Sekunde " + Str(Sekunde) + "-" + Str(Sekunde + 1) + ": " + Str(RI_Status_Dauer) + "ms")
Sekunde + 1
ElseIf RI_Status_Dauer >= 850 And RI_Status_Dauer < 950
SetGadgetText(22, "Sekunde " + Str(Sekunde) + "-" + Str(Sekunde + 1) + ": " + Str(RI_Status_Dauer) + "ms")
Sekunde + 1
ElseIf RI_Status_Dauer > 1750 ;Ende Minute
SetGadgetText(22, "Sekunde " + Str(Sekunde) + "-" + Str(Sekunde + 1) + ": " + Str(RI_Status_Dauer) + "ms")
If Sekunde = 58
SetGadgetText(20, "") ;oder Text
If RI(0) = 1
SetGadgetText(20, "Fehler. Suche Anfang neue Minute")
Verlauf$ + "x" ;Start-Fehler
Fehler()
ProcedureReturn
EndIf
If RI(16) ;1: Am Ende dieser Stunde wird MEZ/MESZ umgestellt
SetGadgetText(14, "Ja, am Ende dieser Stunde")
Else
SetGadgetText(14, "Nein, nicht am Ende dieser Stunde")
EndIf
If RI(19) ;1: Am Ende dieser Stunde wird eine Schaltsekunde eingefügt
SetGadgetText(18, "Ja, am Ende dieser Stunde")
Else
SetGadgetText(18, "Nein, nicht am Ende dieser Stunde")
EndIf
If RI(17) = RI(18) ;17: 0=MEZ, 1= MESZ; 18: 0=MESZ, 1=MEZ
SetGadgetText(20, "Fehler. Suche Anfang neue Minute")
Verlauf$ + "Z" ;Zeitzonen-Fehler
Fehler()
ProcedureReturn
Else
If RI(17)
SetGadgetText(16, "MESZ")
Else
SetGadgetText(16, "MEZ")
EndIf
EndIf
If RI(20) = 0
SetGadgetText(20, "Fehler. Suche Anfang neue Minute")
Verlauf$ + "z" ;Start-Fehler
Fehler()
ProcedureReturn
EndIf
Minute = RI(21) + (RI(22) * 2) + (RI(23) * 4) + (RI(24) * 8) + (RI(25) * 10) + (RI(26) * 20) + (RI(27) * 40)
If Minute < 60
SetGadgetText(4, RSet(Str(Minute), 2, "0"))
Else
SetGadgetText(4, "Fehler! Minute > 59")
Verlauf$ + "m"
Fehler()
ProcedureReturn
EndIf
PariTest = 0 ;Minute
For i = 21 To 27 ;Minuten-Bits, s.o.
PariTest + RI(i)
Next
If ((PariTest & 1) - RI(28)) <> 0
SetGadgetText(20, "Fehler Parität Minute!")
Verlauf$ + "m"
Fehler()
ProcedureReturn
EndIf
Stunde = RI(29) + (RI(30) * 2) + (RI(31) * 4) + (RI(32) * 8) + (RI(33) * 10) + (RI(34) * 20)
If Stunde < 24
SetGadgetText(2, RSet(Str(Stunde), 2, "0"))
Else
SetGadgetText(2, "Fehler! Stunde > 23")
Verlauf$ + "S"
Fehler()
ProcedureReturn
EndIf
PariTest = 0 ;Stunde
For i = 29 To 34
PariTest + RI(i)
Next
If ((PariTest & 1) - RI(35)) <> 0
SetGadgetText(20, "Fehler Parität Stunde!")
Verlauf$ + "s"
Fehler()
ProcedureReturn
EndIf
Wochentag = RI(42) + (RI(43) * 2) + (RI(44) * 4)
If Wochentag < 8 And Wochentag > 0
SetGadgetText(6, WTag(Wochentag))
Else
SetGadgetText(6, "Fehler! Wochentag > 7")
Verlauf$ + "W"
Fehler()
ProcedureReturn
EndIf
MTag = RI(36) + (RI(37) * 2) + (RI(38) * 4) + (RI(39) * 8) + (RI(40) * 10) + (RI(41) * 20)
SetGadgetText(8, RSet(Str(MTag), 2, "0") + ".") ;Check weiter unten
Monat = RI(45) + (RI(46) * 2) + (RI(47) * 4) + (RI(48) * 8) + (RI(49) * 10)
If Monat < 13 And Monat > 0
SetGadgetText(10, JMonat(Monat))
Else
SetGadgetText(10, "Fehler! Monat > 12")
Verlauf$ + "M"
Fehler()
ProcedureReturn
EndIf
Jahr = RI(50) + (RI(51) * 2) + (RI(52) * 4) + (RI(53) * 8) + (RI(54) * 10) + (RI(55) * 20) + (RI(56) * 40) + (RI(57) * 80)
If Jahr < 100 ;And Jahr > 14
SetGadgetText(12, "20" + RSet(Str(Jahr), 2, "0"))
Else
SetGadgetText(12, "Fehler! Jahr > 99")
Verlauf$ + "J"
Fehler()
ProcedureReturn
EndIf
PariTest = 0 ;für Datum
For i = 36 To 57
PariTest + RI(i)
Next
If ((PariTest & 1) - RI(58)) <> 0
SetGadgetText(20, "Fehler Parität Datum!")
Verlauf$ + "d"
Fehler()
ProcedureReturn
EndIf
If Monat = 2 And Jahr % 4 = 0 ;Februar
MTag - 1 ;Korrektur für Schaltjahr
EndIf
If MTag > TMonat(Monat)
SetGadgetText(8, "Fehler! Tag stimmt nicht!")
Verlauf$ + "t"
Fehler()
ProcedureReturn
EndIf
Verlauf$ + "0" ;Null für alles o.K.
SetGadgetText(31, Verlauf$)
SetGadgetText(27, AktBitNeu$)
SetGadgetText(22, "Sekunde " + Str(Sekunde + 1) + ": " + Str(RI_Status_Dauer) + "ms")
SetGadgetText(20, "Aktuell. Neue Minute hat begonnen")
AktBitAlt$ = AktBitNeu$
SetGadgetText(28, AktBitAlt$)
SetGadgetColor(28, #PB_Gadget_FrontColor, $008800)
AktBitNeu$ = ""
Else
SetGadgetText(20, "Evtl. Minuten-Anfang gefunden")
AktBitNeu$ = ""
Verlauf$ + "A"
SetGadgetText(31, Verlauf$)
EndIf ;Sekunde = 58
Sekunde = 0
EndIf ;If RI_Status_Dauer > 750 And RI_Status_Dauer < 850
;---------------------------------------------------
ElseIf Port_Status_RI = 0 And IsHigh ;also RI = Low. Praktisch fallende Flanke = Ende Impuls
IsHigh = 0
IsLow = 1
T1 = ElapsedMilliseconds()
If Sekunde > 59
Sekunde = 0
SetGadgetText(20, "Fehler. Suche Anfang neue Minute")
AktBitNeu$ = ""
SetGadgetText(27, AktBitNeu$)
Verlauf$ + "Ü" ;Überlauf
SetGadgetText(31, Verlauf$)
T1 = ElapsedMilliseconds()
ProcedureReturn
EndIf
RI_Status_Dauer = T1 - T2
If RI_Status_Dauer >= 150 And RI_Status_Dauer < 250 ;Spielraum muss sein
RI(Sekunde) = 1
AktBitNeu$ + "1"
SetGadgetText(27, AktBitNeu$)
ElseIf RI_Status_Dauer >= 50 And RI_Status_Dauer < 150
RI(Sekunde) = 0
AktBitNeu$ + "0"
SetGadgetText(27, AktBitNeu$)
ElseIf RI_Status_Dauer < 50
Fehler()
EndIf
SetGadgetText(24, "Sekunde " + Str(Sekunde) + ": " + Str(RI_Status_Dauer) + "ms")
If Len(Verlauf$) > 59
Verlauf$ = Mid(Verlauf$, 2, 59)
EndIf
EndIf
EndProcedure
Procedure.l Fehler()
AktBitNeu$ = ""
SetGadgetText(27, AktBitNeu$)
SetGadgetText(31, Verlauf$)
T1 = ElapsedMilliseconds()
Sekunde = 0
EndProcedure
[img]
http://www.mdcc-fun.de/k.helbing/DCF77/Screen-DCF.png
[/img]
Gruß
Helle