(This is part 1 in a small series on using DCF77 for accurate time keeping with an Arduino. You can find post post #2 here and post #3 here)
This post deals with correctly connecting an Arduino to a DCF77 receiver, how to remove noise in the signal, in order to to decode the signal into a valid, atomic-clock-synchronized, time.I use the “DCF-Empfänger BN 641138″ . It is relatively cheap and many others have reported good results. The connection is pretty simple, connect ground, and +5V to the Arduino and DCF output to a digital pin.
I connected the receiver to Arduino pin 2, because we can assign a flank-driven interrupt to it. It is important to connect the output to a pull-up resistor. Since I saw some spikes in the output signal (more on that later), I also added an additional bypass capacitor to decouple the power supply. Looking at the DCF board I see a capacitor that may already function as a bypass capacitor added, so feel free to leave this part out.
The schematic then looks like this:
Note: I used Fritzing to create the breadboard and schematic view. If you want to use this DCF77 component for Fritzing, I added it to the DCF77 library, which you can download here.
May 1, 2012 at 10:33 AM
Hallo Thijs,
Een leuk artikel over de DCF77 ontvanger. Ik heb zelf onlangs de DCF77 van de firma Pollin ontvangen maar nog niet uitgeprobeerd. Ik gebruik de Arduino 0023 versie.
Heb je de arduino code voor deze DCF ontvanger ook in de .pde extensie beschikbaar? Ik zou graag deze versie willen uitproberen met mijn DCF77 ontvanger. Alvast bedankt!
Mvg,
Jack de Zeeuw
May 1, 2012 at 2:46 PM
Hoi Jack,
Bedankt! Je kan de voorbeelden gewoon hernoemen van .ino naar .pde. Voor de DCF77 bibliotheek ligt is dat wat lastiger, maar de Arduino 23 werkt ook prima met .cpp en .h files. Het belangrijkste is dat de files op de goede plek staan. Ik heb geen PDE of INO file gemaakt van de DCF77 van de bibliotheek, omdat ik deze op wilde zetten als een klasse. Een reden om dit te doen is dat de gebruiker van de klasse alleen de functies kan benaderen die hij nodig heeft, namelijk:
DCF77.getTime();
DCF77.getUTCTime();
DCF77.Start();
DCF77Stop();
Je mag natuurlijk de code aanpassen als je wil, dat is het punt niet, maar bij gewoon gebruik vermindert encapsulation en datahiding de kans op fouten. Daarnaast is er er nog ander voordeel: Als ik een update van de DCF77 library doe, hoef ik alleen maar de aanroep van bovenstaande functies gelijk te houden. Je hoeft dan enkel DCF77.cpp en DCF77.h hoeven te vervangen, en je programma blijft werken. Ik laatst een dictaat hierover (Object Georiënteerd Programmeren) tegen, zie http://bd.eduweb.hhs.nl/ogoprg/pdf/Dictaat_OGPiCpp.pdf
May 4, 2012 at 6:46 PM
Hoi Thijs,
Ik heb de bestanden opgeslagen naar de extensie .pde.
Wanneer ik de InternalClockSyn.pde verify/compile krijg ik de volgende foutmelding:
“time_t” does not name a type
scope
InternalClockSync:50: error: ‘year’ was not declared in this scope
Wat doe ik verkeerd?
Mvg,
Jack
May 5, 2012 at 8:49 PM
Hoi Jack,
Ik heb je probleem geprobeerd te reproduceren: Ik heb\arduino-0023\libraries
– Arduino alpha build 23 geinstalleerd
– https://github.com/downloads/thijse/Arduino-Libraries/DCF77.0.9.5.zip gedownload
– de folders DCF77, Time en TimeZone naar
– De samples van .ino naar .pde hernoemd
en ik zag niet jouwfoutmelding, maar ontdekte wel dat de code niet volledig compatibel was met de 23 versie. Er staat een nieuwe versie (0.9.6) op https://github.com/thijse/Arduino-Libraries/downloads die dat wel is
Laat je weten of het werkt?
Thijs
May 7, 2012 at 9:51 PM
Hoi Thijs,
Ik krijg nog dezelfde foutmelding.
Wat doe ik verkeerd?
Vind je het goed als ik je een keer opbelt om mijn probleem te tekkelen.
Mvg,
Jack
June 27, 2012 at 3:21 PM
Beste Thijs,
heb hetzelfde probleem “time t does not name a type”
Ik gebruik de laatste versie van de Arduino IDE. Mijn DCF komt ook van Pollin.
De Arduino draait op een Rainbowduino, maar dat kan eigenlijk niet het probleem zijn. Ik vermoed dat de header file niet staat waar hij moet staan of zo, ben ook nog maar een beginner met Arduino. Zou je zo goed willen zijn even de juiste volgorde van files downloaden, unzippen en plaatsen in de IDe willen doorgeven?
Dank,
Jacob
July 1, 2012 at 11:00 PM
Beste Jacob,
Omdat meerdere mensen tegen dit probleem aan lijken te lopen, heb ik een stap voor stap installatie beschrijving geschreven:
http://thijs.elenbaas.net/2012/07/installing-an-arduino-library/
Ik hoor graag of dit de problemen oplost.
Thijs
July 7, 2012 at 4:53 AM
Hi,
just tried out your library. Really nice work! Got my DCF-77 module working in less than 10 minutes. I waited longer for sucessfully signal synchronisation than I needed time for wiring. It’s the following very cheap module:
http://www.pollin.de/shop/dt/NTQ5OTgxOTk-
There is an extra pin, which allows to enable and disable the module. But attention: use the 3V3 output of Arduino. Furthermore I have added a 1k-resistor between the pins, which is not optimal for level converting, but gives me the feel of security for my DCF-module.
Thank you!
July 7, 2012 at 7:38 PM
Thanks, it’s always nice to hear that! I just had a look at the Pollin module and it is cheap indeed. Only half the price of the Conrad module (which wasn’t that expensive either). The extra pin seems like a good idea. What I understood is that in commercial (battery run) clocks the DCF77 module is turned on only once per day to save energy, typically during the night when reception of the DCF77 signal is typically better.
Perhaps it would be interesting to add an example that implements this?
August 7, 2012 at 10:18 PM
Hello,
thanks for your great work and thanks for sharing the code. i also have a DCF77 module from Pollin.de. On my Arduino, i don’t have free interrupts, is there a possibility to get the time via DCF77 without using interrupts?
August 19, 2012 at 10:00 PM
Hi Thomas,
Thanks! Unfortunately, there is no way to run the library without interrupts (although this library does not use the timer interrupt). Of course, you could change the interrupt part of the code into something that does polling. If you do this, I would suggest using one of the fast digitalRead implementations to minimize overhead. Also, if you do, could you send me the code, so I can posssible integrate it in a next version?
Alternatively, you could try and switch the pin between the DCF receiver and the other functionality. One time DCF update per day would be enough, and signal reception is best during the night, anyways.
August 31, 2012 at 10:04 PM
Hi, nice work about DCF reception!
But I do not understand what you wrote about “It is important to connect the output to a pull-up resistor.”
If you connect some digital equipment to the Arduino which provides high and low levels of +5V and 0V on the output side, those digital outputs can go directly to an Arduino digital input pin. As far as I know.
September 1, 2012 at 4:09 PM
Hello Thijs,
please forget my question about hardware wiring and the pull-up resistor, meanwhile I know the answer myself: Your DCF module seems to provide an “open collector” (or “open drain”) output while my DCF module has a “push-pull” output instead.
You will need to have a pull-up resistor to connect the DCF receivers data output to an Arduino input pin if the receiver provides an open collector data output. And you must connect it directly to the Arduino input if the DCF receiver provides a push-pull data output. My DCF1 module from Pollin provides a very weak (something > 5 µA) push-pull data output.
September 6, 2012 at 10:20 PM
Hi Juergen,
Indeed. My Conrad DCF receiver uses an open collector output, so a pull up resistor is needed. As a side note, the arduino can actually provide an internal pull-up (see this page), but I did not use that.
Out of interest, what are you using your DCF clock time for?
September 7, 2012 at 7:08 PM
Hi Thijs,
I’m planning to use the DCF clock for two things:
At first I’m planning to build a “visitor alert and memorising box” for a handicapped friend of mine.
After that, I’m planning to make my own weather station with indoor and outdoor sensors, data logging and possibly transferring weather data of my home location into the Internet.
In both cases, I’ll use a DCF clock for “low maintenance data logging with correct date/time”.
September 6, 2012 at 1:44 PM
hey,
nice work! it work fine with the modules from ‘C’.
but i have two (china?) that will need an invert input!
it is possible, that you can quickly introduce me, how i change the setting, that your script work with an invert signal?
best regards
e.
September 6, 2012 at 10:08 PM
Hi Eric,
I send you an email with a test version of the library, supporting inverted pulses. If you instantiate it with
DCF77(DCF_PIN,DCF_INTERRUPT, false);
It should use inverted pulses. Let me know if it works, I could not test it with my module
Cheers,
Thijs
September 7, 2012 at 7:39 PM
I think the only change needed for an inverted data logic is to invert the result of the “digitalRead” function that reads the pin where the DCF module provides the data signal.
I have looked into the code and found only one line of source code affected:
int sensorValue = digitalRead(dCF77Pin);
So change that line in library file “DCF77.cpp” to a “not” result:
int sensorValue = !digitalRead(dCF77Pin);
and the library should work with inverted logic on the DCF77 data pin.
November 26, 2012 at 12:59 PM
Hallo Thijs,
In de code wordt het verschil tussen twee tijdwaarden bepaald door ze van elkaar af te trekken.
Wat gebeurt er als de timer in de tussentijd is overgelopen?
Krijg je dan niet een negatief resultaat?
Groeten, Meo
November 28, 2012 at 10:28 PM
Hi Meo,
Klopt, er worden inderdaad twee tijden van elkaar afgetrokken, maar time_t is een 32bit unsigned long, en loopt over in 19 Januari 2038. Ik zal er tzt met een fix komen 😉
November 29, 2012 at 5:28 PM
Hallo Thijs,
Volgens info op de Arduino site gebeurt dat al eerder.
QuoteUnquote
Het zou ook een unsigned long zijn.
Zie http://arduino.cc/en/Reference/Millis
January 3, 2013 at 1:16 PM
Ah, ik zie je punt. Er wordt zowel een milis() verschil als een time_t verschil in de code gebruikt. Eerlijk gezegd maak ik me er niet zoveel zorgen over, er wordt een grondige sanity check gedaan op de resulterende tijd. Niettemin zal ik het meenemen in een volgende versie.
November 29, 2012 at 5:30 PM
Sorry, quote mislukte. Nogmaals:
Returns the number of milliseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days.
January 1, 2013 at 2:17 PM
Hi Thijs,
Wishing you a good 2013!
I’m experimenting with arduino and DCF signal. I guess I’m doing something wrong, but can’t figure it out…
When using the arduino Uno board, I’m able to get a timesynch in a few minutes. When building the circuit on a breadboard (I just pull out the AT328 and put it on a breadboard, connected as needed), I’m not getting a synch at all. When just ‘blinking’ a LED, that’s not a problem. I connected a LED to the OUT of the DCFboard, that’s blinking also. I connected this to pin 4, that should be the equivalent of the D2 signal of the Arduino Uno. The timesynch is indicated by an LED, but it never comes. What could I be doing wrong? The only thing I could imagine is that I use a 16.4MHz crystal instead of 16.0MHz (they were out of stock). As the LED project is resulting in a blinking LED, the AT328 doesn’t seem to have a problem with that, I could imagine that the clock I want to make will run slightly fast, but as it is synchronising with DCF, that won’t be a problem either…
If someone has an idea, please respond…
Thanks.
January 3, 2013 at 1:12 PM
Hmm, I would think you have interference issues again. Can you try moving the receiver a bit further away, twisting the cables going to the receiver and possibly using a different (bigger) by-pass capacitor?
January 3, 2013 at 3:59 PM
Well, I replaced the crystal with a correct 16.000MHz type, and it works! As the DCF signal is a millisec signal, it seems that the input is not correctly read with a 16.4 crystal, while ‘only’ 2,5% difference in frequency.
However, thanks for your reply!
February 19, 2013 at 10:54 PM
Thijs,
Ik heb probleem 🙁 , heb de dcf van conrad, alles aangesloten zoals in je schema staat, de bib gedownload, de voorbeelden getest, weerstand weggelaten, condensator weggelaten, weerstand veranderd… nog maar eens en nog maar eens….maar het werkt niet…
Ik krijg ergens een signaal binnen van de dcf-ontvanger, ik heb geprobeerd met een led op de uitgang en dit pulst ( wel onregelmatig maar vermoed dat dit zo moet zijn )
als ik je voorbeeld dcf-pulslength gebruik krijg ik de volgende output in de SM
heb je een idee, ik zit een beetje vast
Tnx Tom
Cycle: 117 Pulse :34
Cycle: 205 Pulse :0
Cycle: 2 Pulse :45
Cycle: 48 Pulse :1
Cycle: 2 Pulse :0
Cycle: 3 Pulse :1
Cycle: 325 Pulse :10
Cycle: 30 Pulse :33
Cycle: 34 Pulse :12
Cycle: 107 Pulse :1
Cycle: 111 Pulse :1
Cycle: 4 Pulse :1
Cycle: 2 Pulse :1
Cycle: 3 Pulse :0
Cycle: 89 Pulse :12
Cycle: 43 Pulse :6
Cycle: 522 Pulse :1
Cycle: 2 Pulse :5
Cycle: 14 Pulse :24
Cycle: 147 Pulse :1
Cycle: 2 Pulse :1
Cycle: 6 Pulse :0
Cycle: 2 Pulse :13
Cycle: 213 Pulse :1
Cycle: 73 Pulse :20
Cycle: 421 Pulse :144
Cycle: 155 Pulse :15
Cycle: 96 Pulse :2
Cycle: 3 Pulse :1
Cycle: 2 Pulse :4
Cycle: 42 Pulse :15
Cycle: 21 Pulse :19
Cycle: 242 Pulse :67
Cycle: 877 Pulse :1
Cycle: 2 Pulse :2
February 20, 2013 at 1:00 PM
Ha, je hebt een uitdaging! 🙂 Typisch hebben de problemen te maken met stoorsignalen die binnenkomen via de voeding of via de antenne. Je kan het signaal proberen te optimaliseren terwijl je een van bovenstaande sketches draait:
– Sluit een pull-up weerstand aan – dit heeft niet met ruis te maken, maar wordt soms vergeten
– Gebruik een capacitieve bypass op de voeding – dit dempt stoorsignalen, zie schema
– Pas de oriëntatie van de antenne aan – het signaal komt vanuit Duitsland
– Gebruik 2 aard draden, twist er een met de voeding, en de ander met de signaal draad. – Dit verminderd door inductie opgepikte signalen
– Leg je ontvanger niet te dicht bij je PC of voeding.
– Voed je Arduino vanaf een batterij
Succes!
February 25, 2013 at 9:03 AM
2 meter UTP er tussen gehangen en alles werkt!
Tnx
September 2, 2013 at 11:19 PM
Sorry I’m not good enough with Dutch 🙂 , I think I’ve the same or very similar Tom’s issue.
I use a DCF77 rec. from Conrad but I can’t get at all a valid signal.
How can I improve reception?
I have also an alarm clock from Oregon (afaik it use the same DCF sig)that works very well 🙁
I’m in the center part of Italy on the Adriatic sea.
Thanks in advance! 🙂
April 7, 2014 at 9:44 PM
Don’t worry, my Italian isn’t that great either :-). In the comments me and others have suggested several signal improvements: better antenna, position further away from your PC, twisted wires, trying at night, etc. The signal seems to be totally random, though, not one correctly identified pulse. Are you sure everything is correctly connected and you have a pull-down resistor. What does the raw signal look like?
Hope you can make it work!
March 6, 2013 at 10:54 PM
Hallo Thijs,
Ik ben al een tijd bezig om uit het DCF signaal de meteotime data te decoderen. Als basis gebruik ik de informatie van Walter Freywald (een duidelijk blokschema) en een programma dat in C++ geschreven is . Dit laatste komt van de site “pastebin”
Ik werk nooit met de taal C en ben een hobby programeur. Tot nu toe is het me altijd gelukt om de programma’s te schrijven in BASCOM . En de resultaten te laten draaien in ATMEL processoren. Ik heb dus alle belangrijke delen van het C-programma vertaald naar BASCOM. Als test datagebruik ik delogs van DCF die op de diverse sites beschikbaar zijn. Daar staat dan ook het gedecodeerde resultaat bij. Volgens het blokschema van Water Freywald wordt de DCF tijd informatie in twee delen van 20 bits opgesplits. Ook de gedecodeerde data staat in 42 bits.
Het probleem is nu dat ik niet weet of mijn aanname van wat bit 0 en wat time L en H is. Van de DCF-logs maak ik test data. Ik deel de tidbits in twee. En van de data bits verwijder je eerst bit 0 en 7 (over dus 40) Ook deze 40 verdelen in twee. Ook hier is de vraag wat is Chipher LO en Chipher RO. Ik heb de data al op verschillende manieren aan mijn BASCOM programma aangeboden. Maar het resultaat is nooit het resultaat wat in de DCF-logs staat.
Ik zal zeker ergens een programeerfout of denkfout maken, maar ik ben er nu al weken (soms 4 dagen per week) mee bezig.
Misschien wil jij mij op weg helpen waar zit mijn denkfout
Graag je reactie met vriendelijke groet,
L.R
June 10, 2013 at 9:57 PM
Is het mogelijk om de 2 draadjes van de antenne te verlengen of heeft dit nadelige gevolgen voor het ontvangst.
Floris
April 7, 2014 at 10:15 AM
Hmm, Dat zou best eens kunnen. Als je het probeert kan je het beste de draden twisten. Ik ben benieuwd naar de resultaten!
September 5, 2013 at 1:52 PM
Hallo Thijs,
Ik zie dat CET en CEST is gedefinieerd, maar als private. Is er een optie om te zien vragen of het zomer of wintertijd is?
Met vriendelijke groet,
Erik
April 7, 2014 at 10:26 AM
Hallo Erik,
Goed punt. Ik zal CEST public maken in een volgende release
Pingback: DS1302 Real Time Clock | Hard Copy Arduino