From 9a5269ad6d331c6228037d689e071fabdf28f376 Mon Sep 17 00:00:00 2001 From: DCEM Date: Mon, 6 Apr 2020 14:23:15 +0200 Subject: [PATCH 1/5] Add EnableInputPullup to DCF77 constructor Optional argument to allow that will turn on the input-pullup. --- DCF77.cpp | 8 +++++--- DCF77.h | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/DCF77.cpp b/DCF77.cpp index ccfb47b..6f7b0f5 100644 --- a/DCF77.cpp +++ b/DCF77.cpp @@ -25,21 +25,22 @@ #include //http://playground.arduino.cc/code/time #include -#define _DCF77_VERSION 1_0_0 // software version of this library +#define _DCF77_VERSION 1_0_1 // 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) { dCF77Pin = DCF77Pin; dCFinterrupt = DCFinterrupt; pulseStart = OnRisingFlank ? HIGH : LOW; + dCF77PinMode = EnableInputPullup ? INPUT_PULLUP : INPUT; if (!initialized) { - pinMode(dCF77Pin, INPUT); + pinMode(dCF77Pin, dCF77PinMode); initialize(); } initialized = true; @@ -341,6 +342,7 @@ int DCF77::getSummerTime(void) int DCF77::dCF77Pin=0; int DCF77::dCFinterrupt=0; byte DCF77::pulseStart=HIGH; +byte DCF77::dCF77PinMode=INPUT; // Parameters shared between interupt loop and main loop diff --git a/DCF77.h b/DCF77.h index bdd0bf1..d6241b0 100644 --- a/DCF77.h +++ b/DCF77.h @@ -24,6 +24,7 @@ class DCF77 { static int dCF77Pin; static int dCFinterrupt; static byte pulseStart; + static byte dCF77PinMode; // DCF77 and internal timestamps static time_t previousUpdatedTime; @@ -86,7 +87,8 @@ class DCF77 { public: // Public Functions - DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true); + + DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true, bool EnableInputPullup=false); static time_t getTime(void); static time_t getUTCTime(void); From 1789318ad5fd312f14c94221827599f12b702e55 Mon Sep 17 00:00:00 2001 From: DCEM Date: Wed, 8 Apr 2020 23:04:48 +0200 Subject: [PATCH 2/5] Change expamles to use board-independet macros. --- examples/DCFBinaryStream/DCFBinaryStream.ino | 5 ++++- examples/DCFPulseLength/DCFPulseLength.ino | 5 ++++- examples/DCFSignal/DCFSignal.ino | 5 ++++- examples/InternalClockSync/InternalClockSync.ino | 5 ++++- examples/SyncProvider/SyncProvider.ino | 5 ++++- examples/TimeZones/TimeZones.ino | 5 ++++- utility/Utils.cpp | 2 +- 7 files changed, 25 insertions(+), 7 deletions(-) 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/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) From 358ca9bfad77b052473713c39e806e310bb4c2e0 Mon Sep 17 00:00:00 2001 From: DCEM Date: Wed, 8 Apr 2020 23:14:32 +0200 Subject: [PATCH 3/5] Allow to use RTC instead of TimeLib TimeLib can be disabled via define, to archive compability with older versions. A callback is used to allow different RTC. The constructor additionally accepts: CompareToUTC --- DCF77.cpp | 52 +++++++++++++++- DCF77.h | 18 +++++- README.md | 18 ++++++ examples/ZeroRTCSync/ZeroRTCSync.ino | 89 ++++++++++++++++++++++++++++ utility/Utils.h | 4 +- 5 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 examples/ZeroRTCSync/ZeroRTCSync.ino diff --git a/DCF77.cpp b/DCF77.cpp index 6f7b0f5..047e185 100644 --- a/DCF77.cpp +++ b/DCF77.cpp @@ -19,25 +19,33 @@ 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_1 // 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, bool EnableInputPullup) +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, dCF77PinMode); @@ -188,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; @@ -270,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; @@ -284,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); @@ -291,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; @@ -336,6 +364,21 @@ 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 */ @@ -343,6 +386,9 @@ 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 d6241b0..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. @@ -25,6 +31,7 @@ class DCF77 { static int dCFinterrupt; static byte pulseStart; static byte dCF77PinMode; + static bool compareToUTC; // DCF77 and internal timestamps static time_t previousUpdatedTime; @@ -85,10 +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, bool EnableInputPullup=false); + DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true, bool EnableInputPullup=false, bool CompareToUTC=false); static time_t getTime(void); static time_t getUTCTime(void); @@ -96,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/ZeroRTCSync/ZeroRTCSync.ino b/examples/ZeroRTCSync/ZeroRTCSync.ino new file mode 100644 index 0000000..08d683d --- /dev/null +++ b/examples/ZeroRTCSync/ZeroRTCSync.ino @@ -0,0 +1,89 @@ +/* + * 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 "TimeLib.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/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 From 187446e19e6fcc40e874768c7b897271062f7851 Mon Sep 17 00:00:00 2001 From: DCEM Date: Wed, 8 Apr 2020 23:24:40 +0200 Subject: [PATCH 4/5] Update library.properties --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 097741145a3ea8238f53755b7a3d596299d8266d Mon Sep 17 00:00:00 2001 From: DCEM Date: Wed, 15 Apr 2020 14:18:34 +0200 Subject: [PATCH 5/5] Remove - #include "TimeLib.h" from ZeroRTCSync example --- examples/ZeroRTCSync/ZeroRTCSync.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/ZeroRTCSync/ZeroRTCSync.ino b/examples/ZeroRTCSync/ZeroRTCSync.ino index 08d683d..5f9c101 100644 --- a/examples/ZeroRTCSync/ZeroRTCSync.ino +++ b/examples/ZeroRTCSync/ZeroRTCSync.ino @@ -19,7 +19,6 @@ #define DCF77_USE_RTC // define before #include "DCF77.h"; // it "enables" RTC and "disables" TimeLib #include "DCF77.h" -#include "TimeLib.h" #include #define DCF_PIN 12 // Connection pin to DCF 77 device