Section   Top   Features   Ultra HD Video  Design  Time Keeping  Uno Mod  Construction  7 Seg Disp PCB  Summertime Video  Wintertime Video  Autotune Video  LCD Disp  PIR  Schematic  Main PCB  Blutooth  Ctrl Panel  Leap Sec  Leap Sec Video  User Manual  Flow Charts  Code

 

 

 

 

         Home     Binary Clock   Slave Clocks    Calendar Clock    Voltmeter Clock  DCF77 Analyzer Clock  LCD Master Clock    Master Clock Mk1    Guestbook          

        Design and Construction   

   

     

 

                                      

 

 

 

Features

Arduino 328 Microprocessor is used to decode and display Time & date from the DCF77 "Atomic" Clock in Mainflingen near Frankfurt Germany

The DCF77 signal is decoded using the fantastic new DCF77 library written by Udo Klein meaning the clock stays in sync and keeps perfect time even with a massive amount of noise on the received DCF77 signal

Udo Klein's DCF77 library continually "Auto Tunes" the quartz crystal so in the rare event the signal can't be decoded the clock remains accurate within 1 sec over many days

The clock provides the following pulses to drive slave clocks 1 sec alternating, 30 sec, 1 min , 1 hour, 24 hr, 15 min chime of quarter hours, hourly chime of hours

Primary display of time in hours, minutes & seconds are displayed on 1" (26mm) green LED 7 segment displays

Secondary 4x20 I2C LCD display is used to display time & date, fast or slow seconds, summer winter correction, display brightness, sync information, signal quality, auto tune'd frequency, auto tuned quartz accuracy and summer winter time mode

The primary and secondary displays are auto dimmed using and LDR and Pulse Width Modulation

The primary and secondary displays are shutdown during daytime and are activated by Passive Infrared detection when the clock detects someone entering the room

Manually triggered automatic Summer/Winter time correction of 30 second slave clocks

Blue-Tooth link for programming, clock pulse status and PIR adjusting

Auto leap second adjustment of 30 second slave and 1 second slave clocks time and date of leap second can be read via Blue-tooth on your PC or Android mobile or tablet

Recording of fast or slow 1 second slave clock pulses on the LCD display as well as time and date stamping of last fast or slow pulse accessible by Blue-Tooth on your PC or Android mobile or tablet

 

 

Typical setup with Master connected to home made 12" slave clocks

 

 

 

 

Below 1 min Ultra HD video showing clock pulsing and chiming 10 o'clock

 

 

 

 

Design

I designed and built my old Master Clock see photos below in 2004 using a 32.768KHz quartz crystal and logic chips to display the time and derive the pulses to drive all my slave clocks. It also has a DCF77 decoder board that again uses logic chips to decode the DCF77 signal and get a 1 second synchronising pulse to keep the clock on time. The technology used in this clock was actually out of date when I built it as I used the technology I had leant about at college in the late 1970's.  I soon found out from comments that no one really used logic chips for this sort of thing anymore and why had I not used a Microprocessor?

 

Old Logic controlled Master Clock Mk1 showing display board, main board chime board and quartz board. The DCF77 decoder board also logic controlled and is mounted on the rear of the case

 

 

 After a few years I gave microprocessors a try by building a PIC Microprocessor based  Calendar Slave  using Oshon Soft Basic , a Meter Clock using Picbasic Pro v3 and a DCF77 Master Bracket Clock using an Arduino 328.

 

 

Collection of Master & Slave Clocks built over the last 30 years.

 

I decided to use Arduino to control my new Master as it seemed tailor made for my basic programming skills as most of the complicated work is done by the people who design and then share the libraries. Arduino is very well supported hardware wise and many complete parts can be purchased ready built as building block for projects.

A MAX7219 drives the primary display, a 4x20 I2C LCD is used for the secondary these help keeping wiring and Arduino 328 pin use to a minimum.  

I kept the same type of Oak case used in my old master Clock as it fitted 6 x 1" 7 segment displays perfectly and gave me space to fit in all the other modules.

I have used a PIR module for display shutdown/wakeup with it's own timer and sensitivity adjustment as this uses only 1 pin of the Arduino 328.

A EZ Link Bluetooth Serial Board module enables me to program the clock and read data from it remotely from my desktop PC.

New Master Clock MK2 showing reduced chip/component count and wiring

 

 

One of the considerations when building this clock was to reduce the power consumption as the clock is on 24/7. See the table below most of the time the Mk2 clock will draw around 50mA compared to the Mk1's 200mA.

 

Power Consumption

Masterclock Mk1

200mA

   

Masterclock MK2

 
Startup  35mA
Display off during daytime with no movement detected 40mA
Display on 0 brightness 43mA
Display on 2 brightness 50mA
Display on 5 brightness 62mA
Display on 10 brightness 78mA
Display on 15 (max) brightness 90mA

 

 

Arduino Libraries Used

dcf77.h this Library is the heart of the clock. This outstanding new library written by Udo Klein decodes even a noisy DCF77 signal and auto tunes the quartz crystal.

LedControl.h to drive the LED display and LDC backlight via a MAX7219 IC.

LiquidCrystal_I2C.h to drive the LCD display


Wire.h to communicate with I2C devices

 

 

Time keeping

My old Master Clock was a very good time keeper and as long as I had a good DCF77 signal to keep it in sync it was fine. Every now and then when the DCF77 signal was lost for some time it would gain a second and when correcting it it would then make the 1 second slaves loose a second. This only happened a couple of times a year but re-syncing all my 1 second slaves was a pain.

I have decided to keep using the DCF77 signal from the Atomic Clock in Germany. I could have used the MSF signal from the UK but reception is not good in Surrey as the transmitter has move further North. The DCF77 signal is also better supported as it is used across Europe not just the UK. I will be using the Arduino DCF77 decoder library written by Udo Klein . Udo has been developing this code over the last few years to make it synchronize and lock onto a signal even when there is a massive amount of noise and interference on the signal. While prototyping my new clock I consistently manage to synchronize and maintain a lock even though the DCF77 signal  receiver LED that should show a steady 1 second pulse from Germany is flashing multiple times a second.

