brettoliver
Published © CC BY-NC-SA

Arduino "Atomic" Grandfather Clock

I wanted an electro-mechanical Grandfather clock that did not require winding and correcting every week but maintained its antiquity.

AdvancedFull instructions provided11,342
Arduino "Atomic" Grandfather Clock

Things used in this project

Story

Read more

Custom parts and enclosures

"Atomic" Longcase Clock Schematic

Schematics

Schematic

Vero 01

Vero01 back

Code

"Atomic" Longcase Clock Arduino Code v16

Arduino
Arduino Code v16
Requires the following libraries


dcf77.h Note this clock uses Udo Kleins Release 3 library download here DCF77 Release 3
LiquidCrystal_I2C.h
Wire.h
[code]
/*
v16 coded to use Udo Klein's v3 library https://github.com/udoklein/dcf77/releases/tag/v3.0.0
v15 remove moonphase advance fast add mooncountSec advance by 1465 (1/60th phase)

  Longcase Clock
  http://www.brettoliver.org.uk

  Copyright 2014 Brett Oliver

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program. If not, see http://www.gnu.org/licenses/

 
 Based on the DCF77 library by Udo Klein
 http://blog.blinkenlight.net/experiments/dcf77/dcf77-library/
 http://blog.blinkenlight.net/experiments/dcf77/simple-clock/

*/


#include <dcf77.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
using namespace Internal; //v3


/* we always wait a bit between updates of the display */
unsigned long delaytime=250;
//**********************
// set the LCD address to 0x27 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


//**********************

const uint8_t dcf77_analog_sample_pin = 5;
const uint8_t dcf77_sample_pin = A1;  // A5 == d19 (DFC77 signal)changed from A5
const uint8_t dcf77_inverted_samples = 0;
const uint8_t dcf77_analog_samples = 0;
const uint8_t dcf77_monitor_led       = A0; // v3
//const uint8_t dcf77_monitor_pin = A0;  // A4 == d18 changed from A4 removed v3
uint8_t ledpin(const uint8_t led){ //v3
  return led; //v3
} //v3

const int8_t timezone_offset = -1;  // GB is one hour behind CET/CEST

//*********************


int retardOn = 0;

//int infraredSwval = 0; // infrared value
//int infraredSw = A3; // set A3 to input ( pin 13)
int retardcount = 0;
int pulsecount = 0; // pulse counts upto required number to step forward 1 hour
int retardSw = 13; // winter retard switch pin 9
int retardSwval = 0; // value of retardSw
int advanceSw = 9; // summer advance switch pin 13
int advanceSwval = 0; // value of advanceSw
int pulseOn = 0; // 0 pulse off 1 pulse on (summer winter pulsing
int summertest = 0; // equals 1 for summertime and 0 for wintertime
int summerwinter = 0; // summer winter toggle
int extracount = 0; // where quartz seconds needs to miss a pulse
int hourextra = 00; // hour last miss pulse variable
int dayextra = 00; // day last miss pulse variable
int monthextra = 00; // month last miss pulse variable
int minuteextra = 00; // minute last miss pulse variable
int secondextra = 00; // second last miss pulse variable
int yearextra = 00;



int secondsnow = 0; // previous second
int yearmiss = 00;
int daymiss = 00; // day last extra pulse variable
int monthmiss = 00; // month last extra pulse variable
int secsmiss = 0; // works out is seconds need to an extra pulse or miss a pulse
int misscount = 0; // 1 ok 0 needs to miss a pulse 1 needs an extra pulse
int hourmiss = 00; // hour last extra pulse variable
int minutemiss = 00; // minute last extra pulse variable
int secondmiss = 00; // second last extra pulse variable
int signalQual = 0; // computed once per minute and indicates how well 
// the received signal matches the locally synthesized reference signal max 50
int monthval = 0;
int dayval = 0;
//int zero = 0;
int years = 0;
int months = 0;
int days = 0;

int hours = 0;

int minutes = 0;

int seconds = 0;
int secsval = 0;
int minsval = 0;
int hourval = 0;
int led15 = 2; //15 second pulse

int quartzmotor1 = HIGH;  // ledState used to set the quartz motor pin 7 initial state
int quartzmotor2 = LOW;   //  ledState used to set the quartz motor pin 8 initial state
int quartz01 =7;  //  Quartz clock motor pulse 01
int quartz02 =8;  //  Quartz clock motor pulse 02
int stepSecs =11; // when high seconds are advanced

