Mitchy's Geeky Clock

servo_clock2_400x300

Credit where credit is due, this project was inspired by Jon Chandler's Clock for Geeks.

After reading through one of Jon Chandlers recent projects, I was rather inspired to make my own! The Geek Clock is a great spin on a more then well known concept - displaying time. His method employs a Servo, PIC and a little intuition.

 

Design

Rather then using the paper clock face like Jon did, I experimented with a few other methods to spice up the presentation. At work, we recently acquired a large Vinyl Printer and Gerber Cutting machine. Long story short, we can make all sorts of decal stickers (very handy indeed!!). It was a pain staking ordeal creating the clock face on the Omega software (for the vinyl printer/cutter) as it was written in the early 90's and very vector based graphics. In the end I got something that looked like a clock.

Originally I was going to use the decal cut-outs to create the clock face - problem was the decal stickers would not adhere well to wood. I could have used glue, though any excess would have lead to a bad varnish job. Then it struck me - what if I use the external part of the sticker as a template - to paint through? The result was perrrfect! We're about due for a montage:

 

Servo_Clock_Decal

Figure 1. Preparing the Decal.

Servo_Clock_Paint_Dried

Figure 2. Paint is dry, time to start peeling!

Servo_Clock_Peeling

Figure 3. Slow process, don't want to mess it up!

Servo_Clock_Cutting

Figure 4. Removing the little inner bits.

Servo_Clock_Front

Figure 5. Light at the end of the tunnel. Ready for the servo cut-out and then some varnish.

servo_clock2_400x300

Figure 6. The Final Product!

 

The Hardware

The Geek Clock controller was built on the infamous TAP-28 PIC Development Board. I also used the TAP-28 DS1307 RTC Daughter Board and got to it.

I used the DS1307 as it offers an automatic low power mode (to continue clocking time with the absence of main power). It's highly accurate (PIC's generally drift from a few seconds to a minute or two each month), and cheap!

 

The Code

Before I get started on the code - it should be noted that the clock needed calibration first. This was done by using a slightly modified version of Jon's.

Calibration Program

Calibration Program
// Designed to calibrate the geek clock.
// Allows the user to 'wind' the potentiometer to control the servo.
// The servo can be controlled from 400uS to 2400uS pulse widths.
// Displays UART data continously to inform user of calculated position.
Device = 18F2520
Clock = 32
Config MCLRE = Off
 
// only one servo in use
#option Servo_NumberOfServos = 1
 
// all includes can be found @ digital-diy.com ("Swordfish - Module Pack")
Include "InternalOscillator.bas" 
Include "utils.bas"
Include "USART.bas"
Include "convert.bas"
Include "ADC.bas"
Include "Servo.bas" 
 
Dim CalcServoPosition As Word
 
// sample ADC, return a value from 400 to 2400  
Function GetDesiredServoPosition() As Word 
    Result = 400 + ((ADC.Read(0) * 2000) / 1023)     
End Function
 
 
// main program start...
// configure USART
USART.SetBaudrate(br38400) 
// configure ADC
ADC.RightJustify = True
ADC.SetConvTime(FOSC_16)
// enable servo module 
Servo.On
 
While True
    // get desired servo position
    CalcServoPosition = GetDesiredServoPosition
    // update servo position
    ServoPosition(0) = CalcServoPosition    
    // inform user of calculated servo position
    USART.Write("Servo Position = ", DecToStr(CalcServoPosition)13,10)     
    // delay for 200mS
    DelayMS(200)
Wend

Geek Clock Controller

Geek Clock Controller
// Geek Clock, by Mitchy
// for more info: http://digital-diy.com/projects/168-mitchys-servo-clock.html
// Inspired by Jon Chandlers Servo Clock!
 
Device = 18F2520
Clock = 32
Config MCLRE = Off
 
// one servo in use
#option Servo_NumberOfServos = 1
 
// all includes can be found @ digital-diy.com ("Swordfish - Module Pack")
Include "InternalOscillator.bas" 
Include "Servo.bas"
Include "ServoCal.bas"
Include "USART.bas"
Include "DS1307.bas"
Include "Convert.bas"
 
Const AdjustSpeed = 10                                // #mS to decrease delay by on each adjust
 
Dim USART_Second_Poll As Byte,                        // USART polling registers
    USART_Minute_Poll As Byte,                        //
    USART_Hour_Poll As Byte,                          //
    AdjustDelay As Word,                              //
    AdjustTime As PORTB.5                             // Time Adjust Switch
 
// calculate # of minutes elapsed during day
// and display calibrated servo position based on that info
Sub DisplayServoTime()
    Dim TotalMinutes As LongWord
    If Time.Hour < 12 Then
        TotalMinutes = (Time.Hour * 60) + (Time.Minute)
    Else
        TotalMinutes = ((Time.Hour-12) * 60) + (Time.Minute)
    EndIf
    ServoPosition(0) = TimeValues(TotalMinutes)    
End Sub
 
// update the clock registers, then call the servo update sub
Sub UpdateClock()    
    DS1307.Read(Time, Date)
    DisplayServoTime
End Sub
 
// check if the Time Adjust pin is pressed
// if it is, then increment minutes - also,
// if the button is held, then speed the process up!
Sub CheckAdjust()
    If AdjustTime = 0 Then
        Time.Second = 0
        Inc(Time.Minute)
        If Time.Minute >= 60 Then
            Time.Minute = 0
            Inc(Time.Hour)
            If Time.Hour = 24 Then
                Time.Hour = 0
            EndIf
        EndIf
        DS1307.Write(Time,Date)
        DisplayServoTime
        DelayMS(AdjustDelay)
        If (AdjustDelay-AdjustSpeed)>1 Then 
            Dec(AdjustDelay,AdjustSpeed)
        EndIf
    Else
        AdjustDelay = 300       
    EndIf               
End Sub
 
// check any time parameter has changed, if it has then display on UART
Sub SendUART() 
    If USART_Second_Poll <> Time.Second Or USART_Minute_Poll <> Time.Minute Or USART_Hour_Poll <> Time.Hour Then 
        USART.Write(DecToStr(Time.Hour2),":",DecToStr(Time.Minute,2),":",DecToStr(Time.Second,2),13,10)
        USART.Write(DecToStr(Date.Day,2),"/",DecToStr(Date.Month,2),"/",DecToStr(Date.Year,2),13,10)
        USART_Second_Poll = Time.Second
        USART_Minute_Poll = Time.Minute
        USART_Hour_Poll = Time.Hour       
    EndIf
End Sub
 
Sub Initialise() 
    // configure PORTB
    INTCON2.7 = 0                           // enable internal pullups
    Input(AdjustTime)    
    // if the DS1307 device has not been enabled, we need to give
    // it some default values - here we set for 0600
    // on the 1st Jan 2010...
    If Not Enabled Then
       Time.Hour = 6
       Time.Minute = 0
       Time.Second = 0
       Date.Day = 1
       Date.Month = 1
       Date.Year = 10
       DS1307.Write(Time,Date)
    EndIf    
    // initialise servos    
    UpdateClock
    Servo.On        
    // configure UART module
    USART.SetBaudrate(br38400)
    // initialise variables
    AdjustDelay = 300     
    USART_Second_Poll = 255
    USART_Minute_Poll = 255 
    USART_Hour_Poll = 255        
End Sub
 
 
// main program start...
Initialise
 
While True
    UpdateClock                             // grab current time, update servo position
    CheckAdjust                             // check if user is trying to adjust time
    SendUART                                // display current time via UART
Wend    

ServoCal.bas

ServoCal
Module ServoCal
 
