Written by Jon Chandler
Originally Posted To DigitalDIY (RIP) Saturday, 19 December 2009
It's hard to believe I wrote this article 15 years ago (both that it was that long ago and that it was only that long ago)! This was my first microcontroller project as I started this journey. It was published on Digital-DIY, a website that has since disappeared and this article had been lost. It was published on Hack-A-Day, which resulted in so much traffic to Digital-DIY the site crashed repeatedly for several days. This clock graced Metrix Create Space in Seattle for many years (another sad RIP), which was perfect – they opened at noon and closed at midnight. When the clock zipped back to the start at midnight, it was time to go home.
Clocks abound with all kinds of off-beat styles. Here's a clock that appeals to geeks (and also works well for stealth clock watching)
A Geeky Stealth Clock - The Time is about 4:20
The clock is patterned after an analog voltmeter. The meter pointer indicates the time on a meter scale marked in hours, with quarter divisions indicated. The pointer, driven by a servo motor, starts at 12 o'clock on the left, ending at 12 o'clock on the right. The meter pointer travels slowly to the right, indicating the current time. At 12 o'clock, the pointer rapidly transverses from right to left, restarting the process.
Servos have been a mainstay in RC (radio control) cars and planes and more recently in robotics. Turns out they are pretty simple to use. Servos can be used in two ways; the traditional way (used here) is to turn through about 180 degrees to a known position to operate a control surface, or to turn a wheel for steering. Servos can also be modified for continuous rotation, perhaps for driving a robot. When modified for continuous rotation, the speed and direction is easy to control, but the position of the servo can't be determined.
To build the clock, finding a suitable enclosure is the first step. The servo is about 1.25" tall, so some depth is needed. A deep picture frame might be a good option. I found a wood box used for a smoked salmon gift at the thrift store for this clock. Once the enclosure is selected, making the meter scale is the next step. I used a drawing program to create the scale. Depending on the enclosure, an arc of 90° or 120° works well. I divided the scale into 12 major increments for hours, with 4 minor increments showing quarter hours. I sized my drawing to fit on an 8" x 10" sheet, then printed it at a photo kiosk to get a nice glossy face. After trimming, I attached it to the enclosure with spray mount adhesive. Links to sample meter faces for 120° or 90° (PDFs) are below.
90° Clock Face
120° Clock Face
In this application, I used a standard type 4310 Futaba servo, which was about $10 at the local hobby store. The smallest min-servo would be suitable for this application as there is no force being transmitted. The pointer is a piece of carbon fiber rod also from the hobby store, although a piece of piano wire would work as well. The rod is attached to a servo arm (instead of the suppled disk) using some heat shrink tubing. A red piece of heat shrink was added for the pointer. The servo was mounted to the back of the enclosure panel using double-faced tape. Position the hole for the servo carefully at the center of the arc to ensure accuracy.
The picture below shows the enclosure. The back side is used as the meter face.
The Enclosure
Swordfish doesn't have a specific servo module, but pulsing an output pin high and low with delay commands is fine for this application. The "on" time of the servo over a 20,000 µsec period controls the angle of rotation. A 1,500 µsec pulse width results in mid-scale rotation. Something around 1,000 µsec reaches the extreme rotation to one side, about 2,000 µsec is the maximum rotation in the other direction. It is important not to drive the servo too far – it has mechanical stops and something will break if driven too far.
The "calibration" step is about the most difficult part of the project. Write a simple program to pulse the output pin at 1,500 µsec. Position the pointer on the servo to indicate approximately 6 o'clock at this position. The servo arm is splined so get it as close as possible but pointing at exactly 6 o'clock isn't required.
Next, pulse the servo at 2,000 µsec to determine the end point position. In my case, the servo is made for counterclockwise rotation, so the "maximum" position is near the left end of of the scale. Adjust the pulse width until the pointer lines up exactly with the 12 o'clock position. Since this is a one-time operation, I just "brute forced" it and reloaded the program several times to determine the value. Repeat the process for the other end point. This scaling controls how well the pointer actually corresponds to the time, so get it as close as possible. Depending on the linearity of the servo, this may be all that's required for calibration. See the note on linearity below.
Time-keeping is based on Warren Schroeder's methods on the Swordfish web page, counting clock cycles. I modified Warren's fourth method in the following program.
Modifications were made to use a 20 MHz crystal instead of 8 MHz as used in the example. To achieve decent accuracy, an external crystal must be used; a PIC's internal oscillator will not be accurate enough for good time keeping. For increased accuracy, a real time clock chip could be used. The current time is updated once each second, which is overkill for this project. The servo resolution is approximately 1 minute using the DelayMS() command. The servo position is updated each second through a simple procedure. Since nothing else is happening in this program, no interrupts are needed to control the servo.
There are 42,300 seconds in 12 hours. Seconds are counted from zero starting at 12:00 until 42,300 is reached, when the counter is reset to zero. The fraction of seconds for 12 hours (current count / 43,200) is multiplied by the meter span to determine position. Note that integer math is used here and this fraction is less than 1, so it equates to zero in integer terms - the multiplication by meter span must be done before the division.
To power the clock, a 5 volt power supply was salvaged from a cell phone. The servo draws around 10 mA continuously, and peaks at about 100 mA during the brief period the servo is returning from one side to the other.
My prototype tests were done using a meter arc with 90° span. The results acheived by calibrating the two end points were very good and the clock could be read with good accuracy. For the enclosure shown, I expanded the meter arc to 120°. Turns out the servo is slightly non-linear over this range to the point that time readings were too far off. I made measurements at quarter-hour increments, comparing what looked right visually to calculated values. The results, shown below, aren't far off but it's enough to throw the results off. I used a simple scheme to linearize the data using a CASE SELECT command.
Linearity, 120° Clock Face
The clock runs on a PIC18F1320 (which I happened to have), hand-assembled on a pref board. A picture of the board and a schematic are shown below. Most PIC 18F-series will work for this circuit - a proto-board with an 18F452 was used for code development, The two buttons are for setting the time. Because the servo has its own internal electronics, it has 3 connections for control signal, power and ground. No high-current drivers are needed by the circuit.
Servo Clock Circuit
Clock Circuit, Built on Perf Board
The black 6 conductor wire at the upper right is from the PICKit 2 programmer. The 3 conductor wire is the servo cable. The power supply isn't hooked up yet - power is supplied by the PICKit2.
The guts of the clock. The PIC controller is on the perf board. The black rectangular object at ceneter bottom is the servo. And a 5 volt wall-wart powers the circuit.
The Guts
The software was written in Swordfish Basic, a fast compiled Basic similar to Visual Basic 6 for Microchip PIC18F-series micros. It's still my preferred coding language today (2024), and it's continuously updated for the latest, greatest PIC-18F devices. The special edition of Swordfish Basic is a trial version with generous code-length limits and no time-length expiration. Many users handle fairly complex programs with no need to upgrade to the paid version.