Master Clock MK2   Master Clock   Atomic Time Synchronisation Circuit         Voltmeter Clock     Slave Clocks    LCD Master Clock

Pulse controlled Slave Calendar and Tide clock

 12" Slave Calendar & Tide Clock P1000576

 

 

 

The clock displays the Month day and tide using 3 analogue dials.

The day hand is driven by a 30 sec slave clock motor and the month and tide hands by standard 1 second quartz motors.

The tide clock is pulsed from the Master Clocks 1 second alternating pulse output while the Month and days are controlled by a PIC microprocessor on receipt of the 24 hour midnight pulse also from the Master Clock.

 

The PIC microprocessor calculates how many days in the current month including leap years and will automatically step the day and month hand to the next month at midnight on the last day of that month.

 

Pulse controlled Slave Calendar and Tide clock

12" Slave Calendar & Tide Clock calendar01

 

 

 

 

Download full documentation as word file

Download full documentation as a pdf

Split screen demo showing the calendar clock stepping from 29th Feb (leap year) to 01 March. The lower screen is the PC display showing the com port data as the calendar steps.

The calendar is setup using the same connection.

 

 

 

 

Calendar Clock connected to a Laptop 

Calendar Slave Serial Connection P1000621-03

The date in the calendar microprocessor can be set on power up or via the serial port. The date is stored on the microprocessor in case of power failure. As long as power is restored just before midnight the calendar will still work.

 

The dial is held in place by a brass catch and folds back giving access to the control switches and serial port socket.

 

The microprocessor used in this calendar clock is a PIC18F1320. The serial interface is provided by a MAX232 IC.

 

 

P1000619-02

Case open to show circut board and controls 

 

 
 

 

Flow Chart for the 18F1320 microprocessor code

Calendar clock code

 

 

Calendar Clock Controls & Serial Port

 

The Calendar has manual controls for date and month setting via a row of switches behind the hinged dial.

 

The Calendar clock is setup and monitored via the serial port of a PC and has a 9pin socket also mounted behind the dial.

 

 

Output from Calendar Clock Serial Port

Calendar Setting with Nexus 7 running Slick USB app

  12" Electromechanical Calendar Clock

 

 

Calendar dial showing number of pulses required to step month and day hands

The month display uses the seconds hand of a standard quartz movement. This will do 1 revolution per 60 pulses from the clock driver.

To get the display to stop on each month the clock driver will need to send out 5 alternate polarity pulses (60/12=5) at midnight on the last day of the month.

 

The day display uses a 30 sec clock movement and uses the minute hand to show days.

Each revolution of the min hand requires 120 pulses. Each month has a max of 31 days so each day mark requires 3 pulses to step the the next day.

In total this would be 93 pulses for a 31 day month, 90 pulses for a 30 day month, 87 pulses for a 29 day month and 84 pulses for a 28 day month.

Therefore in order to get back to day 1 at the beginning of a month a variable number of pulses depending on the last day of the month will need to be sent at midnight on the last day of the month.

The pic chip algorithms take into account each different month including leap years.

 

below. 3 pulses to step the day hand forward to the next day and 5 pulses to step the month hand to the next month.

At the end of each month the number of pulses required will depend on the month and year and will be from 30 to 39.

 

 

. Example of the serial output  from the calendar clock on a laptop connected to the clock serial port.

In this example the calendar was set to 28/02 in the 4th year of a leap year.

On receipt of the 24 hour midnight pulse the calendar is pulsed 33 times from the 29 position on the dial to set the hands to the first day of March.

 

 

Setup & Operation

Ensure all switches are in their normal positions see fig 7 below and a programmed PIC is in place.

Power up your PC and run a terminal program like Putty. Configure the serial connection. See diagram below (Putty) .

Plug in the serial or USB to serial lead into your computer.

Plug the other end of the lead into the Calendar Clock serial port behind the dial.

To check the stored settings press and release the “PIC Date Check” button. If the connection is OK the PIC should send the settings over the serial port to your PC screen and should be as follows.

 “Month toggle x” where x is 0 or 1.

  “D=xx:yy:zz” where xx is the day, yy is the month, and zz is the leap year number from 1 to 4

On first setting up the calendar the month movement  must be setup in sync with the pulses from the PIC. The month movement requires an alternating pulse to step it on so if the correct polarity pulse is not received it will step the month 4 times instead of the 5 required each month.

To sync the month movement set the calendar to the last day of any month as follows.

 

