Shop OBEX P1 Docs P2 Docs Learn Events
DCF77 signal — Parallax Forums

DCF77 signal

TumblerTumbler Posts: 323
edited 2009-10-11 19:10 in BASIC Stamp
Hello,

I have a dcf77 module but have a problem reading its output.

quote from wikipedia: A 0.1 second reduction denotes a binary 0, a 0.2 second reduction denotes a binary 1. As a special case, the last second of every minute is marked with no carrier power reduction.

How can i measure the pulse time with a bs2pe so i can create a new binary string. The problem is also, how to start a new string. (there is no signal in the last second )

dcf77 wiki: http://en.wikipedia.org/wiki/DCF77

regards

·

Comments

  • dev/nulldev/null Posts: 381
    edited 2009-10-06 18:26
    You can't use COUNT, as it will not provide accurate enough timing, and the max. pulse width for PULSIN is 123.6 ms, so that won't do.

    I am thinking this will be very difficult to accomplish with a Stamp, as you need precise timing within the second to measure the pulses. Maybe there are A/D converters that can help you. I am even thinking a 555 timer circuit could do.

    The difficult part is to syncronize with the signal. You need to look for an unreduced second followed by a zero bit, then set of a trigger that goes for 59 seconds, then start the syncrionization again.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Don't worry. Be happy
  • C-BobC-Bob Posts: 19
    edited 2009-10-06 19:43
    Sync maybe not to hard, Tip: only one diference between two minuts. You must find minute bits. Also only one chnge indicate good quality of signal and valid data. After you have right time, you need only second sync pulse.

    555 in monostabile mode is great idea if you right calculate time constant you have decoded output 0 and 1

    Of course, one big minus in basic stamp chips is absence of interupts (i didnt find it...).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    C-Bob

    Every problem·have at least one·nice, simply and·wrong solution.
  • Larry~Larry~ Posts: 242
    edited 2009-10-06 20:25
    Lets see If I have this every second has a pulse of either 100ms = 0 or 200ms = 1 except the 59th bit which has no output, so if we look for this one second period prior to the start of bit 1 and use it for sync. so pulsin and keep looking for a 1 second period of no output.
  • Larry~Larry~ Posts: 242
    edited 2009-10-07 01:34
    here are a couple of timming programs from Tracy Allen's site that could help if pulsin does not work


    ' snippet measures the time P0 stays low.
    xc var word
    loop1: ' 1418 loops per second, 7.05E-4 seconds per loop
    xc=xc+1
    branch in0,[noparse][[/noparse]loop1] ' count until in0 goes high

    ' snippet measures the time P0 stays high.
    xc var word
    loop2: ' 1426 loops per second, 7.013E-4 seconds per loop
    xc=xc+1
    if in0 then loop2 ' count until in0 goes low
    debug dec xc**45960,cr ' ** converts the count to straight milliseconds
  • TumblerTumbler Posts: 323
    edited 2009-10-07 10:03
    Ok thx all.
    After some test with rctime, pulsin and branch,i got this.

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    ' {$PORT COM4}
     
    i VAR Word
    xc VAR Word
    
     
    INPUT 0    ' input from dcf module
     
    DEBUG "Searching signal...",CR
      search:
        xc=xc+1
        BRANCH IN0,[noparse][[/noparse]search] ' count until in0 goes high
          i = xc**45960
          IF i>1900 THEN init
          xc=0
        GOTO search
      init:
        DEBUG "Initialize...",CR
        xc=0
        GOTO search
    

    It seems that i found the 'empty' second.
    Now it's time to get those signals [noparse]:)[/noparse]
    plz correct me if i'm on the wrong way...
  • dev/nulldev/null Posts: 381
    edited 2009-10-07 10:17
    I don't understand how you will get a HIGH or LOW signal from the device. It differs in value only 25% from the normal, and lasts only a fraction of a second...

    But the problem is that you need to convert the signal to a bit stream. This will add (unknown) time delays to your program, and you will get out of sync with the signal.

    Suggested solution:
    A) Make a 555 astable circuit that produces a pulse every second.
    B) Make a monostable 555 circuit that is triggered from the first one and lasts 200 ms.
    C) The first 555 circuit (A) triggers a transistor that sends a HIGH signal to a Stamp pin.
    D) The second 555 circuit (B) triggers a transistor the enables an A/D converter for 200 ms.
    E) Loop the Stamp and check the value of the A/D whenever C) is HIGH, which will give you the right value for the bit that's processed.

    Then you need something to syncronize the signal (to start the 555 timer circuit) at every minute, which can be in a similar manner.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Don't worry. Be happy

    Post Edited (dev/null) : 10/7/2009 10:25:20 AM GMT
  • TumblerTumbler Posts: 323
    edited 2009-10-07 10:37
    dev/null said...
    This will add (unknown) time delays to your program
    I noticed [noparse]:)[/noparse]

    I think i have to build something like dev/null said.

    thx

    Post Edited (Tumbler) : 10/7/2009 10:43:04 AM GMT
  • Larry~Larry~ Posts: 242
    edited 2009-10-07 14:53
    I posted somthing for you to try, if this pulsin loop value times out and has a 0 value your synced
    now as far as the timing I think pulsin will work for each line and why do you need a string you need to store bits about 3.7 words worth.
    there is a 50% difference in value 0 being 100mS and a 1 being 200mS so a pulsin will read these values with ease.
    do a pulsin loop, read the value figure which it is a 0 or 1 store it in a bit value and return to the top of the pulsin loop.
    the biggest pulse is 200mS that gives you 800mS to do your compare and store your value in a bit variable you may have too much time and could serout or debug out the bits one at a time as pulsin times out at .131mS if no pulse is seen.

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}

    sync VAR Word

    Sync_Second:
    DO
    PULSIN 1,0,sync
    LOOP WHILE sync > 100
  • Larry~Larry~ Posts: 242
    edited 2009-10-07 15:21
    This is the way Im thinking, try something like this below. now it can be cleaned up but Im trying to show the Idea.

    this is close to the way you would read the value of IR remote control, work with this a little and see if you can make it work.

    sync_second if sync second returns a value of 0 or 100 or less then its in the blank second and you should go to read_pulses now you may need a debug at the end of this section saying start or something, as the pulsin will end in .131mS and you have over 800mS of wait time·before the start of the first read. and then you just start reading the values as there sent, you will need to format the debug statement for your own needs try to get all values on one line. You will maybe need a counter that will stop at 58 and go back to the sync_second loop. you could even use The timing lines from Tracy Allens site instead of pulsin.· Im seeing a couple of ways to do this.

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}

    sync· VAR Word
    value VAR Word

    Sync_Second:
    DO
    PULSIN 1,0,sync
    LOOP WHILE sync > 100

    READ_Pulses:
    DO
    PULSIN 1,0,value
    IF value > 300 THEN
    value = 1
    ELSE
    value = 0
    ENDIF
    DEBUG value
    LOOP
  • dev/nulldev/null Posts: 381
    edited 2009-10-07 16:02
    Hi

    The problem with PULSIN is that the max. pulse width for the BS2pe is 123.6 ms. In your example, with BS2, it's 131.07 ms. PULSIN won't catch the 200ms signal. If PULSIN doesn't detect the signal, OR it times out because pulse width is too long, it will return 0.

    I'm not sure your program logic will be adequate, even if PULSIN supported a longer pulse width.

    In any case, I'm sceptic of having a Stamp measuring things which needs highly accurate timing signals. You are generally safer when adding external circuitry. The 555 timers will work "offline", so you can do some processing while they do their thing.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Don't worry. Be happy

    Post Edited (dev/null) : 10/7/2009 4:08:10 PM GMT
  • Larry~Larry~ Posts: 242
    edited 2009-10-07 17:00
    Well I admit I did not see the bs2pe and have no timings for this chip, I still use stamp manual 1.9 maybe I should update!!! maybe not

    as far as highly accurate timing signals this is not, all you need is to know if its 100mS or 2x longer, and make it a 1 or 0. So if the pulsin value is greater than lets say 105, 110, 115 or 120 mS then its a one if not its a 0 the actual value is not needed we just need to know if its longer, now 105mS may be too close but you see anything above a threshold is a one. so it could be if value >50 then value = 0 else value = 1 Or better yet look for the 0 zero value in pulsin if value = 0 then value = 1 else value = 0 you get a zero value if the pulse is longer than 123.6mS

    Ok I admit, I just HATE 555's and will try anything before using one, in fact I don't think I have ever used one! I will even use a cd4060 with resinator for IR instead of 555 so its out and now you can see my resistance to this, ( I read 555 and started shaking)

    Now these are possibilities and things I would try first, along with Tracy Allen's timer loop, rather than building another circuit first.
  • TumblerTumbler Posts: 323
    edited 2009-10-07 17:26
    ok Larray, i will try your pulsin example tomorrow.

    thx
  • dev/nulldev/null Posts: 381
    edited 2009-10-07 21:43
    I see Larry, that might actually work. Have a go at it Tumbler. If it works, it's easier than building 555 circuits, allltough circuits like that are pretty simple.

    I'd rather leave out PULSIN and just do:
    (I am assuming you get HIGH and LOW signals from your device Tumbler):

    ' {$STAMP BS2pe}
    ' {$PBASIC 2.5}
    
    TheBit       VAR Bit
    BitCounter   VAR Byte
    Counter      VAR Byte
    Hours        VAR Byte
    
    ' Wait for minute start sequence (a HIGH signal for 950 ms will do)
    Init:
      DO WHILE IN0 = 1
        Counter = Counter + 1
        PAUSE 10
        IF Counter >= 95 THEN GOTO Main
      LOOP
      Counter =  0
      GOTO Init ' Try again
    
    ' Get the bits
    Main:
    
      FOR BitCounter = 0 to 59
    
        '  Check one bit
        ' -----------------------------------------------------------------
        DO WHILE IN0 = 1 : LOOP        ' Wait for the signal to go low
        TheBit = 0                     ' Default zero
        PAUSE 150                    ' Pause 150 ms
        IF IN0 = 0 THEN TheBit = 1     ' If signal is still low, it's a bit 1
    
        ' -----------------------------------------------------------------
        ' I have my bit and can do something with it
        ' DO SOMETHING
        SELECT CASE BitCounter
          CASE 29 : Hours.bit0 = TheBit
          CASE 30 : Hours.bit1 = TheBit
          CASE 31 : Hours.bit2 = TheBit
          CASE 32 : Hours.bit3 = TheBit
          CASE 33 : Hours.bit4 = TheBit
          CASE 34 : Hours.bit5 = TheBit
        ENDSELECT
        ' Make sure it doesn't take longer than about 750 ms, or this won't work
        ' -----------------------------------------------------------------
    
        PAUSE 100                       ' Make sure the signal has gone HIGH again
    
      NEXT
    
      GOTO Main
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Don't worry. Be happy

    Post Edited (dev/null) : 10/8/2009 8:16:22 AM GMT
  • TumblerTumbler Posts: 323
    edited 2009-10-08 08:16
    The init is not working properly, a timing isue i guess.
    I replaced it with my init routine.
    Now it receives 0's and 1's, but also a timing prob or maybe some noise in the signal (wich i can't measure)

    Yes dev/null, i get High's and Low's [noparse]:)[/noparse]
  • dev/nulldev/null Posts: 381
    edited 2009-10-08 11:45
    An oscilloscope is very useful when working with signals! smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Don't worry. Be happy
  • Larry~Larry~ Posts: 242
    edited 2009-10-11 17:49
    Ok gotta know
    Did you ever find out what time it was??
  • TumblerTumbler Posts: 323
    edited 2009-10-11 19:10
    When i take at the clock:· 21:11 (right now) lol.gif
  • Voici un simple décodage du signal DCF77.5 Khz avec un BS2p24 tout simplement

    Explications :

    1) Le signal reçu et mis en forme avec un circuit CMOS de type Trigger de schmitt
    2) On attends le flanc montant du signal reçu (à tous moment) à l'aide d'une variable

    ' {$STAMP BS2p}
    ' {$PBASIC 2.5}

    ' Prog_001 RoueDCF.bpx (BS2p24)

    ' Début programme
    ' Analyse sur l'entrée de P0, le signal si il est montant, début d'une seconde
    ' La boucle1 tourne sur elle même pour trouver un flanc montant induquand un 0 ou un 1
    ' Troisième programme, compte la durée d'une seconde reçues de 1 à nx
    ' Prépare les octets à envoyer au MAX7219

    ' P0 = input signal DCF77.5 Khz

    ' H15 L0 '1=Output, 0=Input
    DIRS = %0000000000000000

    ' Réservation des variables

    dubit VAR Word ' valeur recue en durée pour identifier '0' ou '1'
    espace VAR Word ' valeur recue en durée entre 0/1 (id 59)
    recbit VAR Bit ' valeur 0 ou 1
    minutes VAR Byte ' 0-59 secondes = 6 adresses recues
    i VAR Nib ' 0-7 [0-15]
    indbit VAR Byte ' 0 - 59
    t VAR Byte(8) ' tableau de 8 octets (puissance 1,2,4,8,16,32,64,128)
    e VAR Byte(8) ' tableau de 8 octets
    sortie VAR Byte ' octet de sortie à écrire dans le MAX7219 (Registres)
    Registre VAR Nib ' 0-7
    Y VAR Byte

    ' Tableau t(i) de puissance de 2
    t(0) = 1
    t(1) = 2
    t(2) = 4
    t(3) = 8
    t(4) = 16
    t(5) = 32
    t(6) = 64
    t(7) = 128

    ' Début programme
    dubit = 0 ' Initialise le compteur de durée pulse '0' ou '1' à zéro

    ' Première boucle
    Boucle1:
    espace = espace + 1
    IF IN0 = 1 THEN ana1 ' sort au signal montant du premier '0' ou '1' recu
    GOTO boucle1

    ' Deuxième boucle, durée pulse reçue
    ana1:
    IF IN0 = 1 THEN
    dubit = dubit + 1 ' durée totale du '0' ou du '1' reçu
    GOTO ana1
    ENDIF

    'minutes = minutes + 1 ' incrémente de une adresse par seconde recue
    IF dubit < 400 THEN
    Recbit = 0
    ENDIF

    IF dubit > 401 AND dubit < 800 THEN
    recbit = 1
    ENDIF

    minutes = minutes + 1

    IF espace > 4500 THEN ' id synchro 59 ème minutes
    recbit = 0
    minutes = 59
    i = 0
    Registre = 0
    ENDIF

    '................................................................

    ' Bit reçu '0' ou '1' à additionner dans un octet
    IF recbit = 0 THEN ' Bit reçu
    e(i) = 0 ' Si reçu '0' = valeur '0'
    ELSE
    'READ i, Y

    'DEBUG "i= ",DEC i, " Y= ",DEC Y,CR

    e(i) = t(i) ' Si reçu '1' = valeur du tableau selon passage avec 'i'
    'e(i) = 2^i ' Si reçu '1' = valeur du tableau selon passage avec 'i'
    ENDIF

    ' Sommation des sorties de puissances de 2 (bin)
    sortie = e(7)+e(6)+e(5)+e(4)+e(3)+e(2)+e(1)+e(0)

    IF i > 7 THEN
    i = 0 ' Pointeur du tableau de réception pour former l'octet
    Registre = Registre + 1 ' Numéro du Registre 0 - 7 Y dans le MAX7219
    ENDIF

    IF minutes > 59 THEN minutes = 0

    DEBUG DEC recbit," ",DEC2 minutes," ",BIN8 sortie,
    " i= ",DEC i," t(i)= ",DEC t(i)," R= ",DEC registre," e(i)= ",DEC e(i),CR

    'Remettre le compteur à zéro
    dubit = 0
    espace = 0
    i = i + 1

    GOTO boucle1 ' Recommencer au début d'une seconde

    END

  • Voici un simple décodage du signal DCF77.5 Khz avec un BS2p24 tout simplement

    Explications :

    1) Le signal reçu et mis en forme avec un circuit CMOS de type Trigger de schmitt.

    2) On attends le flanc montant du signal reçu (à tous moment) à l'aide d'une variable 'espace' (voir la boucle1)

    3) On crée une deuxième boucle avec (dubit) = durée du bit reçu

    4) Si la durée de boucle avec la variable dubit est plus petite que 400 points, c'est que l'on a reçu une valeur data '0'.

     Si la durée de boucle avec la variable dubit est plus grande que 400 points (max 800 points), c'est que l'on a reçu une valeur data '1'.
    

    5) A ce moment du programme, on dispose de la seconde (signaux reçu '0' ou '1'), on peut enregistrer ces valeurs data dans un tableau de variables, j'utilise la RAM ScratchPad interne au BS2p24.

    6) Avec la variable 'espace' on décode l’absence de la porteuse qui correspond à la 59ème seconde.

      IF espace > 4500 THEN nous donne la synchronisation 59ème seconde, en même temps, une adresse de synchronisation au moment de sa détection ce qui nous permet d'écrire les data reçu aux bonnes adresses pour un décodage correcte.
    

    7) il n'y a plus qu'à recommencer l'opération compète de la trame suivante et de passer les 700 à 800 ms qui reste pour le décodage des infos hms, jma et plus.

    Au plaisir de vous lire pour une discution avec vous.

    ' {$STAMP BS2p}
    ' {$PBASIC 2.5}

    ' Prog_001 RoueDCF.bpx (BS2p24)

    ' P0 = input signal DCF77.5 Khz

    ' H15 L0 '1=Output, 0=Input
    DIRS = %0000000000000000

    ' Réservation des variables

    dubit VAR Word ' valeur recue en durée pour identifier '0' ou '1'
    espace VAR Word ' valeur recue en durée entre 0/1 (id 59)
    recbit VAR Bit ' valeur 0 ou 1
    minutes VAR Byte ' 0-59 secondes = 6 adresses recues
    i VAR Nib ' 0-7 [0-15]
    indbit VAR Byte ' 0 - 59
    t VAR Byte(8) ' tableau de 8 octets (puissance 1,2,4,8,16,32,64,128)
    e VAR Byte(8) ' tableau de 8 octets
    sortie VAR Byte ' octet de sortie à écrire dans le MAX7219 (Registres)
    Registre VAR Nib ' 0-7
    Y VAR Byte

    ' Tableau t(i) de puissance de 2
    t(0) = 1
    t(1) = 2
    t(2) = 4
    t(3) = 8
    t(4) = 16
    t(5) = 32
    t(6) = 64
    t(7) = 128

    ' Début programme
    dubit = 0 ' Initialise le compteur de durée pulse '0' ou '1' à zéro

    ' Première boucle
    Boucle1:
    espace = espace + 1
    IF IN0 = 1 THEN ana1 ' Sort au signal montant du premier '0' ou '1' recu
    GOTO boucle1

    ' Deuxième boucle, durée pulse reçue
    ana1:
    IF IN0 = 1 THEN
    dubit = dubit + 1 ' durée totale du '0' ou du '1' reçu
    GOTO ana1
    ENDIF

    'minutes = minutes + 1 ' incrémente de une adresse par seconde recue
    IF dubit < 400 THEN
    Recbit = 0
    ENDIF

    IF dubit > 401 AND dubit < 800 THEN
    recbit = 1
    ENDIF

    minutes = minutes + 1

    IF espace > 4500 THEN ' id synchro 59 ème minutes
    recbit = 0
    minutes = 59
    i = 0
    Registre = 0
    ENDIF

    '................................................................

    ' Bit reçu '0' ou '1' à additionner dans un octet
    IF recbit = 0 THEN ' Bit reçu
    e(i) = 0 ' Si reçu '0' = valeur '0'
    ELSE
    'READ i, Y

    'DEBUG "i= ",DEC i, " Y= ",DEC Y,CR

    e(i) = t(i) ' Si reçu '1' = valeur du tableau selon passage avec 'i'
    'e(i) = 2^i ' Si reçu '1' = valeur du tableau selon passage avec 'i'
    ENDIF

    ' Sommation des sorties de puissances de 2 (bin)
    sortie = e(7)+e(6)+e(5)+e(4)+e(3)+e(2)+e(1)+e(0)

    IF i > 7 THEN
    i = 0 ' Pointeur du tableau de réception pour former l'octet
    Registre = Registre + 1 ' Numéro du Registre 0 - 7 Y dans le MAX7219
    ENDIF

    IF minutes > 59 THEN minutes = 0

    DEBUG DEC recbit," ",DEC2 minutes," ",BIN8 sortie,
    " i= ",DEC i," t(i)= ",DEC t(i)," R= ",DEC registre," e(i)= ",DEC e(i),CR

    'Remettre le compteur à zéro
    dubit = 0
    espace = 0
    i = i + 1

    GOTO boucle1 ' Recommencer au début d'une seconde

    Alain Pilloud / Suisse ( pilloud.alain.123456789@gmail.com)

Sign In or Register to comment.