- Published: Tuesday, 02 March 2010
- Written by Jon Chandler
- Hits: 68236
[Note: a more rigorous calibration approach for dealing with non-linear servos can be found here.]
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) .
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.
Graham has a great explanation of servos in the Proton section. 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 degrees or 120 degrees 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. A sample meter face for a 120 degree arc is here. A 90 degree face is here.
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 supplied 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.
Graham's servo description covers the basics nicely. 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 usec period controls the angle of rotation. A 1,500 usec pulse width results in mid-scale rotation. Something around 1,000 usec reaches the extreme rotation to one side, about 2,000 usec 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 ms. 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 usec 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.
A Geeky Stealth Clock - The Time is about 4:20
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.
A Note About Linearity
My prototype tests were done using a meter arc with 90 degree span. The results achieved 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 degrees. 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 SELCT command.
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.
PIC18F1320 on Perfboard
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 Assembled Clock