Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 52 additions & 4 deletions DCF77.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,36 @@
11 Apr 2012 - initial release
23 Apr 2012 - added UTC support
2 Jul 2012 - minor bugfix and additional noise rejection

modified by DCEM - https://github.com/DCEM/
08 Apr 2020
*/

#include <DCF77.h> //https://github.com/thijse/Arduino-Libraries/downloads
#include <TimeLib.h> //http://playground.arduino.cc/code/time
#include <Utils.h>
#ifndef DCF77_USE_RTC
#include <TimeLib.h> //http://playground.arduino.cc/code/time
#else
#define now altNow
#endif

#define _DCF77_VERSION 1_0_0 // software version of this library
#define _DCF77_VERSION 1_1_0 // software version of this library

using namespace Utils;

/**
* Constructor
*/
DCF77::DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank)
DCF77::DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank, bool EnableInputPullup, bool CompareToUTC)
{
dCF77Pin = DCF77Pin;
dCFinterrupt = DCFinterrupt;
pulseStart = OnRisingFlank ? HIGH : LOW;
dCF77PinMode = EnableInputPullup ? INPUT_PULLUP : INPUT;
compareToUTC = CompareToUTC;

if (!initialized) {
pinMode(dCF77Pin, INPUT);
pinMode(dCF77Pin, dCF77PinMode);
initialize();
}
initialized = true;
Expand Down Expand Up @@ -187,6 +196,10 @@ bool DCF77::receivedTimeUpdate(void) {
// Since the received signal is error-prone, and the parity check is not very strong,
// we will do some sanity checks on the time
time_t processedTime = latestupdatedTime + (now() - processingTimestamp);
if (compareToUTC) {
int UTCTimeDifference = (CEST ? 2 : 1)*SECS_PER_HOUR;
processedTime = processedTime - UTCTimeDifference;
}
if (processedTime<MIN_TIME || processedTime>MAX_TIME) {
LogLn("Time outside of bounds");
return false;
Expand Down Expand Up @@ -269,7 +282,12 @@ bool DCF77::processBuffer(void) {

// Calculate parities for checking buffer
calculateBufferParities();
#ifndef DCF77_USE_RTC
tmElements_t time;
#else
tm time;
#endif

bool proccessedSucces;

struct DCF77Buffer *rx_buffer;
Expand All @@ -283,13 +301,24 @@ bool DCF77::processBuffer(void) {
rx_buffer->CEST != rx_buffer->CET)
{
//convert the received buffer into time
#ifndef DCF77_USE_RTC
time.Second = 0;
time.Minute = rx_buffer->Min-((rx_buffer->Min/16)*6);
time.Hour = rx_buffer->Hour-((rx_buffer->Hour/16)*6);
time.Day = rx_buffer->Day-((rx_buffer->Day/16)*6);
time.Month = rx_buffer->Month-((rx_buffer->Month/16)*6);
time.Year = 2000 + rx_buffer->Year-((rx_buffer->Year/16)*6) -1970;
latestupdatedTime = makeTime(time);
#else
time.tm_sec = 0; /**< seconds after the minute - [ 0 to 59 ] */
time.tm_min = rx_buffer->Min-((rx_buffer->Min/16)*6); /**< minutes after the hour - [ 0 to 59 ] */
time.tm_hour = rx_buffer->Hour-((rx_buffer->Hour/16)*6); /**< hours since midnight - [ 0 to 23 ] */
time.tm_mday = rx_buffer->Day-((rx_buffer->Day/16)*6); /**< day of the month - [ 1 to 31 ] */
time.tm_mon = rx_buffer->Month-((rx_buffer->Month/16)*6); /**< months since January - [ 0 to 11 ] */
time.tm_year = 2000 + rx_buffer->Year-((rx_buffer->Year/16)*6) - 1900; /**< years since 1900 */
time.tm_isdst = rx_buffer->CEST; /**< Daylight Saving Time flag */
latestupdatedTime = mktime(&time);
#endif
CEST = rx_buffer->CEST;
//Parity correct
return true;
Expand Down Expand Up @@ -335,12 +364,31 @@ int DCF77::getSummerTime(void)
return (CEST)?1:0;
}

void DCF77::setCallbackFunctionRTC( time_t (*fptr)() ) {
fptr_CallbackFunctionRTC = fptr;
}

time_t DCF77::altNow() {
time_t output;
if( 0 != fptr_CallbackFunctionRTC ) {
output = (*fptr_CallbackFunctionRTC)();
}
else {
LogLn('error: callback funtion for RTC needs to be set');
}
return output;
}

/**
* Initialize parameters
*/
int DCF77::dCF77Pin=0;
int DCF77::dCFinterrupt=0;
byte DCF77::pulseStart=HIGH;
byte DCF77::dCF77PinMode=INPUT;
bool DCF77::compareToUTC=false;
typedef time_t (*callback_ptr_type)();
callback_ptr_type DCF77::fptr_CallbackFunctionRTC = 0;

// Parameters shared between interupt loop and main loop

Expand Down
20 changes: 17 additions & 3 deletions DCF77.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
#else
#include <WProgram.h>
#endif
#include <TimeLib.h>
#ifndef DCF77_USE_RTC
#include <TimeLib.h>
#else
#include <time.h>
#define SECS_PER_MIN ((time_t)(60UL))
#define SECS_PER_HOUR ((time_t)(3600UL))
#endif

#define MIN_TIME 1334102400 // Date: 11-4-2012
#define MIN_TIME 1586270068 // Date: 7-4-2020
#define MAX_TIME 4102444800 // Date: 1-1-2100

#define DCFRejectionTime 700 // Pulse-to-Pulse rejection time.
Expand All @@ -24,6 +30,8 @@ class DCF77 {
static int dCF77Pin;
static int dCFinterrupt;
static byte pulseStart;
static byte dCF77PinMode;
static bool compareToUTC;

// DCF77 and internal timestamps
static time_t previousUpdatedTime;
Expand Down Expand Up @@ -84,16 +92,22 @@ class DCF77 {
bool static processBuffer(void);
void static appendSignal(unsigned char signal);

//RTC callback
static time_t altNow();
static time_t (*fptr_CallbackFunctionRTC)();

public:
// Public Functions
DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true);

DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true, bool EnableInputPullup=false, bool CompareToUTC=false);

static time_t getTime(void);
static time_t getUTCTime(void);
static void Start(void);
static void Stop(void);
static void int0handler();
static int getSummerTime();
static void setCallbackFunctionRTC( time_t (*fptr)() );
};

#endif
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,24 @@ can be found here:
Serial.print(digits);
}

## Changes in 2020 by DCEM
The constructor now additionally accepts:

- EnableInputPullup
- CompareToUTC

Allow to use RTC instead of TimeLib.

To archive this, you have to `#define DCF77_USE_RTC` before `#include "DCF77.h"`.
This should work with any RTC. Since the DCF77 library needs to get the time from the RTC you need to put
the function call inside the `RTC_Callback_Wrapper()`. Look at the ZeroRTCSync example for more details.

Added example sketch:

- ZeroRTCSync.ino

It shows how to fetch a DCF77 time and synchronize the internal RTC of an Arduino Zero.

## On using and modifying libraries

- [http://www.arduino.cc/en/Main/Libraries](http://www.arduino.cc/en/Main/Libraries)
Expand Down
5 changes: 4 additions & 1 deletion examples/DCFBinaryStream/DCFBinaryStream.ino
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
#include <TimeLib.h> //http://www.arduino.cc/playground/Code/Time

#define DCF_PIN 2 // Connection pin to DCF 77 device
#define DCF_INTERRUPT 0 // Interrupt number associated with pin
#define DCF_INTERRUPT digitalPinToInterrupt(DCF_PIN) // Interrupt number associated with pin
#ifdef SERIAL_PORT_MONITOR
#define Serial SERIAL_PORT_MONITOR
#endif

time_t time;
DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT);
Expand Down
5 changes: 4 additions & 1 deletion examples/DCFPulseLength/DCFPulseLength.ino
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@

*/

#define BLINKPIN 13
#define BLINKPIN LED_BUILTIN
#define DCF77PIN 2
#ifdef SERIAL_PORT_MONITOR
#define Serial SERIAL_PORT_MONITOR
#endif

int flankUp = 0;
int flankDown = 0;
Expand Down
5 changes: 4 additions & 1 deletion examples/DCFSignal/DCFSignal.ino
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@

*/

#define BLINKPIN 13
#define BLINKPIN LED_BUILTIN
#define DCF77PIN 2
#ifdef SERIAL_PORT_MONITOR
#define Serial SERIAL_PORT_MONITOR
#endif

int prevSensorValue=0;

Expand Down
5 changes: 4 additions & 1 deletion examples/InternalClockSync/InternalClockSync.ino
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
#include "TimeLib.h"

#define DCF_PIN 2 // Connection pin to DCF 77 device
#define DCF_INTERRUPT 0 // Interrupt number associated with pin
#define DCF_INTERRUPT digitalPinToInterrupt(DCF_PIN) // Interrupt number associated with pin
#ifdef SERIAL_PORT_MONITOR
#define Serial SERIAL_PORT_MONITOR
#endif

time_t time;
DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT);
Expand Down
5 changes: 4 additions & 1 deletion examples/SyncProvider/SyncProvider.ino
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
#include <TimeLib.h> //http://www.arduino.cc/playground/Code/Time

#define DCF_PIN 2 // Connection pin to DCF 77 device
#define DCF_INTERRUPT 0 // Interrupt number associated with pin
#define DCF_INTERRUPT digitalPinToInterrupt(DCF_PIN) // Interrupt number associated with pin
#ifdef SERIAL_PORT_MONITOR
#define Serial SERIAL_PORT_MONITOR
#endif

time_t prevDisplay = 0; // when the digital clock was displayed
time_t time;
Expand Down
5 changes: 4 additions & 1 deletion examples/TimeZones/TimeZones.ino
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
#include <Timezone.h> //https://github.com/JChristensen/Timezone

#define DCF_PIN 2 // Connection pin to DCF 77 device
#define DCF_INTERRUPT 0 // Interrupt number associated with pin
#define DCF_INTERRUPT digitalPinToInterrupt(DCF_PIN) // Interrupt number associated with pin
#ifdef SERIAL_PORT_MONITOR
#define Serial SERIAL_PORT_MONITOR
#endif

// more time zones, see http://en.wikipedia.org/wiki/Time_zones_of_Europe
//United Kingdom (London, Belfast)
Expand Down
88 changes: 88 additions & 0 deletions examples/ZeroRTCSync/ZeroRTCSync.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* InternalClockSync.ino
* example code illustrating time synced from a DCF77 receiver
* Thijs Elenbaas, 2012-2017
* This example code is in the public domain.

This example shows how to fetch a DCF77 time and synchronize
the internal clock. In order for this example to give clear output,
make sure that you disable logging from the DCF library. You can
do this by commenting out #define VERBOSE_DEBUG 1 in Utils.cpp.

NOTE: If you used a package manager to download the DCF77 library,
make sure have also fetched these libraries:

* RTCZero | or the appropiate library for your RTC

*/

#define DCF77_USE_RTC // define before #include "DCF77.h";
// it "enables" RTC and "disables" TimeLib
#include "DCF77.h"
#include <RTCZero.h>

#define DCF_PIN 12 // Connection pin to DCF 77 device
#define DCF_OnRisingFlank false // false: DCF device signal inverted
#define DCF_EnableInputPullup true // true: connection pin input pullup enabled
#define DCF_CompareToUTC true // true: library compares to UTC instead of localtime
#define DCF_INTERRUPT digitalPinToInterrupt(DCF_PIN) // Interrupt number associated with pin
#ifdef SERIAL_PORT_MONITOR
#define Serial SERIAL_PORT_MONITOR
#endif

RTCZero rtc;
DCF77 DCF = DCF77(DCF_PIN, DCF_INTERRUPT, DCF_OnRisingFlank, DCF_EnableInputPullup, DCF_CompareToUTC);


void setup() {
Serial.begin(9600);
rtc.begin(); // initialize RTC
DCF.Start();
DCF.setCallbackFunctionRTC(RTC_Callback_Wrapper); // change in RTC_Callback_Wrapper, not here
Serial.println("Waiting for DCF77 time ... ");
Serial.println("It will take at least 2 minutes until a first update can be processed.");
}

void loop() {
time_t DCFtime = DCF.getUTCTime(); // Check if new DCF77 time is available
if (DCFtime!=0)
{
if (DCFtime != rtc.getEpoch()) {
Serial.println("Time is updated");
rtc.setEpoch(DCFtime);
} else {
Serial.println("0 delta");
}
}

digitalClockDisplay();
delay(1000);
}

void digitalClockDisplay(){
// digital clock display of the time
Serial.print(rtc.getHours());
printDigits(rtc.getHours());
printDigits(rtc.getSeconds());
Serial.print(" ");
Serial.print(rtc.getDay());
Serial.print(" ");
Serial.print(rtc.getMonth());
Serial.print(" ");
Serial.print(rtc.getYear());
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);
}

time_t RTC_Callback_Wrapper()
{
// change rtc.getEpoch() to the apporpiate function for your RTC
return rtc.getEpoch();
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=DCF77
version=1.0.0
version=1.1.0
author=Thijs Elenbaas
maintainer=Thijs Elenbaas
sentence=Read and decode the atomic time broadcasted by the DCF77 radiostation.
Expand Down
2 changes: 1 addition & 1 deletion utility/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Utils {

#define DEBUG_BLINK_PIN 13 // Connected to debug led
#define DEBUG_BLINK_PIN LED_BUILTIN // Connected to debug led
//#define VERBOSE_DEBUG 1 // Verbose

void LogLn(char*s)
Expand Down
4 changes: 3 additions & 1 deletion utility/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#else
#include <WProgram.h>
#endif
#include <TimeLib.h>
#ifndef DCF77_USE_RTC
#include <TimeLib.h> //http://playground.arduino.cc/code/time
#endif

#define intDisable() ({ uint8_t sreg = SREG; cli(); sreg; })
#define intRestore(sreg) SREG = sreg
Expand Down