Udo's DCF77 library code is very very complex but in very basic terms it locks onto the DCF77 frequency using a phased-locked loop and once locked it will actually predict what the DCF77 code should contain and then look for snippets of this code in a very noisy signal. As things like the date do not change that often his code can look for this data in the signal to help it stay locked on! Once in sync with the DCF77 signal it uses it to "auto tune" the backup quartz crystal ensuring if the DCF77 signal is losed the clock still stays in sync.

 You can read full details of the development of this library and much more on Udo's site/blog here Blinkenlight.

 

The only small down side to this library is that it needs an accurate time base on the Arduino to lock into the DCF77 frequency. Modern Arduino boards don't use a quartz crystal ( the one you see on the board is for the serial port) but an inferior 16MHz ceramic resonator. Udo has written a test program to check if your Arduino boards resonator/crystal are up to the job of running his library and can be found here DCF77 Scope . If your board is not up to the job it is very easy to remove the resonator and replace it with a quartz crystal and a couple of capacitors. I have modified my Arduino UNO and it works perfectly with the library.

Modified UNO board

Before

 

After

 

 

Resonator & Resistor removed and a 16MHz crystal with 2 x 22pf capacitors soldered in place of the resonator

 

 

The other option is to build your own Arduino as I have done in my LCD Master Clock and on this project. You can get an Arduino chip, holder, crystal and capacitors in a kit for a few ús. If your are using Windows to compile your code you will need an updated compiler see how to do it here  (update new versions of the Arduino compiler now work fine). Linux already has this installed but I am not sure about Macs.

 

 

Main clock display

I used 1" (26mm) 7 segment display to display time as these have worked perfectly well on my old Master Clock and are legible from a good distance at night and also in daylight. These are driven by a MAX7219  display driver as it can talk directly to the Arduino using a couple of wires and it's multiplexed display simplifies wiring.

 

 

 

Secondary display

4x20 I2C LCD display

 

 

The secondary display as well as showing the time and date will give information on the running of the clock in particular the DCF77 decoding performance. I have used an I2C 4x 20 LCD display for this. Again these displays talk directly to the Arduino over a 3 wire interface and are very good at displaying lots of information close up.

 

 

Pulse Monitor

Pulse monitoring uses simple LEDs as they provide a quick visual indication of what pulses are being transmitted by the clock.

 

 

Manually Triggered Automatic Summer/Winter time correction of  30 second Slave Clocks