Put on caps lock and type the following.

D31:01:01:00 and “Enter” this sets the date to the 31st Jan, 1st year of a leap year with toggle 0.

The screen should show the date set “Echo Date=31:01:01:00”

 

Move the “PIC Date” switch to the “Step” position and wait for the day hand to start stepping before returning to the “Auto” position.

The PC screen should show 3 pulses as the hand is driven to the next day. Note it does not matter for now where the hands are set.

 

 

As the end of Jan is set the screen will now show “31 day month” and show the extra 30 pulses counting up from 1.

After pulse 30 the month pulses start and the display shows Mth1, Mth2 etc as the month pulse are sent followed by “Month toggle 0” and then “Month toggle now 1”.

Make sure the month hand moves on the first pulse and steps 5 times to move 1 full month segment.

 

If the month hand does not move 5 times when the date is resent to the PIC you must use toggle 0, if it moves OK you must send toggle 1 to the pic.

 

Before setting the final date set the month hand to the correct month by setting the Month Ctrl switch to “Man” and operate the “Step Month” button up and down to the two “step” position repeatedly. When the correct month is indicated return the “Month Ctrl” switch to “Auto”

Now set the day hand to the correct date using the armature or by spinning the drive cog.

The final working date can now be sent to the PIC using the format

“Dday:month:leap year:toggle”

Eg for 20th September in a leap year with toggle at 0 ie the above test failed enter

“D20:09:04:00”

Or if the above test worked and the month stepped correctly type.

“D20:09:04:01”

 

When complete the screen should confirm the correct date has been sent.

Pressing the “PIC Date check” button will confirm the correct date has been stored.

 

Shut down the terminal program and disconnect the serial cable from the calendar clock, close the calendar clock and lock the dial into place.

 

When inserting a new PIC turn the power off using the “PIC PWR” button then set up the new PIC as above.

 

Note when setting the Master clock forward past midnight (when clocks go back) switch the “Pic Date” switch to off. This prevents the Calendar clock stepping as the Master steps past midnight.

 

 

 

Shematic

 

Veroboard layout

 

Circuit Operation Tide Clock

 

The Tide movement is a standard quartz type tide clock and is driven from the 2 sec quartz driving pulse from the master via a repeater circuit.

The repeater circuit uses 4 Nand Schmitt triggers to repeat the alternating pulse from the master. Each pair can drive 3 movements but 1 pair is used to drive the Tide movement only. The other pair is spare and not used.

 

 

 

 

Circuit Operation 18F1320

The 18F1320 is configured as follows. PORTA are inputs and PORTB are outputs.

PORTA.4 is the midnight pulse input, PORTA.5 if held at 1 enables divide by 2 not used in this circuit. PORTA.6 if held at 1 enables the divide by 30 input also not used in this circuit. PORTA.7 if held at 0 by the reset switch SW3 loads stored date data from the EEPROM. If held at 1 on power up loads date data from the software upload .                         

 

PORTB.5 is the output for the day hand and drives Q3 then Q1. PORTB.0 & PORTB.3 drive the month hand and are always inverted with respect to each other when the month hand is being driven. When not being driven they are both set to 0 to ensure no current passes through the month coil. The month is driven via SW2 Mth Ctrl set to Auto (Step Mth set to off).

To manual step the Month SW2 is set to Man and the Mth Switch SW1 is operated alternately to the Step positions.

 

The PIC Date Switch SW5 is used to control Auto & Manual date stepping of the PIC and also to turn off receiving midnight pulses when for example setting the master for winter time.

 

 

 

Circuit Operation Max232

A MAX232 IC is used as an RS232 driver & receiver. Only 1 half of this IC is used. Connection to the RS232 I/P & O/P is via a standard 9 Pin connector.

 

 

Vero layout with Max232 highlighted .

 

 

Max232cpe  pin outs

 

 

 

The PIC code

Note The pic code and circuit for this calendar clock was supplied to me by members of the Electro Tech Online Forum and they have kindly given me permission to post it online.

Where I have added extra code or added more notes, I have added a note in the comments field thus " 'Brett " .

The Calendar Clock uses a PIC microprocessor IC to step the days and month movements the correct amount. This circuit uses a 18F1320 PIC chip and the code is written in OshonSoft basic and then compiled and loaded into the PIC.

Code

Define CONFIG1L = 0x00

Define CONFIG1H = 0xc8  '11001000 int RC osc RA6/7 ports

Define CONFIG2L = 0x0c  '00001100

Define CONFIG2H = 0x1e  '00011110

Define CONFIG3L = 0x00

Define CONFIG3H = 0x00  '00000000

Define CONFIG4L = 0x81  '10000001

Define CONFIG4H = 0x00

Define CONFIG5L = 0x03  '00000011

Define CONFIG5H = 0xc0  '11000000

Define CONFIG6L = 0x03  '00000011

Define CONFIG6H = 0xe0  '11100000

Define CONFIG7L = 0x03  '00000011

Define CONFIG7H = 0x40  '01000000

 

 

 

'*********  18FPulsar V1 ******************

 

'PulsarVer3 Date Wheel Driver for Mark Basic #1

'29/11/2007  Using 16F628A converted to 18F1320  30/09/2009

'1st off Oshonsoft Version for Brett  31/08/2009

'****************************************************

'the Date input from the PC is at 9600baud, no parity, 1 start/stop bit [normal usage]

'the pic expects Ddd:mm:yy:tt  format,, if a number is less than 10 add a leading zero

'eg:  D07:02:09:01 Brett the last 2 digits are the month toggle

'when the Date is received OK by the PIC, it retransmits it back on the uart.

 

'the uart outputs at midnight, the new date also the extra pulse markers.

 

 

Define CLOCK_FREQUENCY = 4

 

AllDigital

 

'Define SIMULATION_WAITMS_VALUE = 1  'make=0 before prog a PIC ****************

'Define SEROUT_DELAYUS = 1000

 

Dim ascbfr0 As Byte

Dim ascbfr1 As Byte

Dim ascbfr2 As Byte

Dim ascbfr3 As Byte

Dim ascbfr4 As Byte

Dim ascbfr5 As Byte

Dim ascbfr6 As Byte

Dim ascbfr7 As Byte

Dim ascbfr8 As Byte  'Brett

Dim ascbfr9 As Byte  'Brett

Dim ascbfr10 As Byte 'Brett

 

Dim day_end_cntr As Byte

Dim month_cntr As Byte  'months count on T0CK inputs [days inp]

Dim year_cntr As Byte  'years count

Dim roll_over_cnt As Byte

Dim leap As Byte

Dim pulse As Byte

Dim sec_cntr As Byte

Dim temp1 As Byte

Dim temp2 As Byte

Dim month As Byte  'Brett

''

Dim aschigh As Byte

Dim asclow As Byte

Dim b2a_value As Byte

Dim units As Byte

Dim tens As Byte

 

 

OSCCON = %01100000

 

TRISA = 0xf0  'PORTA high pins 1nputs, low 4 are outputs

TRISB = 0  'makes all PORTB pins 0utputs

 

''''''''''''''''''  timer0 changes for 1320

T0CON.T08BIT = 1

T0CON.TMR0ON = 1

T0CON.T0CS = 1

T0CON.T0SE = 0

T0CON.PSA = 1

T0CON.T0PS2 = 0

T0CON.T0PS1 = 0

T0CON.T0PS0 = 0

 

TMR0L = 255  'this is the number day inputs To make the t0 timer overflow

INTCON.TMR0IE = 1  'enables the T0 timer to Interrupt, when timer overflows

 

RCON.IPEN = 0

 

Hseropen 9600  ''enable uart serial output at 9600 baud

 

If PORTA.5 = 1 Then

Goto div2

Endif

 

If PORTA.6 = 1 Then

Goto div30

Endif

 

If PORTA.7 = 0 Then  'Reset button NOT pressed

'recall values from EEPROM if RA7, pin16 is LOW

Read 0, day_end_cntr

Read 1, month_cntr

Read 2, year_cntr

Read 3, month

Goto skip_init

Endif

 

'if RA7 pin16 is HIGH at power up read these values

'reinitialise all counters to these settings

'Mark you can change these values, save testing waiting!

'put them back to current TODAY's values when you have done testing

'when you program a PIC these are the values it will save and use.

 

'TODAY is 31/08/09.... 27day, 11mon[30days in month].. 1st year of a 4 year cycle

'Brett set month to 0 for month movement

init_loop:

day_end_cntr = 27

month_cntr = 09

year_cntr = 1

month = 0  'Brett

 

'save values to EEPROM

Write 0, day_end_cntr

Write 1, month_cntr

Write 2, year_cntr

Write 3, month  'Brett

 

skip_init:

'serial output header at power up

b2a_value = day_end_cntr

Gosub byte2asc2

Hserout "Init Date=", aschigh, asclow, ":"

b2a_value = month_cntr

Gosub byte2asc2

Hserout aschigh, asclow, ":"

temp1 = year_cntr Or 0x30

Hserout temp1, CrLf

WaitMs 500

If PORTA.7 = 1 Then

Goto init_loop

Endif

 

INTCON.TMR0IE = 1  'enables the T0 timer to Interrupt, when timer overflows

Enable High  'this enables the Interrrupts

 

'==============================================================================

 

'just keep looping until a day input pulse causes an Interrupt

loop:

 

If PIR1.RCIF = 0 Then

Goto skip1

Endif

 

Hserin temp1

 

If temp1 = "D" Then 'Brett note keyboard input

Goto rx_date

Else

Goto skip1

Endif

 

rx_date:

 

Hserin ascbfr0 ' Brett note defines 10 keys in order

Hserin ascbfr1

Hserin ascbfr2

Hserin ascbfr3

Hserin ascbfr4

Hserin ascbfr5

Hserin ascbfr6

Hserin ascbfr7

Hserin ascbfr8  'Brett

Hserin ascbfr9  'Brett

Hserin ascbfr10  'Brett

 

''

Hserout CrLf

temp1 = ascbfr0

temp1 = temp1 And 0x0f

temp2 = ShiftLeft(temp1, 4)

 

temp1 = ascbfr1

temp1 = temp1 And 0x0f

temp1 = temp1 Or temp2

Gosub bcd2bin

If temp1 = 0 Then

temp1 = 1

Endif

Write 0x0, temp1

day_end_cntr = temp1

''''''''''''''''''''''''''''''''''''

temp1 = ascbfr3

temp1 = temp1 And 0x0f

temp2 = ShiftLeft(temp1, 4)

temp1 = ascbfr4

temp1 = temp1 And 0x0f

temp1 = temp1 Or temp2

Gosub bcd2bin

If temp1 = 0 Then

temp1 = 1

Endif

Write 0x1, temp1

month_cntr = temp1

''''''''''''''''''''''''''''''''''''

temp1 = ascbfr6

temp1 = temp1 And 0x0f

temp2 = ShiftLeft(temp1, 4)

temp1 = ascbfr7

temp1 = temp1 And 0x0f

temp1 = temp1 Or temp2

Gosub bcd2bin

temp1 = temp1 Mod 4

 

If temp1 = 0 Then

temp1 = 4

Endif

 

Write 0x2, temp1

year_cntr = temp1

''''''''''''''''''''''''''''''''''''

'Brett

temp1 = ascbfr9

temp1 = temp1 And 0x0f

temp2 = ShiftLeft(temp1, 4)

temp1 = ascbfr10

temp1 = temp1 And 0x0f

temp1 = temp1 Or temp2

Gosub bcd2bin

temp1 = temp1  'Mod 4

 

Write 0x3, temp1

month = temp1

'end Brett

''''''''''''''''''''''''''''''''''''

Hserout CrLf

Hserout "Echo Date="

Hserout ascbfr0, ascbfr1, ascbfr2

Hserout ascbfr3, ascbfr4, ascbfr5

Hserout ascbfr6, ascbfr7, ascbfr8, ascbfr9, ascbfr10, CrLf   'Brett ascbfr9, ascbfr10

 

 

temp1 = 0

temp2 = 0

 

skip1:

Enable High

'========================================

 

If PORTA.7 = 1 Then

Disable Low

 

'serial output current dates if use presses button, after power up.

Hserout CrLf   'Brett

Hserout "Month toggle " #month   'Brett

Hserout CrLf

b2a_value = day_end_cntr

Gosub byte2asc2

Hserout "Date Check=", aschigh, asclow, ":"

 

 

b2a_value = month_cntr

Gosub byte2asc2

Hserout aschigh, asclow, ":"

temp1 = year_cntr Or 0x30

Hserout temp1, " of 4" CrLf

Endif

 

If PORTA.7 = 1 Then

WaitMs 500

Goto loop

Endif

 

Enable High

Goto loop

 

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'divide by 30, from 1sec input,to give a pulse every 30sec

div30:

INTCON.TMR0IE = 1 'enables the T0 timer to Interrupt, when timer overflows

TMR0L = 255

 

div30a:

If PORTA.7 = 1 Then

sec_cntr = 0

Endif

If PORTA.7 = 1 Then

