-----

The objective was to create a real time clock using three analog voltmeters controlled via Pulse Width Modulation (PWM) to display "hours", "minutes", and "seconds". At the press of a button the three meters display temperature in degrees F, C, and K.

-----

Here is a short (time lapse) video of the rig in action:

-----

There are four major components to the build.

- PICAXE 14M2 microcontroller

- DS1307 Real Time Clock (RTC) module

- DS18B20 Temperature Sensor

- Three 0-2VDC analog voltmeters (refaced to display as "hours", "minutes", and "seconds")

-----

The meters were taken apart to install custom faces. A free program called "MeterBasic" was used to create the custom faces for the three voltmeters (see pic below). Note that the meters have labeling to display temperature in degrees F, C, and K.

The meters were taken apart to install custom faces. A free program called "MeterBasic" was used to create the custom faces for the three voltmeters (see pic below). Note that the meters have labeling to display temperature in degrees F, C, and K.

-----

See the black button below the "seconds" meter? Pressing this button causes the meters to display their respective temperature.

See the black button below the "seconds" meter? Pressing this button causes the meters to display their respective temperature.

-----

Here are a few shots of the build process. The "red thing with the black tip" is the DS18B20 temperature sensor. In front of the meter in the middle (what will be the minutes meter), you can see a small PCB with two buttons. These are used to set the time on the DS1307 Real Time Clock. Pressing both buttons will set the seconds to zero.

------

The digital outputs on the PICAXE 14M2 put out about 5VDC maximum. Our analog voltmeters only go to 2VDC maximum. We set up a voltage divider circuit and a trimpot to allow the output from the PICAXE 14M2 to read full on our 2VDC meter. The 100K trimpot (the little blue things in the pic below) allow for precise adjustment of the full scale reading. Pushing the hour set, minute set, and read temperature button at the same time will force all meters to full scale. This is to provide for precise tuning of the trimpots to calibrate the full scale reading of each meter.

After we have calibrated the meters to read "0" with no voltage and "full scale" from a high digital output on the PICAXE 14M2 we still have to be able to control the meters to display the time. This is done by reading the time on DC1307 RTC via the I2C bus and the PICAXE 14M2. Pulse Width Modulation control is used to convert the time (hours, minutes, and seconds) into a corresponding "average" voltage. That PWM signal drives the three meters to display time. The PICAXE 14M2 has four PWM output drivers that are well up to the job for this.

-----

Here is another look at the time set buttons. They are located on the bottom side of the clock enclosure.

-----

The rig is powered by a rescued wall wart from an old Sony CD player. The wall wart puts out 9VDC which is tamed to 5VDC with a LM7805 voltage regulator.

The rig is powered by a rescued wall wart from an old Sony CD player. The wall wart puts out 9VDC which is tamed to 5VDC with a LM7805 voltage regulator.

-----

If you want to build your own, the schematic looks like this. The source code is below.

-----

Another pic of the finished rig.

-----

If you're still with us, here the PICAXE code:

If you're still with us, here the PICAXE code:

; *******************************

; ***** www.whiskeytangohotel.com *****

; *******************************

; Project Name: 3 Panel Meter Clock

; REV: FIN (everything works fine with clock and temp)

;

; Start Date: Feb 12, 2012

;

; Program Rev History/Ideas:

; - to set clock push M or H button

; - push main button to display temp F, C, and K

; - Routine to drive 3 meters to full scale when main button AND (M OR H)

; is pressed. This is to allow adjustment of trimmers to full scale.

; Adjustment to zero scale should be done first with power off.

;

; *******************************

; PICAXE PE Rev: MacAXEPad 1.3.2

;

#picaxe14m2

'define memory locations as symbols

symbol hour_meter = c.0 'LEG 7

symbol minute_meter = c.2 'LEG 5

symbol second_meter = b.2 ' LEG 11

symbol temp_switch = pinc.4 ' LEG3

symbol temp_sensor = b.5 'LEG8

symbol hour_set = pinc.3 'LEG3

symbol minute_set = pinc.1 'LEG6

symbol CthermoValue = b10

symbol FthermoValue = b11

symbol KthermoValue = w6 'b12 and b13

symbol seconds = b0

symbol minutes = b1

symbol hours = b2

symbol day = b3

symbol date = b4

symbol month = b5

symbol year = b6

symbol blinky = b7

symbol Tens_Digi = b8 ;Used to get the Tens Digit from the $HEX RTC value

symbol Ones_Digi = b9 ;Used to get the Ones Digit from the $HEX RTC value

' w7 (b14 and b15) is used to control the PCM to the meters

' Set the time on the DS1307 RTC

i2cslave %11010000, i2cslow, i2cbyte ; set PICAXE as master and DS1307 slave address

pause 50

'Set all meters to full scale with 100% duty cycle

pwmout hour_meter,99,400

pwmout minute_meter,99,400

pwmout second_meter,99,400

'\/ \/ \/ \/ Un_REM THESE LINES (BELOW) IF SETTING UP A NEW RTC \/ \/ \/ \/

#rem

' Set the RTC chip time

; write time and date e.g. to 11:59:00 on Thurs 25/12/03

'; would be "writei2c 0,($00, $59, $11, $03, $25, $12, $03, 010000)"

' readi2c 0, (b0,b1,b2,b3,b4,b5,b6,b7) reads back the data

let seconds = $00 ; 00-59 Note all BCD format

let minutes = $00 ; 00-59 Note all BCD format

let hours = $01 ; 01-12 Note all BCD format

let day = $03 ; program does not use date, date, month, year

let date = $22

let month = $03

let year = $12

let blinky = 000000 ; 010000 would Enable output at 1Hz blink rate. 000000 is no blink

writei2c 0,(seconds, minutes, hours, day, date, month, year, blinky)

pause 50

#endrem

'/\ /\ /\ /\ Un_REM THESE LINES (ABOVE) IF SETTING UP A NEW RTC /\ /\ /\ /\

; POWER ON SELF TEST. Send all three meters to FULL Scale and back to 0

'NOTE: pwmduty hour_meter, w7 ---->> w7 ranges from 0 to 400 to move meter from 0VDC to 2VDC

for w7 = 400 to 0 step -1' pwmduty needs a (W)ord var, not a (B)yte var

pwmduty hour_meter, w7 'adjust PWM Duty from 100% to 0%

pwmduty minute_meter, w7

pwmduty second_meter, w7

next w7

main:

if temp_switch = 1 then

do ' while hour_set = 1 or minute_set = 1 then 'if main buttom and H or M set button pushed then

pwmduty hour_meter, 400 ' move all meters to full scale to allow trimmer adjust. Do 0 meter adjust 1st with power off.

pwmduty minute_meter, 400

pwmduty second_meter, 400

loop while hour_set = 1 or minute_set = 1

end if ' temp_switch = 1

if temp_switch = 1 and hour_set = 0 and minute_set = 0 then

do 'while temp_switch is pressed

gosub DisplayTemp

loop while temp_switch = 1 and hour_set = 0 and minute_set = 0

end if

'read the RTC and display the time

readi2c 0, (seconds, minutes, hours, day, date, month, year, blinky)

pause 10

'\/ \/ \/ \/ \/ SECONDS SECONDS SECONDS \/ \/ \/ \/ \/

;Convert the Seconds from the RTC to Base10 and update the meter

if temp_switch = 0 and minute_set = 1 and hour_set = 1 then 'all pressed. Seconds to $00

gosub Seconds_set

end if

Ones_digi = seconds & 0x0F ' zero out the top four bits

Tens_Digi = seconds & 0xF0 ' zero out the lower four bits

Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the

Tens_Digi = Tens_Digi / 2 ' bits LEFT. Four shift get

Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits

Tens_Digi = Tens_Digi / 2

Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

seconds = Tens_Digi + Ones_Digi 'complete. Now $ss is ss (in Base10)

' Update the seconds meter with a w9 value of 0 to 400

w7 = seconds * 677 / 100 ; (400/59=6.77) scale 0-59 seconds to 0-400 for PWM

pwmduty second_meter, w7

'/\ /\ /\ /\ SECONDS END /\ /\ /\ /\ /\ /\ /\

'\/ \/ \/ \/ MINUTES MINUTES MINUTES \/ \/ \/ \/ \/

if temp_switch = 0 and minute_set = 1 and hour_set = 0 then 'if temp_switch and M is pressed then add on minute

gosub Minutes_set

end if

;Convert the Minutes from the RTC to Base10 and update the meter

Ones_digi = minutes & 0x0F ' zero out the top four bits

Tens_digi = minutes & 0xF0 ' zero out the lower four bits

Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the

Tens_Digi = Tens_Digi / 2 ' bits LEFT. Four shift get

Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits

Tens_Digi = Tens_Digi / 2

Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

minutes = Tens_Digi + Ones_Digi 'complete. Now $mm is mm (in Base10)

'Update the minutes meter with a w9 value of 0 to 400

If minute_set = 0 then 'dont update if we are setting the minutes. Should correct this in Minutes_set routine

w7 = minutes * 677 / 100 ; (400/59=6.77) scale 0-59 minutes to 0-400 for PWM

pwmduty minute_meter, w7

end if

'/\ /\ /\ /\ /\ MINUTES END /\ /\ /\ /\ /\

'\/ \/ \/ \/ \/ HOURS HOURS HOURS \/ \/ \/ \/

if temp_switch = 0 and minute_set = 0 and hour_set = 1 then 'if temp_switch and M is pressed then add on minute

gosub Hours_set

end if

;Convert the Hours from the RTC to Base10 and update the meter

Ones_digi = hours & 0x0F ' zero out the top four bits

Tens_digi = hours & 0xF0 ' zero out the lower four bits

Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the

Tens_Digi = Tens_Digi / 2 ' bits LEFT. Four shift get

Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits

Tens_Digi = Tens_Digi / 2

Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

hours = Tens_Digi + Ones_Digi 'complete. Now $hh is hh (in Base10)

if hours > 12 then

hours = hours - 12

end if

if hours = 0 then

hours = 12

end if

' Update the hours meter with a w9 value of 0 to 400

w7 = hours * 3636 ; (400/11 = 36.36) scale 1 to 12 hours to 0-400 for PWM

w7 = w7 - 3636 'subtract y interceot to start PCM at 0 to 1 o'clock.

w7 = w7 / 100 'scale 1 to 12 hours to 0-400 for PWM

pwmduty hour_meter, w7

'/\ /\ /\ /\ /\ HOURS END /\ /\ /\ /\ /\

goto main

DisplayTemp:

readtemp temp_sensor, CthermoValue

w7 = CthermoValue * 677 / 100 '(400/59=6.77) scale C to 0-400 for PWM

pwmduty minute_meter, w7 'C (raw) in the minutes meter)

'Convert C to F

FthermoValue = 9 * CthermoValue / 5 + 32

w7 = FthermoValue * 364 ; (400/11 = 36.36) scale 10 to 120F to 0-400 for PWM

w7 = w7 - 3636 'subtract y interceot to start PCM at 0 to 10F

w7 = w7 / 100 'scale 0-400 for PWM

pwmduty hour_meter, w7 '(F (x10) on the hours meter

'Convert C to K

KthermoValue = CthermoValue + 273

w7 = KthermoValue / 10

w7 = w7 * 677 / 100

pwmduty second_meter, w7 'Kelvin *100 on the seconds meter

return 'DisplayTemp

Seconds_Set:

seconds = $00

writei2c 0,(seconds, minutes, hours, day, date, month, year, blinky)

pause 50

w7 = seconds * 677 / 100 ; (400/59=6.77) scale 0-59 seconds to 0-400 for PWM

pwmduty second_meter, w7

return 'Seconds_set

Minutes_Set:

readi2c 0, (seconds, minutes, hours, day, date, month, year, blinky)

;Convert the Minutes from the RTC to Base10 and update the meter

Ones_digi = minutes & 0x0F ' zero out the top four bits

Tens_digi = minutes & 0xF0 ' zero out the lower four bits

Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the

Tens_Digi = Tens_Digi / 2 ' bits LEFT. Four shift get

Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits

Tens_Digi = Tens_Digi / 2

Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

minutes = Tens_Digi + Ones_Digi 'complete. Now $mm is mm (in Base10)

minutes = minutes + 1

if minutes > 59 then

minutes = 0

end if

'convert base10 minutes to BCD here then write new minute value to RTC

Ones_Digi = minutes // 10

Tens_Digi = minutes - Ones_Digi

Tens_Digi = Tens_Digi / 10

Tens_Digi = Tens_Digi * 2 ' shift the lower right bits

Tens_Digi = Tens_Digi * 2 ' to the upper left.

Tens_Digi = Tens_Digi * 2

Tens_Digi = Tens_Digi * 2

Tens_Digi = Tens_Digi OR Ones_Digi 'OR function on the two values to get 8 bit BDC

'Now Ten_digi = minutes in packed BCD. Just using Tens_Digi as a temp var

writei2c 0,(seconds, Tens_Digi, hours, day, date, month, year, blinky)

pause 50

'Update the minutes meter with a w9 value of 0 to 400

w7 = minutes * 677 / 100 ; (400/59=6.77) scale 0-59 minutes to 0-400 for PWM

pwmduty minute_meter, w7

pause 500

return ' Minutes_Set

Hours_Set: 'HOURS SET WORKS PERFECT

readi2c 0, (seconds, minutes, hours, day, date, month, year, blinky)

;Convert the Hours from the RTC to Base10 and update the meter

Ones_digi = hours & 0x0F ' zero out the top four bits

Tens_digi = hours & 0xF0 ' zero out the lower four bits

Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the

Tens_Digi = Tens_Digi / 2 ' bits LEFT. Four shift get

Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits

Tens_Digi = Tens_Digi / 2

Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

hours = Tens_Digi + Ones_Digi 'complete. Now $hh is hh (in Base10)

hours = hours + 1

if hours > 12 then

hours = hours - 12

end if

if hours = 0 then

hours = 12

end if

if hours > 9 then

if hours = 10 then

hours = $10

end if

if hours = 11 then

hours = $11

end if

if hours = 12 then

hours = $12

end if

end if

writei2c 0,(seconds, minutes, hours, day, date, month, year, blinky)

pause 50

;Convert the Hours from the RTC to Base10 and update the meter

Ones_digi = hours & 0x0F ' zero out the top four bits

Tens_digi = hours & 0xF0 ' zero out the lower four bits

Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the

Tens_Digi = Tens_Digi / 2 ' bits LEFT. Four shift get

Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits

Tens_Digi = Tens_Digi / 2

Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

hours = Tens_Digi + Ones_Digi 'complete. Now $hh is hh (in Base10)

' Update the hours meter with a w9 value of 0 to 400

w7 = hours * 3636 ; (400/11 = 36.36) scale 1 to 12 hours to 0-400 for PWM

w7 = w7 - 3636 'subtract y interceot to start PCM at 0 to 1 o'clock.

w7 = w7 / 100 'scale 1 to 12 hours to 0-400 for PWM

pwmduty hour_meter, w7

pause 1000

return ' Hours_Set

-----