diff --git a/DCF77.cpp b/DCF77.cpp index ccfb47b..047e185 100644 --- a/DCF77.cpp +++ b/DCF77.cpp @@ -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 //https://github.com/thijse/Arduino-Libraries/downloads -#include //http://playground.arduino.cc/code/time #include +#ifndef DCF77_USE_RTC + #include //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; @@ -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 (processedTimeMAX_TIME) { LogLn("Time outside of bounds"); return false; @@ -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; @@ -283,6 +301,7 @@ 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); @@ -290,6 +309,16 @@ bool DCF77::processBuffer(void) { 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; @@ -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 diff --git a/DCF77.h b/DCF77.h index bdd0bf1..dd6c0d9 100644 --- a/DCF77.h +++ b/DCF77.h @@ -6,9 +6,15 @@ #else #include #endif -#include +#ifndef DCF77_USE_RTC + #include +#else + #include + #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. @@ -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; @@ -84,9 +92,14 @@ 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); @@ -94,6 +107,7 @@ class DCF77 { static void Stop(void); static void int0handler(); static int getSummerTime(); + static void setCallbackFunctionRTC( time_t (*fptr)() ); }; #endif diff --git a/README.md b/README.md index ee4a8a9..ccbf4ba 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/examples/DCFBinaryStream/DCFBinaryStream.ino b/examples/DCFBinaryStream/DCFBinaryStream.ino index d3494fa..b3f35f6 100644 --- a/examples/DCFBinaryStream/DCFBinaryStream.ino +++ b/examples/DCFBinaryStream/DCFBinaryStream.ino @@ -23,7 +23,10 @@ #include //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); diff --git a/examples/DCFPulseLength/DCFPulseLength.ino b/examples/DCFPulseLength/DCFPulseLength.ino index 9cb4a60..cbbf19d 100644 --- a/examples/DCFPulseLength/DCFPulseLength.ino +++ b/examples/DCFPulseLength/DCFPulseLength.ino @@ -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; diff --git a/examples/DCFSignal/DCFSignal.ino b/examples/DCFSignal/DCFSignal.ino index 29e0597..26951c2 100644 --- a/examples/DCFSignal/DCFSignal.ino +++ b/examples/DCFSignal/DCFSignal.ino @@ -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; diff --git a/examples/InternalClockSync/InternalClockSync.ino b/examples/InternalClockSync/InternalClockSync.ino index c869aab..27925cc 100644 --- a/examples/InternalClockSync/InternalClockSync.ino +++ b/examples/InternalClockSync/InternalClockSync.ino @@ -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); diff --git a/examples/SyncProvider/SyncProvider.ino b/examples/SyncProvider/SyncProvider.ino index dc8f268..787d1b6 100644 --- a/examples/SyncProvider/SyncProvider.ino +++ b/examples/SyncProvider/SyncProvider.ino @@ -20,7 +20,10 @@ #include //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; diff --git a/examples/TimeZones/TimeZones.ino b/examples/TimeZones/TimeZones.ino index 4f221f7..af8126b 100644 --- a/examples/TimeZones/TimeZones.ino +++ b/examples/TimeZones/TimeZones.ino @@ -22,7 +22,10 @@ #include //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) diff --git a/examples/ZeroRTCSync/ZeroRTCSync.ino b/examples/ZeroRTCSync/ZeroRTCSync.ino new file mode 100644 index 0000000..5f9c101 --- /dev/null +++ b/examples/ZeroRTCSync/ZeroRTCSync.ino @@ -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 + +#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(); +} diff --git a/library.properties b/library.properties index bb2426a..3c0ff0f 100644 --- a/library.properties +++ b/library.properties @@ -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. diff --git a/utility/Utils.cpp b/utility/Utils.cpp index 5b32bad..5cde87d 100644 --- a/utility/Utils.cpp +++ b/utility/Utils.cpp @@ -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) diff --git a/utility/Utils.h b/utility/Utils.h index 0b08811..447eb57 100644 --- a/utility/Utils.h +++ b/utility/Utils.h @@ -6,7 +6,9 @@ #else #include #endif -#include +#ifndef DCF77_USE_RTC + #include //http://playground.arduino.cc/code/time +#endif #define intDisable() ({ uint8_t sreg = SREG; cli(); sreg; }) #define intRestore(sreg) SREG = sreg