I am building a DCF77 Master Bracket Clock as a backup to my main master & slave clock system.
I have used a DCF77 receiver module to get the time and display it on a 4x20 LCD display and a old quartz skeleton clock. The pulse outputs to drive my various slaves are displayed by LEDs.
I ran the project on breadboard and all seemed fine. Now I have put the clock together and started driving the quartz clock motor with pulses I seem to be missing a few seconds a day.
The code loop below relies on the change of display each second to generate my Quartz drive pulse.
99.9% of the time it is fine but when I leave the clock running overnight I nearly always find the seconds on the quartz clock are a few seconds out. I have never been watching when the clock misses a second so I am not sure when it fails.
The Time and Timezone libraries are used.
I am not quite sure how the Time library corrects/decodes the DCF77 signal but I think it must jump the odd second every now and then causing the program to miss a loop.
Is there a way to force the loop every second even if the display misses a second while keeping in sync with the DCF77?
EG if the display does not change for a second then start the loop and check again the next second.
void loop()
{
if( now() != prevDisplay) //update the display only if the time has changed
{
prevDisplay = now();
//lcd.clear(); //clear LCD screen
digitalClockDisplay();
}
}
void digitalClockDisplay(){
digitalWrite(led01, HIGH); // turn the LED on (HIGH is the voltage level)
delay(25);
digitalWrite(led01, LOW); // turn the LED off (LOW is the voltage level)
// Quartz clock driver
// toggle Quartz drive A2 & A3 evey second
if (quartzmotor1 == LOW)
quartzmotor1 = HIGH;
else
quartzmotor1 = LOW;
digitalWrite(quartz01, quartzmotor1); // set the quartz motor drive A2 pin
if (quartzmotor2 == HIGH)
quartzmotor2 = LOW;
else
quartzmotor2 = HIGH;
digitalWrite(quartz02, quartzmotor2); // set the quartz motor drive A3 pin
// digital clock display of the time
Serial.println("");
//Serial.print(hour()); add leading 0 on hour and prob :
lcd.setCursor(0,0); // set LCD to row 1 pos 1
//************
printDigitsH(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.print(" "); // adds space before following
//~~~~~~~~~~~~~~~~~~
// printP01(second()); // prints every second
printPTen(second()); // prints secs ie 0 every 60 secs
printP30(second()); // prints 0 or 30 on 0 or 30 secs
printP05(second()); // prints every 5 secs
printP10(second()); // prints every 10 secs
printP15(second()); // prints every 15 secs
printP20(second()); // prints every 20 secs
printPhour(minute()); // print every hour eg when ever mins at 00
printPday(hour()); // print when hour is 0 eg every 24 hour
Serial.println();
printLCDH(hour()); //adds leadng zero if hour is less than 10
printLCD(minute()); //adds leadng zero and colon if minute is less than 10
printLCD(second()); //adds leadng zero and colon if seond is less than 10
lcd.print(" ");
printLCDH(day()); // adds leadng zero if day is less than 10
lcd.print("/");
printLCDH(month()); // adds leadng zero if month is less than 10
lcd.print("/");
lcd.print(year());
// display last sync time
lcd.setCursor(0,1);
lcd.print("Last Sync ");
// show last sync time on LCD
printLCDH(hoursync);
lcd.print(":");
printLCDH(minutesync);
lcd.print(":");
printLCDH(secondsync);
lcd.setCursor(0,2);
lcd.print("Sync Status 0");
lcd.print(timeStatus());
lcd.print(" GMT");
lcd.setCursor(0,3);
lcd.print(" DCF77 Master Clock");
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0 on mins and secs
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void printLCD(int LCDdigits){
// utility function for digital clock display: prints preceding colon and leading 0 on mins and secs
lcd.print(":");
if(LCDdigits < 10)
lcd.print('0');
lcd.print(LCDdigits);
}
void printLCDH(int LCDdigitH){
// utility function for digital clock display: prints leading 0 on hours
//Serial.print(":"); colon not needed for hours
if(LCDdigitH < 10)
lcd.print("0"); // Print hour on first line
lcd.print(LCDdigitH);
}
void printDigitsH(int digitH){
// utility function for digital clock display: prints leading 0 on hours
if(digitH < 10)
Serial.print('0');
Serial.print(digitH);
}
void printPTen(int PTen){ // light LED every min on 00
if(PTen == 00)
{
Serial.print(PTen);
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(PTen != 00)
digitalWrite(led, LOW); // turn the LED off (LOW is the voltage level)
}
void printP30(int P30){ // light LED every 30 seconds
if(P30 == 00 || P30 == 30)
{
Serial.print(P30);
digitalWrite(led30, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(P30 != 00 || P30 !=30)
digitalWrite(led30, LOW); // turn the LED off (LOW is the voltage level)
}
void printP05(int P05){ // light LED 10 every 5 seconds
if(P05 == 00 || P05 == 05 || P05 == 10 || P05 == 15 || P05 == 20 || P05 == 25 || P05 == 30 || P05 == 35 || P05 == 40 || P05 == 45 || P05 == 50 || P05 == 55)
{
Serial.print(P05);
digitalWrite(led05, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(P05 != 00 || P05 !=05 || P05 !=10 || P05 !=15 || P05 !=20 || P05 !=25 || P05 !=30 || P05 !=35 || P05 !=40 || P05 !=45 || P05 !=50 || P05 !=55)
digitalWrite(led05, LOW); // turn the LED off (LOW is the voltage level)
}
void printP10(int P10){ // light LED 09 every 10 seconds
if(P10 == 00 || P10 == 10 || P10 == 20 || P10 == 30 || P10 == 40 || P10 == 50)
{
Serial.print(P10);
digitalWrite(led10, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(P10 != 00 || P10 !=10 || P10 !=20 || P10 !=30 || P10 !=40 || P10 !=50)
digitalWrite(led10, LOW); // turn the LED off (LOW is the voltage level)
}
void printP15(int P15){ // light LED 03 every 15 seconds
if(P15 == 00 || P15 == 15 || P15 == 30 || P15 == 45)
{
Serial.print(P15);
digitalWrite(led15, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(P15 != 00 || P15 !=15 || P15 !=30 || P15 !=45)
digitalWrite(led15, LOW); // turn the LED off (LOW is the voltage level)
}
void printP20(int P20){ // light LED 08 every 20 seconds
if(P20 == 00 || P20 == 20 || P20 == 40)
{
Serial.print(P20);
digitalWrite(led20, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(P20 != 00 || P20 !=20 || P20 !=40)
digitalWrite(led20, LOW); // turn the LED off (LOW is the voltage level)
}
void printPhour(int Phour){ // light LED every hour on 00
if(Phour == 00 && second() == 00)
{
Serial.print(Phour);
digitalWrite(ledh, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(second() != 00) // turn off hour pulse when secs are not 00
digitalWrite(ledh, LOW); // turn the LED off (LOW is the voltage level)
}
void printPday(int Pday){ // light LED every day on 00
if(Pday == 00 && second() == 00)
{
Serial.print(Pday);
digitalWrite(ledd, HIGH); // turn the LED on (HIGH is the voltage level)
}
else if(second() != 00) //turn off day pulse when secs are not 00
digitalWrite(ledd, LOW); // turn the LED off (LOW is the voltage level)
}
unsigned long getDCFTime()
{
time_t DCFtime = DCF.getUTCTime(); // Get UTC time
if (DCFtime!=0) {
time_t LocalTime = UK.toLocal(DCFtime); // Convert to UK time
Serial.print("Syncronized ");
// when sycn'd show this time as time synch'd
hoursync = hour();
minutesync = minute();
secondsync = second();
return LocalTime;
}
return 0;
}