(This is part 3 in a small series on using DCF77 for accurate time keeping with an Arduino. You can find post #1 here and post #2 here)
Before we start to look at the library, let me start by saying that this is by no means the first Arduino DCF77 decoder. In fact, a large part of this library is based on the sketch made by Matthias Dalheimer. I did not intend to write a new library, but because of the noise spikes I was picking up, I started rewriting parts to make it work under noisy circumstances and, as these things seem to go, ending up writing a whole new library.
Because of the noise I added, besides the spike rejection, some checks on the decoded time. Furthermore I made made another major change in the code: The class library attaches an interrupt function to the DCF77 pin, which fills a buffer with the received bits. This interrupt-driven part is made to be quite lightweight, while the hard work (checking parity, calculating time, doing a few sanity checks) is done in the code called from the main loop. But because the interrupt driven loop fills the buffer (and starts filling a new buffer after that), so there is no real hurry in the main loop to re-enter the getTime function.
To use the library, first download the DCF77 library here:
[download id=”1″ format=”1″]
and install it in the Arduino Library folder. For a tutorial on how to install new libraries for use with the Arduino development environment please refer to the following website: http://www.arduino.cc/en/Reference/Libraries. If the library is installed at the correct location, you can find the examples discussed in this and the previous post under Examples > DCF77. I also added the time library to the archiver for convenience.
Below is a demonstration of how the library processes the binary data and returns a time and date. In order for the example to give output on the binary stream make sure that logging is turned on in the DCF library. You can do this by adding the #define VERBOSE_DEBUG 1 in Utils.cpp.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#include <Utils.h> #include <DCF77.h> #include <Time.h> using namespace Utils; #define DCF_PIN 2 // Connection pin to DCF 77 device #define DCF_INTERRUPT 0 // Interrupt number associated with pin time_t time; DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT); void setup() { Serial.begin(9600); Serial.println("1 - binary 1 corresponding to long pulse"); Serial.println("0 - binary 0 corresponding to short pulse"); Serial.println("BF - Buffer is full at end of time-sequence. This is good"); Serial.println("EoB - Buffer is full before at end of time-sequence"); Serial.println("EoM - Buffer is not yet full at end of time-sequence"); DCF.Start(); } void loop() { delay(1000); time_t DCFtime = DCF.getTime(); if (DCFtime!=0) { digitalClockDisplay(DCFtime); } } void digitalClockDisplay(time_t _time){ tmElements_t tm; breakTime(_time, tm); Serial.println(""); Serial.print("Time: "); Serial.print(tm.Hour); Serial.print(":"); printDigits(tm.Minute); Serial.print(":"); printDigits(tm.Second); Serial.print(" Date: "); Serial.print(tm.Day); Serial.print("."); Serial.print(tm.Month); Serial.print("."); Serial.println(tm.Year+1970); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits); } |
After the first full cycle we get the feedback “time inconsistent” because:
- The difference between the DCF77 time and the internal time (still close to 0 -which translates to a date in 1970-) is too big
- The difference with there is no previous DCF77 time measurement is too big because, well, there is no previous measurement.
After the second cycle there is a previous measurement and both measurement points are consistent, and we get our first DCF77 time. Success! Note that the time queried with DCF.getTime() is compensated for the period between receiving the time from the receiver and the moment that it is queried from the library.
Now, let’s try an example that actually updates the internal clock time. For this example the output I turned logging off.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#include "Utils.h" #include "DCF77.h" #include "Time.h" using namespace Utils; #define DCF_PIN 2 // Connection pin to DCF 77 device #define DCF_INTERRUPT 0 // Interrupt number associated with pin time_t time; DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT); void setup() { Serial.begin(9600); DCF.Start(); Serial.println("Waiting for DCF77 time ... "); Serial.println("It will take at least 2 minutes until a first update can be processed."); } void loop() { delay(1000); time_t DCFtime = DCF.getTime(); // Check if new DCF77 time is available if (DCFtime!=0) { Serial.println("Time is updated"); setTime(DCFtime); } digitalClockDisplay(); } void digitalClockDisplay(){ // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits); } |
Resulting in the following output:
Finally, that kind of wraps things up. However, I want to demonstrate one last thing. I used the Time libraryquite a lot in the library, but it also has a feature that is you can nicely use in your main program.
Below is an example sketch showing how to use the syncProvider functionality to simplify the sketch code. Note that the loop code does not require any logic to maintain time sync and even the getDCFTime function could be removed to make the code even more concise. The Time library will automatically monitor DCF77 and sync the time as necessary.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
#include "Utils.h" #include "DCF77.h" #include "Time.h" using namespace Utils; #define DCF_PIN 2 // Connection pin to DCF 77 device #define DCF_INTERRUPT 0 // Interrupt number associated with pin time_t prevDisplay = 0; // when the digital clock was displayed time_t time; DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT); void setup() { Serial.begin(9600); DCF.Start(); setSyncInterval(30); setSyncProvider(getDCFTime); // It is also possible to directly use DCF.getTime, but this function gives a bit of feedback //setSyncProvider(DCF.getTime); Serial.println("Waiting for DCF77 time ... "); Serial.println("It will take at least 2 minutes until a first update can be processed."); while(timeStatus()== timeNotSet) { // wait until the time is set by the sync provider Serial.print("."); delay(2000); } } void loop() { if( now() != prevDisplay) //update the display only if the time has changed { prevDisplay = now(); digitalClockDisplay(); } } void digitalClockDisplay(){ // digital clock display of the time Serial.println(""); Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits); } unsigned long getDCFTime() { time_t DCFtime = DCF.getTime(); // Indicator that a time check is done if (DCFtime!=0) { Serial.print("X"); } return DCFtime; } |
ps. After writing this library I discovered another Arduino DCF77 class that is based on the code of Matthias Dalheimer at http://fiendie.net/arduino/funkuhr. I haven’t tried it, but the code looks quite clean, so give it a shot.
April 28, 2012 at 2:49 PM
Hallo Thijs,
Als ik het InternalClockSync programma viade verify toets test dan krijg ik volgende foutmeldingen.
InternalClockSync.cpp:13:19: error: DCF77.h: No such file or directory
InternalClockSync:19: error: ‘DCF77’ does not name a type
InternalClockSync.cpp: In function ‘void setup()’:
InternalClockSync:24: error: ‘DCF’ was not declared in this scope
InternalClockSync.cpp: In function ‘void loop()’:
InternalClockSync:31: error: ‘DCF’ was not declared in this scope
Ik gebruik Arduino 1.0.
Heb je enig idee wat de oorzaak kan zijn?
Alvast bedankt,
Michielsen Luc
April 29, 2012 at 9:39 PM
Hi Luc,
Het probleem is dat de DCF77 niet gevonden kan worden, en in de meeste gevallen betekent dit dat de files op de verkeerde locatie staan.
Op de Arduino site staat er dit over geschreven:
http://www.arduino.cc/en/Hacking/Libraries
Ik heb hier zelf alleen ervaring mee onder Windows (7), daar heb je 2 opties:\libraries\DCF77\DCF77.h, DCF77.cpp, etc \Documents\Arduino\DCF77\DCF77.h, DCF77.cpp, etc
– Als een standaard bibliotheek: D:\
Zo heb ik de boel geinstalleerd, maar het volgende zou ook moeten werken:
– Per gebruiker, dan zou de file hier terecht moeten komen C:\Users\
Als het goed is zie je dan in de Arduino IDE de examples onder Examples>DCF77.
Succes!
Thijs
July 2, 2012 at 9:24 PM
Hi Thijs,
I just downloaded your DCF77 library from the Arduino Playground. It
works great, thank you very much!
Maybe you are interested to know that there is a little thing at line
94 in DCF77.cpp that prevents the user from changing the DCF input pin.
In function void DCF77::int0handler() it says:
int sensorValue = digitalRead(2);
but should be:
int sensorValue = digitalRead(dCF77Pin);
This is only for your information – I am far away to complain!
Have fun!
Regards
Sabine
July 2, 2012 at 9:58 PM
Hi Sabine,
Thanks for caching that! I will solve this in the next release. Good luck using the library. if you have been able to use it in a project, I’m always interested to hear about it.
Thijs
July 3, 2012 at 9:00 PM
Hi Thijs,
I am trying to build a standalone rf transmitter for the digital ham radio mode WSPR using an Arduino and a DDS. With the help of your library, I now got he time base running and will now try to set the DDS to the MFSK frequencies to transmit. Hope I will succeed! 😉
Best regards
Sabine
August 8, 2012 at 12:02 AM
Hi Thijs,
when I use the library with the DCF-2 hardware ( http://www.elv.de/i-c-realtime-clock-i2c-rtc-komplettbausatz.html ), the DCFPulseLength example sketch
prints unexpected results: the cycle length is around 1000 ms, but the
Pulse length is always in a range around 900 ms (maybe 800-920).
This probably is the reason why the time is never synchronized. Do you have an
idea about the reason for this effect, and how to debug it?
Heiner
August 8, 2012 at 12:11 AM
Sorry, I posted the wrong URL. The correct one is as follows:
http://www.elv.de/dcf-empfangsmodul-dcf-2.html
August 19, 2012 at 9:49 PM
Hi Heiner,
I had a look at the specifications of the DCF-2 hardware, and they seem pretty much similar to the ones of the Conrad DCF module that I’m using. One thing I see is that the manual suggests a pull up resistor of 0.5 – 1 kOhm, rather than the 10kOhm I used in my schematic. You could also try and remove the by-pass capacitor and see what happens. Is there something interesting to see in the DCFSignal sample?
Good luck, Thijs
August 20, 2012 at 7:41 PM
I found the cause of the problem: the hardware delivers an inverted
signal. Taking this into account the library worked, as in more
detail pointed out in
http://arduino.cc/forum/index.php/topic,102039.0.html
Thank you for your help, and for the great library.
August 22, 2012 at 7:20 PM
Hey Thijs,
tried out your Libary today. It works perfect for me. The only thing I had to change was the pull-up resistor. I used 1.1kOhm insted of the proposed 10kOhm. Also I didn’t used the capacitor described in the first post.
Thank you for sharing.
August 31, 2012 at 12:18 PM
Great to hear! I’ll update the article mentioning the variety in pull pull up resistors
August 26, 2012 at 6:20 PM
Hi Thijs,
Firstly, thank you for making your excellent DCF77 library available for others to use.
I am trying to get the Symtrik MSF60 receiver to work, here in the UK, with an Arduino (that is already hooked up to a DS3232 RTC) and was looking around for some suitable code to decode the output. The MSF examples I’ve found will not compile due to dependency issues with IDE 1.0+. Your code is bang up to date, and I have been able to use the DCFSignal and DCFPulseLength sketches to look at the receiver output in raw form, though obviously the DCFBinaryStream code cannot decode the MSF protocol.
Do you have any pointers on how to modify the DCF77 library for use with MSF protocol?
I guess it should be reasonably straightforward but I have a feeling that it is going to require a lot of experimentation and a huge learning curve!
Best Regards,
Squire
August 30, 2012 at 8:14 AM
Hey squire, could you send me a sample of such a msf library? I could have a look at how easy it would be to make a msf library’based on the dcf library. No promises, though. Also, the debugging would have to be done by you, though, as I do t have such a receiver.
For starters, you could send me send me some screenshots of the output of dcfpulselength and dcfbinarystream?
September 7, 2012 at 10:18 PM
About length of pulses using DCFPulseLength: With my DCF1 module from Pollin I find, that short pulses are at an average of roundabout 106 ms (range 95..110) and long pules are roundabout at an average of 206 ms (range 195..210).
So pulses with my DCF module hardware seem to be much shorter than you found with your DCF hardware.
August 28, 2012 at 10:05 PM
Hi, Nice work 🙂 I’m looking at this MSF60 module http://www.earthshineelectronics.com/clock-modules/110-msf-60khz-time-receiver-module.html and wonder if I will need to make any changes to your code to get it working? …. any thoughts apreciated 🙂
August 30, 2012 at 8:17 AM
Yes, it wil definitely require significant changes: the pulse coding is different, I believe, and bit rearrange differently to a time structure.
August 31, 2012 at 10:50 PM
Hallo Thijs,
thanks for your library!
Unfortunately I could not make the library fully work with my DCF1 module from Pollin, most likely because of an inverted output signal and no reverse signal output available on that cheap module I have.
It seems as if your library cannot handle inverted output for decoding the time.
Only the example sketch “DCFPulseLength” works well with my module and this programming example helped me a lot to find a good place for the module: Placed directly in front of my monitor, the module only got random spikes, but no clear one second pulses. So at first I thought, that my own DCF programming is full of bugs, or the hardware is not wired correctly or maybe the module is faulty. But your example “DCFPulseLength” showed me, that I just had to place the module wide enough away from my PC and LCD monitor and then the signal becomes a strong one second pulse.
So that helped me a lot to program my own DCF decoding sketch.
The better the signal quality, the better the decoding.
I knew that DCF modules have no reception when operated near CRT (cathode ray tube) monitors and TVs, but I didn’t think about that the same happens when they are placed near LCD monitors. For my module, 1 metre is the minimum distance I have to keep the module away from LCD and PC, or the signal gets bad.
January 3, 2013 at 1:21 PM
Hi,
I’m sorry to reply this late. The noise susceptibility of the DCF receiver is indeed very high. I’m glad to hear you got your problem solved! I’m trying to buy a bigger DCF77 antenna. I will write post if this makes a realy difference.
August 31, 2012 at 11:18 PM
I think that MSF60 decoding needs a slightly different decoder library as the decoding of MSF60 differs in some aspects from DCF77. Here is a link to a technical document I found:
http://www.npl.co.uk/upload/pdf/MSF_Time_Date_Code.pdf
Some things are identically, such as 60 seconds within one minute and an extra long pulse as the marker for the beginning of a new minute. And the BCD coding of the decimal values for hour, minute, day and so on is nearly the same.
But on the other side there are some strange two-bit codes at least in the first 16 seconds of each minute, so that MSF60 does not only has three different pulse lengths (short pulse, long pulse, minute marker pulse) but has one pulse length extra: short pulse, long pulse, extra long pulse, minute marker pulse
I think if you write some code that ignores the first 16 seconds which have the two-bit coding with three different pulse lengths, the coding is not so much different from DCF77. The actual time and date in MSF60 is coded with only two pulse lengths, just as DCF77. MSF60 is a bit different from DCF77, and so is the decoding.
I’m just wondering if I am in the receiving range of the MSF60 transmitter. I’m living near Hamburg, Germany.
August 31, 2012 at 11:50 PM
Thijs,
Thank you. I found a project by a fellow radio amateur, G7KSE, here:
http://g7kse.co.uk/projects/arduino-msf-receiver/
Which is based on this code:
http://www.jarkman.co.uk/catalog/robots/MSFTimeExample.zip
Symtrik MSF60 receiver details:
http://www.pvelectronics.co.uk/rftime/SYM-RFT-XX.pdf
MSF protocol from NPL:
http://www.pvelectronics.co.uk/rftime/msf/MSF_Time_Date_Code.pdf
I will post the serial monitor logs from my Ubuntu PC.
Thanks,
Squire
October 20, 2012 at 12:10 PM
Hi Thijs,
thanks a lot for your DCF77 library for arduino. It’s very easy to start with.
I wired a cheap DCF77 receiver from Pollin: http://www.pollin.de/shop/dt/NTQ5OTgxOTk-/
It works out of the box. No extra components were necessary. 🙂
Then I ran your examples bundled with the library. It turns out that SyncProvider is one minute ahead at the first sync. InternalClockSync works as expected.
Please find the output of InternalClockSync at http://pastebin.com/ZbtzWtqZ
The output of SyncProvider is here: http://pastebin.com/5DSfAkjZ
In line 4 of the output of SyncProvider it’s 12:01:00 actually. After the next sync the time is corrected (line 126).
I tried both examples a couple of times. The hardware wasn’t touched or even looked at… 😉 The DCF77 signal is quite clear.
Any idea what’s going wrong?
Best regards
Franz
October 26, 2012 at 12:43 PM
Hi Franz,
Thanks for using the library! The issue you see is weird, how did you know it was a minute late? It is suspicious that the difference is precisely 1 minute. The only things I can think of now is the following: when a new time is received, a time stamp from the system clock is stored together with the dcf time. Storing both is not implemented as a atomic action, so it could be one is updated while the other is not, because the transfer was interrupted. Another option is that the internal clock is updated after the timestamp but before syncProvider is called. I will try to reproduce this when I have time. do you have some sample code that produces this issue?
October 26, 2012 at 11:00 PM
Hi Thijs,
I just ran your example Arduino\libraries\DCF77\examples\SyncProvider\SyncProvider.pde bundled with the library.
Another output is here: http://pastebin.com/SWJBXFSy
I calculated the time difference to a NTP synced server:
http://i50.tinypic.com/34ozg2g.png
Best regards
Franz
January 3, 2013 at 1:32 PM
Hi Franz,
This is very strange. I have almost reached the stage in my clock project, where I start integrating the DCF77 receiver. At that time I will start getting a handle on this.
Happy New Year!
Thijs
October 29, 2012 at 8:12 PM
Hi again,
I enabled VERBOSE_DEBUG and recorded a video of the output:
http://dl.dropbox.com/u/87685034/SyncProvider_3_converted.avi
Maybe this helps to get a better insight… 🙂
Best regards
Franz
November 17, 2012 at 6:16 PM
Hi,
thanks for this nice DCF library. I have only one problem, tried this, but it didn’t work:
// Check DCF signal
void CP5_TBZ::checkDCF ()
{
time_t DCFtime = DCF.getTime();
if (DCFtime != 0)
{
m_bCurrDCF = true;
setTime(DCFtime);
}
else { m_bCurrDCF = false; }
}
The var “m_bCurrDCF” nerver gets true, also if my LCD displays the actual time. That isn’t logical and i think ” if (DCFtime != 0)” nerver gets true. You have any idea how i control if i have the new time, the actual one?
Best regards
Janni
November 19, 2012 at 5:44 PM
Hallo again,
i solved my problem.
best regards 🙂
November 28, 2012 at 10:21 PM
Hi Janny,
Glad to hear you got it solved!
November 30, 2012 at 11:29 PM
Hi,
Thanks for you clear postings on using the Conrad DCF receiver with an Arduino. I used as a basis for a timer that indicates to the kids that they have to sleep (red led), are allowed to wake up and play silently (yellow led) or can make noise and ask for breakfast (green led).
Two remarks:
– I found out that the combination Arduino/receiver has to be at least one meter (or about the length of a standard USB cable) away from a computer to function.
– I only managed to get the combination running using a USB cable, either from a computer or from a mobile phone charger. When I tried to use it with an AC adapter on the power supply connector, the Arduino was not able to synchronize to the DCF signal. Do you have experience in this area?
regards,
Gerrit
January 3, 2013 at 12:09 PM
Hi Gerrit,
It nice to see the library being put to good use. I really like your idea! my daughter is now nearly 2 year old, so a little early yet for her, but I’ll try to remember it.
About the bad signal: Since the time code is transmitted in the longwave range by amplitude modulation, it can therefore be easily disturbed, resulting in erroneous peaks. A source or RF noise is indeed the PC, the level of noise may depend on the shielding by the case.
The samples I included in the package may help you to get a better grasp of the signal quality.
I have been explained that noise may also creep up through the mains, either by picking up signal in the power lines or through the power supply. The latter I tried to minimize by using a by-pass capacitor. You could try using a bigger one and see if you AC power source works better. To minimize picking up signal, you can twist the cables going the DCF receiver
Another thing you can try is buying a better antenna:
http://fpga-xilinx.blogspot.nl/2012/04/your-6-hourly-digest-for-electronics_9462.html
Meanwhile, I’m following Udo Kleins blog, he’s introducing a phase locked loop and exponential filtering (a simple moving average filter). This will make the library even more robust to noise:
http://blog.blinkenlight.net/2012/12/01/dcf77-project/
Beste wensen voor 2013!
December 9, 2012 at 6:39 PM
Hi Thijs,
I got the DCF77 module as well and got it all quite easy to run, but I experience a not so good reception. even in front of a window, whereas my casio watch receives well.
you got any tips to receive the signal better.
January 3, 2013 at 12:15 PM
About the bad reception: I wrote this as a reply to essentially the same question by Gerrit, just below: the time code is transmitted in the longwave range by amplitude modulation, it can therefore be easily disturbed, resulting in erroneous peaks. A source or RF noise is indeed the PC, the level of noise may depend on the shielding by the case.
The samples I included in the package may help you to get a better grasp of the signal quality.
I have been explained that noise may also creep up through the mains, either by picking up signal in the power lines or through the power supply. The latter I tried to minimize by using a by-pass capacitor. You could try using a bigger one and see if you AC power source works better. To minimize picking up signal, you can twist the cables going the DCF receiver.
I wonder if your Casio is really doing that much better. I most cases it is enough to get a DCF update once a day, as long if you also have a real-time clock.
Another thing you can try is buying a better antenna:
http://fpga-xilinx.blogspot.nl/2012/04/your-6-hourly-digest-for-electronics_9462.html
Meanwhile, I’m following Udo Kleins blog, he’s introducing a phase locked loop and exponential filtering (a simple moving average filter). This will make the library even more robust to noise:
http://blog.blinkenlight.net/2012/12/01/dcf77-project/
Beste wensen voor 2013!
January 3, 2013 at 2:14 PM
Hi Thijs,
Beste wensen too!! Thanks for this, this is very helpful!
Meanwhile I have been looking into your library and decided to make some changes for my own benefit, basically for the user interface experience as i connected a 2x16char screen to my Arduino. If you want I can post my changes, they are :
– added a boolean that is false when the pulse was rejected by the int0handler or true when the boolean was accepted, basically indicating the reception (more or less)
– indicating if a first buffer was finalized and return what the current buffer position is. this way i can display ‘Time in xx seconds’
January 3, 2013 at 2:14 PM
Hi Thijs,
Beste wensen too!! Thanks for this, this is very helpful!
Meanwhile I have been looking into your library and decided to make some changes for my own benefit, basically for the user interface experience as i connected a 2x16char screen to my Arduino. If you want I can post my changes, they are :
– added a boolean that is false when the pulse was rejected by the int0handler or true when the boolean was accepted, basically indicating the reception (more or less)
– indicating if a first buffer was finalized and return what the current buffer position is. this way i can display ‘Time in xx seconds’
January 21, 2013 at 1:14 AM
Yes, I’m very interested in your change suggestions. I you can send them, I will see if I can integrate them in the next version
December 21, 2012 at 11:54 PM
Hi Thijs,
Ik probeer de interne klok van mijn ‘Uno R3’ te synchen, maar geen resultaat. De ‘DCFSignal’ geeft een andere output dan ik op jouw screenshot zie.
Aangesloten zoals jouw schema.
Enig idee wat hier fout gaat?
Groet,
Casper
0000000000000
1100000000
1000000000000000
11111100000000
10
11111111100
10
1111111111000000000000
111100
1110000000
1100
100000000000
111000000000
1000
1110
111111111111111000
10000000000000000000
11111111111111111100000
111000000000000000000000
11111111111111000
December 22, 2012 at 12:16 AM
He, het lijkt erop dat de antenne flink ver van de PC af moet liggen. En mijn USB signaal is niet al te best heb ik het idee. Hij werkt nu wel. Dank voor al je voorbereidend werk!
Groet,
casper
January 3, 2013 at 1:09 PM
Hi Casper,
Graag gedaan! De punten waar jij tegen aanloopt, RF interferentie, en ruis op de voeding, zijn bekende problemen. DCF77 is een lange golf signal met amplitude modulatie, en dat maakt hem gevoelig voor allerlei soorten ruis.
Thijs
January 13, 2013 at 1:32 PM
Hoi Thijs ,
ik heb zojuist de ontvanger van Conrad aan mijn Arduino Mega 2560 gehangen, maar de klok wordt niet op tijd gezet. Nou had ik deze aan pin 53 gehangen (omdat de pinnen ernaast gebruikt worden voor een lcdtje, dacht alles mooi bij elkaar te zetten) en natuurlijk heb ik het pin-nummer aangepast in de sketch. Maar toen ik ‘m toch maar aan 2 hing, wat eerst in de sketch stond, gebeurde er nog steeds niets. Ik krijg nog altijd output met de tijd die nog in het jaar 1970 zit. Enig idee waarom?
January 22, 2013 at 5:05 PM
Volgens mij is het probleem dat een ethernet Shield de pininterrupt gebruikt 🙂
January 25, 2013 at 2:47 PM
Hi,
thanks for the library, after some troubleshooting I found out that I needed to use interrupt 1 instead of 0 (#define DCF_INTERRUPT 1) on pin 2 to get it working with my arduino leonardo! The other examples without interrupt really helped me alot, because I knew at least the dcf signal was fine! 🙂
greetz
skunkjoe
February 20, 2013 at 12:56 PM
Great to hear!
Have fun playing with it
February 18, 2013 at 10:37 AM
Hallo, ich habe eine Frage. Wenn ich Beispiele DCFsignal verwenden oder so DCFsyncprovider Arduino funktioniert, wenn ich mein Programm DCFsync Arbeit zu nutzen. Bitte haben Sie konsultiert. Danke
/* Verze: 18.2.2013 Martin Pihrt
SD ctecka pro LED panel…
Posilaji se ASCI znaky na seriovou linku.
Dale se posila prikaz na rolovani textu…
Pripojeni SD karty:
** CLK/SCK – pin D13
** MISO – pin D12
** MOSI – pin D11
** CS – pin D10
Pripojeni cidla DS18B20:
** pin #1 ds18b20 – gnd
** pin #2 ds18b20 – pin D9
** pin #3 ds18b20 – +5V
** rezistor 4K z +5V na pin D9
Pripojeni DCF prijimace:
** data DCF out – pin D2
*/
//knihovny
#include “DCF77.h”
#include “Time.h”
#include
#include
File myFile;
OneWire ds(9); // prirazeni cidla teploty k pinu D9
int led = 14; // prirazeni LED DCF k pinu 14 tj A0
int led2 = 15; // prirazeni LED SD k pinu 15 tj A1
// DCF
#define DCF_PIN 2 // prijimaci modul DCF 77 pripojen k pinu D2
#define DCF_INTERRUPT 0 // preruseni asociovane s pinem
time_t prevDisplay = 0;
time_t time;
DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT);
//prenosova rychlost serial portu
#define BAUD_RATE 115200
//pocet segmentu – zde zadat pocet panelu tj. delku textu znaku
#define SEGMENT 3
// pocet sloupcu tj zobrazovanych znaku
#define pSloupcu (SEGMENT * 4)
unsigned int znak = 0;
int ctiSd;
//teplota
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
///////////////////// nastaveni ////////////////
void setup()
{
Serial.begin(BAUD_RATE);
delay(500); // pockame na desku LED po resetu
Serial.print(“C”); //vymaz bufer led panelu
delay(50);
DCF.Start();
//setTime(12,00,00,18,2,2013); //setTime(hr,min,sec,day,month,yr);
setSyncInterval(30); // Set the number of
// seconds between re-sync
setSyncProvider(getDCFTime); // Set the external time
// provider
pinMode(10, OUTPUT); // SD karta pin CS vystup
pinMode(led, OUTPUT); // kontrolni LED DCF synchronizace OK vystup
digitalWrite(led, LOW);
pinMode(led2, OUTPUT); // kontrolni LED cteni z SD OK vystup
digitalWrite(led2, LOW);
// vypis reklamy na panelu a info verze sw
// Serial.print(“\”INFO V”);
// Serial.write(0xdd); //cz znak y
// Serial.print(“PIS: \””);
// delay(1000);
// Serial.print(“11A”); //odsun vlevo
// delay(3000);
// Serial.print(“T”); //zobraz text info
// delay(30000);
// Serial.print(“21A”); //odsun vpravo
// delay(3000);
// kontrola SD karty
Serial.print(“\”KONTROLA SD:\””);
delay(1000);
Serial.print(“11A”); //odsun vlevo
delay(3000);
if (!SD.begin(10))
{
Serial.print(“\”CHYBA-KARTA!\””);
delay(2000);
Serial.print(“21A”); //odsun vpravo
delay(3000);
return;
} else {
digitalWrite(led2, HIGH);
Serial.print(“\”KARTA je OK \””);
}
delay(1000);
digitalWrite(led2, LOW);
Serial.print(“21A”); //odsun vpravo
delay(3000);
// SD overeni souboru led.txt
Serial.print(“\”KONTROLA \””);
delay(1500);
Serial.print(“\”DAT na SD…\””);
delay(1000);
Serial.print(“11A”); //odsun vlevo
delay(3000);
if (SD.exists(“LED.TXT”)) {
digitalWrite(led2, HIGH);
Serial.print(“\”SOUBOR je OK\””);
}
else {
Serial.print(“\”NA KAR”);
Serial.write(0x8d); //cz znak T
Serial.print(“E \””);
delay(1500);
Serial.print(“\”NEN”);
Serial.write(0xe5); //cz znak I
Serial.print(” SOUBOR:\””);
delay(1500);
Serial.print(“\”LED.txt! \””);
}
delay(1000);
digitalWrite(led2, LOW);
Serial.print(“21A”); //odsun vpravo
delay(3000);
//SD soubor otevreni
myFile = SD.open(“LED.TXT”);
if (myFile) {
Serial.print(“\””);
Serial.print(“START \””);
delay(1000);
digitalWrite(led2, HIGH);
Serial.print(“21A”); //odsun vpravo
delay(3000);
digitalWrite(led2, LOW);
Serial.print(“C”);
} else {
Serial.print(“\”CHYBA “);
Serial.write(0xc8); //cz znak C
Serial.print(“TEN”);
Serial.write(0xe5); //cz znak I
Serial.print(” \””);
delay(1500);
Serial.print(“\”ZE SOUBORU \””);
delay(3000);
Serial.print(“21A”); //odsun vpravo
delay(3000);
} //konec else
} //konec setup
void loop() /////////////// hlavni smycka //////////////////
{
tiskzSD();
tiskteploty();
if( now() != prevDisplay) //update the display only if the time has changed
{
prevDisplay = now();
digitalClockDisplay();
}
} /////////////// konec hlavni smycka //////////////////
//*********************************************************
unsigned long getDCFTime()
{
time_t DCFtime = DCF.getTime();
// Indicator that a time check is done
if (DCFtime!=0) {
digitalWrite(led, HIGH);
delay(100);
digitalWrite(led, LOW);
}
return DCFtime;
}
//*********************************************************
void tiskzSD()
{
myFile = SD.open(“led.txt”); // otevreme soubor na SD karte
if (myFile)
{
ctiData();
delay(10);
} // konec if
myFile.close(); // uzavereme soubor led.txt – konec prace s SD
}
//******************************************
void ctiData()
{
while (myFile.available())
{
digitalWrite(led2, HIGH);
for (int i=0; i < (pSloupcu + 2); i++) // pr: 12 znaku + 2 uvozovky = 14 znaku
{
ctiSd=(myFile.read());
if (ctiSd == '"')
{
znak = 0;
delay(10);
}
Serial.write(ctiSd); // zapiseme na vystup data z karty
if (znak == pSloupcu)
{
delay (2000); // cekáme na dalsi cteni radku z SD karty
znak = 0;
digitalWrite(led2, LOW);
}
znak++; // pocitadlo znaku
} // konec for
} // konec while
} // konec void
//*********************************************************
void digitalClockDisplay() //// vypis casu /////
{
Serial.print("\"P");
Serial.write(0xd8); //cz znak R 216
Serial.print("ESN");
Serial.write(0xdd); //cz znak Y 221
Serial.print(" ");
Serial.write(0xc8); //cz znak C 200
Serial.print("AS: \"");
delay(500);
Serial.print("21A"); //odsun vpravo
delay(3000);
Serial.print("\"");
Serial.print(hour());
printDigits(minute());
printDigits(second());
delay(3000);
Serial.print("\"");
Serial.print("C"); //smazat led panel
delay(50);
Serial.print("\"DATUM: \"");
delay(500);
Serial.print("21A"); //odsun vpravo
delay(3000);
Serial.print("C"); //smazat led panel
delay(50);
Serial.print("\"");
Serial.print(" ");
Serial.print(day());
Serial.print(".");
Serial.print(month());
Serial.print(".");
Serial.print(year());
Serial.print("\"");
delay(3000);
}
//*********************************************************
void printDigits(int digits) // pomocna funkce na zobrazeni nul pred casem
{
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
//*********************************************************
void temp() //zpracovani teploty z cidla dallas
{
if ( !ds.search(addr)) {
ds.reset_search();
delay(250);
return;
}
if (OneWire::crc8(addr, 7) != addr[7]) {
return;
}
switch (addr[0]) {
case 0x10:
type_s = 1;
break;
case 0x28:
type_s = 0;
break;
case 0x22:
type_s = 0;
break;
default:
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
// convert the data to actual temperature
unsigned int raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// count remain gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 – data[6];
}
} else {
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
}
//*********************************************************
void tiskteploty() //// vypis teploty /////
{
Serial.print("\"TEPLOTA: \"");
delay(500);
Serial.print("21A"); //odsun vpravo
delay(3000);
Serial.print("\"");
temp(); // zpracuj teplotu
Serial.print(celsius);
Serial.write(0xb0); //znak ° stupnu asci 0176
Serial.print("C");
Serial.print("\"");
delay(3000);
}
February 20, 2013 at 12:55 PM
Hi,
I have trouble understanding your question, but I assume it is “The sample application is working, but the same code is not working in my own program. What could be the problem?”
I would investigate the following:
– Make use that none of your other libraries are using interrupt 0.
– It could be that the blinking of your led (or writing to the SD card) influences the source going to the DCF receiver. This can mess with the signal. Try turning off these and see if a time is received
Good luck,
Thijs
February 20, 2013 at 1:27 PM
Hello, thank you for your answer. The problem really causes SD library. thank you
March 12, 2013 at 1:49 PM
Hi,
great work thanks a lot.
Just a question is your library also exporting the weekday?
I didn’t find any information about it?
Cheers Robert
April 21, 2013 at 8:49 AM
Hi Robert,
No, the DCF77 library doesn’t, but the time library with which the DCF library interacts does, see: http://playground.arduino.cc/Code/time.
In order to have good separation of concerns, I want the DCF library just to receive and output the time, and do time-displaying, -conversion and -manipulation outside of it
April 22, 2013 at 11:50 AM
Beste Thijs,
Bedankt voor de artikel serie. Ben zeer onder de indruk. Heb een tijd geleden geprobeerd om dezelfde ontvanger aan de praat te krijgen.
Nu met de hulpprogramma’s kan ik wat zien.
Sinds kort ook een RIGO scoop.
Deze aan pin 13 gehangen nu zie ik en de resultaten van de arduino op het scherm en ook op de scoop.
Mijn vraag is; heb je enig idee hoelang de verbinding tussen de arduino en de ontvanger mag zijn?
Met vriendelijke groet,
Jan Kromhout
Hellevoetsluis
May 23, 2013 at 8:55 AM
Hoi Jan,
Bedankt voor het compliment! Ik heb niet gekeken naar de afstand tussen de Arduino en ontvanger. De beste manier om er achter te komen, is door het te proberen. Als het niet lukt zou ik een Arduino redelijk dicht bij de ontvanger zetten en deze laten communiceren met een Arduino verder weg. Dat kan via ethernet, wifi, bluetooth, zigbee of serieel.
Succes! Thijs
June 1, 2013 at 4:15 PM
Hoi Thijs,
ik kreeg de library met DCFBinaryStream en VERBOSE_DEBUG aan, eerst niet aan de praat op een Arduino Pro Mini. Terwijl ik met DCFSignal en DCFPulseLength wel goeie output kreeg.
Totdat ik de interrupt handler zoals hieronder aangegeven aanpaste. (De debug logging en returns eruit gehaald). heb verder niet uitgezocht hoe dat precies komt, maar is wel reproduceerbaar. (Mogelijk verpesten de returns of de debug logging de stack op een of andere manier).
Iigv bedankt voor de mooie library.
— mijn aanpassing/workaround in int0handler —
void DCF77::int0handler() {
int flankTime = millis();
byte sensorValue = digitalRead(dCF77Pin);
// Added by BJMD 01062013
/**/ boolean validpulse = true;
// If flank is detected quickly after previous flank up
// this will be an incorrect pulse that we shall reject
if ((flankTime-PreviousLeadingEdge)<DCFRejectionTime) {
// Removed by BJMD 01062013
// org LogLn("rCT");
// org return;
// Added by BJMD 01062013
/**/ validpulse = false;
}
// If the detected pulse is too short it will be an
// incorrect pulse that we shall reject as well
if ((flankTime-leadingEdge) DCFSyncTime) {
finalizeBuffer();
}
PreviousLeadingEdge = leadingEdge;
// Distinguish between long and short pulses
if (difference < DCFSplitTime) { appendSignal(0); } else { appendSignal(1); }
Up = false;
}
}
// added by BJMD 01062013
/**/ } // validpulse
}
September 23, 2013 at 10:57 PM
Hoi Ben,
Bedankt voor het compliment. Ik zie ook niet helemaal waarom je fix het probleem oplost, maar mocht ik er ook tegenaan lopen, zal ik hier zeker aan denken!
Pingback: Magic Smoke » PongClock 1.5 – DCF77 Funkuhr
October 16, 2013 at 11:45 PM
Hoi Thijs,
Allereerst bedankt voor de ontwikkeling van de DCF77 Library! Ik ondervind echter een probleem. Als ik de DCF aansluit op pin 2 van de arduino uno dan werkt alles perfect, sluit ik hem echter aan op een andere pin (uiteraard met de aanpassing in de sketch naar diezelfde pin) dan wordt de tijd niet gesynced. Wat op zich vreemd is daar ik in de code niets gehardcoded zie naar die bewuste pin 2. Helaas kan ik de DCF niet op pin 2 laten omdat het seeedstudio tft scherm deze reeds in gebruik geeft. Enige idee wat de oorzaak kan zijn?
April 6, 2014 at 4:37 PM
Hoi Wim,
Dat heeft te maken met de interupt, er is voor een bepaald aantal pinnen, per pin een interrupt die wordt aangeroepen als het signaal verandert. Als je de pin verandert, moet je dus ook een andere interrupt instellen, indien beschikbaar is. Zie http://arduino.cc/en/Reference/attachInterrupt
November 17, 2013 at 7:15 PM
Hi,
i’m just trying to use this library with my Arduino Leonardo.
The compiling and uploading works, even pin 13 is blinking in the second rythm. But i can’t get any time from the examples.
I made some screenshots from the serial output from some example sketches.
http://imgur.com/a/rSF9N
April 6, 2014 at 2:54 PM
Hi,
The pulses look quite nice, so it is probably not the signal quality, but the triggering on flank changes. The samples come with the correct pin and interrupt for an Arduino, but for a Leonardo, you should probably use DCF_PIN 3 and DCF_INTERRUPT 0, see: http://arduino.cc/en/Reference/attachInterrupt.
April 13, 2014 at 7:43 PM
Derp!
Ah, yes the interrupts.
It works now thanks.
January 27, 2014 at 1:14 PM
Hallo Thijs,
ben net begonnen met de arduino en zag je project dus nagebouwd en het werkte in een keer. Nu vraag ik me nog af hoe de dag en maand er uit te krijgen zijn. Ik ben totaal geen programmeur dus dat is lastiger………. Heb jij misschien een hint of voorbeeld?
Groetjes
Hans
January 27, 2014 at 10:05 PM
Hoi Hans,
Ja hoor, ik heb wel een hint. Bij de DCF77 library is ook de Time library toegevoegd. Deze geeft je allemaal functies om
time_t
om te zetten, bv naar dag en maand. Ziehttp://playground.arduino.cc/Code/time
.Succes!
February 17, 2014 at 5:53 PM
Hallo Thijs,
Ik ben erg onder de indruk van het (denk)werk wat in je DCF77 library is gegaan! Ik ben met 49 jaar net begonnen met de Arduino en er gaat een wereld voor me open.
Omdat ik compleet verzot ben op DCF klokken, al vanaf het begin, is je library een geweldig cadeau!
(mijn vraag staat onderaan, eerst wat uitleg… 😉 )
Ik ben bezig met een hele speciale DCF klok. Ik wil namelijk 2 rijen van 59 LED’s onder elkaar plaatsen met daarboven een normaal 7seg display met tijd/datum en temp.
De eerste rij LED’s maakt de binnenkomende DCF pulsen zichtbaar (0=uit/1=aan) en als er een 100% volledig minuut signaal is ontvangen, dan wordt de bovenste rij ‘opgeschoven naar de onderste en begin alles weer van voor af aan.
Je kunt dus de onderste rij LED’s de huidige tijd zien in gecodeerde vorm en de DCF pulsen die binnenkomen op de bovenste rij (leuk om te zien!)
Daarnaast heb ik vanuit je dcf77.cpp library de fout meldingen ‘omgezet’ in LED output.
Als er foute signalen binnenkomen zie je de betreffende LED oplichten en er gaat een ‘ERROR’ led branden ten teken dat de binnenkomende pulsen niet de juiste tijd aangeven. de onderste rij van 60 LED’s dooft dan ook.
Als het signaal weer ‘ok’ is, er zijn dan 2 minuten lang juiste pulsen ontvangen, gaat er een groene LED branden en wordt de puls info weer weergeven op de 2 rijen van 59 LED’s.
Overigens heb ik een antenne en dcf print gekocht bij http://www.hkw-elektronik.de
GEWELDIG! De Conrad ontvanger viel helemaal dood als ik mijn Chinese maxim7219 chips activeerde (ik ga nu originele chips kopen) maar de HWK ontvanger werkt onvoorstelbaar veel beter. (voor maar 18 euro notabene)
Maar nu loop ik tegen mijn zeer beperkte kennis van programmeren aan. Ben nog maar pas begonnen met c++
Ik ben er zelfs niet in geslaagd je mooie dcf77 library te ontcijferen wat betref de ‘flow’, de volgorde. Ik begrijp niet helemaal hoe eea gekoppeld is etc. Maar ik leer nog.
Wat ik beschreef, heb ik nu ondergebracht in de dcf77.cpp file omdat ik niet weet hoe dat anders zou moeten. het weergeven van de actuele tijd op het 7seg display lukt wel alleen klopt de sec. weergave niet. ook loopt de boel na een tijdje vast.
Ik heb geprobeerd de dcf77.cpp file om te zetten naar de ‘normale’ library maar dat ging hopeloos mis omdat ik niet weet waar ik op moet letten.
Ik zie nu de bomen door het c++ bos niet meer en ws. wil ik teveel als beginner… 🙁
Ik vraag geen kant en klare oplossing maar hoe zou ik de 7 zeg displays moeten aansturen? Doe ik dat net als de 2 matrixen van 59 led’s ook vanuit de dcf77.cpp file?
De ultieme klok zou een RTC hebben die elke minuut met DCF wordt vergeleken.
Kan je me svp richting geven of een (hoop ik niet te ingewikkeld) c++ boek aanbevelen?
Heb me suf gezocht naar meer info over libraries maar zoals gezegd raak ik verdwaald.
Mocht je tijd hebben, bedankt!!
Erik de Ruiter
March 12, 2014 at 3:32 PM
Dag Erik,
Welkom in de Arduino wereld! en wat leuk dat mijn library goed bevalt 🙂 Het is inderdaad zo dat de DCF77 bibliotheek wat lastig te begrijpen is. Dat komt in essentie omdat hij interrupt gestuurd is. Er zijn daardoor 2 flows in de applicatie:
De eerste wordt getriggered door een interrupt op een flank verandering van het DCF signaal. De aangeroepen code probeert enkel te bepalen of er een puls binnengekomen is van 100, 200, of meer dan 1000 ms. De eerste 2 worden opgeslagen als een 0 of 1 in het data buffer, de laatste betekend dat de minuut afgelopen is. De tweede flow wordt aangeroepen door hoofd applicatie als je de tijd opvraagt. Het buffer wordt dan geïnterpreteerd met een data structuur die datum, tijd en een serie checks oplevert. De interrupts resulteren in de noodzaak om statische functies te gebruiken, de dubbele flow zorg ervoor dat we volatile variabelen nodig hebben.
De interrupt gedreven implementatie is handig omdat er enkel op een flank verandering een klein stukje code uitgevoerd hoeft te worden, en het hoofdprogramma de rest van de tijd de processor tot zijn beschikking heeft. In jouw applicatie is het uitlezen van de atoomklok de hoofdzaak, dus kan je een implementatie maken zonder interrupt. De sample die de 1 en 0 teruggeeft is daarvoor een goed begin.
Als ik je een tip mag geven: gezien je redelijk nieuw bent met c++ zou ik je project opbreken in kleinere stukken, en van simpel naar moeilijk werken: Ik zou eerst kijken of je de 1 en 0 kan afbeelden op een led matrix, en pas daarna gaan proberen om de tijd uit te lezen. Als je zover bent wil ik wel mee kijken. Wat betreft het aansturen van de leds kom je in een ander leuk Arduino gebied terecht. Verreweg de simpelste manier om een dergelijke hoeveelheid leds aan te sturen, is door een programmeerbare ledstrip te gebruiken: .
Wat betreft een goed c++ boek, ik heb mijn eerste stappen gezet rond 1980 aan de hand Ammeraal: http://www.bol.com/nl/p/basiscursus-c/666842990/ . Het is echt heel basis, dus prima om mee te starten. Het zal je misschien niet DCF77 compleet laten begrijpen, maar wel een heel stuk helpen.
Ik hoop dat je hier wat mee kan en heel veel succes!
Thijs
March 13, 2014 at 2:30 PM
Hallo Thijs,
Bedankt voor je tips!
Ik heb de 2 rijen van 59 LED’s werkend. erg leuk om te zien.
Op de eerste rij LED’s zijn dus de binnenkomende pulsen zichtbaar en als er een volledige minuut is binnengekomen, wordt het ‘display’ van de eerste rij gekopieerd naar de 2e rij LED’s en begint alles opnieuw.
Op twee 7-segment displays is de tijd te zien en de temperatuur.
Op een bepaald momenten elke minuut wordt kort de datum weergegeven
Fouten in de ontvangst heb ik zichtbaar gemaakt op een aantal andere LED’s
Ik afwachting van je antwoord had ik inmiddels een boek gevonden en doorgelezen: “Beginning C for Arduino van Jack Purdum”. Fantastisch boek!
Nu nog een RTC integreren voor het geval het DCF signaal niet zichtbaar is en later een ontvanger om een draadloze thermometer uit te lezen.
De RTC en de werking van de Syncprovider is nog lastig te begrijpen. Ik wil de onderliggende principes begrijpen en daar loop ik vast nog. Onvoorstelbaar weinig info hierover te vinden op het web!? Ben toch aardig ervaren in het zoeken naar info maar helaas. Enfin, door vallen en opstaan komen we er wel.
Als ik vastloop maak ik graag gebruik van je aanbod even mee te kijken, bedankt!
Groeten!
Erik
March 17, 2014 at 5:24 AM
I absolutely love your blog.. Great colors &
theme. Did you build this web site yourself?
Please reply back as I’m trying to create my own website and would love to know
where you got this from or just what the theme is named.
Kudos!
April 4, 2014 at 11:36 PM
Hi! Actually it’s a free WordPress theme: Yoko, but with some minor changes. You can find it here: https://wordpress.org/themes/yoko. Have fun with it!
March 18, 2014 at 3:58 PM
Hallo Thijs!
Ik ben erin geslaagd je dcf77 library weer om te zetten naar 1 sketch zodat ik de flow beter kan volgen en code kan invoegen tbv matrix display’s en led’s.
Voor een beginner als mij is dat duidelijker… 😉
Alles werkt mits ik onderstaande regel code uit de Int0 functie sloop.
pulseStart = OnRisingFlank ? HIGH : LOW;
Wat gebeurt hier? Ik kan nergens vinden wat ‘? en ‘:’ betekent.
Alvast bedankt!
April 2, 2014 at 2:39 PM
Hi Erik!
?: is een ternary operator, en wordt door wikidedia beter uitgelegd dan ik kan: http://en.wikipedia.org/wiki/%3F:#C.2B.2B
Deze regel bepaalt of een puls start bij een opgaande of neergaande flank, afhankelijk van OnRisingFlank. Dit moet instelbaar zijn omdat bij sommige DCF77 ontvangers de pulse geïnverteerd wordt.
Groeten, Thijs
G
Pingback: DCF77 | SNODES
April 4, 2014 at 11:31 PM
Thanks for referring to my library. I have not investigated it, but my first guess would be that the attiny85 has other pins on which interrupts can be triggered. An interrupt is used to only call the the library when a new pulse is coming in.
March 31, 2014 at 1:37 PM
Dear Thijs,
many thanks for your excellent DCF77 library, all is working very well by my arduino UNO.
But I have one question:
What I have to do, when I want to activate a alarm or activate a output in my arduino sketch ( switch on or switch off) at different time?
Many thanks for your answer in advance.
Franz
April 4, 2014 at 11:11 PM
Hi Franz, Thanks! The DCF77 library only deals with fetching the current time and giving it back in standard time format. It is considered good practice to separate responsibilities in different libraries (classes). However, the DCF77 works together with the Time library, and this in turn works with the TimeAlarms library: http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
I hope this helps you set up your alarms!
Good luck, Thijs
April 7, 2014 at 10:14 AM
Dear Thijs,
many thanks – it works very well.
Thanks again.
Franz
April 7, 2014 at 6:06 PM
Dear Thijs,
great work.
After playing around with the library and various DCF receivers I have a suggestion to help out all the people who didnt get a signal and moving around antennas like me 😉
I used sometime the Utils.h logs to get the info of the signal streaming in but it somewhat chrashes my sketches if that runs too long….cant explain it yet.
As a help/workaround for quality/receiving signal I have defined a boolean variable called receiveDCF in your library.
It gets its information from the various int0handler methods like this:
if ((flankTime-leadingEdge)<DCFRejectPulseWidth) {
DCF77::receiveDCF=false;
LogLn("rPW");
return;
Here the definition:
public:
// Public Functions
DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true);
static time_t getTime(void);
static time_t getUTCTime(void);
static void Start(void);
static void Stop(void);
static void int0handler();
static bool receiveDCF;
What do you say ?
Best regards
Marcus
April 7, 2014 at 9:33 PM
I believe the crash has something to do with the interrupt function interfering with the Serial interrupt, or possibly the interrupt function taking too much time in logging, and being called again while processing. Thanks for your suggestion! What are trying to get done,exactly? Also, when receiveDCF is set to false, is it never set to true again?
April 8, 2014 at 8:24 AM
Hi Thijs,
I call DCF77::receiveDCF in my main display routines and visualize the result.
As its slow changing you can see if you receive a signal or not every second or so. Like that:
if(DCF.receiveDCF) lcd.print(“DCF77 “);
else lcd.print(“No DCF”);
Even better would be some calculations on #of rejected signals/pulsewidth
in an arry for example to measure the quality of the signal more precise as signal/no signal. Maybe you have an idea.
Here the logic of receiveDCF …very simple:
false if rCT or rPW…like your logs.
true if appendSignal method is used…
intitalized as:
bool DCF77::receiveDCF=false;
if ((flankTime-PreviousLeadingEdge)<DCFRejectionTime) {
DCF77::receiveDCF=false;
LogLn("rCT");
return;
}
// If the detected pulse is too short it will be an
// incorrect pulse that we shall reject as well
if ((flankTime-leadingEdge)<DCFRejectPulseWidth) {
DCF77::receiveDCF=false;
LogLn("rPW");
return;
}
inline void DCF77::appendSignal(unsigned char signal) {
Log(signal, DEC);
DCF77::receiveDCF=true;
runningBuffer = runningBuffer | ((unsigned long long) signal < 59) {
// Buffer is full before at end of time-sequence
// this may be due to noise giving additional peaks
LogLn(“EoB”);
finalizeBuffer();
}
}