Aktuelle Zeit: 22.07.2018 14:49

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Kleine DCF77-Bastelei
BeitragVerfasst: 27.06.2015 18:49 
Offline
Benutzeravatar

Registriert: 11.11.2004 16:13
Wohnort: Magdeburg
Bei meiner letzten Pollin-Bestellung konnte ich nicht widerstehen und habe deren DCF77-Modul mitbestellt (knapp 5 €). Im Gegensatz zu anderen Modulen (z.B.Conrad) muss man selbst noch etwas Elektronik dazu aufbauen; genau das Richtige. Schaltungs-Vorschläge findet man einige, aber was der eine empfiehlt, ist für den anderen großer Käse, z.B. als Eingang erstmal einen Schmitt-Trigger zu setzen. Da der Oszi aber am Modul-Ausgang schon brauchbare Rechteck-Signale zeigte, habe ich auch darauf verzichtet. Hier meine Schaltung:
[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:
;- 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

Das Ergebnis sieht dann etwa so aus:
[img]
http://www.mdcc-fun.de/k.helbing/DCF77/Screen-DCF.png
[/img]

Gruß
Helle


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Kleine DCF77-Bastelei
BeitragVerfasst: 27.06.2015 20:40 
Offline
Benutzeravatar

Registriert: 14.08.2007 15:41
Wohnort: Lelbach
Helle hat geschrieben:
Bei meiner letzten Pollin-Bestellung konnte ich nicht widerstehen...
Ja...das kenne ich! Ist halt der Reiz, etwas interessantes zu haben, was man aber nicht wirklich braucht! :mrgreen:

Stand letztens im Aldi und habe mit mir gekämpft, die per Internet fernsteuerbare Überachungskammera mit IR-Beleuchtung für lumpige 49,-€ NICHT zu kaufen....es gab -trotz krampfhaftem Nachdenkens- definitiv keinen plausiblen Einsatzzweck :mrgreen:

_________________
- alles was ich hier im Forum sage/schreibe ist lediglich meine Meinung und keine Tatsachenbehauptung
- unkommentierter Quellcode = unqualifizierter Müll


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Kleine DCF77-Bastelei
BeitragVerfasst: 29.06.2015 00:05 
Offline
Benutzeravatar

Registriert: 26.06.2008 10:42
Hui, da kommt der Elektroniker in mir wieder hoch.

Damit solltest du am Dienstag gegen Mitternacht (30. Juli 2015) eine Schaltsekunde beobachten können, ein Screenshot ab 23:00 wär interessant ;)

Gruß, Alex

_________________
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Kleine DCF77-Bastelei
BeitragVerfasst: 29.06.2015 11:30 
Offline
Admin
Benutzeravatar

Registriert: 29.08.2004 11:27
Toll, wie einfach das geht. Danke für das Teilen :allright:

Gruß,
Falko

_________________
Bild
Win10 Pro 64-Bit, PB_5.4,GFA-WinDOS, Powerbasic9.05-Windows, NSBasic/CE, NSBasic/Desktop, NSBasic4APP, EmergenceBasic


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye