Home   Master Clock   LCD Master Clock    Kenley Weather

Section   Top  Video  Design  Connections   Chime  Ctrl Panel  LCD Display  Dial  Day Ctrl  Month Ctrl Tide Clock Schematic Vero Board Test Circuit Code

 

 

 

 

Arduino 12" Perpetual Calendar Clock

with full Westminster Chime

Stand alone no Master Clock required

Built in Decoder for the DCF77 "Atomic Clock"

Electro-mechanical Day, Month & Tide displays

Microprocessor calculates days per month inc leap years

Auxiliary LCD display

Westminster Chime of Quarter Hours & Hours.

 

 

 

below clock backboard with clock controls, PSU, speakers, circuit board and LCD display

 

 

 

 

 

side view

 

 

 

 

 

 

 

Video

 

 

above video shows clock at 06:00hrs on 30th June, chiming 4th quarter Westminster Chime option 2 hand bells, the hour chime and stepping to July 1st

 

 

above video shows clock at 06:00hrs on 30th June, chiming 4th quarter Westminster Chime option 1 Glockenspiel, the hour chime and stepping to July 1st

 

 

 

 

 

 

Design

The clock is designed around a 12" (300mm) English Office Dial Clock case that I picked up off Ebay with no movement.

The metal dial was stripped off, repainted and re-lettered using my own dial design

The oak dial surround was stripped back, disassembled re-glued and screwed.  It was then bleached to lighten the colour.

I fitted hinges and a catch so the dial can be opened to get access to the controls/electronics inside.

The clock has a large back box that houses the electronics (mouse over image to reveal).

                                                    

 

 

 

 

 

 

 

Connections

Arduino

    DCF77 Library by Udo Klein
IC Pin IDE Pin Sketch Name Function
1 Reset   Reset
2 0   Serial Read/Write
3 1   Serial Read/Write
4 2 long hour chime long hour chime output
5 3 half chime half chime output
6 4 three quarter chime three quarter chime output
7 NA   4.4v
8 NA   Gnd
9 NA   Xtal1
10 NA   Xtal2
11 5 dcf77_analog_sample_pin dcf77_analog_sample_pin
12 6 quarter chime  quarter chime output
13 7 quartz01 drive month clock
14 8 quartz02 drive month clock
15 9 hourchime hour chime output
16 10 full chime full Westminster chime
17 11 calmotor calendar motor output
18 12 manstepmonth5 manual step of month by 5 increments (1 month)
19 13  chimectrl  locks chime on when  power restored
20 NA   4.4v
21 NA   AREF
22 NA   Gnd
23 A0 dcf77_monitor_pin dcf77 signal monitor output
24 A1 dcf77_sample_pin dcf77 input
25 A2 manstepmonth1 manual step of month by 1 increments
26 A3 infraredSw display on/off
27 A4 SDA I2C SDA pin for LCD
28 A5 SCL I2C SCL pin for LCD

 

Adafruit FX Sound Board
Board Pin Arduino IC Pin Arduino IDE Pin Audio File Function/Connection
Vin NC NC   5 volts
Gnd NC NC   Gnd
Bus NC NC    
PB NC NC    
TX NC NC    
RX NC NC    
UG NC NC    
Vol + NC NC   Vol + Switch
Vol- NC NC   Vol + Switch
CS NC NC    
Gnd NC NC   Gnd
R NC NC   Right Speaker
L NC NC   Left Speaker
Gnd NC NC   Gnd
Rst NC NC    
0 NC NC T00.ogg Vol Test Sound Switch
1 12 6 T01.ogg quarter chime
2 5 3 T02.ogg half chime
3 6 4 T03.ogg three quarter chime
4 16 10 T04.ogg full chime
5 4 2 T05.wav long hour chime
6 15 9 T06.wav hour chime
7 NC NC    
8 NC NC    
9 NC NC    
10 NC NC    
Act NC NC    
Gnd NC NC   Gnd

 

 

 

 

 

 

 

Chimes

The clock sounds the Quarter hours and hours via an  adafruit Audio FX Sound Board + 2x2W Amp

There are 2 different chime options available for this clock

Option1

The hour chimes are recorded from a 4" longcase clock bell and the quarter chimes from a Glockenspiel.

Option 2

The hours chime is a combination of hand bells and a long case clock bell while the Qtr chime is on hand bells.

 

           

  Hour Bell sample source. Long case clock bell with 30 second clock movement to actuate the bell.

Each note has been sampled separately and then put together in Audacity to make each section of music for the chimes.

For each type there are six chime samples in total, four for each quarter and two for the hour chime.

The quarter chimes are made up in sections and give a Westminster type chime.

 

Option 1 (Glockenspiel)

There are for sections

Section 1 notes FAGC Quater Chime T01.wav

