Section   Top   Features   Meter Dials  Ctrl Panel  Operating  Manual  Program Flowchart  Clock Pics  Schematic  PCBs  Clock Video  Sync Video  Code

 

 

 

Master Clock MK2   Master Clock  Atomic Time Synchronisation Circuit  DCF77 Analyzer Clock  Slave Clocks  LCD Master Clock  Calendar Clock

 

Voltmeter Clock

 

 

 

Voltmeter Slave Clock

 

Based on a Multimeter Clock design by Alan Parekh

Alan Parekh's Multimeter Clock kit.

 

 

See Alan's site for a full kit of parts, circuit diagrams, videos, hex and bas files for his project.

 

 

 

 

Features

This clock is based largely on Alan's code and circuit with a few changes.

I purchased a kit of parts for the main board from Alan's site.

I have used three voltmeters and mounted them on a wooden plinth with a clear Perspex cover to give the clock an industrial look.

I have modified Alan's code to run on PICBasic Pro version 3. I have also added the following.

Switched display On and Off (keeping battery backup as per Alan's design) but also allows me to turn meters Off in full power mode.

Synchronization to my Master Clock every 30 seconds

Synchronized LED & Re-Synch LED

Synchronization On & Off

Transistor meter drivers

Separate hourly Chime Circuit

Pulsed "tick tock" seconds sound.

 

The standard clock due to limits of the 20Mhz quartz crystal (you can't get a precise 1 sec pulse) runs fast by several seconds per day. In order to keep correct time the clock is connected to my Master Clock  or LCD Master Clock and is kept in sync by 30 second pulses form the Master Clock ( the Master Clock is synchronized to the DCF77 transmitter).

The Clock also has an electronic chime via an ISD1730 audio record and playback kit from Sure Electronics. This was used to record my Long case clock chime then play it back on pulses from the master clock.

The chimes are also controlled via the Master Clock. The clock has battery backup on mains fail and can also be manually switch to backup mode (display off switch) if required.

 

 

The meters have had their original scales (left) removed and are then rubbed down to bare metal before being re-sprayed in off white to make them look old.

The new scales were drawn up in TurboCad and then printed on inkjet transfer paper before being cut out and applied to the blank scales.

Download meter templates

The scales were then varnished over to seal them.

 

 

 

 

Clock Controls & indicators

Chime LED- lights while clock is chiming

Sync Pulse LED- lights when sync pulse received from master

Re-Sync LED- lights when Sync Pulse corrects clock

Seconds Led-Indicates Seconds

Hour/Meter Select- Sets hours and when Scale Adjust is On selects which meter scale to adjust

Minutes/Scale Increase- Sets Minutes and when Scale Adjust is On increases scale deflection

Seconds/Scale Decrease- Resets Seconds and when Scale Adjust is On decreases scale deflection

Scale Adjust-When On enables meter scale adjustment

Chime-Turns Hour Chime On & Off

Smooth Sec- When On Seconds meter deflect smoothly with each second, when off each seconds moves the meter in 1 second increments

Sync-Turns the Master Clock sync On & Off

Display-Turns the meter displays On or Off correct synchronised time is also maintained.

Chime Record Jack-Audio input to Sure Electronics Digital record and playback board for recording hour Chime

 

 

 

 

Using the Voltmeter Clock

When the clock is first powered up the PWM outputs will default to about 50% of max output. You will first need to adjust the scale of all three meters. This is done by operating the “Scale Adjust” switch. In this mode only the meter being adjusted will be powered.

  • The first button “Hour/ Meter Select” (also used to advance the hours when in clock mode) is used to select which meter is to be adjusted.
  • The second button (also used to advance the minutes when in clock mode) is used to decrease the full scale setting of the powered meter.
  • The third button (also used to reset the seconds when in clock mode) is used to increase the full scale setting of the powered meter.

The goal here is to move all three meters to exactly full scale. When complete remove the scale adjust jumper to return to normal clock mode, at this time the settings will be saved to non-volatile memory.

The time will also need to be set. The time is adjusted using the three buttons.

  • The hour button increments the current time by one hour.
  • The minute button increments the current time by one minute.
  • The second button resets the seconds.

Once set the time and the “Sync” switch is operated the time is checked against the Master Clock 30 seconds pulses on zero and 30 seconds. If the clock is not in sync then the seconds are corrected on chip and the second hand is moved to show the exact time.

In “Display Off “ mode the clock is also kept in sync but only on the 30 second pulse. The clock is chimed via chime pulses from the master Clock that operates a relay that in turn operates the chime board.

See the Winbond ISD1700 chip data sheet for operation details. The chime sound is recorded on the ISD1700 chip via an audio socket  in the clock. The chime is turned ON & OFF by the “Chime” switch.

 

 

 

 

Download the Voltmeter Clock Document

 

 

 

 

 

 

Voltmeter Clock Picbasic Pro v3 software flowcharts

 

 

 

 

 

 

 

 

Voltmeter Clock front view

Meter Clock

 

 

 

& below board layout and wiring

The base for the case is cut out of a block of wood and strips of the same wood are used to seat the perspex cover and surround the dials.

 

 

 

 

 

 

Voltmeter Clock Circuit Diagram

 

 

 

 

 

 

 

 

Man Board layout from kit of parts from Alan Parekh store http://alan-parekh.vstore.ca/

 

 

Meter Driver Board

Driver boards are mounted on each meter

 

Clock Pulse Converter Board converts pulses from my Master Clock

 

Trigger board enabling clock to chime & sync on +ve pulses

Sure Electronics Digital record and playback board for sounding the hourly chime

 

 

 

 

 

 

 

Video showing clock from 11:59:55 to 12:00:32 including synchronization pulses at 30 and 60 seconds from the Master Clock

 

 

 

 

 

 

 

 
   

 

Video Showing fast running clock being synchronised at 60 secs by the Digital Master Clock

 

 

 

 

 

 

 

 

50 second Time-lapse Video showing clock running for 90 mins. Hi-lights 30 sec sync pulses and re-sync as clock drifts

 

Modified Picbasic Pro  v3 code

 
'****************************************************************
'*  Name    : multi_meter_clock.BAS                             *
'*  Author  : [Alan Parekh]                                     *
'*          : Alan's Electronic Projects Inc.                   *
'*  Notice  : Copyright (c) 2009  modified Brett Oliver 2013    *
'*          : All Rights Reserved                               *
'*  Date    : January 8, 2010                                   *
'*  Version : 1.3                                               *
'*  Notes   : Modified for Picbasic Pro v 3 and syncronisation  *
'*          : to 30 second master clock pulse inc standby and   *
'*          : mechanical tick                                   *
'****************************************************************
   
     #CONFIG
       __config _HS_OSC & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _CP_OFF
     #ENDCONFIG
    
    DEFINE OSC 20 ' running at 20 MHZ  
    
    'we are going to store 300 as the starting value of the meter PWM for full scale
    'the storage we are using holds one byte (8 bits) so we will use 2 locations to hold the word
    '300 = 012C in HEX
    'the upper portion of the value (01) will be stored in the first location and the lower portion (2C) will be stored in the second
    data @1,$01   ;store the first byte of 300 in location 1 at burn time (default max PWM time for the hour meter)
    data @2,$2C   ;store the second byte of 300 in location 2 at burn time (default max PWM time for the hour meter)
    data @3,$01   ;store the first byte of 300 in location 1 at burn time (default max PWM time for the minute meter)
    data @4,$2C   ;store the second byte of 300 in location 2 at burn time (default max PWM time for the minute meter)
    data @5,$01   ;store the first byte of 300 in location 1 at burn time (default max PWM time for the second meter)
    data @6,$2C   ;store the second byte of 300 in location 2 at burn time (default max PWM time for the second meter)
    
    'included this for the seria port use, it could be removed if the serial
    'port is no longer needed
    include "modedefs.bas"
    'serialOutput var porta.1  'serial output  was porta.1   was porta.4
    
    'Turn ON PortB pull-ups
    OPTION_REG.7 = 0 
    ;*************30second sync*********************
    'OPTION_REG.4 = 0 ' increment on low to high transition RA4
   ' OPTION_REG.5 = 1
    ;*************end 30second sync*********************
    ;force port a into digital mode (defaults into analog)
    CMCON = 7
    
    'set pin input and output directions
    trisb = %10001111
    trisa = %00010100 'Brett old %00000100    was %00000110
    
    ;pin assignments
    incHourTimeButton var portb.1       ;pressing this button connected here will advance the current hour
    incMinTimeButton var portb.2        ;pressing this button connected here will advance the current minute
    resetSecTimeButton var portb.3      ;pressing this button connected here will reset the seconds
    meterScaleSetSwitch var portb.0     ;putting the jumper in here will allow the meter max position to be set
    hourOutput var portb.4              ;output to hour meter 
    minOutput var portb.5               ;output to minute meter 
    secOutput var portb.6               ;output to second meter 
    smoothSecondSwitch var portb.7      ;input for the smooth second option, when this is on the second dial will move without ticking
    heartBeatLED var porta.3            ;one second heart beat indicator
    mainPowerDetect var porta.2         ;used to detect if the system is running on main power or on backup power 
    ;*************30second sync*********************
    syncpulse var porta.4               ;used to detect 30 second sync pulse  was porta.1
    syncLED var porta.0               ;used to show synchcronising Red LED
    ticktock var porta.5              ;pulses ticktock relay
    syncIndLED var porta.1         ;lights Green sync LED
    ;*************end 30second sync*********************
    ;housekeeping
    buttonActive con 0    ;buttons are active low
    true con 1  ;indicates what true means
    false con 0 ;indicates what false means
    ValueOn con 1  ;indicates what on means
    ValueOff con 0 ;indicates what off means
    hourScaleSet con 0 ;indicates that we are currently setting the hour scale
    minuteScaleSet con 1 ;indicates that we are currently setting the minute scale
    secondScaleSet con 2 ;indicates that we are currently setting the second scale
    powerOn con 1        ;indicates what the value is on for the mainPowerDetect pin 
    powerOff con 0       ;indicates what the value is on for the mainPowerDetect pin     
     ;*************30second sync*********************
    syncpulseOn con 1        ;indicates what the value is on for the syncpulse pin 
    syncpulseOff con 0       ;indicates what the value is on for the syncpulse pin      
     ;*************end 30second sync*********************   
        
    ;interrupt setup
    DEFINE INTHAND intRoutine
     
    T1CON = %00110001    ;TMR1ON ON, 1:8 PRESCALE
    INTCON = %11000000   ;GIE AND INTE ON Brett old %11000000 changed to %10010000 should it read PEIE
    PIE1 = %00000001     ;TMR1IE ON
    
    'set the timer to 3036 (OBDC Hex) to allow for the timer to count to 62500
    TMR1L_Setpoint var byte bank0
    TMR1H_Setpoint var byte bank0
    TMR1L_Setpoint = $DC
    TMR1H_Setpoint = $0B
    
    '''''''''''''''''
    ' Variables to keep track of time
    '''''''''''''''''   
    hour var byte   ;keep track of the current clock hour
    minute var byte   ;keep track of the current clock minute
    second var byte   ;keep track of the current clock second
    tenthSecond var byte bank0 ;keep track of the current clock tenth second
    secondCounter var word ; used as a resetable second timer
    pwmTimer var word    ;used when performing PWM timing on the meter outputs
    buttonPressed var bit ;used to keep track of user button presses
    buttonScanDelayTimer var word 'used when debouncing the button scan key presses
    buttonScanDelay var word 'used to hold the button scan debounce value
    buttonScanDelay = 10     'the button scan delay is a multiple of the PWM update time
    startupMode var bit      'used to indicate that the system in in startup mode
    startupModeTimer var byte  'used in the startup mode
    disableSerialOutput var bit 'used to turn off the serial output
    maxPWMValue var Word    'this is the largest PWM value that can be counted, this should be greater than full scale on the meters
    maxPWMValue = 600       'this is the PWM max count value
    
    'These numbers repersent the portion of the maxPWM value that is needed to get full scale on the meter
    maxHourPWMValue var word  'the PWM value for full scale on the hours meter
    maxMinutePWMValue var word  'the PWM value for full scale on the minutes meter
    maxSecondPWMValue var word  'the PWM value for full scale on the seconds meter
    
    oneHourValue var word   'this holds the PWM value of one hour
    oneMinuteValue var word   'this holds the PWM value of one minute
    oneSecondValue var word   'this holds the PWM value of one second

    currentHourValue var word   'This holds the current PWM hour value
    currentMinuteValue var word   'This holds the current PWM hour value
    currentSecondValue var word   'This holds the current PWM hour value
    
    currentScaleSetMeter var byte 'this holds the value of the meter currently having the scale set
    currentScaleSetMeter = hourScaleSet 'default it to the hour meter
   
    wsave   VAR     BYTE $20 system
    wsave1  VAR     BYTE $a0 system ' Necessary for devices with RAM in bank1
    wsave2  VAR     BYTE $120 system ' Necessary for devices with RAM in bank2
    ;wsave3  VAR     BYTE $1a0 system ' Necessary for devices with RAM in bank3
    ssave   VAR     BYTE bank0 system
    psave   VAR     BYTE bank0 system
    
     ;*************30second sync*********************
    syncOff var bit ' once synced stops resync until after a second
    ;*************30second sync*********************
    ;start the actual program
    goto start 
  
    ;the following is the interrupt routine 
   ASM 
intRoutine
    
    ; Uncomment the following if the device has less than 2k of code space
	movwf	wsave			; Save W
	swapf	STATUS, W		; Swap STATUS to W (swap avoids changing STATUS)
	clrf	STATUS			; Clear STATUS
	movwf	ssave			; Save swapped STATUS
	movf	PCLATH, W		; Move PCLATH to W
	movwf	psave			; Save PCLATH
    
    ;set the low timer setpoint

    movf _TMR1L_Setpoint,W
    movwf TMR1L
    ;set the high timer setpoint
    movf _TMR1H_Setpoint,W
    movwf TMR1H
       
    incf _tenthSecond,F ;inc counter
    
    ;clear int flag
    bcf PIR1, 0
    
    movf    psave, W	; restore the state of everything
    movwf   PCLATH
    swapf   ssave, W
    movwf   STATUS
    swapf   wsave, F
    swapf   wsave, W

    retfie
    
    endASM

'This function will keep the clock time up to date  
updateClock:
  
      'Check if clock is in sync
     ;*************30second sync*********************                 
      if syncpulse = syncpulseOn and second < 5 and tenthSecond > 2 and syncOff =0 then  ' check for sync pulse (0) on porta.4 arrives between 0.2 and 5 seconds
       high syncLED 'indicates sync pulse has resynchronised clock turns on Red LED to indicate clock has been syncronised in last second
       syncOff = 1 ' stops further sync pulse reseting clock
       second = 0
       secondCounter = 0
       tenthSecond = 0
       
      elseif syncpulse = syncpulseOn and second < 30 and second > 25 and syncOff =0 then  ' check for sync pulse (0) on porta.4 arrives between 25 and 35 seconds
       high syncLED 'indicates sync pulse has resynchronised clock turns on Red LED to indicate clock has been syncronised in last second
       syncOff = 1 ' stops further sync pulse reseting clock
       second = 30
       secondCounter = 30
       tenthSecond = 0
       endif
      if syncpulse = syncpulseOn then
      high syncIndLED 'Green LED Indicates sync pulse received and clock in sync
      endif                  
       
      ;*************30second sync*********************
    ;check to see if we have a full second
    if  tenthSecond >= 10 then
        
        ;since we are going to use the tenthSecond variable for two operation turn off the interrupt
        PIE1 = %00000000 ;disable the interrupt for the next three operations
        second = second + (tenthSecond / 10)    ;add the correct number of seconds
        secondCounter = secondCounter + (tenthSecond / 10)    ;add the correct number of seconds 
        tenthSecond = tenthSecond // 10         ;keep track of the remaining tenthSecond units not removed above  
        PIE1 = %00000001 ;re-enable the interrupt 
        
        'indicate that a second has passed on the heart beat LED
        toggle heartBeatLED
        ;*************30second sync*********************
        toggle ticktock 'operate or release ticktock relay
         low syncIndLED ' turn off Green sync ind LED after 1 sec
         low syncLED 'turns off RED resynchronize LED after 1 sec
        ;*************30second sync********************* 
    
        ;check to see if the seconds have rolled over
     if second >= 60 then
            second = second - 60
            minute = minute + 1 
             ;*************30second sync*********************
               syncOff = 0  'sets syncOff ready for sync on 
             ;*************30second sync*********************  
            ;check to see if the minutes have rolled over
            if minute >= 60 then
                minute = 0
                hour = hour + 1
            
                ;check to see if the hours have rolled over
                if hour >= 13 then
                    hour = 1
                endif
                             
            endif
            
        endif
        
    endif
      
    return

'advances the clock by one hour    
incrementHours:

    hour = hour + 1
    
    ;check to see if the hours have rolled over
    if hour >= 13 then
        hour = 1
    endif
    
    RETURN
    
'advances the clock by one minute    
incrementMinutes:

    minute = minute + 1
    
    ;check to see if the minutes have rolled over
    if minute >= 60 then
        minute = 0
        hour = hour + 1
    
        ;check to see if the hours have rolled over
        if hour >= 13 then
            hour = 1
        endif
                     
    endif
    
    return  

'resets the clock seconds
resetSeconds:

    second = 0     
    return

;just here as a jump point 
start:   

    'perform any initial startup functions that need to be done when the clock starts up
    gosub startup
   
   'drop into the clock management function
        
ClockManagement:
     
    gosub updateClock ;ensure the time stored is accurate
    
    'check if we are operating on backup power, if we are don't power the meters
    
    ;*************30second sync*********************
         'Sync clock on backup power  
         if syncpulse = syncpulseOn and second > 25 and second < 35 and mainPowerDetect = powerOff then  ' check for sync pulse (0) on porta.4 arrives between 25 and 35 seconds
           high syncLED 'indicates sync pulse has reset clock turns off Green LED and turn on Red LED to indicate clock has been syncronised in last second
           gosub turnTimeOutputsOff
           second = 30
           secondCounter = 30
           tenthSecond = 0
           ;*************30second sync*********************  
    elseif mainPowerDetect = powerOff then
    
        'make sure we are not powering anything
        gosub turnTimeOutputsOff
        low heartBeatLED
        ;*************30second sync*********************
        low ticktock 'release ticktock relay on power fail
        low syncLED  'turns off sync LED unless clock synced
        ;*************30second sync********************* 
        
        gosub outputNewLine
        'serout serialoutput,N9600,[#hour, ":", #minute,":", #second]
         
        'do nothing for a second, we can't sleep since the clock interrupt still needs to fire
        pause 1000
        
        'keep in low power mode until main power has been established
        goto ClockManagement
        
    endif
          
    gosub refreshClock ;output the correct PWM based on the current time
   
    'service any current button press
    gosub buttonScan
    
    'check if we are in scale set mode
    if meterScaleSetSwitch = buttonActive then
         goto setMeterScales
    
    endif

    'update the time output once per minute
    if (tenthSecond = 0 and second = 0 and minute = 0) then
        'output the time
        if disableSerialOutput = false then
            gosub outputNewLine
            'serout serialoutput,N9600,["Time is ", #hour, ":", #minute,":", #second]
        endif 
    endif

    goto ClockManagement

'PWM output the current time to move the meter hands to the correct locations
refreshClock:

    'get the current PWM values needed for the current time
     currentHourValue = (hour * oneHourValue) / 10 'convert hours to a PWM value
     currentMinuteValue = (minute * oneMinuteValue) / 10 'convert minutes to a PWM value
     currentSecondValue = (second * oneSecondValue) / 10 'convert seconds to a PWM value
     
     'add in the 10ths of a second to smooth things out if desired, otherwise the second hand will tick
     if smoothSecondSwitch = buttonActive then
        currentSecondValue = currentSecondValue +  (tenthSecond * oneSecondValue) / 100 'add in the tenths of a second for a smoother display
     endif
     
     'check if we are setting the meter scales or in startup mode
     if meterScaleSetSwitch = buttonActive or startupMode = true then
        
        'start by setting all of the meter values to 0 so that only the one being adjusted will be shown
        currentHourValue = 0
        currentMinuteValue = 0
        currentSecondValue = 0
        
        'METER SCALE ADJUST MODE
        Select Case currentScaleSetMeter
        
            case hourScaleSet 
                currentHourValue = maxHourPWMValue
                
            case minuteScaleSet 
                currentMinuteValue = maxMinutePWMValue
                
            case secondScaleSet 
                currentSecondValue = maxSecondPWMValue
                        
		End Select 
        		
    endif
     
     'turn on all outputs
     gosub turnTimeOutputsOn
     
     'loop through all possible hand (meter pointer) locations for seconds
     for pwmTimer = 0 to maxPWMValue                

        'check to see if the hour meter should still be on
        if pwmTimer >= currentHourValue then
            low hourOutput                
        endif
        
        'check to see if the minute meter should still be on
        if pwmTimer >= currentMinuteValue then
            low minOutput                
        endif

        'check to see if the second meter should still be on
        if pwmTimer >= currentSecondValue then
            low secOutput                
        endif
        
        pauseus 1 'add a small delay
                                
     next     
      
     return

'turn on all the meter outputs
turnTimeOutputsOn:

    high hourOutput
    high minOutput
    High secOutput
    
    return
    
'turn off all the meter outputs
turnTimeOutputsOff:

    low hourOutput
    low minOutput
    low secOutput
    
    return

'check to see if any of the time adjustment buttons are being pressed    
buttonScan:

    'default the button to not pressed
    buttonPressed = false

    'check for the hour increment button
    if incHourTimeButton = buttonActive then
        gosub incrementHours
        buttonPressed = true
    endif
    
    'check for the minute increment button
    if incMinTimeButton = buttonActive then
        gosub incrementMinutes
        buttonPressed = true    
    endif
    
    'check for the second reset button
    if resetSecTimeButton = buttonActive then
        gosub resetSeconds
        buttonPressed = true   
    endif
    
    'check to see if a button was actually pressed, add a small delay if it was
    if buttonPressed = true then
        for buttonScanDelayTimer = 1 to buttonScanDelay
            gosub refreshClock  'keep updating the clock so that the needles don't fall
        next
        
        'output the new time
        if disableSerialOutput = false then
            gosub outputNewLine
            'serout serialoutput,N9600,["Updated time is ", #hour, ":", #minute,":", #second,":", #tenthSecond]    
        endif
    endif

    return    

'this function will allow the scales of the meters to be set so that the max PWM count will
'allow the meter to reach exactly full scale
setMeterScales:

    'the three buttons will be used to adjust the three meter scales
    'Hour button - this button will change which meter is being adjusted.
    'Minute button - this button will decrement the PWM value for full scale
    'Second button - this button will increment the PWM value for full scale
    
    'default the button to not pressed
    buttonPressed = false
    
    'check if we are swill in scale set mode or if we are complete
    if meterScaleSetSwitch != buttonActive then
         'we are done, save value and go back to normal mode
                                                   
         gosub writeMeterPWMValuesToFlash 'save new max values
         gosub calculateMeterPWMValues 'calculate new incremental values
         
         'return to normal clock mode
         goto ClockManagement
    endif
    
    'check for the hour increment button, in this case that means to move to the next meter to be set
    if incHourTimeButton = buttonActive then
        'move to the next meter
        currentScaleSetMeter = currentScaleSetMeter +1
        
        'there are three meters, mod by 3 just incase we fell off the end of the meter count
        currentScaleSetMeter = currentScaleSetMeter // 3
        buttonPressed = true  'keep track of the button press
    endif
    
    'check for the minute increment button, in this case we will decrement the current meter PWM value
    if incMinTimeButton = buttonActive then
        
        'we need to decrement the full scale PWM value of the meter selected
        Select Case currentScaleSetMeter
        
            case hourScaleSet 
                maxHourPWMValue = maxHourPWMValue -1
                
            case minuteScaleSet 
                maxMinutePWMValue = maxMinutePWMValue -1
                
            case secondScaleSet 
                maxSecondPWMValue = maxSecondPWMValue -1
                        
		End Select     
        
        'make sure we still have a valid PWM value
        gosub maxPWMBoundsCheck
        
        buttonPressed = true  'keep track of the button press
        
    endif
    
    'check for the second reset button, in this case we will decrement the current meter PWM value
    if resetSecTimeButton = buttonActive then
                
        'we need to decrement the full scale PWM value of the meter selected
        Select Case currentScaleSetMeter
        
            case hourScaleSet 
                maxHourPWMValue = maxHourPWMValue +1
                
            case minuteScaleSet 
                maxMinutePWMValue = maxMinutePWMValue +1
                
            case secondScaleSet 
                maxSecondPWMValue = maxSecondPWMValue +1
                        
		End Select     
        
        'make sure we still have a valid PWM value
        gosub maxPWMBoundsCheck
        
        buttonPressed = true  'keep track of the button press
         
    endif
    
    'check to see if a button was actually pressed, add a small delay if it was
    if buttonPressed = true then
    
        gosub pwmSettingOutput  'display the current settings using serial out
        
        'allow for different button delay lengths depending if we are selecting meters or changing the meter scale
        if incHourTimeButton = buttonActive then
            'if we are selecting the meter to be adjusted stretch the delay
            for buttonScanDelayTimer = 1 to (buttonScanDelay *2)
                gosub refreshClock  'keep updating the clock so that the needles don't fall
            next
        
        else
            'scale increment or decrement have been pressed, add a short delay to allow quick adjustment
            for buttonScanDelayTimer = 1 to (buttonScanDelay /2)
                gosub refreshClock  'keep updating the clock so that the needles don't fall
            next
        
        endif

    else
        'if no button was pressed just refresh the clock once
         gosub refreshClock    
    endif
                        
    gosub updateClock ;ensure the time stored is accurate 
    
    'keep looping till we are complete the adjustment
    goto setMeterScales
 
'output the pwm settings via serial
pwmSettingOutput:

    if disableSerialOutput = false then
        'serout serialoutput,N9600,["h ", #maxHourPWMValue, "  m ", #maxMinutePWMValue, "  s ", #maxSecondPWMValue, "mode", #currentScaleSetMeter ]
        gosub outputNewLine 
    endif
        
    return 

'make sure the PWM values are within the bounds, if not adjust them       
maxPWMBoundsCheck:

    'check and adjust min bounds
    if maxHourPWMValue < 1 then
       maxHourPWMValue = 1    
    endif
    
    if maxMinutePWMValue < 1 then
       maxMinutePWMValue = 1    
    endif
    
    if maxSecondPWMValue < 1 then
       maxSecondPWMValue = 1    
    endif
    
    'check and adjust max bounds
    if maxHourPWMValue > maxPWMValue then
       maxHourPWMValue = maxPWMValue    
    endif
    
    if maxMinutePWMValue > maxPWMValue then
       maxMinutePWMValue = maxPWMValue    
    endif
    
    if maxSecondPWMValue > maxPWMValue then
       maxSecondPWMValue = maxPWMValue    
    endif
    
    return 
    
'calculate the PWM values needed to display full scale    
calculateMeterPWMValues:

    'set the PWM values 10 times larger than actual to help INT math become more accurate 
    oneHourValue = (maxHourPWMValue * 10) / 12          
    oneMinuteValue =  (maxMinutePWMValue * 10) / 60
    oneSecondValue = (maxSecondPWMValue * 10) /60
    
    return
       
'store the full scale PWM meter values to permanent memory    
writeMeterPWMValuesToFlash:
        
    'write the values to permanent memory
    write 1, maxHourPWMValue.HIGHBYTE
    write 2, maxHourPWMValue.LowBYTE
    write 3, maxMinutePWMValue.HIGHBYTE
    write 4, maxMinutePWMValue.LowBYTE
    write 5, maxSecondPWMValue.HIGHBYTE
    write 6, maxSecondPWMValue.LowBYTE
        
    return                     

'read the full scale PWM values from permanent memory        
readMeterPWMValuesFromFlash:
        
    'read the values to permanent memory
    read 1, maxHourPWMValue.HIGHBYTE
    read 2, maxHourPWMValue.LowBYTE
    read 3, maxMinutePWMValue.HIGHBYTE
    read 4, maxMinutePWMValue.LowBYTE
    read 5, maxSecondPWMValue.HIGHBYTE
    read 6, maxSecondPWMValue.LowBYTE
    
    'perform a bounds check on the values just read in
    gosub maxPWMBoundsCheck
                              
    return

'Advance the console to a new line        
outputNewLine:
    'line feed and carage return ascii characters        
    'serout serialoutput,N9600,[10,13] 
return  
  
'Startup and show the user that the meters are operational (or not)    
startup:

    startupMode = true 'indicate that we are in startup mode, this is used to perform startup meter tests
    
    'turn the outputs off
    gosub turnTimeOutputsOff
    
    high heartBeatLED            'turn on the heartbeat LED during startup
    ;*************30second sync*********************
        low ticktock 'release ticktock relay during startup
        high syncLED 'test Green sync LED during startup
        high syncIndLED 'test RED syncInd LED during startup       
    ;*************30second sync********************* 
    
    'set if the serial output should be used
    disableSerialOutput = true
    
    'get the PWM value for full scale on the meters
    gosub readMeterPWMValuesFromFlash
    
    'calculate scale PWM unit values
    gosub calculateMeterPWMValues 
    
    ;default the time to 12:00
    hour = 12
    minute = 0
    second = 0
    tenthSecond = 0
    secondCounter = 0 

    'show full scale on each of the 3 meters to test them
    currentScaleSetMeter = hourScaleSet
    for startupModeTimer = 1 to 100
        gosub refreshClock
    next
    
    currentScaleSetMeter = minuteScaleSet
    for startupModeTimer = 1 to 100
        gosub refreshClock
    next
    
    currentScaleSetMeter = secondScaleSet
    for startupModeTimer = 1 to 100
        gosub refreshClock
    next
    
    'set the current scale set back to the hour scale
    currentScaleSetMeter = hourScaleSet
    
    gosub outputNewLine    
    'serout serialoutput,N9600,["Startup complete."]
    gosub outputNewLine 
    startupMode = false   
    return