int hrminmotor1 = HIGH;              // ledState used to set the quartz motor pin 1 initial state
int hrminmotor2 = LOW;              //  ledState used to set the quartz motor pin 2 initial state
int hrmin01 =12;  //  Quartz clock motor pulse 01
int hrmin02 =2;  //  Quartz clock motor pulse 02


//Moon Display
unsigned long mooncountSec = 1; // counts every sec until 43245 then moonphase is advanced by 1
unsigned long moontime = 1; 
int moonphase = 0; // advances 1 every 43245 secs and 86490 secs until 60 when it is reset to 2 (moon dial advanced to 1)
int moonphasedisp = 1; // advances 1 every 86490 secs until moonphase 60 when it is reset to 1 (moon dial advanced to 1)
int moondisAdv = 3; // advances moon phase display once per second
int moonphaseAdv = 4; //advances moon phase count once per second
//int moonphaseAdvfast = 11; //advances moon phase count 5 once per second
int mooncountSecAdv = 11; //advances mooncountSec  1465 once per second
int moonReset = A3; // resets moon phase and count to 1 new moon
int moonmotor1 = HIGH;              // ledState used to set the quartz motor pin 5 initial state
int moonmotor2 = LOW;              //  ledState used to set the quartz motor pin 6 initial state
int moon01 =5;  //  Moon clock motor pulse 01
int moon02 =6;  //  Moon clock motor pulse 02

float h, m;
int s = 0;
unsigned long over = 0;

// End Moon Display
int  LCDdispCtrl = A2;
int step15 = 10; //step hour mins forward by 15 seconds

//********************

namespace Timezone {
  uint8_t days_per_month(const Clock::time_t &now) { //v3 mod
    switch (now.month.val) {
    case 0x02:
      // valid till 31.12.2399
      // notice year mod 4 == year & 0x03
       return 28 + ((now.year.val != 0) && ((bcd_to_int(now.year) & 0x03) == 0)? 1: 0);
            case 0x01: case 0x03: case 0x05: case 0x07: case 0x08: case 0x10: case 0x12: return 31;
            case 0x04: case 0x06: case 0x09: case 0x11:                                  return 30;
            default: return 0;
     
    }
  }   

  void adjust(Clock::time_t &time, const int8_t offset) { //v3 mod
    // attention: maximum supported offset is +/- 23h

    int8_t hour = BCD::bcd_to_int(time.hour) + offset;

    if (hour > 23) {
      hour -= 24;
      uint8_t day = BCD::bcd_to_int(time.day) + 1;
      uint8_t weekday = BCD::bcd_to_int(time.weekday) + 1; //v3
      if (day > days_per_month(time)) {
        day = 1;
        uint8_t month = BCD::bcd_to_int(time.month);
        ++month;
        if (month > 12) {
          month = 1;
          uint8_t year = BCD::bcd_to_int(time.year);                  
          ++year;
          if (year > 99) {
            year = 0;
          }
          time.year = BCD::int_to_bcd(year);
        }                
        time.month = BCD::int_to_bcd(month);
      }
      time.day = BCD::int_to_bcd(day);
      time.weekday = BCD::int_to_bcd(weekday); //v3
    }

    if (hour < 0) {
      hour += 24;
      uint8_t day = BCD::bcd_to_int(time.day) - 1;
      uint8_t weekday = BCD::bcd_to_int(time.weekday) - 1; //v3
      if (day < 1) {
        uint8_t month = BCD::bcd_to_int(time.month);
        --month;
        if (month < 1) {
          month = 12;
          int8_t year = BCD::bcd_to_int(time.year);                  
          --year;
          if (year < 0) {
            year = 99;
          }
          time.year = BCD::int_to_bcd(year);
        }                
        time.month = BCD::int_to_bcd(month);
        day = days_per_month(time);
      }
      time.day = BCD::int_to_bcd(day);
       time.weekday = BCD::int_to_bcd(weekday); //v3
    }

    time.hour = BCD::int_to_bcd(hour);
  }
}

uint8_t sample_input_pin() {
  const uint8_t sampled_data =
    dcf77_inverted_samples ^ (dcf77_analog_samples? (analogRead(dcf77_analog_sample_pin) > 200)
    : digitalRead(dcf77_sample_pin));

  //digitalWrite(dcf77_monitor_pin, sampled_data); // removed v3
  digitalWrite(ledpin(dcf77_monitor_led), sampled_data); // v3
  return sampled_data;
}