Section 2 notes CGAF Half Chime T02.wav

Section 3 notes AGFC Three Quater Chime T03.wav

Section 4 notes CGAF Full Chime T04.wav

Quarter Past the Hour plays Section1

Half Past the Hour plays Section 1 then section 2

Three Quarters past the hour plays Section 1,2 then section 3.

Full Hour plays section 1,2,3 then Section 4.

Note the full hour chime is played on 59min 49 seconds so it can play out before the hour chime starts on the hour.  Mod the code at line 843 to 49 eg    if ( minutes == 59 && seconds == 49 && chimepwr == 1) // allows full Westminster chime to sound before hour chime starts was 49 old chimes

 

The hour chime comprises of 2 samples both single chimes. The first sample lasts just under a second and then the chime is faded out at the end. Hour Short T06.wav

The second sample lasts 9 seconds and contains the full single chime as it slowly fades away. Hour Long T05.wav

In a real clock the hammer hits the bell causing it to ring. Normally it would gently fade out to nothing but if the clock strikes the bell again e.g. if it is chiming more than 1 o'clock then the bell stops fading out and rings again loudly.

To simulate this effect all but the last chime are short chimes the last 9 second chime giving the effect of the bell ringing out.

 

Option 2 (Hand bells)

There are for sections

Section 1 notes FAGC Quater Chime T01.wav

Section 2 notes CGAF Half Chime T02.wav

Section 3 notes AGFC Three Quater Chime T03.wav

Section 4 notes CGAF Full Chime T04.wav

Quarter Past the Hour plays Section1

Half Past the Hour plays Section 1 then section 2

Three Quarters past the hour plays Section 1,2 then section 3.

Full Hour plays section 1,2,3 then Section 4.

Note the full hour chime is played on 59min 47 seconds so it can play out before the hour chime starts on the hour. Mod the code at line 843 to 47 eg    if ( minutes == 59 && seconds == 47 && chimepwr == 1) // allows full Westminster chime to sound before hour chime starts was 49 old chimes

 

The hour chime comprises of 2 samples both single chimes. The first sample lasts just under a second and then the chime is faded out at the end. Hour Short T06.wav

The second sample lasts 9 seconds and contains the full single chime as it slowly fades away. Hour Long T05.wav

In a real clock the hammer hits the bell causing it to ring. Normally it would gently fade out to nothing but if the clock strikes the bell again e.g. if it is chiming more than 1 o'clock then the bell stops fading out and rings again loudly.

To simulate this effect all but the last chime are short chimes the last 9 second chime giving the effect of the bell ringing out.

There is also a test wave file that is played when the "Test Tone Button" is pressed. This allows you to set the volume without having to wait for the clock to strike. T00.wav

 

 

Hour Chime Sequence

On the hour.

1 o'clock- long chime

2 o'clock- short chime then long chime

3 o'clock- short chime, short chime then long chime

4 o'clock- short chime, short chime, short chime then long chime.

etc.

 

 

 

Audio FX Sound Board

Below Audio FX Sound Board + 2x2W Amp - WAV/OGG Trigger - 16MB

 



16MB of storage on the board itself, so you can store up to 15 minutes of quality compressed audio. Double that if you go with mono instead of stereo


Built in Mass Storage USB - Plug any micro USB cable into the Sound Board and your computer, you can drag and drop your files right on as if it were a USB key


Compressed or Uncompressed audio - Go with compressed Ogg Vorbis files for longer audio files, or uncompressed WAV files


High Quality Sound -44.1KHz 16 bit stereo. The decoding hardware can handle any bit/sample rate and mono or stereo


11 Triggers - Connect up to 11 buttons or switches, each one can trigger audio files to play


Stereo line out - There's a breakout for both left and right channels, at line level, so you can always hook up to any kind of stereo or powered speaker


Five different trigger effects - by changing the name of the files, you can create five different types of triggers which will cover a large range of projects without any programming

 

 

 

 

 

 

 

 

Control Panel

Apart from the Arduino reset switch on the main board the control panel houses the switches to control the calendar clock.

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

Control Panel
Switch Type Name Function
1 3 way locking Step Month 1 Step month hand 1 step
1 3 way locking Off Off
1 3 way locking Step Month 5 Step Month hand 5 steps or 1 month
2 1 way locking LCD Off LCD display off (LCD always on on restart)
2 1 way locking LCD On LCD display on
3 1 way non locking Chime On On power up chime is off. Press to lock chimes on
4 1 way non locking Test Tone Plays 30 second test tone so volume can be set
5 3 way center locking Vol + Turns volume up active when sample playing only
5 3 way center locking Vol - Turns volume down active when sample playing only
6 1 way locking DPDT Speaker Off Turns speaker off
6 1 way locking DPDT Speaker On Turns speaker on

 

 

 

 

 

 

 