Goto div30a

Endif

Enable Low  'this enables the Interrrupts

 

div_loop:

Goto div30a

 

''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'divide by 2, from 1sec input,crystal clock drive

div2:

 

INTCON.TMR0IE = 1  'enables the T0 timer to Interrupt, when timer overflows

TMR0L = 255

 

div2a:

If PORTA.7 = 1 Then

sec_cntr = 0

Endif

 

If PORTA.7 = 1 Then

Goto div2a

Endif

Enable Low  'this enables the Interrrupts

 

div2_loop:

Goto div2a

 

End  'sub routines MUST go after this END 

      

'convert hex to decimal [99max]

byte2asc2:

 

temp1 = b2a_value Mod 10

asclow = temp1 Or 0x30

temp2 = 0

While b2a_value > 9

b2a_value = b2a_value - 10

temp2 = temp2 + 1

Wend

aschigh = temp2 Or 0x30

 

Return                                           

 

 

'convt rtc packed bcd to a bin number for inc/dec usage

bcd2bin:

units = temp1 And 0x0f

tens = temp1 And 0xf0

tens = ShiftRight(tens, 4)

tens = tens * 10

temp1 = tens + units

Return                                            

 

'***************************************************************************

 

'any interrupts MUST go at the END

On High Interrupt  'occurs at midnight every night

 

Save System

 

 

INTCON.TMR0IF = 0  'clears the Interrupt flag, set by T0 timer day count

INTCON.TMR0IE = 0  'disables the T0 timer to Interrupt

 

If PORTA.5 = 1 Then

Goto int2

Endif

 

If PORTA.6 = 1 Then

Goto int30

Endif

 

'always send 1 pulse at midnight

 

'************ Brett pulse 3 times at midnight

WaitMs 1000 'waits for 30sec slaves to pulse

For pulse = 1 To 3

PORTB.5 = 1 'set PORTB.5 high, PULSE OUT

WaitMs 400  'a  50mSec, this will be [waitms 400]

PORTB.5 = 0  'sets PORTB.5 low,  this simulates the pulse to the Slave

WaitMs 400

Hserout " " #pulse

Next pulse

Hserout CrLf

 

 

day_end_cntr = day_end_cntr + 1  'inc day counter

 