void setup() {
  digitalWrite(led15, HIGH); // turn 15 sec clocks off at start
 

  lcd.begin(20,4);   // initialize the lcd for 20 chars 4 lines, turn on backlight 
 // using namespace Internal; // v3 Removed
  //*************
 // lcd.backlight(); // backlight on not needed as controlled by 7 MAX2719
  lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print("DCF77 Longcase Clock");  





  //***************
  Serial.begin(9600);
  /*  Serial.println();
   Serial.println(F(" DCF77  Longcase  Clock "));
   Serial.println(F("(c) Brett Oliver 2014"));
   Serial.println(F("http://www.brettoliver.org.uk"));
   Serial.println(F("Based on the DCF77 library by Udo Klein"));
   Serial.println(F("www.blinkenlight.net"));
   Serial.println();
   Serial.print(F("Sample Pin:     ")); 
   Serial.println(dcf77_sample_pin);
   Serial.print(F("Inverted Mode:  ")); 
   Serial.println(dcf77_inverted_samples);
   Serial.print(F("Analog Mode:    ")); 
   Serial.println(dcf77_analog_samples);
   Serial.print(F("Monitor Pin:    ")); 
   Serial.println(dcf77_monitor_pin);
   Serial.print(F("Timezone Offset:")); 
   Serial.println(timezone_offset);
   Serial.println();
   Serial.println();
   Serial.println(F("Initializing..."));
   */
 // pinMode(dcf77_monitor_pin, OUTPUT); // removed v3

  pinMode(dcf77_sample_pin, INPUT);
  digitalWrite(dcf77_sample_pin, HIGH);


  //*******************

  //pinMode(led15, OUTPUT);
  pinMode(quartz01, OUTPUT);
  pinMode(quartz02, OUTPUT);
  pinMode(moon01, OUTPUT);
  pinMode(moon02, OUTPUT);
  pinMode(hrmin01, OUTPUT);
  pinMode(hrmin02, OUTPUT);
  pinMode(ledpin(dcf77_monitor_led), OUTPUT); // v3
  
 
  //pinMode(17, INPUT); // infrared switch
  pinMode(advanceSw,INPUT);
  pinMode(retardSw,INPUT);
  pinMode(moonphaseAdv,INPUT);
  //pinMode(moonphaseAdvfast,INPUT);
  pinMode(mooncountSecAdv,INPUT);
  pinMode(moondisAdv,INPUT);
  pinMode(moonReset,INPUT);
  pinMode(LCDdispCtrl,INPUT);
  pinMode(step15,INPUT); // 15 second (hour min) man advance
 // pinMode(stepSecs,INPUT); // secs man advance
  

  //*******************

  DCF77_Clock::setup();
  DCF77_Clock::set_input_provider(sample_input_pin);


  // Wait till clock is synced, depending on the signal quality this may take
  // rather long. About 5 minutes with a good signal, 30 minutes or longer
  // with a bad signal
  
  
  
  
  for (uint8_t state = Clock::useless; //v3 Mod
         state == Clock::useless || state == Clock::dirty; //v3 Mod
         state = DCF77_Clock::get_clock_state()) {

    // wait for next sec
    Clock::time_t now; //v3 mod
    DCF77_Clock::get_current_time(now);

    // render one dot per second while initializing
    static uint8_t count = 0;
    Serial.print('.');
    ++count;
    if (count == 60) {
      count = 0;
      Serial.println();
    }
  }
}

void paddedPrint(BCD::bcd_t n) {
  Serial.print(n.digit.hi);
  Serial.print(n.digit.lo);
}
void LCDpaddedPrint(BCD::bcd_t n) { 
  lcd.print(n.digit.hi); 
  lcd.print(n.digit.lo); 
}