LCD Display

The clock has a 4x20 LCD display mounted on the back board.

The display is used to monitor the DCF77 library and some basic clock functions.

A switch on the control panel is used to turn the display on and off and is normally left on only when the clock is opened.

                                                 

The display shows the following info.

Row 1

Time and date. Note the date is in the UK format dd/mm/yyyy

 

Row 2

Section 1 rotates between 3 states

1 Displays the next calculated leap year

2 The quartz tuned frequency as set by the DCF77 library

3 The quartz crystal accuracy in Hz.

Note this is not the clock accuracy but the quartz crystal accuracy should the DCF77 signal be lossed.

The DCF77 library auto tunes the Arduino quartz crystal frequency by comparing it to the DCF77 signal.

 

Section 2 time zone and summer/winter time indicator

 

Row 3

Section 1 Shows if the chimes have been disabled on power up. Chimes are disabled on power up as the sound board defaults to full volume on power restore.

I don't want to be woken up by full volume chimes in the middle of the night after a power cut.

Chimes are enabled by pressing the "Chime On" switch on the control panel. Once on they stay on until the power cut  and restored.

There is a manual " Speaker On/Off" switch on the control panel if needed.

 

Section 2 Displays the DCF77 library status "Sync'd", "Locked", "Dirty", or "Fail"

 

Row 4

Section 1 Shows Signal match as a percentage. The library predicts what the signal should be and compares it to the incoming DCF77 signal.

 

Secton 2 Displays the status of the Month Motor logic.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Dial

The Calendar Clock dial was designed and drawn up using Turbo Cad.

The final design is then printed out on A3 Lazertran inkjet paper as a giant decal.

The original dial is first rubbed down to remove all old paint and lettering. It is then primed and painted an off white colour (white looks terrible in an old clock case).

The dial decal is then applied to the blank dial and then when dry 3 coats of acrylic varnish are sprayed over the top.

This makes the decal background go clear so the off white dial can be seen with the dial lettering on top.

 

                                  

                                        above blank dial ready for mounting clock movements

                                        below blank dial designed in Turbo Cad

                                  

 

 

 

 

 

 

 

Day Movement Control

The day movement is a 30 second slave movement. These movements were fitted to clocks in offices and factories and were stepped once every 30 seconds by a master Clock.

                                   

                                                               above 30 second clock movement front

The parts and operation are as follows (mouse over image to identify)
A is the main ratchet-wheel, having 120 teeth
B the operating electromagnet
C the armature
D the armature lever
E the driving pawl, which moves the ratchet-wheel one tooth on the release of the armature
F the driving spring, which normally holds the driving pawl in engagement with the ratchet wheel, and the armature away from the electromagnet
G the back-stop lever, which prevents movement of the ratchet-wheel when the armature is attracted, as might be possible from vibration or on clocks with exposed dials - by pressure of wind on the hands
H the momentum stop, which prevents the ratchet wheel being moved more than one tooth per impulse and, with the pawl E, locks the ratchet wheel between pulses
J the stroke-limit stop, which limits the travel of the armature, and


When electromagnet B is energized by a pulse from the Master Clock, the armature C is attracted, pawl E is propelled to the right against the pressure of spring F, and drops into the next tooth on ratchet-wheel A.
When the pulse ceases, spring F drives the paw! E forward, and the ratchet-wheel rotates one tooth, equivalent to a half-minute on the dial. The ‘minute’ hand is attached to the. ratchet-wheel which also drives the ‘hour’ hand through a train of gears having a reduction ratio of 12 to 1.

Operating current
The operating current for the movement is 250 mA. The resistance of the electromagnets is between 7.5 and 10 ohms and they may be connected in circuit without reference to polarity.
 

 

                                   

                                                             above 30 second clock movement front

 

The minute hand drive is used to indicate the day of the month. This hand is directly connected to the 120 tooth wheel driven by the clock motor ratchet.

Therefore in the original clock 120 x 30 second pulses would drive the minute hand exactly 1 hour.

In the image below the 120 tooth wheel is enlarged and superimposed over the clock display to show how each tooth relates to the day of the month.

There are a maximum of 31 days in each month so 120 teeth divided by 31 gives 3.87 teeth to move the hand 1 day segment.

This clearly is not possible so the clock is designed to move the day hand 3 teeth each day. This uses a maximum of 3x31 days or 93 teeth in a month.

At the end of each month extra pulses are added to move the day hand to the 1st of the month.

As the number of days in each month varies the Arduino Microcontroller works out when each month ends and how many extra pulses are required to move the day hand to the 1st of the month.

 

                                        

above 120 tooth wheel enlarged and superimposed over the main dial

 

Table below shows how many extra pulses are required to step the day hand back to the 1st from the end of each month.

Month Days in Month Extra Pulses at End of Month
Jan 31 30
Feb 28 39
Feb* 29 36
Mar 31 30
Apr 30 33
May 31 30
Jun 30 33
Jul 31 30
Aug 31 30
Sep 30 33
Oct 31 30
Nov 30 33
Dec 31 30
* leap year    

 

This can be seen on the on the image below. To move the day hand from 1 day to the next requires 3 pulses so for example at the end of a 31 day month an extra

30 pulses are sent to stop the day hand at the 1st of the month.

                          

above 120 tooth wheel enlarged and superimposed over the main dial showing number of extra pulses at the end of each type of month

 

 

 

 

 

 

 

 

 

 

Month Indicator

                                              

The month hand is driven by a Lavet type stepping motor.

The motor is sourced from a quartz clock movement with the quartz control board cut out. The motor requires very low current to drive it and can be driven direct from the Arduino output via a trimmer resistor.

The resistor is used to adjust the current to the motor so it works without being over driven.

The motor is driven by reversing the polarity to the drive coil which causes the permanent magnet toothed rotor (in red below) to turn 180°. The toothed rotor will continue to turn in the same direction each time the drive motor polarity is reversed.   2 output pins from the Arduino are used to pulse the drive motor with 1 pin always the opposite to the other.

                                 

                                                                 above Month Hand Lavet type motor stepping. The red toothed rotor turns 180° each time the polarity of the motor coil changes.

 

The Month indicator hand is connected to the seconds cog wheel. This wheel turns once every 60 polarity changes and as there are 12 months in a year the clock motor has to be stepped 5 times (60 teeth/12months) to move the month hand 1 month on the dial.

Note the code always sends 6 pulses as the first pulse will be ignored as the polarity will not have changed. At the end of the 6 pulses both Arduino pins are set to "LOW" so no current is passed through the drive coil until the next month.

On initial setup the month hand can be controlled by 2 switches, "stepmonth 1" & "stepmonth 5". This is a single centre off locking switch.

The "stepmonth 1" switch applies single alternating pulses to the month motor once per second and is held on until the hand starts to move. If the switch is left on the month motor will continue to step until the switch is moved to the centre off position.

The "stepmonth 5" switch applies 5 alternating pulses to the moth motor once per second. To use move the switch to the on position and wait for the month hand to start moving then return to the centre off position. The month hand will then advance 1 whole month then stop.

To set the month hand first use the "stepmonth 1" switch to set the hand to a month then use the "stepmonth 5" switch to step whole months until the correct month is shown.

 

 

 

 

 

 

 

 

 

Tide Clock

                           

 

The tide clock displays the time to Low or High tide. As tide times are affected by many variables the tide clock uses an off the shelf tide clock module with just the tide hand connected.

To use find the tide times for your local seaside off the internet and just set with the adjusting wheel on the clock movement.

 

 

 

 

 

 

 

 

 

 

 

Schematic

 

 

 

 

 

 

 

 

Vero Board Layout

The components for the Arduino and the sound effects board are mounted on the vero board. This is then mounted on the backboard of the clock see blow. The board has a reverse polarity protection diode fitted

and this will drop the input voltage by a fraction of a volt. The board shows 5.6volts connect but this will need to be adjusted down so the supply is 5volts or less before the Arduino and sound boards are connected.

                                                                                      

 

 

 

 

 

 

 

 

 

Testing

As the clock is fully automatic and there is no manual setting of time and date. All testing is done by transmitting dummy radio time and date code in the DCF77 format to the clock.

Luckily Udo Klein the designer of the DCF77 library used to decode the DCF77 signal in this clock has also designed a DCF77 radio code generator for the Arduino.

                                                            

                                                                                above calendar clock testing using Udo Klein's DCF77 generator

 

To use the generator download Udo's code and program the Uno via the serial port.

Once the board is programmed connect a 1K resistor to pin 3 and a small loop of wire to the Gnd pin.

Loop the wire once around the DCF77 aerial of the device you are testing.

Load up a terminal program or just open the serial monitor from the Arduino interface.

Set the baud rate to 115200 and hit enter.

You should see the following on the serial monitor

running
output on pin D3


To set target time use one of the following formats

simple mode:
sYY.MM.DD hh:mm.ss

extended mode:
x:YY.MM.DD hh:mm.ss w sbtl

current time setup (YY.MM.DD hh:mm.ss w sbtl)
w = weekday, s = summertime, b = backup antenna, t = timzone change scheduled, l = leap second scheduled
09.01.01 00:52:03 4 8001

 

This gives you basic instruction of how to set the time and date on the Uno ready to be set as the time and date on your device.

As an example to test my calendar stepping from 30th June to the 1st July I send this command "x16.07.01 06:30:00 1 1000" to set the date and time to 1st July 2016 06:30:00. My clock is set for GMT so when it decodes it will be set to 05:30. On all months bar January on the first of the month the calendar is set to correct at 06:00hrs rather than midnight (due to noise of the clock movement).

Remember once you send the command to your DCF77 generator the clock start at the time you set so by the time your clock decodes it it will be several minutes later. This is why I set it to 05:30 not 06:00 hrs.

This give my calendar clock time to decode the signal ready to step the time and date on at 06:00hrs.

 

 

Here is another example

To trigger a leap second for GMT (for CET take an hour off)

Send

x15.01.01 00:45:00 1 0001
 

Outputs

running
output on pin D3
current time setup (YY.MM.DD hh:mm.ss w sbtl)
w = weekday, s = summertime, b = backup antenna, t = timzone change scheduled, l = leap second scheduled
15.01.01 00:45:00 1 232001


To set target time use one of the following formats

simple mode:
sYY.MM.DD hh:mm.ss

extended mode:
x:YY.MM.DD hh:mm.ss w sbtl

current time setup (YY.MM.DD hh:mm.ss w sbtl)
w = weekday, s = summertime, b = backup antenna, t = timzone change scheduled, l = leap second scheduled
15.01.01 00:45:00 1 232001

This actually set my clock (set to GMT) once decoded to 23:45 31st December 2015 plus a few minutes for decoding time.

I used this on my Master Clock to check the injected leap second was detected and passed onto my 1 second slave clocks.

 

 

Further examples

x15.01.01 00:45:00 1 0001 = 23:52:00 31/12/2015 gmt+0 triggers a leap second


x14.03.30 01:50:00 1 0010 = 00:45:00 30/03/14 gmt+0 trigger clock +1 hour


x14.10.26 02:50:00 1 1000 = 02:45:00 26/10/14 gmt+1 trigger clocks go back


x21.03.01 05:20:00 1 1000 = 21.03.01 05:20:00 1 49000 after 28 Feb no leap year trigger at 06:00hrs


x16.02.28 06:20:00 1 1000 = 05:20 28 feb 2016 a leap year step to 29


x16.03.01 06:30:00 1 1000 = 05:30 01 March 2016 leap year step from 29 to 01


x16.07.01 06:30:00 1 1000 = 05:30 01 Jul 2016 step from 30 to 01


x14.03.30 23:30:00 1 0000 = 22:30 30 Mar 2014


x14.03.30 01:30:00 1 0000 = 00:30 30 Mar 2014


x14.03.30 13:30:00 1 0000 = 12:30 30 Mar 2014

 

 

 

 

 

 

 

 

 

Code v18 for Udo Klein's v3 library

Download the code here  Note updated 07/01/17 to correct errors in end of month stepping

 