The Master Clock itself auto corrects for summer wintertime changes at 02:00hrs but due to the loud clunk of the 30 second clocks being advanced during summer changes I have added a switch to initialise automatic Summer advance and Winter retard. This is a single non-locking key and the Master Clock will advance or retard the 30 second slaves depending on the current time of year. If it is summertime the clock is advanced 1 hour and winter time the clocks are retarded 1 hour (pulsing stopped for 1 hour as slaves can't go backwards).

 

In summer time correction mode 120 extra pulses are sent to the 30 sec slave clocks. The LCD display will show "Summer Advance" and will count the 120 extra pulses. When the time is at 00 or 30 seconds the extra pulses are stopped and the 30 sec clocks pulses are sent out as normal. This means whenever the 120 pulses are started the 30 sec slave clocks are  only advanced exactly 1 hour.

See demo You Tube video here

 

 

 

 

 

 

In winter time correction mode the clock waits for the next 30 sec pulse before pausing for 120 30 sec pulses. The LCD display will show "Winter Retard" to show 30 sec clocks are being retarded and show the number of missed pulses.

See demo You Tube video here

 

 

 

 

Construction

My old master Clock had to be completely wired by hand and this took around 4 weeks to complete all the boards. As I can't produce my own PCBs I have used modular construction on my new clock to keep the wiring/vero board construction to a minimum . This also helps with maintenance as I can just swap out a module if it goes faulty.

 

 

 

 

 

 

 

Master Clock prototyped so I can test the software. The small 7 segment test displays are driven by a MAX7219

and uses the LEDcontrol library by Eberhard Fahle. For testing I used a Arduino Uno with a quartz crytal and capacitors added so it worked with Udo Klein's DCF77 library

 

 

 

 

Master Clock Construction

 

The Master Clock case is made of solid Oak. I have stripped back the old dark varnish from this recycled box and re varnished in clear lacquer.

The case is identical to my old master clock but is now a lighter Oak colour.

 

Display vero board has been spray painted green and comprises 2 parts (7 segment board and LCD/LED board) bolted together and mounted in the case on threaded M5 studding.

In the finished clock the threaded bolts will be covered over with brass tube.

 

The LED displays are mounted on SIL headers.

 

 

 

 

 

LCD Display mounted into a hole cut in the veroboard.

 

 

 

Lid removed to show display board and main board mounting

All 7 segment displays, LCD and LEDs mounted. LDR is on the right of the LCD.

PIR detector is now mounted outside of case as it will not work through the case glass.

 

Case needs 2nd pane of glass added so displays can be labelled with white Letraset.

Once the 2nd glass panel is in place brass tubing can be cut to length to cover the studding.

 

 

 

 

 

 

Wiring of main board to display board, switch panel, main fuse and EZ link Bluetooth board.

 

 

 

Master Clock construction almost completed. Oak Bezel added to LCD display, brass pillars added over display board studding

and 2nd layer of glass added held in place by brass clips ready for letroset labelling.

 

 

 

 

 

 

Completed Master Clock with letroset labelling applied to the 2nd inner piece of glass.

The 2 glass layers are seperated by a 1mm rubber gasket.

 

 

 

Master Clock and Slaves on test bed ready for testing

 

 

 

 

 

7 Segment Display Board

 

 

 

Completed 1" 7 segment display board with MAX2719 board mounted on reverse

The MAX2719 DP driver is connected to the transistor to control the LCD backlight

 

 

 

MAX7219 Board layout

 

 

 

 

 

Short video clip showing the almost complete master clock running on my test bench.

As the clock is in day mode the displays can be seen turning off and on as the clocks PIR detects movement.

The 7 segment display has the decimal points activated in software but the Max2719 decimal point output connected to the LCD backlight LED via a transistor to allow the Max2719 to control the  brightness of both displays at the same time.

Display now records the Total of Slow 1 Second clock pulses Pulses ( when the master clock corrects forward ) and Fast pulses ( when the master clock corrects back) this resets daily.

As the Udo's DCF77 decoder library is working 100% there are none so far. My other DCF77 LCD Master Clock will show around 8 missed pulses per day. I have decided not to implement pulse correction as Udo's DCF77 library is working so well. I have only added

leap second correction for my 1 second clock pulses.

View on You Tube

 

 

 

 

 

Summertime Correction including 30 Second Slaves

1 minute video clip showing clock correcting a 30 second slave clock for summertime. Note when the Master is at 30 or 60 seconds pulse counting is stopped to let the slave clock step as normal.

This means 120 pulses will always step the 30 second slaves ahead 1 hour.

The Master Clock itself auto corrects for summer wintertime changes at 02:00hrs but due to the loud clunk of the 30 second clocks being advanced

summer winter changes are initialised by an "Advance/Retard" key the next day. This is a single non-locking key and the Master Clock will advance or retard the 30 second slaves

depending on the current time of year. If it is summertime the clock is advanced 1 hour and winter time the clocks are retarded 1 hour (pulsing stopped for 1 hour as slaves can't go backwards).

View in You Tube

 

 

 

 

 

Wintertime Correction including 30 Second Slaves

Video Showing Wintertime Correction

30 second clocks can't move backwards so they are retarded by stopping pulses for 1 hour (120 pulses)

On operating the Advance Retard switch the missed pulses are counted from the next 30 second pulse.

View in You Tube

 

 

 

 

 

Video showing Auto Tune on LCD Display

View in You Tube

 

When the DCF77 signal fails the Master Clock reverts back to Quartz crystal control.

The crystal has a 16MHz frequency and is not very good at keeping time. Udo Klein's DCF77 library now includes "Auto Tune".

The DCF77 signal is used to tune the Quartz crystal frequency over a number of days.

The Auto Tune'd Quartz crystal accuracy and frequency is shown on the bottom of the LCD display.

With auto tune in operation even if the DCF77 signal is absent for long periods of time the clock will stay in sync. This is very important for my slave clock control.

 

The accuracy of "Auto Tune" is dependant of the temperature of the Arduino 16Mhz quartz crystal and this of course is dependant on the outside and inside temperatures.

I have now managed to get an accuracy of 1Hz but this can vary upto 2Hz.

 

 

 

 

 

The LCD Display shows the following information

Row 0

Current time and date should be identical to LED display

 

Row 1

Clock Name

My Name & software version no

1 second slave clocks total missed (fast) pulses and extra (slow) pulses. When the clock drifts and then resets a second ahead of clock time. An extra 1 second pulse (slow)  is required to keep correct time on 1 second clocks.  When the clock drifts and then resets a second behind clock time. A 1 second pulse is missed (fast) to keep correct time on 1 second clocks. The total  is reset at 06:10 in the morning.

This row also displays the Summer/Winter advance retard information when the clock is correcting the 30 sec slaves

 

Row 2

7 segment intensity setting. This is controlled by an LDR. 1 is dimmest  15 is brightest setting. This row also displays decoding status Sync'd, Locked, Dirty and Fail

 

Row 3

This row shows the received signal accuracy in %, the Auto Tuned Quartz crystal frequency accuracy down to 1 Hz and the actual Auto Tuned Quartz crystal tuned frequency in Hz.

Summertime/wintertime indicator GMT/GMT+1

 

 

 

 

Semi Auto winter Summer correction of 30 second slaves

Summer/winter correction is triggered by a momentary switch with a fail safe "Arm" switch in series.

The single switch will auto advance the 30 seconds clocks an hour in summer and retard them by an hour in winter. The 30 second slaves are advanced by pulsing once per second when the advance/retard switch is operated. This will take 120 additional pulses not including any normal pulses during the advance period.

The clock automatically allows for the normal pulses when advancing by ignoring any normal pulses on 30 and 60 seconds. As 30 second slave clocks cannot be stepped backwards the clocks are retarded by stopping them for an hour on operation of the advance/retard switch. When in retard mode the clock waits for the next 30 second pulse then waits for 120 pulses to pass before starting up again.

The 30 second slave clocks and electro mechanical chimes are driven by monostables and transistors.  Pulse length is adjusted by cermet presets on the monostables.

 

 

 

 

Pyroelectric IR Infrared PIR Motion Sensor Detector Module

I have added an infrared motion detector to the clock. I want to keep the running costs down to a minimum especially as the clock will be running 24/7.

I need the clock on at night so have fitted auto dimming of the 7 segment displays now to 16 levels. I have also connected the decimal point output from the Max7219 to a transistor and the LCD backlight. The transistor then controls the LCD backlight as the 7 segment display is dimmed by the Max7219.

The displays (7 segment and LCD backlight) are now turned off from 08:00hrs to 22:00hrs. The infrared detector will turn them on if motion is detected i.e. you step in front of the clock and they will then turn off after a preset time.

 

 

 

PIR Module above and modified module below.

 

 

The standard PIR module is modified to work outside of the clock case. The pyroelectric sensor is de-soldered from the module main board.

The main board is fixed inside the clock and the pyroelectric sensor is mounted on an external board facing out from below the clock.

The sensor is then covered over by a circular lens.

 

 

 

 

Shematic

 

Master Clock Mk2 Schematic

 

 

 

 

 

 

Rear of Display Board

 

 

 

Front of Arduino Board

Mouse over to see rear.

 

 

 

 

 

 

Blue-Tooth Programming & Reading

 

EZ Link Bluetooth Serial Board

I have added Bluetooth programming via an EZ Link board.

My clock can now be programmed remotely by my PC (will not work with MACs use USB cable & CP2102 module instead) and also monitored remotely by my Android Phone/Tablet

The pair switch mounted on the main switch panel is connected across the Pair switch on the Bluetooth Board (soldered to the 2 resistors see pic above)

 

 

Android Bluetooth serial monitor  showing Slow and fast 1 second clock pulses with date and time of error pulse ( in this case it shows start-up time), PIR detection,  date/time and  summer winter offset

The EZ link Bluetooth Serial Board is mounted on the base of the clock.

The 3 LEDs Connection (Or), Receive (Bl) & Transmit (Bl) can be seen through the display vero board holes.

 

 

 

 

 

Clock Control Panel

 

Manual Controls

30 Second Clocks

On - turns On/Off the pulses to the 30 seconds clocks

Advance/Retard - Depending on the clock showing summer or winter time when held down for 1 second steps the 30 second clocks forward 1 hour or retards the clocks 1 hour.

Only works when the Arm switch is set to the Arm position and On/Off switch is On.

 

Master Clock

 Reset - resets the Arduino so the clock will resync

 

Bluetoth

On - Turns Bluetooth On & Off

Pair - Pairs the clock to a new device

 

 

 

 

 

Leap Second Detection and Correction

The clock now detects leap seconds. This is built into the library and the LCD and 7 segment displays auto adjust.

The problem was how to auto correct the 1 seconds clocks. The leap second is added at the end of a minute so instead of the seconds counting to 59

then starting again from 0 the seconds count to 60 and then resets to 0.

The clock looks for the seconds counting to 60 then waits 1 second before starting to pulse the 1 second clock pulse again.

This can be seen on the serial display on my mobile via the EZ-Link Bluetooth board in my clock. I used a test program written by Udo Klein to send dummy leap year data to my clock.

The phone display below shows 0 slow seconds and 1 fast second. The 1st slow second is always there on startup and indicates when the clock was first sync'd up in this case 23:51:44 on the 31/12/14.

These are day totals and are reset at 06:00 am.

The  fast second (the seconds are fast compared to DCF77 time) shows the date and time the fast seconds were detected in this case 0:0:0 01/01/15. This is when the leap second was added and the seconds pulsing

 was stopped for 1 second to keep in sync with DCF77 time.

This was tested using Udo Klein's DCF77 radio code generator for the Arduino.

see my page here for setup details  or Udo's site here. The code makes an Arduino into a low powered DCF77 transmitter so you can send any date and time to any DCF77 clock for testing.

 

 

 

The image below shows the actual output from my clock from the real leap second on the 30/06/15.

The clock displays the fast second as received at 00:59:60 on the 01/07/15 as British Summertime in in operation.

After "Slow Seconds" and "Fast Seconds" on the serial display is the error count per day.

On the image below they show zero as the day count is reset to zero at 06:10hrs every day.

The time and date of the last fast or slow pulse is then recorded on the LCD display.

I have removed the current time and date from the serial out on the latest version of the code.

 

 

 

 

View in You Tube

 

Short video showing the Master Clock detecting a leap second and stopping the 1 second clock to enable it to stay in sync.

The leap second when detected is time stamped and stored and can be read from the serial port of your PC or Android phone.

It can be seen as "Fast Seconds" (above on my Android mobile) as the 1 second clock had to be paused to stay in sync.

 

 

 

 

 

                                                                      

View as word doc                                                                   View as PDF                              

 

 

 

 

 

 

Program Flow Charts

 

Initial Power Up

 

 

Main Program Loop

Continued from main program loop above- Summer Winter Correction and Pulse generation

 

 

 

 

 

 

Arduino Master Clock Mk2 Code v2.1 long term testing in progress

V2.1 now uses Udo Klein's DCF77 library with "auto tune" Note this clock uses Udo Kleins Release 2 library download here DCF77 Release 2

Uses all Atmega328 Pins and nearly all available memory 28406 bytes

Requires the following libraries

LedControl.h
dcf77.h Note this clock uses Udo Kleins Release 2 library download here DCF77 Release 2
LiquidCrystal_I2C.h
Wire.h

Download the code here


//  Master Clock Mk 2
//  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/
//
// v4 changed Quartz driver pins to 7 and 8
// UTC
// 30 sec pulse
// DCF77 Status reverted
// 7 segment display hr min sec
// pulses
// signal stats
// Time date moved on to row 1
// 7 segment time moved to 4 for testing hour and mins roll over
// hour and min rollover corrected
// signal stats further updates
// signal stats to LCD
// DCF77 Master Clock/Brett Oliver v no toggle
// Qtr & Hour chime
// qual stats rotate
// LDR display adjust
// move signal match from row 2 to row 3
// 7 seg intensity to LCD row 2
// add leading zero on intensity
// add missed seconds pulse and add extra seconds pulse
// swap Master Clock and Miss count rows
// add extra seconds pulse display inc total to LCD row 1
// add 30 sec clock winter summer correction using sumwinSw switch input on pin 13. Not completed.
// add sum  advance
// remove mised and extra pule time date
// and add winter retard
// change outputs for 30 sec clock to low out
// add infrared detection for displays
// 7 segment intesity values now 16
// corrected hour min and seconds values obtained
// scan limit to 6 x 7 segment displays added
// change Qtr & Hour chime to normal high
// change infrared detect to stop LED display freezing on no movement
// added extra serial output
// changed infrared detection so it is not triggered after 21:00 and b4 08:00
// cut down to be under 28k limit
// remove ignoring of initial pulses for extra and missed pulses
// change extra second pulse (secsmiss) detection so it does not auto detect
// add leap second detect for 1 second clock pulse
// summertime variable used to display GMT+ instead of timezone offset
// 1.2 mod to extra count to pick up leap second at 60 seconds
// 1.6 added autotune data on LCD
// 1.7 modified LED removed extra lc.clearDisplay(0) and lc.setScanLimit(0, 5); to stop display pulsing
// 1.8 remove lcd.backlight() & lcd.noBacklight not needed as controlled by MAX2719
// 1.9 mod auto tune on LCD
// 2.0 mod to LDR values 
// 2.1 LDR removed 0 intensity as too dim at night
#include <LedControl.h>
#include <dcf77.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
/*
 
 ***** These pin numbers will probably not work with your hardware *****
 pin 12 is connected to the DataIn 
 pin 11 is connected to the CLK 
 pin 10 is connected to LOAD 
 We have only a single MAX72XX.
 */
LedControl lc=LedControl(12,11,10,1);

/* 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_pin = A0;  // A4 == d18 changed from A4

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

//*********************
//int UTCcheck = 0;
//int 30secstep = 0:
//int 30secstep1 = 0;

int retardOn = 0;
//int retardtens = 0;
//int retard = 0;
int infraredSwval = 0; // infrared value
int infraredSw = 17; // set A3 to input ( pin 13)
int retardcount = 0;
int pulsecount = 0; // pulse counts upto required number to step forward 1 hour
int sumwinSwval = 0; // value of sumwinSw
int sumwinSw = 13; // summer winter switch pin 13
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 startextra = 0; // delays checking of extra pule intil start extra = 3
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 intensity; // 7 segment intensity
int ldr = A2; // LDR connected to analogue A2 pin
unsigned int ldrValue; // LDR value
int hourchime = 9;
int qtrchime = 6;

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 hours2 = 0; //2nd 7 segment hour digit
int hours1 = 0; //1st 7 segment hour digit
int hours = 0;
int minutes2 = 0; //2nd 7 segment minute digit
int minutes1 = 0; //1st 7 segment minute digit
int minutes = 0;
int seconds2 = 0;  //2nd 7 segment seconds digit
int seconds1 = 0; //1st 7 segment seconds digit
int seconds = 0;
int secsval = 0;
int minsval = 0;
int hourval = 0;
int led30 = 2;
int led1min = 3;
int led1hr = 4;
int led1day = 5;
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
//********************

namespace Timezone {
  uint8_t days_per_month(const DCF77_Clock::time_t &now) {
    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(DCF77_Clock::time_t &time, const int8_t offset) {
    // 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;
      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);
    }

    if (hour < 0) {
      hour += 24;
      uint8_t day = BCD::bcd_to_int(time.day) - 1;
      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.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);
  return sampled_data;
}

void setup() {
  digitalWrite(led30, HIGH); // turn 30 sec clocks off at start
  digitalWrite(qtrchime, HIGH); // turn Qtr chime off at start
  digitalWrite(hourchime, HIGH); // turn Hour chime off at start

  //****** 7 seg
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,0);
  /* and clear the display */
  lc.clearDisplay(0);
  lc.setScanLimit(0, 5); // set to 6 digits

  lcd.begin(20,4);   // initialize the lcd for 20 chars 4 lines, turn on backlight 
  using namespace DCF77_Encoder;
  //*************
 // 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 Master Clock");  





  //***************
  Serial.begin(9600);
  /*  Serial.println();
   Serial.println(F(" DCF77 Master 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);

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


  //*******************
  pinMode(qtrchime, OUTPUT);
  pinMode(hourchime, OUTPUT);
  pinMode(led30, OUTPUT);
  pinMode(led1min, OUTPUT);
  pinMode(led1hr, OUTPUT);
  pinMode(led1day, OUTPUT);
  pinMode(quartz01, OUTPUT);
  pinMode(quartz02, OUTPUT);

  pinMode(17, INPUT); // summer winter switch
  pinMode(infraredSw,INPUT);
  //pinMode(infraredSw, INPUT); // infrared sensor output

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

  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 = DCF77::useless;
         state == DCF77::useless || state == DCF77::dirty;
         state = DCF77_Clock::get_clock_state()) {

    // wait for next sec
    DCF77_Clock::time_t now;
    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() {

  DCF77_Clock::time_t now;

  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 (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) // if extra second pulse required
     {
     delay(100); // add delay so seconds mtor can operate again in the same second
     secondsmotor (); // function steps quartz motor and adds extra pulse if secmiss is >1
     }
     
     */



    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(13,2);
    //lcd.print(" Wait  ");
    switch (DCF77_Clock::get_clock_state()) {
      // case DCF77::useless: Serial.print(F("useless ")); break;
      case DCF77::useless: 
      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 DCF77::dirty:   
      lcd.print(F(" Dirty ")); 
      break;
      case DCF77::synced:  
      lcd.print(F(" Sync'd")); 
      break;
      case DCF77::locked:  
      lcd.print(F(" Locked")); 
      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);


    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

    //LEDseconds(); // converts secsval to seconds
    // LEDminutes(); // converts minsval to minutes
    // LEDhours(); // converts hourval to minutes
    //LEDseconds1(); // converts seconds to 2 single digits for 7 segment seconds display
    seconds2 = floor(seconds/10); //gets 2nd seconds char from seconds for 7 segment display
    seconds1 = seconds - (seconds2 * 10); //gets 1st seconds char from seconds for 7 segment display

    minutes2 = floor(minutes/10); //gets 2nd seconds char from seconds for 7 segment display
    minutes1 = minutes - (minutes2 * 10); //gets 1st seconds char from seconds for 7 segment display

    hours2 = floor(hours/10); //gets 2nd seconds char from hours for 7 segment display
    hours1 = hours - (hours2 * 10); //gets 1st seconds char from hours for 7 segment display

    // start infrared detect #######################################
    int infraredSw = digitalRead(17); // reads infrared detector output
    Serial.print ("Infrared ");
    Serial.println (infraredSw);
    Serial.println ("");



    if (hours < 8 && hours > 21) // displays are on if between 22:00 and 08:00 time or infrared detects movement

    { 
      lc.shutdown(0, false); // turns on the 7 segment display
     // lcd.backlight(); // backlight on not needed as controlled by MAX2719
      lcd.display(); //display on

    }

    else if (infraredSw == 1) // turns displays on during the day if infrared detects movement

    {
      lc.shutdown(0, false); // turns on the 7 segment display
    //  lcd.backlight(); // backlight on not needed as controlled by MAX2719
      lcd.display(); //display on   

    }
    else if (infraredSw == 0 && hours >= 8 && hours <= 21) // turns displays off during the day unless infrared detects movement
    {
      lc.shutdown(0, true); // turns off the 7 segment display and puts it into standby mode
     // lcd.noBacklight(); // LCD backlight off not needed as controlled by MAX2719
      lcd.noDisplay(); //LCD display off 

    }
    // end infrared detect #######################################

    // shows 7 segment display if infrared detected or time is after 22:00 and before 08:00
    /* Set the brightness to a medium values */
    //lc.setIntensity(0,8);
    lc.setIntensity(0,intensity); // set 7 segment intensity to value of "intensity"
   // lc.setScanLimit(0, 5);
    /* and clear the display */
    // lc.clearDisplay(0); 
    lc.setChar(0,0,seconds1,true); // print 1st seconds digit on 7 segment display and "true" lights dp so LCD backlight can be controlled
    lc.setChar(0,1,seconds2,true); // print 2nd seconds digit on 7 segment display and "true" lights dp so LCD backlight can be controlled
    lc.setChar(0,2,minutes1,true); // print 1st minutes digit on 7 segment display and "true" lights dp so LCD backlight can be controlled
    lc.setChar(0,3,minutes2,true); // print 2nd minutes digit on 7 segment display and "true" lights dp so LCD backlight can be controlled
    lc.setChar(0,4,hours1,true); // print 1st minutes digit on 7 segment display and "true" lights dp so LCD backlight can be controlled
    lc.setChar(0,5,hours2,true); // print 2nd minutes digit on 7 segment display and "true" lights dp so LCD backlight can be controlled
    lc.setChar(0,6,' ',false);
    lc.setChar(0,7,' ',false);

    /*  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);
    //**************




    //  Serial.print(offset_to_utc<0? '-':'+');
    // lcd.print(offset_to_utc<0? '-':'+');
    //  if (abs(offset_to_utc) < 10) {
    //     Serial.print('0');
    //  lcd.print('0');
    //   }
    //   Serial.println(summertest);
  }

  //*******************
  // secsval = (now.second.val);
  //  minsval = (now.minute.val);
  //  hourval = (now.hour.val);

  // Serial.print ("Secs Val ");
  //  Serial.print (secsval);
  //  Serial.print (" Min Val ");
  //  Serial.print (minsval);
  //  Serial.print (" Hr Val ");
  //  Serial.print (hourval);



  // ########################
  // Quater chime
  if (( minutes ==15 || minutes ==30 || minutes==45) && seconds==0)
  {
    digitalWrite(qtrchime, LOW);
    // lc.clearDisplay(0); // Test reset LED display on Qtr Chime to pevent corrupted display
  }

  else if (minutes ==59 && seconds==57)
  {
    digitalWrite(qtrchime, LOW);
  }
  else digitalWrite(qtrchime, HIGH);
  // End quater chime
  // ########################

  // ########################
  // Hour chime

  if (minutes == 0 && (hours == 1 || hours == 13) && seconds == 0 )
  {
    digitalWrite(hourchime, LOW);
  }
  else
    if (minutes == 0 && (hours == 2 || hours == 14) && (seconds == 0 || seconds ==2 ))
    {
      digitalWrite(hourchime, LOW); 
    } 
    else
      if (minutes == 0 && (hours == 3 || hours == 15) && (seconds == 0 || seconds ==2 || seconds ==4 ))
      {
        digitalWrite(hourchime, LOW); 
      } 
      else
        if (minutes == 0 && (hours == 4 || hours == 16) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 ))
        {
          digitalWrite(hourchime, LOW); 
        } 
        else
          if (minutes == 0 && (hours == 5 || hours == 17) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 ))
          {
            digitalWrite(hourchime, LOW);  
          }
          else
            if (minutes == 0 && (hours == 6 || hours == 18) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 || seconds ==10 ))
            {
              digitalWrite(hourchime, LOW);
            }
            else
              if (minutes == 0 && (hours == 7 || hours == 19) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 || seconds ==10 || seconds ==12 ))
              {
                digitalWrite(hourchime, LOW);
              }  
              else
                if (minutes == 0 && (hours == 8 || hours == 20) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 || seconds ==10 || seconds ==12 || seconds ==14))
                {
                  digitalWrite(hourchime, LOW); 
                } 
                else
                  if (minutes == 0 && (hours == 9 || hours == 21) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 || seconds ==10 || seconds ==12 || seconds ==14 || seconds ==16))
                  {
                    digitalWrite(hourchime, LOW);
                  }  
                  else
                    if (minutes == 0 && (hours == 10 || hours == 22) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 || seconds ==10 || seconds ==12 || seconds ==14 || seconds ==16 || seconds ==18))
                    {
                      digitalWrite(hourchime, LOW); 
                    } 
                    else
                      if (minutes == 0 && (hours == 11 || hours == 23) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 || seconds ==10 || seconds ==12 || seconds ==14 || seconds ==16 || seconds ==18 || seconds ==20))
                      {
                        digitalWrite(hourchime, LOW); 
                      } 
                      else
                        if (minutes == 0 && (hours == 12 || hours == 0) && (seconds == 0 || seconds ==2 || seconds ==4 || seconds ==6 || seconds ==8 || seconds ==10 || seconds ==12 || seconds ==14 || seconds ==16 || seconds ==18 || seconds ==20 || seconds ==22))
                        {
                          digitalWrite(hourchime, LOW); 
                        } 
                        else      
                          digitalWrite(hourchime, HIGH);

  // end of Hour Chime

  // ########################
  //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  // Quality display on LCD


  if (seconds >= 0 && seconds <= 12)
  { 
    signalmatch(); // Quality factor
  }

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

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

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

 else if (seconds >= 39 && seconds <= 40)
  {
      lcd.setCursor(0,3);
  lcd.print("Frequency      ");
  }

  else if (seconds >= 41 && seconds <= 58)
  {
    freqadj(); //frequency adjustment and actual frequency
  }

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

   else if (seconds == 11)
   {
   blankrow3(); //Blanks row 3
   }
   
   else if (seconds >= 12 && seconds <= 16)
   {
   phasequal(); //Phase lock quality
   }
   
   else if (seconds == 17)
   {
   blankrow3(); //Blanks row 3
   }
   
   
   else if (seconds >= 18 && seconds <= 21)
   {
   secsqual(); //seconds quality
   }
   
   
   else if (seconds == 22)
   {
   blankrow3(); //Blanks row 3
   }
   
   
   else if (seconds >= 23 && seconds <= 29)
   {
   hourqual(); // hour quality
   }
   
   
   else if (seconds == 30)
   {
   blankrow3(); //Blanks row 3
   }
   
   
   else if (seconds >= 31 && seconds <= 36)
   {
   wkdayqual(); //weekday quality
   }
   
   
   else if (seconds == 37)
   {
   blankrow3(); //Blanks row 3
   }
   
   else if (seconds >= 38 && seconds <= 43)
   {
   dayqual(); //day quality
   }
   
   else if (seconds == 45)
   {
   blankrow3(); //Blanks row 3
   }
   
   
   else if (seconds >= 45 && seconds <= 51)
   {
   monthqual(); // month quality
   }
   
   else if (seconds == 52)
   {
   blankrow3(); //Blanks row 3
   }
   
   
   else if (seconds >= 53 && seconds <= 58)
   {
   yearqual(); // year quality
   }
   
   else if (seconds == 59)
   {
   blankrow3(); //Blanks row 3
   }
   */

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



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

  if (summertest == 1 && pulsecount < 120 && (seconds == 0 || seconds == 30) && (sumwinSwval == 1 || pulseOn == 1))
    // summertest is 1 in summertime and  0 in wintertime  advance on 00 & 30 secs does not advance pulse count

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

    digitalWrite(led30, LOW);   // turn the PULSE ON trigger mono stable (HIGH is the voltage level)
    delay(10);
    digitalWrite(led30, HIGH);   // turn the PULSE OFF trigger mono stable(HIGH is the voltage level)

  }

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

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

    digitalWrite(led30, LOW);   // turn the PULSE ON trigger mono stable (HIGH is the voltage level)
    delay(10);
    digitalWrite(led30, HIGH);   // turn the PULSE OFF trigger mono stable(HIGH is the voltage level)
  }

  else  
  {
    pulseOn = 0; // 
    // sumwinSwval = 0;
    pulsecount = 0;
  } 

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



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

  if (summertest == 0 && retardcount < 120 && sumwinSwval == 1) 
  {
    retardOn = 1;
  }

  else if (summertest == 0 && retardcount < 120 && (seconds == 0 || seconds == 30) && (sumwinSwval == 1 || retardOn == 1))
  {
    retardOn = 1;
    retardcount = retardcount + 1;
  }

  else if (summertest == 0 && retardcount < 120 && (sumwinSwval == 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 == 120 )  //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 Master 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  v2.1 ");
  }

  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 == 119 ) //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 == 120 )  //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 ##############################






  // 30 second clock pulses
  if ((retardOn == 0 && pulseOn ==0) && (seconds == 0 || seconds == 30)) // will only pulse if retardOn = 0 ( not in winter retard mode)
  {
    digitalWrite(led30, LOW);   // turn the LED on (HIGH is the voltage level)
    //  Serial.println(" Normal 30 sec ");    

  }

  else if ((retardOn == 0 && pulseOn ==0) && (seconds != 0 || seconds !=30)) // will only pulse if retardOn = 0 ( not in winter retard mode
  {
    digitalWrite(led30, HIGH);   // turn the LED off (LOW is the voltage level)  

  }
  // end 30 second clock pulses

  // 1 min pulse
  {
    if (seconds == 0) 
    {
      digitalWrite(led1min, HIGH);   // turn the LED on (HIGH is the voltage level)

    }      

    else if(seconds != 0)

      digitalWrite(led1min, LOW);   // turn the LED off (LOW is the voltage level)  

  }


  // 1 hour pulse
  {
    if (minutes == 0 && seconds== 0) 
    {
      digitalWrite(led1hr, HIGH);   // turn the LED on (HIGH is the voltage level)

    }      

    else if (minutes != 0 || seconds !=0)

      digitalWrite(led1hr, LOW);   // turn the LED off (LOW is the voltage level)  

  }

  // 1 day pulse
  {
    if (hours == 0 && minutes == 0 && seconds == 0) 
    {
      digitalWrite(led1day, HIGH);   // turn the LED on (HIGH is the voltage level)

    }      

    else if(hours != 0 || minutes != 0 || seconds != 0)

      digitalWrite(led1day, LOW);   // turn the LED off (LOW is the voltage level)  

  }

} 