// replace constant data with that of your own results with the spreadsheet found at http://digital-diy.com/forum/download/file.php?id=290
Public Const TimeValues(721) As Word =  ( 
1966,1964,1963,1961,1960,1958,1957,1955,1954,1952,1951,1949,1948,1946,1945,
1944,1941,1939,1937,1935,1933,1931,1929,1927,1925,1923,1921,1919,1917,1915,
1913,1911,1909,1908,1906,1904,1903,1901,1899,1898,1896,1894,1893,1891,1889,
1888,1886,1884,1882,1881,1879,1877,1875,1874,1872,1870,1868,1867,1865,1863,
1862,1860,1858,1856,1854,1853,1851,1849,1847,1845,1844,1842,1840,1838,1836,
1835,1833,1832,1830,1829,1828,1826,1825,1823,1822,1821,1819,1818,1816,1815,
1814,1812,1810,1809,1807,1806,1804,1802,1801,1799,1798,1796,1794,1793,1791,
1790,1787,1785,1783,1780,1778,1776,1773,1771,1769,1766,1764,1762,1759,1757,
1755,1753,1752,1751,1750,1749,1747,1746,1745,1744,1743,1741,1740,1739,1738,
1737,1735,1733,1731,1729,1727,1725,1723,1721,1719,1717,1715,1713,1711,1709,
1708,1706,1705,1703,1702,1701,1699,1698,1696,1695,1694,1692,1691,1689,1688,
1687,1685,1683,1682,1680,1679,1677,1675,1674,1672,1671,1669,1667,1666,1664,
1663,1661,1659,1658,1656,1655,1653,1652,1650,1649,1647,1646,1644,1643,1641,
1640,1637,1635,1633,1630,1628,1626,1623,1621,1619,1616,1614,1612,1609,1607,
1605,1603,1601,1600,1598,1597,1595,1593,1592,1590,1589,1587,1585,1584,1582,
1581,1578,1576,1574,1572,1570,1568,1566,1564,1562,1560,1558,1556,1554,1552,
1550,1548,1546,1544,1542,1541,1539,1537,1535,1533,1532,1530,1528,1526,1524,
1523,1521,1519,1518,1516,1515,1513,1511,1510,1508,1507,1505,1503,1502,1500,
1499,1496,1494,1492,1490,1488,1486,1484,1482,1480,1478,1476,1474,1472,1470,
1468,1466,1464,1462,1461,1459,1457,1455,1454,1452,1450,1448,1447,1445,1443,
1442,1439,1437,1435,1433,1431,1429,1427,1425,1423,1421,1419,1417,1415,1413,
1411,1409,1407,1406,1404,1403,1401,1400,1398,1397,1395,1394,1392,1391,1389,
1388,1386,1385,1383,1382,1380,1379,1377,1376,1374,1373,1371,1370,1368,1367,
1366,1363,1361,1359,1357,1355,1353,1351,1349,1347,1345,1343,1341,1339,1337,
1335,1333,1331,1329,1327,1326,1324,1322,1320,1318,1317,1315,1313,1311,1309,
1308,1306,1305,1304,1303,1302,1300,1299,1298,1297,1296,1294,1293,1292,1291,
1290,1287,1285,1283,1281,1279,1277,1275,1273,1271,1269,1267,1265,1263,1261,
1259,1257,1255,1253,1251,1249,1247,1245,1243,1241,1239,1237,1235,1233,1231,
1230,1228,1227,1225,1224,1222,1221,1219,1218,1216,1215,1213,1212,1210,1209,
1208,1206,1204,1203,1201,1200,1198,1197,1195,1194,1192,1191,1189,1188,1186,
1185,1183,1181,1179,1178,1176,1174,1172,1171,1169,1167,1165,1164,1162,1160,
1159,1156,1154,1152,1150,1148,1146,1144,1142,1140,1138,1136,1134,1132,1130,
1128,1126,1124,1123,1121,1120,1118,1117,1115,1114,1112,1111,1109,1108,1106,
1105,1103,1102,1101,1099,1098,1097,1095,1094,1093,1091,1090,1089,1087,1086,
1085,1083,1081,1079,1077,1076,1074,1072,1070,1068,1067,1065,1063,1061,1059,
1058,1056,1054,1052,1051,1049,1047,1045,1044,1042,1040,1038,1037,1035,1033,
1032,1029,1027,1025,1022,1020,1018,1015,1013,1011,1008,1006,1004,1001,999,
997,995,994,993,992,991,990,989,987,986,985,984,983,982,981,
980,978,976,975,973,972,970,968,967,965,964,962,960,959,957,
956,954,952,951,949,947,946,944,942,941,939,937,936,934,932,
931,928,926,924,922,920,918,916,914,912,910,908,906,904,902,
900,898,897,896,894,893,892,890,889,888,886,885,884,882,881,
880,878,876,874,872,871,869,867,865,863,862,860,858,856,854,
853,851,850,848,847,845,844,842,841,839,838,836,835,833,832,
831,829,827,826,824,823,821,820,818,817,815,814,812,811,809,
808,806,805,804,802,801,800,798,797,796,794,793,792,790,789,
788,786,784,782,780,778,776,774,772,770,768,766,764,762,760,
759,757,755,753,752,750,748,746,745,743,741,739,738,736,734,
733
)

 

Schematic

Not that the schematic matters much - the TAP-28 Development Board already has 95% of the hardware. The other 5% is the RTC Daughter Board! IF you wanted to make something similar, then message Jon Chandler and get in on the next TAP-28 production run, or you could submit the Gerber files and make your own!

As for the DS1307 board, well I did post the Gerber files for it, and the design is easy enough to make on a protoboard.

Geek_Clock_Schematic

Forum Activity

Member Access