If day_end_cntr > 33 Then  ''''''''''

day_end_cntr = 1

Endif

 

'table of months +1 day , NOTE: a '0' in position '0'.

roll_over_cnt = LookUp(0, 32, 29, 32, 31, 32, 31, 32, 32, 31, 32, 31, 32), month_cntr

 

 

If year_cntr = 4 And roll_over_cnt = 29 Then

roll_over_cnt = 30

Endif

 

 

If day_end_cntr = roll_over_cnt Then 'compare day count with number of days in month+1

 

'do action for month length

Select Case roll_over_cnt

 

Case 29, 30  'do this if its a 28 day month [feb]

leap = 36  'Brett steps to 1 from 28

Hserout "28 day month "   'Brett

Hserout CrLf

If year_cntr = 4 Then

leap = 33  'Brett steps to 1 from 29

Hserout "Leap year so 29 day month "  'Brett

Hserout CrLf

Endif

 

For pulse = 1 To leap

PORTB.5 = 1  'set PORTB.5 high, PULSE OUT

WaitMs 400  'a  50mSec, this will be [waitms 400]

PORTB.5 = 0  'sets PORTB.5 low,  this simulates the pulse to the Slave

WaitMs 400

'for serial output

Hserout " " #pulse   'Brett

Next pulse

Hserout CrLf

 

 

'************Brett start of 5 pulse month stepping

If month > 1 Then

month = 1

Endif

If month = 0 Then  'Alternates polarity of start pulse for quartz movement

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000  'delay, this will be [waitms 400]

Hserout " Mth1"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth2"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth3"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth4"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth5"

Hserout CrLf

Endif

 

If month = 1 Then  'Alternates polarity of start pulse for quartz movement

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000  'delay, this will be [waitms 400]

Hserout " Mth1"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth2"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth3"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth4"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth5"

Hserout CrLf

Endif

 

PORTB.0 = 0  'sets PORTB.0 low 'Brett turns off power to quartz motor until next month

PORTB.3 = 0  'setsPORTB.3 low

 

Hserout "Month toggle " #month

Hserout CrLf

 

If month = 0 Then  'Toggles month from 0 to 1 or 1 to 0

month = 1

Else

month = 0

Endif

Hserout " Month toggle now " #month

Hserout CrLf

 

month_cntr = month_cntr + 1  'inc monthr counter

day_end_cntr = 1  'reset day counter to zero

b2a_value = day_end_cntr

Gosub byte2asc2

 

Case 31  'do this if its a 30 day month?

Hserout "30 day month "

Hserout CrLf

For pulse = 1 To 30  'Brett steps to 1 from 30

PORTB.5 = 1  'setsPORTB.5 high, PULSE OUT

WaitMs 400  'delay, this will be [waitms 400]

PORTB.5 = 0  'sets PORTB.5 low,  this simulates the pulse to the Slave

WaitMs 400

'for serial output

Hserout " " #pulse

Next pulse

Hserout CrLf

 

'************Brett start of 5 pulse month stepping

If month > 1 Then 

month = 1

Endif

If month = 0 Then  'Alternates polarity of start pulse for quartz movement

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000  'delay, this will be [waitms 400]

Hserout " Mth1"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth2"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth3"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth4"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth5"

Hserout CrLf

Endif

 

If month = 1 Then  'Alternates polarity of start pulse for quartz movement

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000  'delay, this will be [waitms 400]

Hserout " Mth1"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth2"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth3"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth4"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth5"

Hserout CrLf

Endif

 

PORTB.0 = 0  'sets PORTB.0 low 'Brett turns off power to quartz motor until next month

PORTB.3 = 0  'setsPORTB.3 low

 

Hserout "Month toggle " #month

Hserout CrLf

 

If month = 0 Then  'Toggles month from 0 to 1 or 1 to 0

month = 1

Else

month = 0

Endif

Hserout " Month toggle now " #month

Hserout CrLf

 

month_cntr = month_cntr + 1  'inc monthr counter

day_end_cntr = 1  'reset day counter to zero

b2a_value = day_end_cntr

Gosub byte2asc2

'Hserout "d=", aschigh, asclow, ":"  'serial out

 

Case 32  'do this if its a 31 day month?

Hserout "31 day month "

Hserout CrLf

For pulse = 1 To 27  '27 'Brett steps to 1 from 31

PORTB.5 = 1  'setsPORTB.5 high, PULSE OUT

WaitMs 400  'delay, this will be [waitms 400]

PORTB.5 = 0  'sets PORTB.5 low,  this simulates the pulse to the Slave

WaitMs 400

'for serial output

Hserout " " #pulse

Next pulse

Hserout CrLf

 

 

'************Brett start of 5 pulse month stepping

If month > 1 Then 

month = 1

Endif

If month = 0 Then  'Alternates polarity of start pulse for quartz movement

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000  'delay, this will be [waitms 400]

Hserout " Mth1"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth2"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth3"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth4"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth5"

Hserout CrLf

Endif

 

If month = 1 Then  'Alternates polarity of start pulse for quartz movement

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000  'delay, this will be [waitms 400]

Hserout " Mth1"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth2"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth3"

Hserout CrLf

PORTB.0 = 1  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 0  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth4"

Hserout CrLf

PORTB.0 = 0  'setsPORTB.0 high, PULSE OUT for quartz motor

PORTB.3 = 1  'setsPORTB.3 low, PULSE OUT for quartz motor

WaitMs 1000

Hserout " Mth5"

Hserout CrLf

Endif

 

PORTB.0 = 0  'sets PORTB.0 low 'Brett turns off power to quartz motor until next month

PORTB.3 = 0  'setsPORTB.3 low

 

Hserout "Month toggle " #month

Hserout CrLf

 

If month = 0 Then  'Toggles month from 0 to 1 or 1 to 0

month = 1

Else

month = 0

Endif

Hserout " Month toggle now " #month

Hserout CrLf

 

month_cntr = month_cntr + 1  'inc monthr counter

day_end_cntr = 1  'reset day counter to zero

b2a_value = day_end_cntr

Gosub byte2asc2

 

 

EndSelect

 

'-----------------------------------------------------------------------------------

Endif

 

If month_cntr = 13 Then  'overflow so reset to 1

month_cntr = 1  'reset month counter to 1[jan]

year_cntr = year_cntr + 1  'inc year counter

Endif

 

If year_cntr = 5 Then  'overflow so reset to year 1, its a 4 year cycle

year_cntr = 1

Endif

 

 

 

'convert binary To ascii For uart

b2a_value = day_end_cntr

Gosub byte2asc2

Hserout "D=", aschigh, asclow, ":"  'serial out

 

 

b2a_value = month_cntr

Gosub byte2asc2

Hserout aschigh, asclow, ":"

temp1 = year_cntr Or 0x30

Hserout temp1, CrLf

 

 

TMR0L = 255  'you must reload the t0 timer Count

 

'they temporarily NOT used during Simulation, slows the Sim down

'save values in EEPROM, in case of power failure

Write 0, day_end_cntr

Write 1, month_cntr

Write 2, year_cntr

Write 3, month    'Brett

Goto skip30

 

'''''''''''''''''''''''''''''''''''''''''''''''