//  Chime & Calendar Clock
//  http://www.brettoliver.org.uk
//
//  Copyright 2014 Brett Oliver
//  v16 uses Udo Klein's V3 DCF77 Library
//  v18 added 1 to pulsecount to add 1 more pulse (cal was stopping 1 short each month) 
//
//  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 UTCcheck = 0;
int i = 0;
int chime_hours = 0; //see hour chime
int LCDctrl = 17; // set A3 to input ( pin 17)
int monthpulse1On = 0;
int pulsecountmth1 = 0;
int pulsecountjan = 0; //
int pulsecountmonth = 0; //
int pulsecountmthjan = 0; //
int pulsecountday = 0; //
int pulsecount30 = 0; //
int pulsecount33 = 0; //
int pulsecount39 = 0; //
int pulsecount36 = 0; //
int monthpulsecount = 0; //
int manstepmonth1 = A2; // manual step of month by 1 increment pin 12
int manstepmonth5 = 12; // manual step of month by 5 increments (1 month) pin A2
int chimectrl = 13; // chime pwr on start switch
int chimepwr = 0; // used to lock chime On
int janpulseOn = 0; // turns on pulsing in Jan 1st
int monthpulseOn = 0; // turns on pulsing on 1st if the month
int monthpulsejanOn = 0; // turns on pulsing on 1st Jan if the month
int daypulseOn = 0; // turns on pulsing in not 1st of the month
int pulseOn30 = 0; // turns on 30 step month
int pulseOn33 = 0; // turns on 33 step month
int pulseOn39 = 0; // turns on 39 step month
int pulseOn36 = 0; // turns on 36 step month
int summertest = 0; // equals 1 for summertime and 0 for wintertime
int hourchime = 9;
int longhrchime = 2; // last chime of hour chime is longer to let bell ring out
int qtrchime = 6; //Westminster
int halfchime = 3; //Westminster
int threeqtrchime = 4; //Westminster
int fullchime = 10; //Westminster

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 years = 0;
int LeapYear = 0; // will be 0 if a leap year
int LeapDisp = 0; // yes if leap year no if not
int months = 0;
int daysmonth = 0;
int Monthpulse; // number of pulses needed to step cal at end of month
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 calmotor = 11;
int monthmotor1 = HIGH;              // ledState used to set the quartz motor pin 7 initial state
int monthmotor2 = LOW;              //  ledState used to set the quartz motor pin 8 initial state
int quartz01 = 7; //  Quartz clock month motor pulse 01
int quartz02 = 8; //  Quartz clock month motor pulse 02
//********************

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(calmotor, HIGH); // turn 30 sec cal clock motor off at start
  digitalWrite(qtrchime, HIGH); // turn Qtr Westminster chime off at start
  digitalWrite(hourchime, HIGH); // turn Hour chime off at start
  digitalWrite(longhrchime, HIGH); // turn long Hour chime off at start
  digitalWrite(halfchime, HIGH); // half Westminster chime off at start
  digitalWrite(threeqtrchime, HIGH); // 3 Qtr Westminster chime off at start
  digitalWrite(fullchime, HIGH); // full Westminster chime off at start



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





  //***************
  Serial.begin(9600);
  
  pinMode(dcf77_sample_pin, INPUT);
  digitalWrite(dcf77_sample_pin, HIGH);


  //*******************
  pinMode(qtrchime, OUTPUT);
  pinMode(halfchime, OUTPUT);
  pinMode(threeqtrchime, OUTPUT);
  pinMode(fullchime, OUTPUT);
  pinMode(ledpin(dcf77_monitor_led), OUTPUT); //v3
  pinMode(hourchime, OUTPUT);
  pinMode(longhrchime, OUTPUT);
  pinMode(calmotor, OUTPUT);
  // pinMode(led1min, OUTPUT);
  // pinMode(led1hr, OUTPUT);
  // pinMode(led1day, OUTPUT);
  pinMode(quartz01, OUTPUT);
  pinMode(quartz02, OUTPUT);

  pinMode(manstepmonth1, INPUT); // manual step of month by 1 increment
  pinMode(manstepmonth5, INPUT); // manual step of month by 5 increments (1 month)
  pinMode(LCDctrl, INPUT);
  pinMode(chimectrl, INPUT); // Pin 13 chime On/Off


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

  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;

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

    signalQual = DCF77_Clock::get_prediction_match();
    if (signalQual == 255 || signalQual == 0 )
    {
      signalQual = 00;
    }
    else
    {
      signalQual = (signalQual * 2) - 1;
    }
   


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



    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

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

    // detect  next leap year

    LeapYear = years % 4; // eg modulo of year/4. Will be 0 if a leap year

    if ( LeapYear == 0 )
    {
      LeapDisp = years;
    }
    else
    {
      LeapDisp = years + 4 - LeapYear; // Leapyear = 0 leap year, 1 leap year + 1, 2 leap year + 2 or 3 leap year + 3,
    }
   

    //*************************************************
    
   // LCD Disp Signal Quality
  signalmatch();
  
  // End LCD Disp Signal Quality 
    
    // Check Month Pulse 1 and 5 sw status on LCD
    
   lcd.setCursor(15, 3);
   lcd.print("M");
   lcd.setCursor(16, 3);
   lcd.print(monthmotor1);
   
   lcd.setCursor(17, 3);
  lcd.print(" M");
  lcd.setCursor(19, 3);
  lcd.print(monthmotor2);
    
   

    // detect trigger for calendar change
    // Note when calendar steps @ 06:00 hrs the month is the month after eg month +1 so March is stepped on 1st April @ 06:00hrs
    //----------------------------------------------------------------
    // New years Day
    if (months == 1 && days == 1 && hours == 0 && minutes == 0 && seconds == 0 || janpulseOn == 1 ) // New year day step calendar at midnight
    {
      janpulseOn = 1;


      // Serial.println ("Pulse Test Jan ");

      if (pulsecountjan < 30 && janpulseOn == 1)
      {
        janpulseOn = 1;
        pulsecountjan = pulsecountjan + 1;

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

      else
      {
        janpulseOn = 0;

        pulsecountjan = 0;
      }


    }


    //---------------------------------------------------
    // Every day bar 1st month and new years day
    else if ((months > 1 && days > 1 && hours == 6 && minutes == 0 && seconds == 0 || daypulseOn == 1) || (months == 1 && days > 1 && hours == 6 && minutes == 0 && seconds == 0 || daypulseOn == 1))
      // Every day bar Jan and bar 1st month at 6am or Every day in Jan apart from Jan 1st at 6am
    {
      daypulseOn = 1;


      // Serial.println ("Pulse Test day ");

      if (pulsecountday < 3 && daypulseOn == 1)
      {
        daypulseOn = 1;
        pulsecountday = pulsecountday + 1;

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

      else
      {
        daypulseOn = 0;
        pulsecountday = 0;
      }


    }


    //----------------------------------------------------



    //####################################################################################################################################################################################
    // 1st Month not new years day (month is month before the actual month eg for Jan to Feb step clock  06:00 am Feb 01)
    if (months > 1 && days == 1 && hours == 6 && minutes == 0 && seconds == 0 || pulseOn30 == 1 || pulseOn33 == 1 || pulseOn39 == 1 || pulseOn36 == 1) // Every 1st day of the month bar Jan
    {

      // detect days in each month & pulses to add 

      if (months == 2 || months == 4 || months == 6 || months == 8 || months == 9 || months == 11 || pulseOn30 == 1 )  // 31 days to step from previous month
      {
        // Monthpulse = 30;
        //  daysmonth = 31;
        //*******************************
        {
          pulseOn30 = 1;


          

          if (pulsecount30 < 30 && pulseOn30 == 1)
          {
            pulseOn30 = 1;
            pulsecount30 = pulsecount30 + 1;

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

          else
          {
            pulseOn30 = 0;
            pulsecount30 = 0;
          }
          //*******************************
        }
      }
      else if ( months == 5 || months == 7 || months == 10 || months == 12 || pulseOn33 == 1 )  // 30 days to step from previous month
      {

        //*******************************
        pulseOn33 = 1;


        

        if (pulsecount33 < 33 && pulseOn33 == 1)
        {
          pulseOn33 = 1;
          pulsecount33 = pulsecount33 + 1;

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

        else
        {
          pulseOn33 = 0;
          pulsecount33 = 0;
        }
        //*******************************
      }

      else if ((months == 3 && LeapYear != 0) || pulseOn39 == 1 )  // 28 days Feb non leap year
      {
        
        //*******************************
        pulseOn39 = 1;


        

        if (pulsecount39 < 39 && pulseOn39 == 1)
        {
          pulseOn39 = 1;
          pulsecount39 = pulsecount39 + 1;

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

        else
        {
          pulseOn39 = 0;
          pulsecount39 = 0;
        }
        //*******************************
      }

      else if ((months == 3 && LeapYear == 0) || pulseOn36 == 1 )  // 29 days Feb leap year
      {
       
        //*******************************
        pulseOn36 = 1;


        
        if (pulsecount36 < 36 && pulseOn36 == 1)
        {
          pulseOn36 = 1;
          pulsecount36 = pulsecount36 + 1;

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

        else
        {
          pulseOn36 = 0;
          pulsecount36 = 0;
        }
        //*******************************
      }


      //  end detect days in each month & pulses to add


    }
    //#####################################################################################################################################################################
    // Month pulses and manual step 1 whole month (5 steps)
    // New years Day
    manstepmonth5 = digitalRead(12);
    manstepmonth1 = digitalRead(A2);
    


    if ( months == 1 && days == 1 && hours == 0 && minutes == 0 && seconds == 35 || monthpulsejanOn == 1 || manstepmonth5 == 1 ) // New year day step month at midnight
      //  if ( months == 6 && seconds == 35 && days == 13 && hours == 6 || monthpulsejanOn == 1 || manstepmonth5 == 1 ) // test
    {
     

      if (pulsecountmthjan < 6  || manstepmonth5 == 1)// sets number of steps for quartz month motor
      {
        monthpulsejanOn = 1;
        pulsecountmthjan = pulsecountmthjan + 1;

        //#################
        // step month quartz motor
       quartzstep();

        //#################
      }
      else 
      {
      monthpulsejanOn = 0;
      }
    }  
    //***************************************
   else if ( months > 1 && days == 1 && hours == 6 && minutes == 1 && seconds == 0 || monthpulseOn == 1 ) // every 1st month bar Jan step at 06:01 am
      
    {
    

      if (monthpulsecount < 6 )// sets number of steps for quartz month motor
      {
        monthpulseOn = 1;
        monthpulsecount = monthpulsecount + 1;
        //#################
          // step month quartz motor
       quartzstep();


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

      }
      else 
      {
      monthpulseOn = 0;
      }
      }

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

    // Month Manual step 1 second segment
  
  
   else if (manstepmonth1 == 1)
    {
    
       

        //#################
         // step month quartz motor
       quartzstep();


        //#################
      }

      else
      {
        monthpulseOn = 0;
        monthpulsecount = 1;
        monthpulsejanOn = 0;
        pulsecountmthjan = 1;
        // both quartz motor pins set low so no current flows until the 1st of the next month
        digitalWrite(quartz01, LOW); // set the quartz motor drive 7 pin LOW
        digitalWrite(quartz02, LOW); // set the quartz motor drive 8 pin LOW
      //}
    }


    // End Month Manual step 1 second segment
    //########################
  
    //------------------------------------------------------
    // end detect trigger for calendar change


    // start LCD on/off #######################################
    int LCDctrl = digitalRead(17); // reads LCD on off switch



    if (LCDctrl == 1) // turns display on if LCD control sw is on

    {

      lcd.backlight(); // LCD backlight on
      lcd.display(); //LCD display on

    }

    else if (LCDctrl == 0) // turns LCD display on if LCD control sw is on

    {

      lcd.noBacklight(); // LCD backlight off
      lcd.noDisplay(); //LCD display off

    }
    // LCD on off #######################################


    Serial.print ("Time ");
    Serial.print (hours2);

    Serial.print (hours1);
    Serial.print (":");


    Serial.print (minutes2);

    Serial.print (minutes1);
    Serial.print (":");


    Serial.print (seconds2);

    Serial.print (seconds1);
    Serial.println (" ");






    


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

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








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



    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, 1);
    lcd.print("GMT+");
    UTCcheck = offset_to_utc;

    lcd.print(summertest);
    //**************




  }
  chimectrl = digitalRead(13);// chimes are off on power up press "chime On" switch to lock on
  if (chimectrl == 1 || chimepwr == 1)
  {
    chimepwr = 1;
    lcd.setCursor(0, 2);
    lcd.print("Chime On ");
  }
  else if (chimectrl == 0 && chimepwr == 0)
  {
    lcd.setCursor(0, 2);
    lcd.print("Chime Off ");
  }

  // Quater chime
  if (minutes == 15 && seconds == 0 && chimepwr == 1  )
  {
    digitalWrite(qtrchime, LOW);
    // Serial.println("Qtr Westminster Chime");

  }

  else digitalWrite(qtrchime, HIGH);
  // End quater chime
  // ########################




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

  // Half chime
  if (minutes == 30 && seconds == 0 && chimepwr == 1)
  {
    digitalWrite(halfchime, LOW);
    //  Serial.println("Half Westminster Chime");

  }
  else digitalWrite(halfchime, HIGH);
  // End half chime
  // ########################


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

  // 3 Qtr chime
  if (minutes == 45 && seconds == 0 && chimepwr == 1)
  {
    digitalWrite(threeqtrchime, LOW);
    //  Serial.println("Three Qtr Westminster Chime");

  }
  else digitalWrite(threeqtrchime, HIGH);
  // End 3 Qtr chime
  // ########################


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

  // Full Westminster chime
  if ( minutes == 59  && seconds == 47 && chimepwr == 1) // allows full Westminster chime to sound before hour chime starts was 49 old chimes
  {
    digitalWrite(fullchime, LOW);
    // Serial.println("Full Westminster Chime");

  }

  else digitalWrite(fullchime, HIGH);
  // End Full Westminster chime
  // ########################


  // Hour chime
  // map hours to range 1-12
  const uint8_t normalized_hours = hours > 12 ? hours - 12 : hours > 0 ? hours : 12;
  chime_hours = normalized_hours - 1; // chime hours is 1 less than the number of hours to enable last chime to be full length
  // compute chime instead of matching it

  if (chimepwr == 1 && chime_hours > 0 && minutes == 0 && (seconds & 1) == 0 && seconds < 2 * chime_hours)
    // chimes short hour chime every other second hours-1 times. Will not chime if hours =1
  {
    digitalWrite(hourchime, LOW);
    //Serial.println("Short Chime");
  }
  else 
  {
  digitalWrite(hourchime, HIGH);
  }

 
  if (chimepwr == 1 && minutes == 0 && seconds == 2 * chime_hours)
    // chimes long hour chime for last hour chime only but not at 1 oclock
  {
    digitalWrite(longhrchime, LOW);
    //Serial.println("Long Chime");
  }
  else 
  {
  digitalWrite(longhrchime, HIGH);
  }

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

  // 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
  //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$


}

void blankrow3() {
  lcd.setCursor(0, 1);
  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 ");
  sigMatch(signalQual); // adds leading zero to signal qual
  lcd.print("%");
}


void sigMatch(int signalQual){

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


void precision() {
  lcd.setCursor(0, 1);
  lcd.print("Accuracy ");
  lcd.print(DCF77_Frequency_Control::get_confirmed_precision());
  lcd.print("Hz ");
}
/*
void freqadj() {
  lcd.setCursor(0, 1);
  // lcd.print("Qtz ");
  lcd.print(16000000L - DCF77_1_Khz_Generator::read_adjustment());
  lcd.print("Hz");
}

*/
void quartzstep() {
 // step month quartz motor
        if (monthmotor1 == LOW)
        {
          monthmotor1 = HIGH;
        }
        else
          monthmotor1 = LOW;
        {
          digitalWrite(quartz01, monthmotor1); // set the quartz motor drive 7 pin
        }

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