void secondsmotor (){

  if (quartzmotor1 == LOW)
  { 
    quartzmotor1 = HIGH; 
  }
  else
    quartzmotor1 = LOW;
  {
    digitalWrite(quartz01, quartzmotor1); // set the quartz motor drive 7 pin
  }

  if (quartzmotor2 == HIGH)
  { 
    quartzmotor2 = LOW;
  }
  else
    quartzmotor2 = HIGH;
  {
    digitalWrite(quartz02, quartzmotor2); // set the quartz motor drive 8 pin     
  }

}

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

//add extra quartz pulse

// if (secsmiss > 1) // if >1 pulse has been missed so extra quartz pulse is added here





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

void segIntensity(int intensity){

  if(intensity < 10)  
    lcd.print("0"); // Print hour on first line
  lcd.print(intensity);
}

// end

void advance(int pulsecount){ // leading 0  on pulse count
  if (pulsecount < 100)

    lcd.print("0"); 

}

void advancetens(int pulsecount){ // leading 0  on pulse count
  if (pulsecount <10)

    lcd.print("0"); 

}
//******************************

void retard(int retardcount){ // leading 0  on pulse count
  if (retardcount < 100)

    lcd.print("0"); 

}

void retardtens(int retardcount){ // leading 0  on pulse count
  if (retardcount <10)

    lcd.print("0"); 

}











void monthzero(int monthval) { // leading zero on month value
  if (monthval < 10)

    lcd.print("0"); // Print hour on first line
  lcd.print(monthval);
}


void dayzero(int dayval) { // leading zero on day value
  if (dayval < 10)

    lcd.print("0"); // Print hour on first line
  lcd.print(dayval);
}



// intensity of 7 segment display
void intensityValue() { 

 // if (ldrValue < 40)
//  {
  //  intensity = 0;
//  }
  if (ldrValue >= 0 && ldrValue < 90)
  {
    intensity = 1;
  }


  else if (ldrValue >= 90 && ldrValue < 140)
  {
    intensity = 2;
  }

  else if (ldrValue >= 140 && ldrValue < 190)
  {
    intensity = 3;
  }

  else if (ldrValue >= 190 && ldrValue < 240)
  {
    intensity = 4;
  }


  else if (ldrValue >= 240 && ldrValue < 290)
  {
    intensity = 5;
  }


  else if (ldrValue >= 290 && ldrValue < 340)
  {
    intensity = 6;
  }


  else if (ldrValue >= 340 && ldrValue < 390 )
  {
    intensity = 7;
  }



  else if (ldrValue >= 390 && ldrValue < 440)
  {
    intensity = 8;
  }



  else if (ldrValue >= 440 && ldrValue < 490)
  {
    intensity = 9;
  }



  else if (ldrValue >= 490 && ldrValue < 540)
  {
    intensity = 10;
  }



  else if (ldrValue >= 540 && ldrValue < 590)
  {
    intensity = 11;
  }
  else if (ldrValue >= 590 && ldrValue < 640)
  {
    intensity = 12;
  }
  else if (ldrValue >= 640 && ldrValue < 690)
  {
    intensity = 13;
  }
  else if (ldrValue >= 690 && ldrValue < 790)
  {
    intensity = 14;
  }


  else if (ldrValue >= 790)
  {
    intensity = 15;
  }
} 




void blankrow3() {
  lcd.setCursor(0,3);
  lcd.print("               "); 
}





void signalmatch() {

  signalQual = DCF77_Clock::get_prediction_match();
  if(signalQual == 255 || signalQual == 0 )
  {
    signalQual = 00;
  }
  else
  {
    signalQual = signalQual * 2;
  }
  lcd.setCursor(0,3);
  lcd.print("Sig Match ");
  lcd.print(signalQual);
  lcd.print("%");
}



void precision() {
  lcd.setCursor(0,3);
  lcd.print("Accuracy ");
  lcd.print(DCF77_Frequency_Control::get_confirmed_precision());
  lcd.print("Hz "); 
}

void freqadj() {
  lcd.setCursor(0,3);
 // lcd.print("Qtz ");
  lcd.print(16000000L - DCF77_1_Khz_Generator::read_adjustment());
  lcd.print("Hz"); 
}


//}

//Serial.print(F("Quality (p,s,m,h,wd,d,m,y,st,tz,ls,pm): "));
// Serial.print(get_overall_quality_factor(), DEC);
// Serial.print(F(" ("));
// Serial.print(clock_quality.phase.lock_max, DEC);
// Serial.print('-');
//  Serial.print(clock_quality.phase.noise_max, DEC);
//  Serial.print(':');
//  Serial.print(clock_quality_factor.phase, DEC);
//  Serial.print(')');
//  Serial.print('(');
//  Serial.print(clock_quality.second.lock_max, DEC);
//  Serial.print('-');
//  Serial.print(clock_quality.second.noise_max, DEC);
//  Serial.print(':');
//  Serial.print(clock_quality_factor.second, DEC);
// Serial.print(')');
//  Serial.print('(');
// Serial.print(clock_quality.minute.lock_max, DEC);
//  Serial.print('-');
//  Serial.print(clock_quality.minute.noise_max, DEC);
//   Serial.print(':');
// Serial.print(clock_quality_factor.minute, DEC);
//  Serial.print(')');
//  Serial.print('(');
//  Serial.print(clock_quality.hour.lock_max, DEC);
// Serial.print('-');
// Serial.print(clock_quality.hour.noise_max, DEC);
//  Serial.print(':');
//  Serial.print(clock_quality_factor.hour, DEC);
//  Serial.print(')');
// Serial.print('(');
// Serial.print(clock_quality.weekday.lock_max, DEC);
// Serial.print('-');
// Serial.print(clock_quality.weekday.noise_max, DEC);
// Serial.print(':');
//Serial.print(clock_quality_factor.weekday, DEC);
// Serial.print(')');
// Serial.print('(');
// Serial.print(clock_quality.day.lock_max, DEC);
// Serial.print('-');
// Serial.print(clock_quality.day.noise_max, DEC);
// Serial.print(':');
//  Serial.print(clock_quality_factor.day, DEC);
// Serial.print(')');
//  Serial.print('(');
//  Serial.print(clock_quality.month.lock_max, DEC);
//  Serial.print('-');
//  Serial.print(clock_quality.month.noise_max, DEC);
//  Serial.print(':');
//  Serial.print(clock_quality_factor.month, DEC);
//  Serial.print(')');
//  Serial.print('(');
//  Serial.print(clock_quality.year.lock_max, DEC);
//  Serial.print('-');
//  Serial.print(clock_quality.year.noise_max, DEC);
//  Serial.print(':');
//  Serial.print(clock_quality_factor.year, DEC);
//  Serial.print(')');
//  Serial.print(clock_quality.uses_summertime_quality, DEC);
//  Serial.print(',');
//  Serial.print(clock_quality.timezone_change_scheduled_quality, DEC);
//   Serial.print(',');
//  Serial.print(clock_quality.leap_second_scheduled_quality, DEC);
//  Serial.print(',');
//  Serial.println(get_prediction_match(), DEC);
//}