int30:

sec_cntr = sec_cntr + 1

b2a_value = sec_cntr

Gosub byte2asc2

Hserout aschigh, asclow, ","

 

If sec_cntr > 29 Then

PORTB.5 = 1  'set PORTB.5 high, PULSE OUT

WaitMs 40  '''0  'this will be [waitms 400]

PORTB.5 = 0  'sets PORTB.5 low,  this simulates the pulse to the Slave

sec_cntr = 0

Hserout CrLf

Endif

TMR0L = 255

Goto skip30

''''''''''''''''''''''''''''''''''''''''''''''

int2:

Toggle PORTB.5

If PORTB.5 = 1 Then

PORTB.4 = 0

Else

PORTB.4 = 1

Endif

TMR0L = 255

If PORTB.5 = 1 Then

Hserout "^5,",

Else

Hserout "^4,"

Endif

 

skip30:

INTCON.TMR0IE = 1  'enables the T0 timer to Interrupt, when timer overflows

Resume

 

 

 

 

 

 

 

Subroutines and code explanations Green REM Blue Code Explanation

In order to understand and also remember for the future the code used in this clock I have written out explanations for the code.

byte2asc2:

'convt hex to decimal to ASCII

e.g. if b2a_value = 27 in this case the day number

temp1 = b2a_value Mod 10

temp1 = remainder of 27/10 = 7    (Mod 10 means divide by 10 & show remainder)

asclow = temp1 Or 0x30

asclow = 7 in binary (0000 0111) OR’d with 0x30 in binary (0011 0000)

this is

00000111 OR 00110000 = 00110111

00110111 in ASC11 displays 7

temp2 = 0

resets temp2 to 0

While b2a_value > 9

b2a_value = b2a_value - 10

temp2 = temp2 + 1

27-10 = 17

temp2 = 1

17-10 = 7

Temp2 = 2

Wend

aschigh = temp2 Or 0x30

aschigh = 2 in binary (0000 0010) OR’d with 0x30 in binary (0011 0000)

this is

00000010 OR 00110000 = 00110010

00110010 in ASCII displays 2

Return

Used to display the day, month and year number over the serial port see skip_int

 

bcd2bin:  see rx_date below

'convt rtc packed bcd to a bin number for inc/dec usage

 

units = temp1 And 0x0f

tens = temp1 And 0xf0

tens = ShiftRight(tens, 4)

tens = tens * 10

temp1 = tens + units

Return

 

init_loop:

'if RA7 pin16 is HIGH at power up read these values

'reinitialise all counters to these settings

'Mark you can change these values, save testing waiting!

'put them back to current TODAY's values when you have done testing

'when you program a PIC these are the values it will save and use.

'TODAY is 31/08/09.... 27day, 11mon[30days in month].. 1st year of a 4 year cycle

'Brett set month to 0 for month movement

day_end_cntr = 27

month_cntr = 09

year_cntr = 1

month = 0  'Brett

'save values to EEPROM

Write 0, day_end_cntr

Write 1, month_cntr

Write 2, year_cntr

Write 3, month  'Brett

 

skip_init:

'serial output header at power up

b2a_value = day_end_cntr

Gosub byte2asc2

**************************************************************

byte2asc2: 

'convt hex to decimal to ASCII

e.g. if b2a_value = 27 in this case the day number

temp1 = b2a_value Mod 10

temp1 = remainder of 27/10 = 7    (Mod 10 means divide by 10 & show remainder)

asclow = temp1 Or 0x30

asclow = 7 in binary (0000 0111) OR’d with 0x30 in binary (0011 0000)

this is

00000111 OR 00110000 = 00110111

00110111 in ASC11 displays 7

temp2 = 0

resets temp2 to 0

While b2a_value > 9

b2a_value = b2a_value - 10

temp2 = temp2 + 1