void loop() {

  Clock::time_t now; //v3 mod

  DCF77_Clock::get_current_time(now);
  Timezone::adjust(now, timezone_offset);
  
 
  if (now.month.val > 0) {


    //***********
    // get month & day values
    dayval = now.day.val, DEC;
    monthval = now.month.val, DEC;
    // Serial.print(" day ");
    // Serial.print(now.day.val, DEC);
    //  Serial.print(" month ");
    //  Serial.print(now.month.val, DEC);
    //   Serial.print(' ');
    // get month & day values
    // Quartz clock driver
    // toggle Quartz drive 7 & 8 evey second
    secsmiss = seconds - secondsnow;

    if (secsmiss ==-59 || secsmiss ==-60 && seconds ==0) // takes account of seconds rollover -59 or leap second -60
    {
      secsmiss = 1;
    } 





 // If not andvancing seconds then use this (normal)
   if (secsmiss >=1 && seconds !=60) // if zero or less seconds pulse need to be missed. Leap second missed if seconds = 60
    {
      secondsmotor (); // function steps quartz motor
    }




    if (secsmiss < 1 || seconds == 60) //records time of extra sec second (quart motor needs to loose a second)

    {
      extracount = extracount + 1; //increment extra count total (1sec needs to miss pulse)
      hourextra = hours;
      minuteextra = minutes;
      secondextra = seconds;
      yearextra = years;
      monthextra = months;
      dayextra = days;

    }


    if (secsmiss > 1) //records time of miss second (quart motor needs to add a second)
    {
      misscount = misscount + 1; //increment Miss count total (1sec has missed extra pulse)
      hourmiss = hours;
      minutemiss = minutes;
      secondmiss = seconds;
      yearmiss = years;
      monthmiss = months;
      daymiss = days;

    } 



    secondsnow = seconds; 



    if (hours== 6 && minutes == 10 && seconds == 01) // resets miss second counter to 0 at 6:10:01
    {
      misscount = 0;
      extracount = 0;
    }


    // }
    // Enable below to analize missed pulses on serial monitor
    //Serial.print(" ");
    // Serial.print("secsmiss ");
    //  Serial.println(secsmiss);
/*

    Serial.print("Slow Seconds ");
    Serial.print(misscount);
    Serial.print(" ");
    Serial.print(hourmiss);
    Serial.print(":");
    Serial.print(minutemiss);
    Serial.print(":");
    Serial.print(secondmiss);
    Serial.print(" ");
    Serial.print(daymiss);
    Serial.print("/");
    Serial.print(monthmiss);
    Serial.print("/");
    Serial.println(yearmiss);


    Serial.print("Fast Seconds ");
    Serial.print(extracount);
    Serial.print(" ");
    Serial.print(hourextra);
    Serial.print(":");
    Serial.print(minuteextra);
    Serial.print(":");
    Serial.print(secondextra);
    Serial.print(" ");
    Serial.print(dayextra);
    Serial.print("/");
    Serial.print(monthextra);
    Serial.print("/");
    Serial.println(yearextra);


*/




    // end missing second pulse

    // ################################################################################ 
    
    
  

    /*
 Serial.println(F("confirmed_precision [Hz], target_precision v,total_adjust [Hz], frequency [Hz]"));
     Serial.print(DCF77_Frequency_Control::get_confirmed_precision());
     Serial.print(F(", "));
     Serial.print(DCF77_Frequency_Control::get_target_precision());
     Serial.print(F(", "));
     Serial.print(DCF77_1_Khz_Generator::read_adjustment());
     Serial.print(F(", "));
     Serial.print(16000000L - DCF77_1_Khz_Generator::read_adjustment());
     Serial.print(F(" Hz, "));
     
     */

    //***************
    // signal quality

    //  signalQual = DCF77_Clock::get_prediction_match();
    //  if(signalQual == 255 || signalQual == 0 )
    //  {
    // signalQual = 00;
    //  }
    // else
    //{
    //  signalQual = (signalQual * 2) -1;
    //}
    // Serial.print (" Signal Match ");
    // Serial.print (signalQual);
    // Serial.print ("% ");

    // display 7 segment intensity value on LCD
   // lcd.setCursor(0,2);
    //lcd.print("7 Seg Int ");
   // lcd.print("Brightness ");
  //  segIntensity(intensity); // adds leading zero to 7 segment intensity
    

      // end display 7 segment intensity value on LCD   


    // #################################
    //LDR start

  //  ldrValue = analogRead(ldr);
    
   //  Serial.print (" LDR Value ");
   //  Serial.print (ldrValue, DEC);
   //  Serial.print (" ");
  //  intensityValue();
    // Serial.print ("Intensity ");
  //   Serial.print (intensity);
  //   Serial.print (" ");
     
    //LDR finish
    //#################################
    //Serial.print (now.second.val);
    // Serial.print (" ");
    lcd.setCursor(17,2);
    //lcd.print(" Wait  ");
    switch (DCF77_Clock::get_clock_state()) {
      // case DCF77::useless: Serial.print(F("useless ")); break;
      case Clock::useless: //v3 mod
      lcd.print(F(" Fail  ")); 
      break;
      // case DCF77::dirty:   Serial.print(F("dirty: ")); break;
      //  case DCF77::synced:  Serial.print(F("synced: ")); break;
      // case DCF77::locked:  Serial.print(F("locked: ")); break;
      case Clock::dirty: //v3 mod  
      lcd.print(F("Dty")); 
      break;
      case Clock::synced:  //v3 Mod
      lcd.print(F("Syn")); 
      break;
      case Clock::locked: //v3 mod 
      lcd.print(F("Lck")); 
      break;
    }

    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    // Get hours minutes and seconds variables
    hours = BCD::bcd_to_int(now.hour);


    minutes = BCD::bcd_to_int(now.minute);


    seconds = BCD::bcd_to_int(now.second);

    years = BCD::bcd_to_int(now.year);

    months = BCD::bcd_to_int(now.month);

    days = BCD::bcd_to_int(now.day);


 

    /*  Serial.print (" H,M,S ");
     Serial.print (hours2);
     
     Serial.print (hours1);
     Serial.print (":");
     
     
     Serial.print (minutes2);
     
     Serial.print (minutes1);
     Serial.print (":");
     
     
     Serial.print (seconds2);
     
     Serial.print (seconds1);
     Serial.print (":");
     
     */
    lcd.setCursor(6,3);



    // 7 segment


    //****************

    lcd.setCursor(0,0);

    LCDpaddedPrint(now.hour);
    lcd.print(":");
    LCDpaddedPrint(now.minute);
    lcd.print(":");
    LCDpaddedPrint(now.second);
    lcd.print("  ");

    LCDpaddedPrint(now.day);
    lcd.print("/");
    LCDpaddedPrint(now.month);
    lcd.print("/");
    lcd.print("20");
    LCDpaddedPrint(now.year);





    //****************
    /*
    
     paddedPrint(now.hour);
     Serial.print(':');
     paddedPrint(now.minute);
     Serial.print(':');
     paddedPrint(now.second);
     Serial.print(' ');
     
     paddedPrint(now.day);
     Serial.print('/');
     paddedPrint(now.month);
     Serial.print('/');
     Serial.print(F("20"));
     paddedPrint(now.year);
     
     
     */



    // const int8_t offset_to_utc = timezone_offset + now.uses_summertime? 2: 1;
    const int8_t offset_to_utc = timezone_offset + (now.uses_summertime? 2: 1);

    // Serial.print(F(" GMT"));

    summertest = (abs(offset_to_utc)); // equals 1 if summertime and 2 if wintertime 

    if (summertest ==2) // if wintertime make summertest =0
    {
      summertest = 0;
    }

    //**************
    lcd.setCursor(15,3);
    lcd.print("GMT+");
    // UTCcheck= offset_to_utc;
    // lcd.print(UTCcheck);
    lcd.print(summertest);
   
  }

 
  // Quality display on LCD
  if (seconds >= 0 && seconds <= 10)
  { 
    signalmatch(); // Quality factor
  }

  else if (seconds == 11)
  {
    blankrow3(); //Blanks row 3
  }

else if (seconds == 12)
  {
    lcd.setCursor(0,3);
  lcd.print("Quartz         ");
  }
  else if (seconds >= 13 && seconds <= 23)
  {
    precision(); //quartz confirmed and target precision
  }

  else if (seconds == 24)
  {
    blankrow3(); //Blanks row 3
  }

 else if (seconds >=25 && seconds <= 35 )
  {
      lcd.setCursor(0,3);
      
  signalmatch(); // Quality factor
  }

  else if (seconds == 36)
  {
    blankrow3(); //Blanks row 3
  }
 
  else if (seconds == 37)
  {
    lcd.setCursor(0,3);
  lcd.print("Quartz         ");
  }
  else if (seconds >= 38 && seconds <= 48)
  {
    precision(); //quartz confirmed and target precision
  }

  else if (seconds == 49)
  {
    blankrow3(); //Blanks row 3
  }

 else if (seconds >=50 && seconds <= 59 )
  {
      lcd.setCursor(0,3);
      
  signalmatch(); // Quality factor
  }

 
  // End of Quality display on LCD
  //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$



  // winter to summer change // clocks go forward#################################
  advanceSwval = digitalRead(advanceSw);   // read advanceSw switch
  // 240 x 15 sec pulses need to be added to normal 15 second pulses to advance by 1 hour
  if (pulsecount < 240 && (seconds == 0 || seconds == 15 || seconds == 30 || seconds == 45) && (advanceSwval == 1 || pulseOn == 1))
    // summertest is 1 in summertime and  0 in wintertime  advance on 00 ,15,30 &45 secs does not advance pulse count

  {
    // sumwinSwval = 1;
    pulseOn = 1;
    //Serial.println(" 15 second test ");

     hrminmotor(); // function steps hr min motor

  }

  else if (pulsecount < 240 && (advanceSwval == 1 || pulseOn == 1)) // summertest is 1 in summertime and  0 in wintertime 

  {
    // sumwinSwval = 1;
    pulseOn = 1;
    pulsecount = pulsecount + 1;

     hrminmotor(); // function steps hr min motor
  }

  else  
  {
    digitalWrite(hrmin01, LOW); // set the hr min motor drive 1 pin LOW
  digitalWrite(hrmin02, LOW); // set the hr min motor drive 2 pin LOW
    pulseOn = 0; // 
    // sumwinSwval = 0;
    pulsecount = 0;
  } 

  // end winter to summer chaange advance ##############################



  //  summer to winter change clocks go back#################################
  retardSwval = digitalRead(retardSw);   // read retardSw switch

  if (retardcount < 240 && retardSwval == 1) // 240 x 15 sec pulses need to be ignored to retard by 1 hour
  {
    retardOn = 1;
  }

  else if (retardcount < 240 && (seconds == 0 || seconds == 15 || seconds == 30 || seconds == 45) && (retardSwval == 1 || retardOn == 1))
  {
    retardOn = 1;
    retardcount = retardcount + 1;
  }

  else if (retardcount < 240 && (retardSwval == 1 || retardOn == 1))
  {
    retardOn = 1;

  }

  else
  {
    retardOn = 0; 
    // sumwinSwval = 0;
    retardcount = 0;
  }  



  // end summer to winter change clocks go back#################################  





  // Display of Title and 30 second pulse correction on row 01 ##############################

  if (retardcount > 0 || retardcount == 119 ) //Prints correction pulse number
  {
    lcd.setCursor(0,1); 
    lcd.print("Winter Retard  ");
    lcd.setCursor(15,1);



    retard(retardcount); // add leading 0 <99
    retardtens(retardcount); // add another leading 0 less than 10
    lcd.print(retardcount);
  }
  else if (retardcount == 240 )  //Prints blank when correction pulse is on last number
  {
    lcd.setCursor(0,1); 
    lcd.print("                    ");
    // lcd.print(retardcount);
  } 


  else if (seconds >= 0 && seconds <= 5 && pulsecount == 0) // Ignored while clock is correcting forward or retarding
  {

    lcd.setCursor(0,1); //Start at character 0 on line 0
    lcd.print("DCF77 Longcase Clock");      

  }
  else if(seconds > 05 && seconds <= 10 && pulsecount == 0) // Ignored while clock is correcting forward or retarding
  {
    lcd.setCursor(0,1); //Start at character 0 on line 0
    //lcd.print(" DCF77 Master Clock ");  
    lcd.print(" Brett Oliver v16.0 ");
  }

  else if(seconds == 11 && pulsecount == 0) // Ignored while clock is correcting forward or retarding
  {
    lcd.setCursor(0,1); //Start at character 0 on line 0

    lcd.print("                    ");
  }

  else if(seconds > 11 && seconds <= 13 && pulsecount == 0) // Ignored while clock is correcting forward or retarding
  {
    lcd.setCursor(0,1); //Start at character 0 on line 0

    // lcd.print("       Pulses       ");
    lcd.print("   1 Second Clocks  ");

  }



  else if(seconds > 13 && seconds <=59 && pulsecount == 0) // Ignored while clock is correcting forward or retarding
  {
    lcd.setCursor(0,1); //Start at character 0 on line 0
    lcd.print("  Slow "); // miss pulse detected so extra 1 second motor pulse added
    lcd.print(misscount);

    lcd.print(" ");
    lcd.print("   Fast ");        
    lcd.print(extracount);
  }

  else if (pulsecount > 0 || pulsecount == 239 ) //Prints correction pulse number
  {
    lcd.setCursor(0,1); 
    lcd.print("Summer Advance ");
    lcd.setCursor(15,1);
    //lcd.print(pulsecount);

    advance(pulsecount); // add leading 0 <99
    advancetens(pulsecount); // add another leading 0 less than 10
    lcd.print(pulsecount);
  }
  else if (pulsecount == 240 )  //Prints blank when correction pulse is on last number
  {
    lcd.setCursor(0,1); 
    lcd.print("                    ");
    //lcd.print(pulsecount);
  } 


  // sum win test print
  //sumwinSwval = digitalRead(sumwinSw);   // read sumwinSw switch
  /* Serial.print(" Sum Win Pulse No ");
   Serial.print(pulsecount);
   Serial.print(" ");
   
   Serial.print("Sum Win SW ");
   Serial.print(sumwinSwval);
   Serial.print(" ");
   Serial.print("Pulse On ");
   Serial.print(pulseOn);
   Serial.print(" ");
   Serial.print("Retard On ");
   Serial.print(retardOn);
   Serial.print(" ");
   Serial.print("Retard Count ");
   Serial.print(retardcount);
   Serial.print(" ");
   Serial.print("Summer Test ");
   Serial.print(summertest);
   Serial.print(" ");
   */

  // end sum win test print 
  //  

  // winter to summer change // clocks go forward#################################

  // End Display of Title and 30 second pulse correction on row 01 ##############################
  //-----------------------------------------------------------------------
  // Moon Phase Dial Display
  mooncountSec = mooncountSec + 1;
 // moontime = 86490 - mooncountSec; //counts down to next phase change
  moontime = mooncountSec; // counts up to next phase change
  // calc/display hour min sec to next moon phase 
  h = int (moontime/3600);
  over = moontime % 3600;
  m = int (over/60);
  over = over % 60;
  s = int (over);
  /*
  Serial.print ("Sec Pulses: ");
  Serial.println (mooncountSec);
  Serial.print ("Sec Pulses: ");
  Serial.println (moontime);
  
  Serial.print ("Next Phase: ");
  Serial.print (h, 0);
  Serial.print ("h ");
  Serial.print (m, 0);
  Serial.print ("m ");
  Serial.print (s, 0);
  Serial.print ("s ");
  
  Serial.println ();
*/
  
  
  //
  
  
  
   // set in this order so Moon motor steps each second until 60 (0)
 /*
   if ( moonphase == 60 ) // was 61
  {
  // delay(100); // add delay so seconds mtor can operate again in the same second
    moonmotor (); // function steps moon motor
  // moonphase = moonphase + 1;
   lcd.setCursor(5,2); //Start at character  on line 2
    lcd.print("  "); // Blank old moon phase  
  moonphase = 0; //resets moonphase count so it displays day 1 (2/60th)on the dial
  moonphasedisp = 0; //resets moonphase LCD count so it displays day 1 (2/60th)on the dial
 // mooncountSec = 1;
  
  }
  */
  /*
  if ( moonphase == 60 )
  {
  // delay(100); // add delay so seconds mtor can operate again in the same second
    moonmotor (); // function steps moon motor
   moonphase = moonphase + 1; 
  }
  
  */
  
  
  // steps moon phase display to 0 and resets mooncountSec when moonphase is 59 and a half
  
  
   // if ( mooncountSec == 43245 && moonphase == 59 )
  if ( moonphase == 59 )
  {
  moonmotor (); // function steps moon motor
  lcd.setCursor(5,2); //Start at character  on line 2
    lcd.print("  "); // Blank old moon phase  
    
  //  moonphase = moonphase + 1;
  //  moonphasedisp = moonphasedisp + 1;
    
   moonphase = 0; //resets moonphase count so it displays day 1 (2/60th)on the dial
  moonphasedisp = 0; //resets moonphase LCD count so it displays day 1 (2/60th)on the dial 
 mooncountSec = 1;
  }
 
  
   if ( mooncountSec == 43245 )
 
  {
  moonmotor (); // function steps moon motor
    moonphase = moonphase + 1;
  }
  
  
  // steps moon phase display and resets mooncountSec after 86490 1 sec pulses (1 day 1min 25sec)
...

This file has been truncated, please download it to see its full contents.

Credits

brettoliver

brettoliver

2 projects • 21 followers
Thanks to Udo Klein.

Comments