27-10 = 17

temp2 = 1

17-10 = 7

Temp2 = 2

Wend

aschigh = temp2 Or 0x30

aschigh = 2 in binary (0000 0010) OR’d with 0x30 in binary (0011 0000)

this is

00000010 OR 00110000 = 00110010

00110010 in ASCII displays 2

Return

**************************************************************

Hserout "Init Date=", aschigh, asclow, ":"

Outputs 2 and 7 from byte2asc2: above

 

b2a_value = month_cntr

Gosub byte2asc2 see above

Hserout aschigh, asclow, ":"

temp1 = year_cntr Or 0x30

Hserout temp1, CrLf

WaitMs 500

If PORTA.7 = 1 Then

Goto init_loop

Endif

 

 

rx_date:   presume 27:09:01 entered

Hserin ascbfr0 ' Brett note defines 10 keys in order

Hserin ascbfr1

Hserin ascbfr2

Hserin ascbfr3

Hserin ascbfr4

Hserin ascbfr5

Hserin ascbfr6

Hserin ascbfr7

Hserin ascbfr8  'Brett

Hserin ascbfr9  'Brett

Hserin ascbfr10  'Brett

 

''

Hserout CrLf

temp1 = ascbfr0

temp1 is ASCII code for 2 and is 00110010

temp1 = temp1 And 0x0f

this is temp 1 ANDed with 0x0f (00001111)

this = 0000010 or 2

temp2 = ShiftLeft(temp1, 4)

so temp2 = 00100000

temp1 = ascbfr1

temp1 is ASCII code for 2 and is 00110111

temp1 = temp1 And 0x0f

this is temp 1 ANDed with 0x0f (00001111)

this = 00000111 or 7

temp1 = temp1 Or temp2

this = 00000111 OR 00100000

so temp 1 = 00100111

Gosub bcd2bin

**************************************************

bcd2bin:

'convt rtc packed bcd to a bin number for inc/dec usage

 

units = temp1 And 0x0f

from above temp1 = 00100111, 0x0f = 00001111

so units = 00100111 AND 00001111

units = 00000111 or 7

tens = temp1 And 0xf0

from above temp1 = 00100111, 0xf0 = 11110000

so tens = 00100111 AND 11110000

tens = 00100000

tens = ShiftRight(tens, 4)

tens = 00000010

tens = tens * 10

tens = 00010100

temp1 = tens + units

temp1 = 00011011

Return

**************************************************

If temp1 = 0 Then

temp1 = 1

Endif

Write 0x0, temp1

0x0 = 00011011 or 27

day_end_cntr = temp1

day_end_cntr = 00011011 or 27

This is repeated for ascbf3, 4, 6, 7, 9 & 10 below.

''''''''''''''''''''''''''''''''''''

temp1 = ascbfr3

temp1 = temp1 And 0x0f

temp2 = ShiftLeft(temp1, 4)

temp1 = ascbfr4

temp1 = temp1 And 0x0f

temp1 = temp1 Or temp2

Gosub bcd2bin

If temp1 = 0 Then

temp1 = 1

Endif

Write 0x1, temp1

month_cntr = temp1

''''''''''''''''''''''''''''''''''''

temp1 = ascbfr6

temp1 = temp1 And 0x0f

temp2 = ShiftLeft(temp1, 4)

temp1 = ascbfr7

temp1 = temp1 And 0x0f

temp1 = temp1 Or temp2

Gosub bcd2bin

temp1 = temp1 Mod 4

 

If temp1 = 0 Then

temp1 = 4

Endif

 

Write 0x2, temp1

year_cntr = temp1

''''''''''''''''''''''''''''''''''''

'Brett

temp1 = ascbfr9

temp1 = temp1 And 0x0f

temp2 = ShiftLeft(temp1, 4)

temp1 = ascbfr10

temp1 = temp1 And 0x0f

temp1 = temp1 Or temp2

Gosub bcd2bin

temp1 = temp1  'Mod 4

 

Write 0x3, temp1

month = temp1

'end Brett

''''''''''''''''''''''''''''''''''''

Hserout CrLf

Hserout "Echo Date="

Hserout ascbfr0, ascbfr1, ascbfr2

Hserout ascbfr3, ascbfr4, ascbfr5

Hserout ascbfr6, ascbfr7, ascbfr8, ascbfr9, ascbfr10, CrLf   'Brett ascbfr9, ascbfr10

 

 

temp1 = 0

temp2 = 0